Merge branch 'master' into upstream-merge-38116

This commit is contained in:
deathride58
2018-06-05 21:30:21 +00:00
committed by GitHub
174 changed files with 6157 additions and 5377 deletions
+1
View File
@@ -67,6 +67,7 @@
#define ADMIN_PUNISHMENT_BSA "Bluespace Artillery Device"
#define ADMIN_PUNISHMENT_FIREBALL "Fireball"
#define ADMIN_PUNISHMENT_ROD "Immovable Rod"
#define ADMIN_PUNISHMENT_SUPPLYPOD "Supply Pod"
#define AHELP_ACTIVE 1
#define AHELP_CLOSED 2
+31
View File
@@ -194,6 +194,37 @@
#define ATMOS_GAS_MONITOR_WASTE_ENGINE "engine-waste_out"
#define ATMOS_GAS_MONITOR_WASTE_ATMOS "atmos-waste_out"
//AIRLOCK CONTROLLER TAGS
//RnD toxins burn chamber
#define INCINERATOR_TOXMIX_IGNITER "toxmix_igniter"
#define INCINERATOR_TOXMIX_VENT "toxmix_vent"
#define INCINERATOR_TOXMIX_DP_VENTPUMP "toxmix_airlock_pump"
#define INCINERATOR_TOXMIX_AIRLOCK_SENSOR "toxmix_airlock_sensor"
#define INCINERATOR_TOXMIX_AIRLOCK_CONTROLLER "toxmix_airlock_controller"
#define INCINERATOR_TOXMIX_AIRLOCK_INTERIOR "toxmix_airlock_interior"
#define INCINERATOR_TOXMIX_AIRLOCK_EXTERIOR "toxmix_airlock_exterior"
//Atmospherics/maintenance incinerator
#define INCINERATOR_ATMOS_IGNITER "atmos_incinerator_igniter"
#define INCINERATOR_ATMOS_MAINVENT "atmos_incinerator_mainvent"
#define INCINERATOR_ATMOS_AUXVENT "atmos_incinerator_auxvent"
#define INCINERATOR_ATMOS_DP_VENTPUMP "atmos_incinerator_airlock_pump"
#define INCINERATOR_ATMOS_AIRLOCK_SENSOR "atmos_incinerator_airlock_sensor"
#define INCINERATOR_ATMOS_AIRLOCK_CONTROLLER "atmos_incinerator_airlock_controller"
#define INCINERATOR_ATMOS_AIRLOCK_INTERIOR "atmos_incinerator_airlock_interior"
#define INCINERATOR_ATMOS_AIRLOCK_EXTERIOR "atmos_incinerator_airlock_exterior"
//Syndicate lavaland base incinerator (lavaland_surface_syndicate_base1.dmm)
#define INCINERATOR_SYNDICATELAVA_IGNITER "syndicatelava_igniter"
#define INCINERATOR_SYNDICATELAVA_MAINVENT "syndicatelava_mainvent"
#define INCINERATOR_SYNDICATELAVA_AUXVENT "syndicatelava_auxvent"
#define INCINERATOR_SYNDICATELAVA_DP_VENTPUMP "syndicatelava_airlock_pump"
#define INCINERATOR_SYNDICATELAVA_AIRLOCK_SENSOR "syndicatelava_airlock_sensor"
#define INCINERATOR_SYNDICATELAVA_AIRLOCK_CONTROLLER "syndicatelava_airlock_controller"
#define INCINERATOR_SYNDICATELAVA_AIRLOCK_INTERIOR "syndicatelava_airlock_interior"
#define INCINERATOR_SYNDICATELAVA_AIRLOCK_EXTERIOR "syndicatelava_airlock_exterior"
//MULTIPIPES
//IF YOU EVER CHANGE THESE CHANGE SPRITES TO MATCH.
#define PIPING_LAYER_MIN 1
+2
View File
@@ -254,6 +254,8 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
#define ORBITRON "Orbitron"
#define SHARE "Share Tech Mono"
GLOBAL_LIST_INIT(pda_styles, list(MONO, VT, ORBITRON, SHARE))
//Color Defines
#define OOC_COLOR "#002eb8"
+8
View File
@@ -26,6 +26,14 @@
return
next_click = world.time + 1
if(multicam_on)
var/turf/T = get_turf(A)
if(T)
for(var/obj/screen/movable/pic_in_pic/ai/P in T.vis_locs)
if(P.ai == src)
P.Click(params)
break
if(check_click_intercept(params,A))
return
+2
View File
@@ -134,6 +134,8 @@
#define ui_ai_take_picture "SOUTH:6,WEST+12"
#define ui_ai_view_images "SOUTH:6,WEST+13"
#define ui_ai_sensor "SOUTH:6,WEST+14"
#define ui_ai_multicam "SOUTH+1:6,WEST+13"
#define ui_ai_add_multicam "SOUTH+1:6,WEST+14"
//Pop-up inventory
#define ui_shoes "WEST+1:8,SOUTH:5"
+29 -1
View File
@@ -164,6 +164,26 @@
var/mob/living/silicon/S = usr
S.toggle_sensors()
/obj/screen/ai/multicam
name = "Multicamera Mode"
icon_state = "multicam"
/obj/screen/ai/multicam/Click()
if(..())
return
var/mob/living/silicon/ai/AI = usr
AI.toggle_multicam()
/obj/screen/ai/add_multicam
name = "New Camera"
icon_state = "new_cam"
/obj/screen/ai/add_multicam/Click()
if(..())
return
var/mob/living/silicon/ai/AI = usr
AI.drop_new_multicam()
/datum/hud/ai
ui_style_icon = 'icons/mob/screen_ai.dmi'
@@ -247,12 +267,20 @@
using.screen_loc = ui_ai_view_images
static_inventory += using
//Medical/Security sensors
using = new /obj/screen/ai/sensors()
using.screen_loc = ui_ai_sensor
static_inventory += using
//Multicamera mode
using = new /obj/screen/ai/multicam()
using.screen_loc = ui_ai_multicam
static_inventory += using
//Add multicamera camera
using = new /obj/screen/ai/add_multicam()
using.screen_loc = ui_ai_add_multicam
static_inventory += using
/mob/living/silicon/ai/create_mob_hud()
if(client && !hud_used)
+4 -2
View File
@@ -12,6 +12,8 @@
var/snap2grid = FALSE
var/moved = FALSE
var/locked = FALSE
var/x_off = -16
var/y_off = -16
//Snap Screen Object
//Tied to the grid, snaps to the nearest turf
@@ -42,8 +44,8 @@
screen_loc = "[screen_loc_X[1]],[screen_loc_Y[1]]"
else //Normalise Pixel Values (So the object drops at the center of the mouse, not 16 pixels off)
var/pix_X = text2num(screen_loc_X[2]) - 16
var/pix_Y = text2num(screen_loc_Y[2]) - 16
var/pix_X = text2num(screen_loc_X[2]) + x_off
var/pix_Y = text2num(screen_loc_Y[2]) + y_off
screen_loc = "[screen_loc_X[1]]:[pix_X],[screen_loc_Y[1]]:[pix_Y]"
moved = screen_loc
+144
View File
@@ -0,0 +1,144 @@
/obj/screen/movable/pic_in_pic
name = "Picture-in-picture"
screen_loc = "CENTER"
plane = GAME_PLANE
var/atom/center
var/width = 0
var/height = 0
var/list/shown_to = list()
var/list/viewing_turfs = list()
var/obj/screen/component_button/button_x
var/obj/screen/component_button/button_expand
var/obj/screen/component_button/button_shrink
var/mutable_appearance/standard_background
var/const/max_dimensions = 10
/obj/screen/movable/pic_in_pic/Initialize()
. = ..()
make_backgrounds()
/obj/screen/movable/pic_in_pic/Destroy()
for(var/C in shown_to)
unshow_to(C)
QDEL_NULL(button_x)
QDEL_NULL(button_shrink)
QDEL_NULL(button_expand)
return ..()
/obj/screen/movable/pic_in_pic/component_click(obj/screen/component_button/component, params)
if(component == button_x)
qdel(src)
else if(component == button_expand)
set_view_size(width+1, height+1)
else if(component == button_shrink)
set_view_size(width-1, height-1)
/obj/screen/movable/pic_in_pic/proc/make_backgrounds()
standard_background = new /mutable_appearance()
standard_background.icon = 'icons/misc/pic_in_pic.dmi'
standard_background.icon_state = "background"
standard_background.layer = SPACE_LAYER
/obj/screen/movable/pic_in_pic/proc/add_buttons()
var/static/mutable_appearance/move_tab
if(!move_tab)
move_tab = new /mutable_appearance()
//all these properties are always the same, and since adding something to the overlay
//list makes a copy, there is no reason to make a new one each call
move_tab.icon = 'icons/misc/pic_in_pic.dmi'
move_tab.icon_state = "move"
move_tab.plane = HUD_PLANE
var/matrix/M = matrix()
M.Translate(0, (height + 0.25) * world.icon_size)
move_tab.transform = M
add_overlay(move_tab)
if(!button_x)
button_x = new /obj/screen/component_button(null, src)
var/mutable_appearance/MA = new /mutable_appearance()
MA.name = "close"
MA.icon = 'icons/misc/pic_in_pic.dmi'
MA.icon_state = "x"
MA.plane = HUD_PLANE
button_x.appearance = MA
M = matrix()
M.Translate((max(4, width) - 0.75) * world.icon_size, (height + 0.25) * world.icon_size)
button_x.transform = M
vis_contents += button_x
if(!button_expand)
button_expand = new /obj/screen/component_button(null, src)
var/mutable_appearance/MA = new /mutable_appearance()
MA.name = "expand"
MA.icon = 'icons/misc/pic_in_pic.dmi'
MA.icon_state = "expand"
MA.plane = HUD_PLANE
button_expand.appearance = MA
M = matrix()
M.Translate(world.icon_size, (height + 0.25) * world.icon_size)
button_expand.transform = M
vis_contents += button_expand
if(!button_shrink)
button_shrink = new /obj/screen/component_button(null, src)
var/mutable_appearance/MA = new /mutable_appearance()
MA.name = "shrink"
MA.icon = 'icons/misc/pic_in_pic.dmi'
MA.icon_state = "shrink"
MA.plane = HUD_PLANE
button_shrink.appearance = MA
M = matrix()
M.Translate(2 * world.icon_size, (height + 0.25) * world.icon_size)
button_shrink.transform = M
vis_contents += button_shrink
/obj/screen/movable/pic_in_pic/proc/add_background()
if((width > 0) && (height > 0))
var/matrix/M = matrix()
M.Scale(width + 0.5, height + 0.5)
M.Translate((width-1)/2 * world.icon_size, (height-1)/2 * world.icon_size)
standard_background.transform = M
add_overlay(standard_background)
/obj/screen/movable/pic_in_pic/proc/set_view_size(width, height, do_refresh = TRUE)
width = CLAMP(width, 0, max_dimensions)
height = CLAMP(height, 0, max_dimensions)
src.width = width
src.height = height
y_off = -height * world.icon_size - 16
cut_overlays()
add_background()
add_buttons()
if(do_refresh)
refresh_view()
/obj/screen/movable/pic_in_pic/proc/set_view_center(atom/target, do_refresh = TRUE)
center = target
if(do_refresh)
refresh_view()
/obj/screen/movable/pic_in_pic/proc/refresh_view()
vis_contents -= viewing_turfs
if(!width || !height)
return
var/turf/T = get_turf(center)
if(!T)
return
var/turf/lowerleft = locate(max(1, T.x - round(width/2)), max(1, T.y - round(height/2)), T.z)
var/turf/upperright = locate(min(world.maxx, lowerleft.x + width - 1), min(world.maxy, lowerleft.y + height - 1), lowerleft.z)
viewing_turfs = block(lowerleft, upperright)
vis_contents += viewing_turfs
/obj/screen/movable/pic_in_pic/proc/show_to(client/C)
if(C)
shown_to[C] = 1
C.screen += src
/obj/screen/movable/pic_in_pic/proc/unshow_to(client/C)
if(C)
shown_to -= C
C.screen -= src
+15
View File
@@ -30,6 +30,9 @@
/obj/screen/orbit()
return
/obj/screen/proc/component_click(obj/screen/component_button/component, params)
return
/obj/screen/text
icon = null
icon_state = null
@@ -604,3 +607,15 @@
holder.screen -= src
holder = null
return ..()
/obj/screen/component_button
var/obj/screen/parent
/obj/screen/component_button/Initialize(mapload, obj/screen/parent)
. = ..()
src.parent = parent
/obj/screen/component_button/Click(params)
if(parent)
parent.component_click(src, params)
@@ -288,6 +288,11 @@
/datum/config_entry/flag/shift_time_realtime
/datum/config_entry/keyed_number_list/antag_rep
/datum/config_entry/number/monkeycap
config_entry_value = 64
min_val = 0
//Cit changes - Adds config options for crew objectives and miscreants
/datum/config_entry/flag/allow_crew_objectives
@@ -304,4 +309,4 @@
/datum/config_entry/number/nightshift_finish
config_entry_value = 6
//End of Cit changes
//End of Cit changes
+16 -6
View File
@@ -6,16 +6,26 @@ SUBSYSTEM_DEF(icon_smooth)
flags = SS_TICKER
var/list/smooth_queue = list()
var/list/deferred = list()
/datum/controller/subsystem/icon_smooth/fire()
while(smooth_queue.len)
var/atom/A = smooth_queue[smooth_queue.len]
smooth_queue.len--
smooth_icon(A)
var/list/cached = smooth_queue
while(cached.len)
var/atom/A = cached[cached.len]
cached.len--
if (A.flags_1 & INITIALIZED_1)
smooth_icon(A)
else
deferred += A
if (MC_TICK_CHECK)
return
if (!smooth_queue.len)
can_fire = 0
if (!cached.len)
if (deferred.len)
smooth_queue = deferred
deferred = cached
else
can_fire = 0
/datum/controller/subsystem/icon_smooth/Initialize()
smooth_zlevel(1,TRUE)
+1 -1
View File
@@ -422,7 +422,7 @@ SUBSYSTEM_DEF(job)
else
M = H
SSpersistence.antag_rep_change[M.client.ckey] += job.antag_rep
SSpersistence.antag_rep_change[M.client.ckey] += job.GetAntagRep()
to_chat(M, "<b>You are the [rank].</b>")
if(job)
+6 -9
View File
@@ -121,7 +121,7 @@ SUBSYSTEM_DEF(mapping)
z_list = SSmapping.z_list
#define INIT_ANNOUNCE(X) to_chat(world, "<span class='boldannounce'>[X]</span>"); log_world(X)
/datum/controller/subsystem/mapping/proc/LoadGroup(list/errorList, name, path, files, list/traits, list/default_traits)
/datum/controller/subsystem/mapping/proc/LoadGroup(list/errorList, name, path, files, list/traits, list/default_traits, silent = FALSE)
var/start_time = REALTIMEOFDAY
if (!islist(files)) // handle single-level maps
@@ -157,8 +157,8 @@ SUBSYSTEM_DEF(mapping)
var/full_path = "_maps/[path]/[file]"
if(!loader.load_map(file(full_path), 0, 0, start_z + files[file], no_changeturf = TRUE))
errorList |= full_path
INIT_ANNOUNCE("Loaded [name] in [(REALTIMEOFDAY - start_time)/10]s!")
if(!silent)
INIT_ANNOUNCE("Loaded [name] in [(REALTIMEOFDAY - start_time)/10]s!")
/datum/controller/subsystem/mapping/proc/loadWorld()
//if any of these fail, something has gone horribly, HORRIBLY, wrong
@@ -187,9 +187,6 @@ SUBSYSTEM_DEF(mapping)
LoadGroup(FailedZs, "Lavaland", "map_files/Mining", "Lavaland.dmm", default_traits = ZTRAITS_LAVALAND)
else if (!isnull(config.minetype))
INIT_ANNOUNCE("WARNING: An unknown minetype '[config.minetype]' was set! This is being ignored! Update the maploader code!")
// load Reebe
LoadGroup(FailedZs, "Reebe", "map_files/generic", "City_of_Cogs.dmm", default_traits = ZTRAITS_REEBE)
#endif
if(LAZYLEN(FailedZs)) //but seriously, unless the server's filesystem is messed up this will never happen
@@ -367,14 +364,14 @@ GLOBAL_LIST_EMPTY(the_station_areas)
away_level = template.load_new_z()
else
return
message_admins("Admin [key_name_admin(usr)] has loaded [away_name] away mission.")
log_admin("Admin [key_name(usr)] has loaded [away_name] away mission.")
if(!away_level)
message_admins("Loading [away_name] failed!")
return
if(GLOB.the_gateway)
//Link any found away gate with station gate
var/obj/machinery/gateway/centeraway/new_gate
-13
View File
@@ -564,19 +564,6 @@
/datum/action/innate/proc/Deactivate()
return
//Preset for action that call specific procs (consider innate).
/datum/action/generic
check_flags = 0
var/procname
/datum/action/generic/Trigger()
if(!..())
return 0
if(target && procname)
call(target, procname)(usr)
return 1
//Preset for an action with a cooldown
/datum/action/cooldown
+4 -1
View File
@@ -11,13 +11,16 @@
/obj/structure/lattice,
/obj/structure/stone_tile,
/obj/item/projectile,
/obj/effect/projectile,
/obj/effect/portal,
/obj/effect/abstract,
/obj/effect/hotspot,
/obj/effect/landmark,
/obj/effect/temp_visual,
/obj/effect/light_emitter/tendril,
/obj/effect/collapse))
/obj/effect/collapse,
/obj/effect/particle_effect/ion_trails
))
/datum/component/chasm/Initialize(turf/target)
RegisterSignal(list(COMSIG_MOVABLE_CROSSED, COMSIG_ATOM_ENTERED), .proc/Entered)
@@ -125,7 +125,7 @@ Bonus
symptom_delay_max = 140
if(A.properties["stage_rate"] >= 8) //serious boom when wet
explosion_power = 2
if(A.properties["transmission"] >= 8) //extra chemicals
if(A.properties["transmittable"] >= 8) //extra chemicals
chems = TRUE
/datum/symptom/alkali/Activate(datum/disease/advance/A)
@@ -60,7 +60,7 @@
/datum/symptom/heal/starlight/Start(datum/disease/advance/A)
if(!..())
return
if(A.properties["transmission"] >= 6)
if(A.properties["transmittable"] >= 6)
nearspace_penalty = 1
if(A.properties["stage_rate"] >= 6)
power = 2
@@ -358,7 +358,7 @@
return
if(A.properties["stage_rate"] >= 7)
power = 2
if(A.properties["trasmission"] >= 6)
if(A.properties["transmittable"] >= 6)
temp_rate = 4
/datum/symptom/heal/plasma/CanHeal(datum/disease/advance/A)
@@ -425,7 +425,7 @@
return
if(A.properties["resistance"] >= 7)
power = 2
if(A.properties["trasmission"] >= 6)
if(A.properties["transmittable"] >= 6)
cellular_damage = TRUE
/datum/symptom/heal/radiation/CanHeal(datum/disease/advance/A)
@@ -33,10 +33,10 @@ Bonus
/datum/symptom/fever/Start(datum/disease/advance/A)
if(!..())
return
if(A.properties["stage_speed"] >= 5) //dangerous cold
if(A.properties["stage_rate"] >= 5) //dangerous cold
power = 1.5
unsafe = TRUE
if(A.properties["stage_speed"] >= 10)
if(A.properties["stage_rate"] >= 10)
power = 2.5
/datum/symptom/shivering/Activate(datum/disease/advance/A)
+1 -1
View File
@@ -55,7 +55,7 @@
if(affected_mob.notransform)
return
affected_mob.notransform = 1
for(var/obj/item/W in affected_mob.get_equipped_items())
for(var/obj/item/W in affected_mob.get_equipped_items(TRUE))
affected_mob.dropItemToGround(W)
for(var/obj/item/I in affected_mob.held_items)
affected_mob.dropItemToGround(I)
+3 -7
View File
@@ -60,9 +60,6 @@
user.remote_control = null
if(!QDELETED(eye))
if(user_good && user.client)
for(var/datum/camerachunk/chunk in eye.visibleCameraChunks)
chunk.remove(eye)
qdel(eye)
eye = null
@@ -205,7 +202,7 @@
/datum/holorecord/proc/set_caller_image(mob/user)
var/olddir = user.dir
user.setDir(SOUTH)
caller_image = getFlatIcon(user)
caller_image = image(user)
user.setDir(olddir)
/obj/item/disk/holodisk
@@ -284,7 +281,7 @@
else
var/datum/preset_holoimage/H = new preset_image_type
record.caller_image = H.build_image()
//These build caller image from outfit and some additional data, for use by mappers for ruin holorecords
/datum/preset_holoimage
var/nonhuman_mobtype //Fill this if you just want something nonhuman
@@ -303,7 +300,7 @@
mannequin.equipOutfit(outfit_type,TRUE)
mannequin.setDir(SOUTH)
COMPILE_OVERLAYS(mannequin)
. = getFlatIcon(mannequin)
. = image(mannequin)
unset_busy_human_dummy("HOLODISK_PRESET")
/obj/item/disk/holodisk/example
@@ -347,4 +344,3 @@
/datum/preset_holoimage/clown
outfit_type = /datum/outfit/job/clown
+8
View File
@@ -115,6 +115,14 @@
// Generates nothing but atmos runtimes and salt
cost = 0
/datum/map_template/ruin/lavaland/ratvar
name = "Dead God"
id = "ratvar"
description = "Ratvars final resting place."
suffix = "lavaland_surface_dead_ratvar.dmm"
cost = 0
allow_duplicates = FALSE
/datum/map_template/ruin/lavaland/hierophant
name = "Hierophant's Arena"
id = "hierophant"
+3
View File
@@ -55,6 +55,9 @@
/datum/quirk/proc/post_add() //for text, disclaimers etc. given after you spawn in with the trait
/datum/quirk/proc/on_transfer() //code called when the trait is transferred to a new mob
/datum/quirk/proc/clone_data() //return additional data that should be remembered by cloning
/datum/quirk/proc/on_clone(data) //create the quirk from clone data
/datum/quirk/process()
if(QDELETED(quirk_holder))
quirk_holder = null
+4
View File
@@ -85,7 +85,11 @@
quirk_holder.SendSignal(COMSIG_CLEAR_MOOD_EVENT, "family_heirloom")
quirk_holder.SendSignal(COMSIG_ADD_MOOD_EVENT, "family_heirloom_missing", /datum/mood_event/family_heirloom_missing)
/datum/quirk/family_heirloom/clone_data()
return heirloom
/datum/quirk/family_heirloom/on_clone(data)
heirloom = data
/datum/quirk/heavy_sleeper
name = "Heavy Sleeper"
-17
View File
@@ -425,23 +425,6 @@
/atom/proc/update_remote_sight(mob/living/user)
return
/atom/proc/add_vomit_floor(mob/living/carbon/M, toxvomit = 0)
if(isturf(src))
var/obj/effect/decal/cleanable/vomit/V = new /obj/effect/decal/cleanable/vomit(src, M.get_static_viruses())
// Make toxins vomit look different
if(toxvomit)
V.icon_state = "vomittox_[pick(1,4)]"
if(M.reagents)
clear_reagents_to_vomit_pool(M,V)
/atom/proc/clear_reagents_to_vomit_pool(mob/living/carbon/M, obj/effect/decal/cleanable/vomit/V)
M.reagents.trans_to(V, M.reagents.total_volume / 10)
for(var/datum/reagent/R in M.reagents.reagent_list) //clears the stomach of anything that might be digested as food
if(istype(R, /datum/reagent/consumable))
var/datum/reagent/consumable/nutri_check = R
if(nutri_check.nutriment_factor >0)
M.reagents.remove_reagent(R.id,R.volume)
//Hook for running code when a dir change occurs
/atom/proc/setDir(newdir)
+14 -10
View File
@@ -161,41 +161,45 @@
else //Diagonal move, split it into cardinal moves
moving_diagonally = FIRST_DIAG_STEP
var/first_step_dir
// The `&& moving_diagonally` checks are so that a forceMove taking
// place due to a Crossed, Collided, etc. call will interrupt
// the second half of the diagonal movement, or the second attempt
// at a first half if step() fails because we hit something.
if (direct & NORTH)
if (direct & EAST)
if (step(src, NORTH))
if (step(src, NORTH) && moving_diagonally)
first_step_dir = NORTH
moving_diagonally = SECOND_DIAG_STEP
. = step(src, EAST)
else if (step(src, EAST))
else if (moving_diagonally && step(src, EAST))
first_step_dir = EAST
moving_diagonally = SECOND_DIAG_STEP
. = step(src, NORTH)
else if (direct & WEST)
if (step(src, NORTH))
if (step(src, NORTH) && moving_diagonally)
first_step_dir = NORTH
moving_diagonally = SECOND_DIAG_STEP
. = step(src, WEST)
else if (step(src, WEST))
else if (moving_diagonally && step(src, WEST))
first_step_dir = WEST
moving_diagonally = SECOND_DIAG_STEP
. = step(src, NORTH)
else if (direct & SOUTH)
if (direct & EAST)
if (step(src, SOUTH))
if (step(src, SOUTH) && moving_diagonally)
first_step_dir = SOUTH
moving_diagonally = SECOND_DIAG_STEP
. = step(src, EAST)
else if (step(src, EAST))
else if (moving_diagonally && step(src, EAST))
first_step_dir = EAST
moving_diagonally = SECOND_DIAG_STEP
. = step(src, SOUTH)
else if (direct & WEST)
if (step(src, SOUTH))
if (step(src, SOUTH) && moving_diagonally)
first_step_dir = SOUTH
moving_diagonally = SECOND_DIAG_STEP
. = step(src, WEST)
else if (step(src, WEST))
else if (moving_diagonally && step(src, WEST))
first_step_dir = WEST
moving_diagonally = SECOND_DIAG_STEP
. = step(src, SOUTH)
@@ -310,8 +314,8 @@
var/area/old_area = get_area(oldloc)
var/area/destarea = get_area(destination)
loc = destination
moving_diagonally = 0
if(!same_loc)
if(oldloc)
@@ -558,7 +562,7 @@
if(visual_effect_icon)
I = image('icons/effects/effects.dmi', A, visual_effect_icon, A.layer + 0.1)
else if(used_item)
I = image(used_item.icon, A, used_item.icon_state, A.layer + 0.1)
I = image(icon = used_item, loc = A, layer = A.layer + 0.1)
// Scale the icon.
I.transform *= 0.75
@@ -143,6 +143,12 @@ Credit where due:
var/datum/team/clockcult/main_clockcult
/datum/game_mode/clockwork_cult/pre_setup()
var/list/errorList = list()
SSmapping.LoadGroup(errorList, "Reebe", "map_files/generic", "City_of_Cogs.dmm", default_traits = ZTRAITS_REEBE, silent = TRUE)
if(errorList.len) // reebe failed to load
message_admins("Rebee failed to load!")
log_game("Rebee failed to load!")
return FALSE
if(CONFIG_GET(flag/protect_roles_from_antagonist))
restricted_jobs += protected_jobs
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
+12 -1
View File
@@ -101,6 +101,17 @@
var/on = TRUE
var/alert = FALSE
/obj/machinery/airlock_sensor/incinerator_toxmix
id_tag = INCINERATOR_TOXMIX_AIRLOCK_SENSOR
master_tag = INCINERATOR_TOXMIX_AIRLOCK_CONTROLLER
/obj/machinery/airlock_sensor/incinerator_atmos
id_tag = INCINERATOR_ATMOS_AIRLOCK_SENSOR
master_tag = INCINERATOR_ATMOS_AIRLOCK_CONTROLLER
/obj/machinery/airlock_sensor/incinerator_syndicatelava
id_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_SENSOR
master_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_CONTROLLER
/obj/machinery/airlock_sensor/update_icon()
if(on)
@@ -150,4 +161,4 @@
/obj/machinery/airlock_sensor/Destroy()
SSradio.remove_object(src,frequency)
return ..()
return ..()
+38
View File
@@ -189,6 +189,31 @@
device = new /obj/item/assembly/control(src)
..()
/obj/machinery/button/door/incinerator_vent_toxmix
name = "combustion chamber vent control"
id = INCINERATOR_TOXMIX_VENT
req_access = list(ACCESS_TOX)
/obj/machinery/button/door/incinerator_vent_atmos_main
name = "turbine vent control"
id = INCINERATOR_ATMOS_MAINVENT
req_one_access = list(ACCESS_ATMOSPHERICS, ACCESS_MAINT_TUNNELS)
/obj/machinery/button/door/incinerator_vent_atmos_aux
name = "combustion chamber vent control"
id = INCINERATOR_ATMOS_AUXVENT
req_one_access = list(ACCESS_ATMOSPHERICS, ACCESS_MAINT_TUNNELS)
/obj/machinery/button/door/incinerator_vent_syndicatelava_main
name = "turbine vent control"
id = INCINERATOR_SYNDICATELAVA_MAINVENT
req_access = list(ACCESS_SYNDICATE)
/obj/machinery/button/door/incinerator_vent_syndicatelava_aux
name = "combustion chamber vent control"
id = INCINERATOR_SYNDICATELAVA_AUXVENT
req_access = list(ACCESS_SYNDICATE)
/obj/machinery/button/massdriver
name = "mass driver button"
desc = "A remote control switch for a mass driver."
@@ -203,6 +228,19 @@
skin = "launcher"
device_type = /obj/item/assembly/control/igniter
/obj/machinery/button/ignition/incinerator
name = "combustion chamber ignition switch"
desc = "A remote control switch for the combustion chamber's igniter."
/obj/machinery/button/ignition/incinerator/toxmix
id = INCINERATOR_TOXMIX_IGNITER
/obj/machinery/button/ignition/incinerator/atmos
id = INCINERATOR_ATMOS_IGNITER
/obj/machinery/button/ignition/incinerator/syndicatelava
id = INCINERATOR_SYNDICATELAVA_IGNITER
/obj/machinery/button/flasher
name = "flasher button"
desc = "A remote control switch for a mounted flasher."
+2 -2
View File
@@ -19,7 +19,6 @@
integrity_failure = 50
var/list/network = list("ss13")
var/c_tag = null
var/c_tag_order = 999
var/status = TRUE
var/start_active = FALSE //If it ignores the random chance to start broken on round start
var/invuln = null
@@ -35,6 +34,7 @@
var/alarm_on = FALSE
var/busy = FALSE
var/emped = FALSE //Number of consecutive EMP's on this camera
var/in_use_lights = 0
// Upgrades bitflag
var/upgrades = 0
@@ -284,7 +284,7 @@
else if (stat & EMPED)
icon_state = "[initial(icon_state)]emp"
else
icon_state = "[initial(icon_state)]"
icon_state = "[initial(icon_state)][in_use_lights ? "_in_use" : ""]"
/obj/machinery/camera/proc/toggle_cam(mob/user, displaymessage = 1)
status = !status
+2 -6
View File
@@ -146,10 +146,6 @@
for (var/j = 1 to i - 1)
a = L[j]
b = L[j + 1]
if (a.c_tag_order != b.c_tag_order)
if (a.c_tag_order > b.c_tag_order)
L.Swap(j, j + 1)
else
if (sorttext(a.c_tag, b.c_tag) < 0)
L.Swap(j, j + 1)
if (sorttext(a.c_tag, b.c_tag) < 0)
L.Swap(j, j + 1)
return L
+2 -1
View File
@@ -203,7 +203,8 @@
H.faction |= factions
for(var/V in quirks)
new V(H)
var/datum/quirk/Q = new V(H)
Q.on_clone(quirks[V])
H.set_cloned_appearance()
+3 -1
View File
@@ -51,7 +51,9 @@
/obj/item/hot_potato/harmless/toy = 1,
/obj/item/card/emagfake = 1,
/obj/item/clothing/shoes/wheelys = 2,
/obj/item/clothing/shoes/kindleKicks = 2)
/obj/item/clothing/shoes/kindleKicks = 2,
/obj/item/storage/belt/military/snack = 2
)
light_color = LIGHT_COLOR_GREEN
+1 -1
View File
@@ -196,7 +196,7 @@
icon_keyboard = "mining_key"
network = list("mine")
circuit = /obj/item/circuitboard/computer/mining
/obj/machinery/computer/security/research
name = "research camera console"
desc = "Used to access the various cameras in science."
@@ -190,7 +190,7 @@
else
moveToNullspace()
if(use_static)
GLOB.cameranet.visibility(src)
GLOB.cameranet.visibility(src, GetViewerClient())
if(visible_icon)
if(eye_user.client)
eye_user.client.images -= user_image
+1 -1
View File
@@ -476,7 +476,7 @@
R.fields["quirks"] = list()
for(var/V in mob_occupant.roundstart_quirks)
var/datum/quirk/T = V
R.fields["quirks"] += T.type
R.fields["quirks"][T.type] = T.clone_data()
if (!isnull(mob_occupant.mind)) //Save that mind so traitors can continue traitoring after cloning.
R.fields["mind"] = "[REF(mob_occupant.mind)]"
@@ -51,7 +51,7 @@
/obj/machinery/computer/communications/Topic(href, href_list)
if(..())
return
if(!is_station_level(z) && !is_centcom_level(z)) //Can only use on centcom and SS13
if(!is_station_level(z) && !is_transit_level(z)) //Can only use in transit and on SS13
to_chat(usr, "<span class='boldannounce'>Unable to establish a connection</span>: \black You're too far away from the station!")
return
usr.set_machine(src)
@@ -79,6 +79,20 @@
opacity = 0
glass = TRUE
/obj/machinery/door/airlock/glass/incinerator
autoclose = FALSE
frequency = FREQ_AIRLOCK_CONTROL
heat_proof = TRUE
req_access = list(ACCESS_SYNDICATE)
/obj/machinery/door/airlock/glass/incinerator/syndicatelava_interior
name = "Turbine Interior Airlock"
id_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_INTERIOR
/obj/machinery/door/airlock/glass/incinerator/syndicatelava_exterior
name = "Turbine Exterior Airlock"
id_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_EXTERIOR
/obj/machinery/door/airlock/command/glass
opacity = 0
glass = TRUE
@@ -107,6 +121,20 @@
opacity = 0
glass = TRUE
/obj/machinery/door/airlock/research/glass/incinerator
autoclose = FALSE
frequency = FREQ_AIRLOCK_CONTROL
heat_proof = TRUE
req_access = list(ACCESS_TOX)
/obj/machinery/door/airlock/research/glass/incinerator/toxmix_interior
name = "Mixing Room Interior Airlock"
id_tag = INCINERATOR_TOXMIX_AIRLOCK_INTERIOR
/obj/machinery/door/airlock/research/glass/incinerator/toxmix_exterior
name = "Mixing Room Exterior Airlock"
id_tag = INCINERATOR_TOXMIX_AIRLOCK_EXTERIOR
/obj/machinery/door/airlock/mining/glass
opacity = 0
glass = TRUE
@@ -287,6 +315,20 @@
opacity = 0
glass = TRUE
/obj/machinery/door/airlock/public/glass/incinerator
autoclose = FALSE
frequency = FREQ_AIRLOCK_CONTROL
heat_proof = TRUE
req_one_access = list(ACCESS_ATMOSPHERICS, ACCESS_MAINT_TUNNELS)
/obj/machinery/door/airlock/public/glass/incinerator/atmos_interior
name = "Turbine Interior Airlock"
id_tag = INCINERATOR_ATMOS_AIRLOCK_INTERIOR
/obj/machinery/door/airlock/public/glass/incinerator/atmos_exterior
name = "Turbine Exterior Airlock"
id_tag = INCINERATOR_ATMOS_AIRLOCK_EXTERIOR
//////////////////////////////////
/*
External Airlocks
+20
View File
@@ -36,6 +36,26 @@
else
INVOKE_ASYNC(src, .proc/close)
/obj/machinery/door/poddoor/incinerator_toxmix
name = "combustion chamber vent"
id = INCINERATOR_TOXMIX_VENT
/obj/machinery/door/poddoor/incinerator_atmos_main
name = "turbine vent"
id = INCINERATOR_ATMOS_MAINVENT
/obj/machinery/door/poddoor/incinerator_atmos_aux
name = "combustion chamber vent"
id = INCINERATOR_ATMOS_AUXVENT
/obj/machinery/door/poddoor/incinerator_syndicatelava_main
name = "turbine vent"
id = INCINERATOR_SYNDICATELAVA_MAINVENT
/obj/machinery/door/poddoor/incinerator_syndicatelava_aux
name = "combustion chamber vent"
id = INCINERATOR_SYNDICATELAVA_AUXVENT
/obj/machinery/door/poddoor/CollidedWith(atom/movable/AM)
if(density)
return 0
@@ -7,11 +7,11 @@
/datum/computer/file/embedded_program/airlock_controller
var/id_tag
var/exterior_door_tag
var/interior_door_tag
var/airpump_tag
var/sensor_tag
var/sanitize_external
var/exterior_door_tag //Burn chamber facing door
var/interior_door_tag //Station facing door
var/airpump_tag //See: dp_vent_pump.dm
var/sensor_tag //See: /obj/machinery/airlock_sensor
var/sanitize_external //Before the interior airlock opens, do we first drain all gases inside the chamber and then repressurize?
state = AIRLOCK_STATE_CLOSED
var/target_state = AIRLOCK_STATE_CLOSED
@@ -211,6 +211,33 @@
var/sensor_tag
var/sanitize_external
/obj/machinery/embedded_controller/radio/airlock_controller/incinerator_toxmix
name = "Incinerator Access Console"
airpump_tag = INCINERATOR_TOXMIX_DP_VENTPUMP
exterior_door_tag = INCINERATOR_TOXMIX_AIRLOCK_EXTERIOR
id_tag = INCINERATOR_TOXMIX_AIRLOCK_CONTROLLER
interior_door_tag = INCINERATOR_TOXMIX_AIRLOCK_INTERIOR
sanitize_external = TRUE
sensor_tag = INCINERATOR_TOXMIX_AIRLOCK_SENSOR
/obj/machinery/embedded_controller/radio/airlock_controller/incinerator_atmos
name = "Incinerator Access Console"
airpump_tag = INCINERATOR_ATMOS_DP_VENTPUMP
exterior_door_tag = INCINERATOR_ATMOS_AIRLOCK_EXTERIOR
id_tag = INCINERATOR_ATMOS_AIRLOCK_CONTROLLER
interior_door_tag = INCINERATOR_ATMOS_AIRLOCK_INTERIOR
sanitize_external = TRUE
sensor_tag = INCINERATOR_ATMOS_AIRLOCK_SENSOR
/obj/machinery/embedded_controller/radio/airlock_controller/incinerator_syndicatelava
name = "Incinerator Access Console"
airpump_tag = INCINERATOR_SYNDICATELAVA_DP_VENTPUMP
exterior_door_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_EXTERIOR
id_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_CONTROLLER
interior_door_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_INTERIOR
sanitize_external = TRUE
sensor_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_SENSOR
/obj/machinery/embedded_controller/radio/airlock_controller/Initialize(mapload)
. = ..()
if(!mapload)
+12
View File
@@ -13,6 +13,15 @@
var/id = null
var/on = FALSE
/obj/machinery/igniter/incinerator_toxmix
id = INCINERATOR_TOXMIX_IGNITER
/obj/machinery/igniter/incinerator_atmos
id = INCINERATOR_ATMOS_IGNITER
/obj/machinery/igniter/incinerator_syndicatelava
id = INCINERATOR_SYNDICATELAVA_IGNITER
/obj/machinery/igniter/on
on = TRUE
icon_state = "igniter1"
@@ -58,6 +67,9 @@
var/base_state = "migniter"
var/datum/effect_system/spark_spread/spark_system
/obj/machinery/sparker/toxmix
id = INCINERATOR_TOXMIX_IGNITER
/obj/machinery/sparker/Initialize()
. = ..()
spark_system = new /datum/effect_system/spark_spread
+1 -1
View File
@@ -180,7 +180,7 @@
// Remove and recycle the equipped items
if(eat_victim_items)
for(var/obj/item/I in L.get_equipped_items())
for(var/obj/item/I in L.get_equipped_items(TRUE))
if(L.dropItemToGround(I))
eat(I, sound=FALSE)
+1 -24
View File
@@ -2,27 +2,4 @@
force = 30
internal_damage_threshold = 50
armor = list("melee" = 30, "bullet" = 30, "laser" = 15, "energy" = 20, "bomb" = 20, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
/obj/mecha/combat/moved_inside(mob/living/carbon/human/H)
if(..())
if(H.client && H.client.mouse_pointer_icon == initial(H.client.mouse_pointer_icon))
H.client.mouse_pointer_icon = 'icons/mecha/mecha_mouse.dmi'
return 1
else
return 0
/obj/mecha/combat/mmi_moved_inside(obj/item/mmi/mmi_as_oc,mob/user)
if(..())
if(occupant.client && occupant.client.mouse_pointer_icon == initial(occupant.client.mouse_pointer_icon))
occupant.client.mouse_pointer_icon = 'icons/mecha/mecha_mouse.dmi'
return 1
else
return 0
/obj/mecha/combat/go_out()
if(occupant && occupant.client && occupant.client.mouse_pointer_icon == 'icons/mecha/mecha_mouse.dmi')
occupant.client.mouse_pointer_icon = initial(occupant.client.mouse_pointer_icon)
..()
mouse_pointer = 'icons/mecha/mecha_mouse.dmi'
+4
View File
@@ -115,6 +115,7 @@
var/smashcooldown = 3 //deciseconds
var/occupant_sight_flags = 0 //sight flags to give to the occupant (e.g. mech mining scanner gives meson-like vision)
var/mouse_pointer
hud_possible = list (DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_TRACK_HUD)
@@ -855,6 +856,7 @@
if(H && H.client && H in range(1))
occupant = H
H.forceMove(src)
H.update_mouse_pointer()
add_fingerprint(H)
GrantActions(H, human_occupant=1)
forceMove(loc)
@@ -912,6 +914,7 @@
brainmob.reset_perspective(src)
brainmob.remote_control = src
brainmob.update_canmove()
brainmob.update_mouse_pointer()
icon_state = initial(icon_state)
update_icon()
setDir(dir_in)
@@ -981,6 +984,7 @@
setDir(dir_in)
if(L && L.client)
L.update_mouse_pointer()
L.client.change_view(CONFIG_GET(string/default_view))
zoom_mode = 0
@@ -47,6 +47,7 @@
/obj/effect/temp_visual/cult/turf/floor
icon_state = "floorglow"
duration = 5
plane = FLOOR_PLANE
/obj/effect/temp_visual/cult/portal
icon_state = "space"
+51 -12
View File
@@ -340,7 +340,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
desc = "A brown roll of tobacco and... well, you're not quite sure. This thing's huge!"
icon_state = "cigaroff"
icon_on = "cigaron"
icon_off = "cigaroff"
icon_off = "cigaroff" //make sure to add positional sprites in icons/obj/cigarettes.dmi if you add more.
type_butt = /obj/item/cigbutt/cigarbutt
throw_speed = 0.5
item_state = "cigaroff"
@@ -492,11 +492,24 @@ CIGARETTE PACKETS ARE IN FANCY.DM
slot_flags = ITEM_SLOT_BELT
var/lit = 0
var/fancy = TRUE
var/overlay_state
var/overlay_list = list(
"plain",
"dame",
"thirteen",
"snake"
)
heat = 1500
resistance_flags = FIRE_PROOF
light_color = LIGHT_COLOR_FIRE
grind_results = list("iron" = 1, "welding_fuel" = 5, "oil" = 5)
/obj/item/lighter/Initialize()
. = ..()
if(!overlay_state)
overlay_state = pick(overlay_list)
update_icon()
/obj/item/lighter/suicide_act(mob/living/carbon/user)
if (lit)
user.visible_message("<span class='suicide'>[user] begins holding \the [src]'s flame up to [user.p_their()] face! It looks like [user.p_theyre()] trying to commit suicide!</span>")
@@ -507,10 +520,10 @@ CIGARETTE PACKETS ARE IN FANCY.DM
return BRUTELOSS
/obj/item/lighter/update_icon()
if(lit)
icon_state = "[initial(icon_state)]_on"
else
icon_state = "[initial(icon_state)]"
cut_overlays()
var/mutable_appearance/lighter_overlay = mutable_appearance(icon,"lighter_overlay_[overlay_state][lit ? "-on" : ""]")
icon_state = "[initial(icon_state)][lit ? "-on" : ""]"
add_overlay(lighter_overlay)
/obj/item/lighter/ignition_effect(atom/A, mob/user)
if(is_hot())
@@ -597,19 +610,44 @@ CIGARETTE PACKETS ARE IN FANCY.DM
desc = "A cheap-as-free lighter."
icon_state = "lighter"
fancy = FALSE
overlay_list = list(
"transp",
"tall",
"matte",
"zoppo" //u cant stoppo th zoppo
)
var/lighter_color
var/list/color_list = list( //Same 16 color selection as electronic assemblies
COLOR_ASSEMBLY_BLACK,
COLOR_FLOORTILE_GRAY,
COLOR_ASSEMBLY_BGRAY,
COLOR_ASSEMBLY_WHITE,
COLOR_ASSEMBLY_RED,
COLOR_ASSEMBLY_ORANGE,
COLOR_ASSEMBLY_BEIGE,
COLOR_ASSEMBLY_BROWN,
COLOR_ASSEMBLY_GOLD,
COLOR_ASSEMBLY_YELLOW,
COLOR_ASSEMBLY_GURKHA,
COLOR_ASSEMBLY_LGREEN,
COLOR_ASSEMBLY_GREEN,
COLOR_ASSEMBLY_LBLUE,
COLOR_ASSEMBLY_BLUE,
COLOR_ASSEMBLY_PURPLE
)
/obj/item/lighter/greyscale/Initialize()
. = ..()
add_atom_colour(color2hex(randomColor(1)), FIXED_COLOUR_PRIORITY)
if(!lighter_color)
lighter_color = pick(color_list)
update_icon()
/obj/item/lighter/greyscale/update_icon()
cut_overlays()
var/mutable_appearance/base_overlay = mutable_appearance(icon,"[initial(icon_state)]_base")
base_overlay.appearance_flags = RESET_COLOR //the edging doesn't change color
if(lit)
base_overlay.icon_state = "[initial(icon_state)]_on"
add_overlay(base_overlay)
var/mutable_appearance/lighter_overlay = mutable_appearance(icon,"lighter_overlay_[overlay_state][lit ? "-on" : ""]")
icon_state = "[initial(icon_state)][lit ? "-on" : ""]"
lighter_overlay.color = lighter_color
add_overlay(lighter_overlay)
/obj/item/lighter/greyscale/ignition_effect(atom/A, mob/user)
if(is_hot())
@@ -619,9 +657,10 @@ CIGARETTE PACKETS ARE IN FANCY.DM
/obj/item/lighter/slime
name = "slime zippo"
desc = "A specialty zippo made from slimes and industry. Has a much hotter flame than normal."
icon_state = "slimezippo"
icon_state = "slighter"
heat = 3000 //Blue flame!
light_color = LIGHT_COLOR_CYAN
overlay_state = "slime"
grind_results = list("iron" = 1, "welding_fuel" = 5, "pyroxadone" = 5)
+1 -1
View File
@@ -310,7 +310,7 @@
/obj/item/storage/bag/tray/update_icon()
cut_overlays()
for(var/obj/item/I in contents)
add_overlay(mutable_appearance(I.icon, I.icon_state))
add_overlay(new /mutable_appearance(I))
/obj/item/storage/bag/tray/Entered()
. = ..()
+47
View File
@@ -326,6 +326,53 @@
GET_COMPONENT(STR, /datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_SMALL
/obj/item/storage/belt/military/snack
name = "tactical snack rig"
/obj/item/storage/belt/military/snack/Initialize()
. = ..()
var/sponsor = pick("DonkCo", "Waffle Co.", "Roffle Co.", "Gorlax Marauders", "Tiger Cooperative")
desc = "A set of snack-tical webbing worn by athletes of the [sponsor] VR sports division."
/obj/item/storage/belt/military/snack/ComponentInitialize()
. = ..()
GET_COMPONENT(STR, /datum/component/storage)
STR.max_items = 6
STR.max_w_class = WEIGHT_CLASS_SMALL
STR.can_hold = typecacheof(list(
/obj/item/reagent_containers/food/snacks,
/obj/item/reagent_containers/food/drinks
))
var/amount = 5
var/rig_snacks
while(contents.len <= amount)
rig_snacks = pick(list(
/obj/item/reagent_containers/food/snacks/candy,
/obj/item/reagent_containers/food/drinks/dry_ramen,
/obj/item/reagent_containers/food/snacks/chips,
/obj/item/reagent_containers/food/snacks/sosjerky,
/obj/item/reagent_containers/food/snacks/syndicake,
/obj/item/reagent_containers/food/snacks/spacetwinkie,
/obj/item/reagent_containers/food/snacks/cheesiehonkers,
/obj/item/reagent_containers/food/snacks/nachos,
/obj/item/reagent_containers/food/snacks/cheesynachos,
/obj/item/reagent_containers/food/snacks/cubannachos,
/obj/item/reagent_containers/food/snacks/nugget,
/obj/item/reagent_containers/food/snacks/pastatomato,
/obj/item/reagent_containers/food/snacks/rofflewaffles,
/obj/item/reagent_containers/food/snacks/donkpocket,
/obj/item/reagent_containers/food/drinks/soda_cans/cola,
/obj/item/reagent_containers/food/drinks/soda_cans/space_mountain_wind,
/obj/item/reagent_containers/food/drinks/soda_cans/dr_gibb,
/obj/item/reagent_containers/food/drinks/soda_cans/starkist,
/obj/item/reagent_containers/food/drinks/soda_cans/space_up,
/obj/item/reagent_containers/food/drinks/soda_cans/pwr_game,
/obj/item/reagent_containers/food/drinks/soda_cans/lemon_lime,
/obj/item/reagent_containers/food/drinks/drinkingglass/filled/nuka_cola
))
new rig_snacks(src)
/obj/item/storage/belt/military/abductor
name = "agent belt"
desc = "A belt used by abductor agents."
+17 -10
View File
@@ -154,7 +154,7 @@
SendSignal(COMSIG_TRY_STORAGE_TAKE, W, user)
user.put_in_hands(W)
contents -= W
to_chat(user, "<span class='notice'>You take a [icon_type] out of the pack.</span>")
to_chat(user, "<span class='notice'>You take \a [W] out of the pack.</span>")
else
to_chat(user, "<span class='notice'>There are no [icon_type]s left in the pack.</span>")
@@ -166,18 +166,20 @@
else
icon_state = initial(icon_state)
add_overlay("[icon_state]_open")
var/i = contents.len
var/cig_position = 1
for(var/C in contents)
var/mutable_appearance/inserted_overlay = mutable_appearance(icon)
inserted_overlay.pixel_x = 1 * (i - 1)
if(istype(C, /obj/item/lighter/greyscale))
inserted_overlay.icon_state = "lighter_in"
else if(istype(C, /obj/item/lighter))
inserted_overlay.icon_state = "zippo_in"
else
inserted_overlay.icon_state = "cigarette"
inserted_overlay.icon_state = "[inserted_overlay.icon_state]_[cig_position]"
add_overlay(inserted_overlay)
i--
cig_position++
else
cut_overlays()
@@ -191,7 +193,7 @@
SendSignal(COMSIG_TRY_STORAGE_TAKE, W, M)
M.equip_to_slot_if_possible(W, SLOT_WEAR_MASK)
contents -= W
to_chat(user, "<span class='notice'>You take a [icon_type] out of the pack.</span>")
to_chat(user, "<span class='notice'>You take \a [W] out of the pack.</span>")
else
..()
else
@@ -293,22 +295,27 @@
/obj/item/storage/fancy/cigarettes/cigars/update_icon()
cut_overlays()
if(fancy_open)
add_overlay("[icon_state]_open")
var/mutable_appearance/cigar_overlay = mutable_appearance(icon, icon_type)
for(var/c = contents.len, c >= 1, c--)
cigar_overlay.pixel_x = 4 * (c - 1)
icon_state = "[initial(icon_state)]_open"
var/cigar_position = 1 //generate sprites for cigars in the box
for(var/obj/item/clothing/mask/cigarette/cigar/smokes in contents)
var/mutable_appearance/cigar_overlay = mutable_appearance(icon, "[smokes.icon_off]_[cigar_position]")
add_overlay(cigar_overlay)
cigar_position++
else
icon_state = "cigarcase"
icon_state = "[initial(icon_state)]"
/obj/item/storage/fancy/cigarettes/cigars/cohiba
name = "\improper cohiba robusto cigar case"
desc = "A case of imported Cohiba cigars, renowned for their strong flavor."
icon_state = "cohibacase"
spawn_type = /obj/item/clothing/mask/cigarette/cigar/cohiba
/obj/item/storage/fancy/cigarettes/cigars/havana
name = "\improper premium havanian cigar case"
desc = "A case of classy Havanian cigars."
icon_state = "cohibacase"
spawn_type = /obj/item/clothing/mask/cigarette/cigar/havana
/*
@@ -1,6 +1,7 @@
//The "BDPtarget" temp visual is created by the expressconsole, which in turn makes two things: a falling droppod animation, and the droppod itself.
#define POD_STANDARD 0
#define POD_BLUESPACE 1
#define POD_CENTCOM 2
//------------------------------------SUPPLY POD-------------------------------------//
/obj/structure/closet/supplypod
@@ -18,17 +19,25 @@
armor = list("melee" = 30, "bullet" = 50, "laser" = 50, "energy" = 100, "bomb" = 90, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80)
anchored = TRUE
anchorable = FALSE
var/generated = FALSE
var/datum/supply_order/SupplyOrder
var/atom/other_delivery
/obj/structure/closet/supplypod/bluespacepod
name = "Bluespace Drop Pod"
desc = "A Nanotrasen Bluespace drop pod. Teleports back to CentCom after delivery."
icon_state = "bluespacepod"
/obj/structure/closet/supplypod/Initialize(mapload, datum/supply_order/so)
/obj/structure/closet/supplypod/bluespacepod/centcompod
name = "CentCom Drop Pod"
desc = "A Nanotrasen Bluespace drop pod, this one has been marked with Central Command's designations. Teleports back to Centcom after delivery."
icon_state = "centcompod"
/obj/structure/closet/supplypod/Initialize(mapload, var/SO)
. = ..()
SupplyOrder = so//uses Supply Order passed from expressconsole into BDPtarget
if(istype(SO, /datum/supply_order))
SupplyOrder = SO//uses Supply Order passed from expressconsole into BDPtarget
else
other_delivery = SO//if the object is not a supply order, we force the object in the pod
addtimer(CALLBACK(src, .proc/open), 30)//open 3seconds after appearing
/obj/structure/closet/supplypod/update_icon()
@@ -47,9 +56,10 @@
/obj/structure/closet/supplypod/open()
var/turf/T = get_turf(src)
opened = TRUE
if(!generated)
generated = TRUE
if(SupplyOrder)
SupplyOrder.generate(T)//not called during populateContents as supplyorder generation requires a turf
if(other_delivery)
new other_delivery(T)
update_icon()
playsound(src, open_sound, 15, 1, -3)
if(istype(src,/obj/structure/closet/supplypod/bluespacepod))
@@ -66,21 +76,24 @@
//------------------------------------FALLING SUPPLY POD-------------------------------------//
/obj/effect/temp_visual/DPfall
icon = 'icons/obj/2x2.dmi'
icon_state = "supplypod_falling"
pixel_x = -16
pixel_y = -5
pixel_z = 200
desc = "Get out of the way!"
layer = FLY_LAYER//that wasnt flying, that was falling with style!
randomdir = FALSE
icon_state = "supplypod_falling"
/obj/effect/temp_visual/DPfall/Initialize(var/dropLocation, var/podID)
if (podID == POD_BLUESPACE)
if (podID == POD_STANDARD)
icon_state = "supplypod_falling"
name = "Supply Drop Pod"
else if (podID == POD_BLUESPACE)
icon_state = "bluespacepod_falling"
name = "Bluespace Drop Pod"
else
icon_state = "supplypod_falling"
name = "Supply Drop Pod"
icon_state = "centcompod_falling"
name = "CentCom Drop Pod"
. = ..()
//------------------------------------TEMPORARY_VISUAL-------------------------------------//
@@ -91,22 +104,34 @@
light_range = 2
var/obj/effect/temp_visual/fallingPod
/obj/effect/DPtarget/Initialize(mapload, datum/supply_order/SO, var/podID)
/obj/effect/DPtarget/Initialize(mapload, var/SO, var/podID)
. = ..()
addtimer(CALLBACK(src, .proc/beginLaunch, SO, podID), podID == POD_BLUESPACE ? 15 : 30)//standard pods take 3 seconds to come in, bluespace pods take 1.5
var/delayTime = 0
switch(podID)
if(POD_STANDARD)
delayTime = 30
if(POD_BLUESPACE)
delayTime = 15
if(POD_CENTCOM)
delayTime = 1
/obj/effect/DPtarget/proc/beginLaunch(datum/supply_order/SO, var/podID)
addtimer(CALLBACK(src, .proc/beginLaunch, SO, podID), delayTime)//standard pods take 3 seconds to come in, bluespace pods take 1.5
/obj/effect/DPtarget/proc/beginLaunch(var/SO, var/podID)
fallingPod = new /obj/effect/temp_visual/DPfall(drop_location(), podID)
animate(fallingPod, pixel_z = 0, time = 3, easing = LINEAR_EASING)//make and animate a falling pod
addtimer(CALLBACK(src, .proc/endLaunch, SO, podID), 3, TIMER_CLIENT_TIME)//fall 0.3seconds
/obj/effect/DPtarget/proc/endLaunch(datum/supply_order/SO, var/podID)
if (podID == POD_BLUESPACE)
/obj/effect/DPtarget/proc/endLaunch(var/SO, var/podID)
if (podID == POD_STANDARD)
new /obj/structure/closet/supplypod(drop_location(), SO)//pod is created
explosion(src,0,0,2, flame_range = 3) //less advanced equipment than bluespace pod, so larger explosion when landing
else if (podID == POD_BLUESPACE)
new /obj/structure/closet/supplypod/bluespacepod(drop_location(), SO)//pod is created
explosion(src,0,0,2, flame_range = 1) //explosion and camshake (shoutout to @cyberboss)
else
new /obj/structure/closet/supplypod(drop_location(), SO)//pod is created
explosion(src,0,0,2, flame_range = 3) //less advanced equipment than bluespace pod, so larger explosion when landing
new /obj/structure/closet/supplypod/bluespacepod/centcompod(drop_location(), SO)
explosion(src,0,0,2, flame_range = 1)
qdel(src)
/obj/effect/DPtarget/Destroy()
@@ -120,4 +145,4 @@
icon = 'icons/obj/module.dmi'
icon_state = "cargodisk"
item_state = "card-id"
w_class = WEIGHT_CLASS_SMALL
w_class = WEIGHT_CLASS_SMALL
@@ -106,7 +106,11 @@
/obj/item/stack/sheet/plasteel,
/obj/item/stack/sheet/mineral/titanium,
/obj/item/stack/sheet/mineral/plastitanium,
/obj/item/stack/rods
/obj/item/stack/rods,
/obj/item/stack/sheet/bluespace_crystal,
/obj/item/stack/sheet/mineral/abductor,
/obj/item/stack/sheet/plastic,
/obj/item/stack/sheet/mineral/wood
)
for(var/i = 0, i<2, i++)
+1 -1
View File
@@ -381,7 +381,7 @@
obj_integrity = max_integrity
/obj/structure/table/bronze
name = "brass table"
name = "bronze table"
desc = "A solid table made out of bronze."
icon = 'icons/obj/smooth_structures/brass_table.dmi'
icon_state = "brass_table"
@@ -243,7 +243,7 @@
/turf/open/floor/bronze
name = "clockwork floor"
name = "bronze floor"
desc = "Some heavy bronze tiles."
icon = 'icons/obj/clockwork_objects.dmi'
icon_state = "clockwork_floor"
@@ -119,6 +119,9 @@
icon_state = "water"
baseturfs = /turf/open/floor/plating/beach/water
/turf/open/floor/plating/beach/coastline_t/sandwater_inner
icon_state = "sandwater_inner"
baseturfs = /turf/open/floor/plating/beach/coastline_t/sandwater_inner
/turf/open/floor/plating/ironsand
name = "iron sand"
+19
View File
@@ -438,3 +438,22 @@
/turf/AllowDrop()
return TRUE
/turf/proc/add_vomit_floor(mob/living/carbon/M, toxvomit = 0)
var/obj/effect/decal/cleanable/vomit/V = new /obj/effect/decal/cleanable/vomit(src, M.get_static_viruses())
// If the vomit combined, apply toxicity and reagents to the old vomit
if (QDELETED(V))
V = locate() in src
// Make toxins vomit look different
if(toxvomit)
V.icon_state = "vomittox_[pick(1,4)]"
if(M.reagents)
clear_reagents_to_vomit_pool(M,V)
/proc/clear_reagents_to_vomit_pool(mob/living/carbon/M, obj/effect/decal/cleanable/vomit/V)
M.reagents.trans_to(V, M.reagents.total_volume / 10)
for(var/datum/reagent/R in M.reagents.reagent_list) //clears the stomach of anything that might be digested as food
if(istype(R, /datum/reagent/consumable))
var/datum/reagent/consumable/nutri_check = R
if(nutri_check.nutriment_factor >0)
M.reagents.remove_reagent(R.id,R.volume)
+1 -1
View File
@@ -29,7 +29,7 @@
body += "<body>Options panel for <b>[M]</b>"
if(M.client)
body += " played by <b>[M.client]</b> "
body += "\[<A href='?_src_=holder;[HrefToken()];editrights=rank;ckey=[M.ckey]'>[M.client.holder ? M.client.holder.rank : "Player"]</A>\]"
body += "\[<A href='?_src_=holder;[HrefToken()];editrights=[(GLOB.admin_datums[M.client.ckey] || GLOB.deadmins[M.client.ckey]) ? "rank" : "add"];ckey=[M.ckey]'>[M.client.holder ? M.client.holder.rank : "Player"]</A>\]"
if(CONFIG_GET(flag/use_exp_tracking))
body += "\[<A href='?_src_=holder;[HrefToken()];getplaytimewindow=[REF(M)]'>" + M.client.get_exp_living() + "</a>\]"
+15 -12
View File
@@ -125,6 +125,7 @@
var/use_db
var/task = href_list["editrights"]
var/skip
var/legacy_only
if(task == "activate" || task == "deactivate" || task == "sync")
skip = TRUE
if(!CONFIG_GET(flag/admin_legacy_system) && CONFIG_GET(flag/protect_legacy_admins) && task == "rank")
@@ -135,10 +136,9 @@
if(D.rank in GLOB.protected_ranks)
to_chat(usr, "<span class='admin prefix'>Editing the flags of this rank is blocked by server configuration.</span>")
return
if(CONFIG_GET(flag/load_legacy_ranks_only) && (task == "rank" || task == "permissions"))
to_chat(usr, "<span class='admin prefix'>Database rank loading is disabled, only temporary changes can be made to an admin's rank or permissions.</span>")
use_db = FALSE
skip = TRUE
if(CONFIG_GET(flag/load_legacy_ranks_only) && (task == "add" || task == "rank" || task == "permissions"))
to_chat(usr, "<span class='admin prefix'>Database rank loading is disabled, only temporary changes can be made to a rank's permissions and permanently creating a new rank is blocked.</span>")
legacy_only = TRUE
if(check_rights(R_DBRANKS, FALSE))
if(!skip)
if(!SSdbcore.Connect())
@@ -165,16 +165,16 @@
return
switch(task)
if("add")
admin_ckey = add_admin(null, use_db)
admin_ckey = add_admin(admin_ckey, use_db)
if(!admin_ckey)
return
change_admin_rank(admin_ckey, use_db)
change_admin_rank(admin_ckey, use_db, null, legacy_only)
if("remove")
remove_admin(admin_ckey, use_db, D)
if("rank")
change_admin_rank(admin_ckey, use_db, D)
change_admin_rank(admin_ckey, use_db, D, legacy_only)
if("permissions")
change_admin_flags(admin_ckey, use_db, D)
change_admin_flags(admin_ckey, use_db, D, legacy_only)
if("activate")
force_readmin(admin_ckey, D)
if("deactivate")
@@ -240,9 +240,11 @@
log_admin("[key_name(usr)] forcefully deadmined [admin_ckey]")
D.deactivate() //after logs so the deadmined admin can see the message.
/datum/admins/proc/change_admin_rank(admin_ckey, use_db, datum/admins/D)
/datum/admins/proc/change_admin_rank(admin_ckey, use_db, datum/admins/D, legacy_only)
var/datum/admin_rank/R
var/list/rank_names = list("*New Rank*")
var/list/rank_names = list()
if(!use_db || (use_db && !legacy_only))
rank_names += "*New Rank*"
for(R in GLOB.admin_ranks)
if((R.rights & usr.client.holder.rank.can_edit_rights) == R.rights)
rank_names[R.name] = R
@@ -297,7 +299,7 @@
message_admins("[key_name_admin(usr)] edited the admin rank of [admin_ckey] to [new_rank] [use_db ? "permanently" : "temporarily"]")
log_admin("[key_name(usr)] edited the admin rank of [admin_ckey] to [new_rank] [use_db ? "permanently" : "temporarily"]")
/datum/admins/proc/change_admin_flags(admin_ckey, use_db, datum/admins/D)
/datum/admins/proc/change_admin_flags(admin_ckey, use_db, datum/admins/D, legacy_only)
var/new_flags = input_bitfield(usr, "Include permission flags<br>[use_db ? "This will affect ALL admins with this rank." : "This will affect only the current admin [admin_ckey]"]", "admin_flags", D.rank.include_rights, 350, 590, allowed_edit_list = usr.client.holder.rank.can_edit_rights)
if(isnull(new_flags))
return
@@ -307,7 +309,7 @@
var/new_can_edit_flags = input_bitfield(usr, "Editable permission flags<br>These are the flags this rank is allowed to edit if they have access to the permissions panel.<br>They will be unable to modify admins to a rank that has a flag not included here.<br>[use_db ? "This will affect ALL admins with this rank." : "This will affect only the current admin [admin_ckey]"]", "admin_flags", D.rank.can_edit_rights, 350, 710, allowed_edit_list = usr.client.holder.rank.can_edit_rights)
if(isnull(new_can_edit_flags))
return
if(use_db)
if(use_db || legacy_only)
var/old_flags
var/old_exclude_flags
var/old_can_edit_flags
@@ -351,6 +353,7 @@
D.rank.rights = new_flags &= ~new_exclude_flags
D.rank.include_rights = new_flags
D.rank.exclude_rights = new_exclude_flags
D.rank.can_edit_rights = new_can_edit_flags
var/client/C = GLOB.directory[admin_ckey] //find the client with the specified ckey (if they are logged in)
D.associate(C) //link up with the client and add verbs
message_admins("[key_name_admin(usr)] edited the permissions of [use_db ? " rank [D.rank.name] permanently" : "[admin_ckey] temporarily"]")
+4 -1
View File
@@ -734,14 +734,17 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
if(!dresscode)
return
var/delete_pocket
var/mob/living/carbon/human/H
if(isobserver(M))
H = M.change_mob_type(/mob/living/carbon/human, null, null, TRUE)
else
H = M
if(alert("Drop Items in Pockets? No will delete them.", "Robust quick dress shop", "Yes", "No") == "No")
delete_pocket = TRUE
SSblackbox.record_feedback("tally", "admin_verb", 1, "Select Equipment") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
for (var/obj/item/I in H.get_equipped_items())
for (var/obj/item/I in H.get_equipped_items(delete_pocket))
qdel(I)
if(dresscode != "Naked")
H.equipOutfit(dresscode)
+1 -1
View File
@@ -290,7 +290,7 @@
/datum/admins/proc/equipAntagOnDummy(mob/living/carbon/human/dummy/mannequin, datum/antagonist/antag)
for(var/I in mannequin.get_equipped_items())
for(var/I in mannequin.get_equipped_items(TRUE))
qdel(I)
if (ispath(antag, /datum/antagonist/ert))
var/datum/antagonist/ert/ert = antag
+17 -1
View File
@@ -1277,7 +1277,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
if(!check_rights(R_ADMIN))
return
var/list/punishment_list = list(ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_GIB, ADMIN_PUNISHMENT_BSA, ADMIN_PUNISHMENT_FIREBALL, ADMIN_PUNISHMENT_ROD)
var/list/punishment_list = list(ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_GIB, ADMIN_PUNISHMENT_BSA, ADMIN_PUNISHMENT_FIREBALL, ADMIN_PUNISHMENT_ROD, ADMIN_PUNISHMENT_SUPPLYPOD)
var/punishment = input("Choose a punishment", "DIVINE SMITING") as null|anything in punishment_list
@@ -1305,6 +1305,22 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
var/turf/startT = spaceDebrisStartLoc(startside, T.z)
var/turf/endT = spaceDebrisFinishLoc(startside, T.z)
new /obj/effect/immovablerod(startT, endT,target)
if(ADMIN_PUNISHMENT_SUPPLYPOD)
///////load the supply pod up with something!
var/target_path = input(usr,"Enter typepath of an atom you'd like to send with the pod (type \"empty\" to send an empty pod):" ,"Typepath","/obj/item/reagent_containers/food/snacks/grown/harebell") as null|text
if (isnull(target_path))
return
if (target_path == "empty")//if you type "abort", spawn an empty pod
new /obj/effect/DPtarget(get_turf(target), null, POD_CENTCOM)
return
var/delivery = text2path(target_path)
if(!ispath(delivery))
delivery = pick_closest_path(target_path)
if(!delivery)
delivery = /obj/item/reagent_containers/food/snacks/grown/harebell
alert("That path is not allowed.")
//send the pod
new /obj/effect/DPtarget(get_turf(target), delivery, POD_CENTCOM)
var/msg = "[key_name_admin(usr)] punished [key_name_admin(target)] with [punishment]."
message_admins(msg)
@@ -44,6 +44,7 @@
icon = 'icons/turf/floors.dmi'
icon_state = "clockwork_floor"
layer = TURF_LAYER
plane = FLOOR_PLANE
/obj/effect/clockwork/overlay/floor/bloodcult //this is used by BLOOD CULT, it shouldn't use such a path...
icon_state = "cult"
@@ -50,7 +50,7 @@
user.emote("scream")
user.apply_damage(30, BRUTE, BODY_ZONE_HEAD)
user.adjustBrainLoss(30)
addtimer(CALLBACK(user, /mob/living.proc/dropItemToGround), src, 1) //equipped happens before putting stuff on(but not before picking items up), 1). thus, we need to wait for it to be on before forcing it off.
addtimer(CALLBACK(user, /mob/living.proc/dropItemToGround, src, TRUE), 1) //equipped happens before putting stuff on(but not before picking items up), 1). thus, we need to wait for it to be on before forcing it off.
/obj/item/clothing/head/helmet/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
if(equipper && !is_servant_of_ratvar(equipper))
+1 -2
View File
@@ -64,7 +64,7 @@
qdel(nullify_spell)
return
BS = possible_spells[entered_spell_name]
if(QDELETED(src) || owner.incapacitated() || !BS)
if(QDELETED(src) || owner.incapacitated() || !BS || (rune && !(locate(/obj/effect/rune/empower) in range(1, owner))) || (spells.len >= limit))
return
to_chat(owner,"<span class='warning'>You begin to carve unnatural symbols into your flesh!</span>")
SEND_SOUND(owner, sound('sound/weapons/slice.ogg',0,1,10))
@@ -271,7 +271,6 @@
attached_action.desc += "<br><b><u>Has [attached_action.charges] use\s remaining</u></b>."
attached_action.UpdateButtonIcon()
if(attached_action.charges <= 0)
remove_mousepointer(ranged_ability_user.client)
remove_ranged_ability("<span class='cult'>You have exhausted the spell's power!</span>")
qdel(src)
@@ -457,7 +457,6 @@
new /obj/effect/temp_visual/cult/sparks(get_turf(target), ranged_ability_user.dir)
attached_action.throwing = FALSE
attached_action.cooldown = world.time + attached_action.base_cooldown
remove_mousepointer(ranged_ability_user.client)
remove_ranged_ability("<span class='cult'>A pulse of blood magic surges through you as you shift [attached_action.throwee] through time and space.</span>")
caller.update_action_buttons_icon()
addtimer(CALLBACK(caller, /mob.proc/update_action_buttons_icon), attached_action.base_cooldown)
@@ -42,7 +42,7 @@
if(!istype(H))
return
for(var/obj/item/I in H.get_equipped_items())
for(var/obj/item/I in H.get_equipped_items(TRUE))
qdel(I)
for(var/obj/item/I in H.held_items)
qdel(I)
@@ -109,11 +109,6 @@
revealed = FALSE
incorporeal_move = INCORPOREAL_MOVE_JAUNT
invisibility = INVISIBILITY_REVENANT
if(staticOverlays.len)
for(var/mob/living/simple_animal/drone/D in GLOB.drones_list)
if(D && D.client && D.seeStatic)
D.staticOverlays.Remove(staticOverlays)
D.client.images.Remove(staticOverlays)
to_chat(src, "<span class='revenboldnotice'>You are once more concealed.</span>")
if(unstun_time && world.time >= unstun_time)
unstun_time = 0
@@ -250,15 +245,6 @@
else
to_chat(src, "<span class='revenwarning'>You have been revealed!</span>")
unreveal_time = unreveal_time + time
if(staticOverlays.len)
for(var/mob/living/simple_animal/drone/D in GLOB.drones_list)
if(D && D.client && D.seeStatic)
if(D.staticChoice in staticOverlays)
D.staticOverlays |= staticOverlays[D.staticChoice]
D.client.images |= staticOverlays[D.staticChoice]
else
D.staticOverlays |= staticOverlays["static"]
D.client.images |= staticOverlays["static"]
update_spooky_icon()
/mob/living/simple_animal/revenant/proc/stun(time)
@@ -373,6 +373,10 @@
to_chat(S, "<span class='warning'>Attempting to dismantle this machine would result in an immediate counterattack. Aborting.</span>")
return FALSE
/obj/machinery/porta_turret_cover/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>Attempting to dismantle this machine would result in an immediate counterattack. Aborting.</span>")
return FALSE
/mob/living/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisperseTarget(src)
return TRUE
@@ -405,6 +409,10 @@
to_chat(S, "<span class='warning'>This object does not contain enough materials to work with.</span>")
return FALSE
/obj/machinery/field/generator/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>Destroying this object would cause a catastrophic chain reaction. Aborting.</span>")
return FALSE
////END CTRL CLICK FOR SWARMERS////
/mob/living/simple_animal/hostile/swarmer/proc/Fabricate(atom/fabrication_object,fabrication_cost = 0)
@@ -164,7 +164,7 @@
kill_objective.find_target()
add_objective(kill_objective)
else
if(prob(15) && !(locate(/datum/objective/download in owner.objectives)))
if(prob(15) && !(locate(/datum/objective/download) in owner.objectives) && !(owner.assigned_role in list("Research Director", "Scientist", "Roboticist")))
var/datum/objective/download/download_objective = new
download_objective.owner = owner
download_objective.gen_amount_goal()
+1 -1
View File
@@ -117,7 +117,7 @@
if(isigniter(assembly.a_left) == isigniter(assembly.a_right))
return
if((src in user.get_equipped_items()) && !user.canUnEquip(src))
if((src in user.get_equipped_items(TRUE)) && !user.canUnEquip(src))
to_chat(user, "<span class='warning'>[src] is stuck to you!</span>")
return
@@ -111,7 +111,7 @@
var/list/cached_gases = air.gases //this speeds things up because accessing datum vars is slow
var/temperature = air.temperature
var/list/cached_results = air.reaction_results
cached_results[id] = 0
cached_results["fire"] = 0
var/turf/open/location = isturf(holder) ? holder : null
var/burned_fuel = 0
@@ -131,7 +131,7 @@
ASSERT_GAS(/datum/gas/water_vapor, air) //oxygen+more-or-less hydrogen=H2O
cached_gases[/datum/gas/water_vapor][MOLES] += burned_fuel/TRITIUM_BURN_OXY_FACTOR
cached_results[id] += burned_fuel
cached_results["fire"] += burned_fuel
if(energy_released > 0)
var/new_heat_capacity = air.heat_capacity()
@@ -148,7 +148,7 @@
item.temperature_expose(air, temperature, CELL_VOLUME)
location.temperature_expose(air, temperature, CELL_VOLUME)
return cached_results[id] ? REACTING : NO_REACTION
return cached_results["fire"] ? REACTING : NO_REACTION
//plasma combustion: combustion of oxygen and plasma (treated as hydrocarbons). creates hotspots. exothermic
/datum/gas_reaction/plasmafire
@@ -169,7 +169,7 @@
var/list/cached_gases = air.gases //this speeds things up because accessing datum vars is slow
var/temperature = air.temperature
var/list/cached_results = air.reaction_results
cached_results[id] = 0
cached_results["fire"] = 0
var/turf/open/location = isturf(holder) ? holder : null
//Handle plasma burning
@@ -206,7 +206,7 @@
energy_released += FIRE_PLASMA_ENERGY_RELEASED * (plasma_burn_rate)
cached_results[id] += (plasma_burn_rate)*(1+oxygen_burn_rate)
cached_results["fire"] += (plasma_burn_rate)*(1+oxygen_burn_rate)
if(energy_released > 0)
var/new_heat_capacity = air.heat_capacity()
@@ -223,7 +223,7 @@
item.temperature_expose(air, temperature, CELL_VOLUME)
location.temperature_expose(air, temperature, CELL_VOLUME)
return cached_results[id] ? REACTING : NO_REACTION
return cached_results["fire"] ? REACTING : NO_REACTION
//fusion: a terrible idea that was fun but broken. Now reworked to be less broken and more interesting. Again.
/datum/gas_reaction/fusion
@@ -62,6 +62,18 @@ Acts like a normal vent, but has an input AND output.
/obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume
name = "large dual-port air vent"
/obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume/incinerator_toxmix
id = INCINERATOR_TOXMIX_DP_VENTPUMP
frequency = FREQ_AIRLOCK_CONTROL
/obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume/incinerator_atmos
id = INCINERATOR_ATMOS_DP_VENTPUMP
frequency = FREQ_AIRLOCK_CONTROL
/obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume/incinerator_syndicatelava
id = INCINERATOR_SYNDICATELAVA_DP_VENTPUMP
frequency = FREQ_AIRLOCK_CONTROL
/obj/machinery/atmospherics/components/binary/dp_vent_pump/high_volume/layer1
piping_layer = PIPING_LAYER_MIN
pixel_x = -PIPING_LAYER_P_X
+1 -1
View File
@@ -520,7 +520,7 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
if(!account_join_date)
account_age = -1
else
var/datum/DBQuery/query_datediff = SSdbcore.NewQuery("SELECT DATEDIFF(Now(),[account_join_date])")
var/datum/DBQuery/query_datediff = SSdbcore.NewQuery("SELECT DATEDIFF(Now(),'[account_join_date]')")
if(!query_datediff.Execute())
return
if(query_datediff.NextRow())
+1 -1
View File
@@ -1380,7 +1380,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(pickedui)
UI_style = pickedui
if("pda_style")
var/pickedPDAStyle = input(user, "Choose your PDA style.", "Character Preference") as null|anything in list(MONO, SHARE, ORBITRON, VT)
var/pickedPDAStyle = input(user, "Choose your PDA style.", "Character Preference", pda_style) as null|anything in GLOB.pda_styles
if(pickedPDAStyle)
pda_style = pickedPDAStyle
if("pda_color")
+1 -1
View File
@@ -168,7 +168,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
ghost_others = sanitize_inlist(ghost_others, GLOB.ghost_others_options, GHOST_OTHERS_DEFAULT_OPTION)
menuoptions = SANITIZE_LIST(menuoptions)
be_special = SANITIZE_LIST(be_special)
pda_style = sanitize_inlist(MONO, VT, SHARE, ORBITRON)
pda_style = sanitize_inlist(pda_style, GLOB.pda_styles, initial(pda_style))
pda_color = sanitize_hexcolor(pda_color, 6, 1, initial(pda_color))
screenshake = sanitize_integer(screenshake, 0, 800, initial(screenshake))
+1 -1
View File
@@ -151,7 +151,7 @@
r_hand = /obj/item/twohanded/fireaxe
/datum/outfit/psycho/post_equip(mob/living/carbon/human/H)
for(var/obj/item/carried_item in H.get_equipped_items())
for(var/obj/item/carried_item in H.get_equipped_items(TRUE))
carried_item.add_mob_blood(H)//Oh yes, there will be blood...
for(var/obj/item/I in H.held_items)
I.add_mob_blood(H)
@@ -87,7 +87,7 @@
return
to_chat(user, "<span class='notice'>You begin recycling [EA]'s components...</span>")
playsound(src, 'sound/items/electronic_assembly_emptying.ogg', 50, TRUE)
if(!do_after(user, 30, target = src)) //short channel so you don't accidentally start emptying out a complex assembly
if(!do_after(user, 30, target = src) || recycling) //short channel so you don't accidentally start emptying out a complex assembly
return
recycling = TRUE
var/datum/component/material_container/mats = GetComponent(/datum/component/material_container)
@@ -286,6 +286,7 @@
push_data()
if(1)
TR.weedlevel = 0
TR.update_icon()
if(2)
if(TR.myseed) //Could be that they're just using it as a de-weeder
TR.age = 0
+6
View File
@@ -49,6 +49,7 @@
var/exp_type_department = ""
//The amount of good boy points playing this role will earn you towards a higher chance to roll antagonist next round
//can be overriden by antag_rep.txt config
var/antag_rep = 10
//Only override this proc
@@ -67,6 +68,11 @@
/datum/job/proc/special_check_latejoin(client/C)
return TRUE
/datum/job/proc/GetAntagRep()
. = CONFIG_GET(keyed_number_list/antag_rep)[lowertext(title)]
if(. == null)
return antag_rep
//Don't override this unless the job transforms into a non-human (Silicons do this for example)
/datum/job/proc/equip(mob/living/carbon/human/H, visualsOnly = FALSE, announce = TRUE, latejoin = FALSE)
if(!H)
+1 -1
View File
@@ -56,7 +56,7 @@
playsound(loc, 'sound/items/gavel.ogg', 50, 1, -1)
user.visible_message("<span class='notice'>[user] starts engraving a message into [T]...</span>", "<span class='notice'>You start engraving a message into [T]...</span>", "<span class='italics'>You hear a chipping sound.</span>")
if(can_use() && do_after(user, tool_speed, target = T) && can_use()) //This looks messy but it's actually really clever!
if(!locate(/obj/structure/chisel_message in T))
if(!locate(/obj/structure/chisel_message) in T)
user.visible_message("<span class='notice'>[user] leaves a message for future spacemen!</span>", "<span class='notice'>You engrave a message into [T]!</span>", "<span class='italics'>You hear a chipping sound.</span>")
playsound(loc, 'sound/items/gavel.ogg', 50, 1, -1)
var/obj/structure/chisel_message/M = new(T)
-2
View File
@@ -11,8 +11,6 @@
layer = LIGHTING_LAYER
invisibility = INVISIBILITY_LIGHTING
blend_mode = BLEND_ADD
var/needs_update = FALSE
var/turf/myturf
+1 -1
View File
@@ -57,12 +57,12 @@
if(!bounds)
return FALSE
smooth_zlevel(world.maxz)
repopulate_sorted_areas()
SSlighting.initialize_lighting_objects(block(locate(bounds[MAP_MINX], bounds[MAP_MINY], bounds[MAP_MINZ]),locate(bounds[MAP_MAXX], bounds[MAP_MAXY], bounds[MAP_MAXZ])))
//initialize things that are normally initialized after map load
initTemplateBounds(bounds)
smooth_zlevel(world.maxz)
log_game("Z-level [name] loaded at at [x],[y],[world.maxz]")
return level
+1 -1
View File
@@ -379,7 +379,7 @@
/mob/living/proc/unequip_everything()
var/list/items = list()
items |= get_equipped_items()
items |= get_equipped_items(TRUE)
for(var/I in items)
dropItemToGround(I)
drop_all_held_items()
@@ -674,23 +674,6 @@
else
to_chat(C, "<span class='unconscious'>You feel a breath of fresh air... which is a sensation you don't recognise...</span>")
/mob/living/carbon/human/generateStaticOverlay()
var/image/staticOverlay = image(icon('icons/effects/effects.dmi', "static"), loc = src)
staticOverlay.override = 1
staticOverlays["static"] = staticOverlay
staticOverlay = image(icon('icons/effects/effects.dmi', "blank"), loc = src)
staticOverlay.override = 1
staticOverlays["blank"] = staticOverlay
staticOverlay = getLetterImage(src, "H", 1)
staticOverlay.override = 1
staticOverlays["letter"] = staticOverlay
staticOverlay = getRandomAnimalImage(src)
staticOverlay.override = 1
staticOverlays["animal"] = staticOverlay
/mob/living/carbon/human/cuff_resist(obj/item/I)
if(dna && dna.check_mutation(HULK))
say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ))
+5 -43
View File
@@ -1,15 +1,5 @@
/mob/living/Initialize()
. = ..()
generateStaticOverlay()
if(staticOverlays.len)
for(var/mob/living/simple_animal/drone/D in GLOB.player_list)
if(D && D.seeStatic)
if(D.staticChoice in staticOverlays)
D.staticOverlays |= staticOverlays[D.staticChoice]
D.client.images |= staticOverlays[D.staticChoice]
else //no choice? force static
D.staticOverlays |= staticOverlays["static"]
D.client.images |= staticOverlays["static"]
if(unique_name)
name = "[name] ([rand(1, 1000)])"
real_name = name
@@ -40,47 +30,14 @@
if(buckled)
buckled.unbuckle_mob(src,force=1)
for(var/mob/living/simple_animal/drone/D in GLOB.player_list)
for(var/image/I in staticOverlays)
D.staticOverlays.Remove(I)
D.client.images.Remove(I)
qdel(I)
staticOverlays.len = 0
remove_from_all_data_huds()
GLOB.mob_living_list -= src
QDEL_LIST(diseases)
return ..()
/mob/living/ghostize(can_reenter_corpse = 1)
var/prev_client = client
. = ..()
if(.)
if(ranged_ability && prev_client)
ranged_ability.remove_mousepointer(prev_client)
/mob/living/proc/OpenCraftingMenu()
return
/mob/living/proc/generateStaticOverlay()
staticOverlays.Add(list("static", "blank", "letter", "animal"))
var/image/staticOverlay = image(getStaticIcon(new/icon(icon,icon_state)), loc = src)
staticOverlay.override = 1
staticOverlays["static"] = staticOverlay
staticOverlay = image(getBlankIcon(new/icon(icon, icon_state)), loc = src)
staticOverlay.override = 1
staticOverlays["blank"] = staticOverlay
staticOverlay = getLetterImage(src)
staticOverlay.override = 1
staticOverlays["letter"] = staticOverlay
staticOverlay = getRandomAnimalImage(src)
staticOverlay.override = 1
staticOverlays["animal"] = staticOverlay
//Generic Collide(). Override MobCollide() and ObjCollide() instead of this.
/mob/living/Collide(atom/A)
if(..()) //we are thrown onto something
@@ -1184,6 +1141,11 @@
clear_fullscreen("remote_view", 0)
update_pipe_vision()
/mob/living/update_mouse_pointer()
..()
if (client && ranged_ability && ranged_ability.ranged_mousepointer)
client.mouse_pointer_icon = ranged_ability.ranged_mousepointer
/mob/living/vv_edit_var(var_name, var_value)
switch(var_name)
if("stat")
@@ -55,7 +55,6 @@
var/mob_size = MOB_SIZE_HUMAN
var/list/mob_biotypes = list(MOB_ORGANIC)
var/metabolism_efficiency = 1 //more or less efficiency to metabolize helpful/harmful reagents and regulate body temperature..
var/list/image/staticOverlays = list()
var/has_limbs = 0 //does the mob have distinct limbs?(arms,legs, chest,head)
var/list/pipes_shown = list()
-2
View File
@@ -1,7 +1,5 @@
/mob/living/Logout()
update_z(null)
if(ranged_ability && client)
ranged_ability.remove_mousepointer(client)
..()
if(!key && mind) //key and mind have become separated.
mind.active = 0 //This is to stop say, a mind.transfer_to call on a corpse causing a ghost to re-enter its body.
+20 -3
View File
@@ -74,7 +74,7 @@
var/nuking = FALSE
var/obj/machinery/doomsday_device/doomsday_device
var/mob/camera/aiEye/eyeobj = new
var/mob/camera/aiEye/eyeobj
var/sprint = 10
var/cooldown = 0
var/acceleration = 1
@@ -85,6 +85,13 @@
var/datum/action/innate/deploy_last_shell/redeploy_action = new
var/chnotify = 0
var/multicam_allowed = FALSE
var/multicam_on = FALSE
var/obj/screen/movable/pic_in_pic/ai/master_multicam
var/list/multicam_screens = list()
var/list/all_eyes = list()
var/max_multicams = 6
/mob/living/silicon/ai/Initialize(mapload, datum/ai_laws/L, mob/target_ai)
. = ..()
if(!target_ai) //If there is no player/brain inside.
@@ -116,8 +123,7 @@
job = "AI"
eyeobj.ai = src
eyeobj.forceMove(src.loc)
create_eye()
rename_self("ai")
holo_icon = getHologramIcon(icon('icons/mob/ai.dmi',"default"))
@@ -871,9 +877,12 @@
current = A
if(client)
if(ismovableatom(A))
if(A != GLOB.ai_camera_room_landmark)
end_multicam()
client.perspective = EYE_PERSPECTIVE
client.eye = A
else
end_multicam()
if(isturf(loc))
if(eyeobj)
client.eye = eyeobj
@@ -993,3 +1002,11 @@
. = ..()
if(!target_ai)
target_ai = src //cheat! just give... ourselves as the spawned AI, because that's technically correct
/mob/living/silicon/ai/proc/camera_visibility(mob/camera/aiEye/moved_eye)
GLOB.cameranet.visibility(moved_eye, client, all_eyes)
/mob/living/silicon/ai/forceMove(atom/destination)
. = ..()
if(.)
end_multicam()
@@ -38,29 +38,63 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
// Updates what the aiEye can see. It is recommended you use this when the aiEye moves or it's location is set.
/datum/cameranet/proc/visibility(mob/camera/aiEye/ai)
// 0xf = 15
var/x1 = max(0, ai.x - 16) & ~(CHUNK_SIZE - 1)
var/y1 = max(0, ai.y - 16) & ~(CHUNK_SIZE - 1)
var/x2 = min(world.maxx, ai.x + 16) & ~(CHUNK_SIZE - 1)
var/y2 = min(world.maxy, ai.y + 16) & ~(CHUNK_SIZE - 1)
/datum/cameranet/proc/visibility(list/moved_eyes, client/C, list/other_eyes)
if(!islist(moved_eyes))
moved_eyes = moved_eyes ? list(moved_eyes) : list()
if(islist(other_eyes))
other_eyes = (other_eyes - moved_eyes)
else
other_eyes = list()
var/list/visibleChunks = list()
var/list/chunks_pre_seen = list()
var/list/chunks_post_seen = list()
for(var/x = x1; x <= x2; x += CHUNK_SIZE)
for(var/y = y1; y <= y2; y += CHUNK_SIZE)
visibleChunks |= getCameraChunk(x, y, ai.z)
for(var/V in moved_eyes)
var/mob/camera/aiEye/eye = V
if(C)
chunks_pre_seen |= eye.visibleCameraChunks
// 0xf = 15
var/static_range = eye.static_visibility_range
var/x1 = max(0, eye.x - static_range) & ~(CHUNK_SIZE - 1)
var/y1 = max(0, eye.y - static_range) & ~(CHUNK_SIZE - 1)
var/x2 = min(world.maxx, eye.x + static_range) & ~(CHUNK_SIZE - 1)
var/y2 = min(world.maxy, eye.y + static_range) & ~(CHUNK_SIZE - 1)
var/list/remove = ai.visibleCameraChunks - visibleChunks
var/list/add = visibleChunks - ai.visibleCameraChunks
var/list/visibleChunks = list()
for(var/chunk in remove)
var/datum/camerachunk/c = chunk
c.remove(ai)
for(var/x = x1; x <= x2; x += CHUNK_SIZE)
for(var/y = y1; y <= y2; y += CHUNK_SIZE)
visibleChunks |= getCameraChunk(x, y, eye.z)
for(var/chunk in add)
var/datum/camerachunk/c = chunk
c.add(ai)
var/list/remove = eye.visibleCameraChunks - visibleChunks
var/list/add = visibleChunks - eye.visibleCameraChunks
for(var/chunk in remove)
var/datum/camerachunk/c = chunk
c.remove(eye, FALSE)
for(var/chunk in add)
var/datum/camerachunk/c = chunk
c.add(eye, FALSE)
if(C)
chunks_post_seen |= eye.visibleCameraChunks
if(C)
for(var/V in other_eyes)
var/mob/camera/aiEye/eye = V
chunks_post_seen |= eye.visibleCameraChunks
var/list/remove = chunks_pre_seen - chunks_post_seen
var/list/add = chunks_post_seen - chunks_pre_seen
for(var/chunk in remove)
var/datum/camerachunk/c = chunk
C.images -= c.obscured
for(var/chunk in add)
var/datum/camerachunk/c = chunk
C.images += c.obscured
// Updates the chunks that the turf is located in. Use this when obstacles are destroyed or when doors open.
@@ -20,10 +20,11 @@
// Add an AI eye to the chunk, then update if changed.
/datum/camerachunk/proc/add(mob/camera/aiEye/eye)
var/client/client = eye.GetViewerClient()
if(client)
client.images += obscured
/datum/camerachunk/proc/add(mob/camera/aiEye/eye, add_images = TRUE)
if(add_images)
var/client/client = eye.GetViewerClient()
if(client)
client.images += obscured
eye.visibleCameraChunks += src
visible++
seenby += eye
@@ -32,10 +33,11 @@
// Remove an AI eye from the chunk, then update if changed.
/datum/camerachunk/proc/remove(mob/camera/aiEye/eye)
var/client/client = eye.GetViewerClient()
if(client)
client.images -= obscured
/datum/camerachunk/proc/remove(mob/camera/aiEye/eye, remove_images = TRUE)
if(remove_images)
var/client/client = eye.GetViewerClient()
if(client)
client.images -= obscured
eye.visibleCameraChunks -= src
seenby -= eye
if(visible > 0)
@@ -11,6 +11,7 @@
var/mob/living/silicon/ai/ai = null
var/relay_speech = FALSE
var/use_static = TRUE
var/static_visibility_range = 16
// Use this when setting the aiEye's location.
// It will also stream the chunk that the new loc is in.
@@ -25,8 +26,8 @@
else
moveToNullspace() // ????
if(use_static)
GLOB.cameranet.visibility(src)
if(ai.client)
ai.camera_visibility(src)
if(ai.client && !ai.multicam_on)
ai.client.eye = src
update_parallax_contents()
//Holopad
@@ -35,6 +36,8 @@
H.move_hologram(ai, T)
if(ai.camera_light_on)
ai.light_cameras()
if(ai.master_multicam)
ai.master_multicam.refresh_view()
/mob/camera/aiEye/Move()
return 0
@@ -45,20 +48,27 @@
return null
/mob/camera/aiEye/proc/RemoveImages()
if(use_static)
for(var/datum/camerachunk/chunk in visibleCameraChunks)
chunk.remove(src)
var/client/C = GetViewerClient()
if(C && use_static)
for(var/V in visibleCameraChunks)
var/datum/camerachunk/c = V
C.images -= c.obscured
/mob/camera/aiEye/Destroy()
ai = null
if(ai)
ai.all_eyes -= src
ai = null
for(var/V in visibleCameraChunks)
var/datum/camerachunk/c = V
c.remove(src)
return ..()
/atom/proc/move_camera_by_click()
if(isAI(usr))
var/mob/living/silicon/ai/AI = usr
if(AI.eyeobj && AI.client.eye == AI.eyeobj)
if(AI.eyeobj && (AI.multicam_on || (AI.client.eye == AI.eyeobj)) && (AI.eyeobj.z == z))
AI.cameraFollow = null
if (isturf(src.loc) || isturf(src))
if (isturf(loc) || isturf(src))
AI.eyeobj.setLoc(src)
// This will move the AIEye. It will also cause lights near the eye to light up, if toggled.
@@ -95,12 +105,19 @@
if(!eyeobj || !eyeobj.loc || QDELETED(eyeobj))
to_chat(src, "ERROR: Eyeobj not found. Creating new eye...")
eyeobj = new(loc)
eyeobj.ai = src
eyeobj.name = "[src.name] (AI Eye)" // Give it a name
create_eye()
eyeobj.setLoc(loc)
/mob/living/silicon/ai/proc/create_eye()
if(eyeobj)
return
eyeobj = new /mob/camera/aiEye()
all_eyes += eyeobj
eyeobj.ai = src
eyeobj.setLoc(loc)
eyeobj.name = "[name] (AI Eye)"
/mob/living/silicon/ai/verb/toggle_acceleration()
set category = "AI Commands"
set name = "Toggle Camera Acceleration"
@@ -96,6 +96,7 @@
/mob/living/silicon/ai/proc/start_RestorePowerRoutine()
to_chat(src, "Backup battery online. Scanners, camera, and radio interface offline. Beginning fault-detection.")
end_multicam()
sleep(50)
var/turf/T = get_turf(src)
var/area/AIarea = get_area(src)
@@ -4,4 +4,6 @@
for(var/obj/machinery/ai_status_display/O in GLOB.ai_status_displays) //change status
O.mode = 1
O.emotion = "Neutral"
if(multicam_on)
end_multicam()
view_core()
@@ -0,0 +1,266 @@
//Picture in picture
/obj/screen/movable/pic_in_pic/ai
var/mob/living/silicon/ai/ai
var/mutable_appearance/highlighted_background
var/highlighted = FALSE
var/mob/camera/aiEye/pic_in_pic/aiEye
/obj/screen/movable/pic_in_pic/ai/Initialize()
. = ..()
aiEye = new /mob/camera/aiEye/pic_in_pic()
aiEye.screen = src
/obj/screen/movable/pic_in_pic/ai/Destroy()
set_ai(null)
QDEL_NULL(aiEye)
return ..()
/obj/screen/movable/pic_in_pic/ai/Click()
..()
if(ai)
ai.select_main_multicam_window(src)
/obj/screen/movable/pic_in_pic/ai/make_backgrounds()
..()
highlighted_background = new /mutable_appearance()
highlighted_background.icon = 'icons/misc/pic_in_pic.dmi'
highlighted_background.icon_state = "background_highlight"
highlighted_background.layer = SPACE_LAYER
/obj/screen/movable/pic_in_pic/ai/add_background()
if((width > 0) && (height > 0))
var/matrix/M = matrix()
M.Scale(width + 0.5, height + 0.5)
M.Translate((width-1)/2 * world.icon_size, (height-1)/2 * world.icon_size)
highlighted_background.transform = M
standard_background.transform = M
add_overlay(highlighted ? highlighted_background : standard_background)
/obj/screen/movable/pic_in_pic/ai/set_view_size(width, height, do_refresh = TRUE)
aiEye.static_visibility_range = (round(max(width, height) / 2) + 1)
if(ai)
ai.camera_visibility(aiEye)
..()
/obj/screen/movable/pic_in_pic/ai/set_view_center(atom/target, do_refresh = TRUE)
..()
aiEye.setLoc(get_turf(target))
/obj/screen/movable/pic_in_pic/ai/refresh_view()
..()
aiEye.setLoc(get_turf(center))
/obj/screen/movable/pic_in_pic/ai/proc/highlight()
if(highlighted)
return
highlighted = TRUE
cut_overlay(standard_background)
add_overlay(highlighted_background)
/obj/screen/movable/pic_in_pic/ai/proc/unhighlight()
if(!highlighted)
return
highlighted = FALSE
cut_overlay(highlighted_background)
add_overlay(standard_background)
/obj/screen/movable/pic_in_pic/ai/proc/set_ai(mob/living/silicon/ai/new_ai)
if(ai)
ai.multicam_screens -= src
ai.all_eyes -= aiEye
if(ai.master_multicam == src)
ai.master_multicam = null
if(ai.multicam_on)
unshow_to(ai.client)
ai = new_ai
if(new_ai)
new_ai.multicam_screens += src
ai.all_eyes += aiEye
if(new_ai.multicam_on)
show_to(new_ai.client)
//Turf, area, and landmark for the viewing room
/turf/open/ai_visible
name = ""
icon = 'icons/misc/pic_in_pic.dmi'
icon_state = "room_background"
flags_1 = NOJAUNT_1
/turf/open/ai_visible/Initialize()
. = ..()
obscured = image(null, src, null)
/area/ai_multicam_room
name = "ai_multicam_room"
icon_state = "ai_camera_room"
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
valid_territory = FALSE
ambientsounds = list()
blob_allowed = FALSE
noteleport = TRUE
hidden = TRUE
safe = TRUE
GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room)
/obj/effect/landmark/ai_multicam_room
name = "ai camera room"
icon = 'icons/mob/landmarks.dmi'
icon_state = "x"
/obj/effect/landmark/ai_multicam_room/Initialize()
. = ..()
qdel(GLOB.ai_camera_room_landmark)
GLOB.ai_camera_room_landmark = src
/obj/effect/landmark/ai_multicam_room/Destroy()
if(GLOB.ai_camera_room_landmark == src)
GLOB.ai_camera_room_landmark = null
return ..()
//Dummy camera eyes
/mob/camera/aiEye/pic_in_pic
name = "Secondary AI Eye"
var/obj/screen/movable/pic_in_pic/ai/screen
var/list/cameras_telegraphed = list()
var/telegraph_cameras = TRUE
var/telegraph_range = 7
/mob/camera/aiEye/pic_in_pic/GetViewerClient()
if(screen && screen.ai)
return screen.ai.client
/mob/camera/aiEye/pic_in_pic/setLoc(turf/T)
if (T)
forceMove(T)
else
moveToNullspace()
if(screen && screen.ai)
screen.ai.camera_visibility(src)
else
GLOB.cameranet.visibility(src)
update_camera_telegraphing()
/mob/camera/aiEye/pic_in_pic/proc/update_camera_telegraphing()
if(!telegraph_cameras)
return
var/list/obj/machinery/camera/add = list()
var/list/obj/machinery/camera/remove = list()
var/list/obj/machinery/camera/visible = list()
for (var/VV in visibleCameraChunks)
var/datum/camerachunk/CC = VV
for (var/V in CC.cameras)
var/obj/machinery/camera/C = V
if (!C.can_use() || (get_dist(C, src) > telegraph_range))
continue
visible |= C
add = visible - cameras_telegraphed
remove = cameras_telegraphed - visible
for (var/V in remove)
var/obj/machinery/camera/C = V
if(QDELETED(C))
continue
cameras_telegraphed -= C
C.in_use_lights--
C.update_icon()
for (var/V in add)
var/obj/machinery/camera/C = V
if(QDELETED(C))
continue
cameras_telegraphed |= C
C.in_use_lights++
C.update_icon()
/mob/camera/aiEye/pic_in_pic/proc/disable_camera_telegraphing()
telegraph_cameras = FALSE
for (var/V in cameras_telegraphed)
var/obj/machinery/camera/C = V
if(QDELETED(C))
continue
C.in_use_lights--
C.update_icon()
cameras_telegraphed.Cut()
/mob/camera/aiEye/pic_in_pic/Destroy()
disable_camera_telegraphing()
return ..()
//AI procs
/mob/living/silicon/ai/proc/drop_new_multicam(silent = FALSE)
if(!multicam_allowed)
if(!silent)
to_chat(src, "<span class='warning'>This action is currently disabled. Contact an administrator to enable this feature.</span>")
return
if(!eyeobj)
return
if(multicam_screens.len >= max_multicams)
if(!silent)
to_chat(src, "<span class='warning'>Cannot place more than [max_multicams] multicamera windows.</span>")
return
var/obj/screen/movable/pic_in_pic/ai/C = new /obj/screen/movable/pic_in_pic/ai()
C.set_view_size(3, 3, FALSE)
C.set_view_center(get_turf(eyeobj))
C.set_ai(src)
if(!silent)
to_chat(src, "<span class='notice'>Added new multicamera window.</span>")
return C
/mob/living/silicon/ai/proc/toggle_multicam()
if(!multicam_allowed)
to_chat(src, "<span class='warning'>This action is currently disabled. Contact an administrator to enable this feature.</span>")
return
if(multicam_on)
end_multicam()
else
start_multicam()
/mob/living/silicon/ai/proc/start_multicam()
if(multicam_on || aiRestorePowerRoutine || !isturf(loc))
return
if(!GLOB.ai_camera_room_landmark)
to_chat(src, "<span class='warning'>This function is not available at this time.</span>")
return
multicam_on = TRUE
refresh_multicam()
to_chat(src, "<span class='notice'>Multiple-camera viewing mode activated.</span>")
/mob/living/silicon/ai/proc/refresh_multicam()
reset_perspective(GLOB.ai_camera_room_landmark)
if(client)
for(var/V in multicam_screens)
var/obj/screen/movable/pic_in_pic/P = V
P.show_to(client)
/mob/living/silicon/ai/proc/end_multicam()
if(!multicam_on)
return
multicam_on = FALSE
select_main_multicam_window(null)
if(client)
for(var/V in multicam_screens)
var/obj/screen/movable/pic_in_pic/P = V
P.unshow_to(client)
reset_perspective()
to_chat(src, "<span class='notice'>Multiple-camera viewing mode deactivated.</span>")
/mob/living/silicon/ai/proc/select_main_multicam_window(obj/screen/movable/pic_in_pic/ai/P)
if(master_multicam == P)
return
if(master_multicam)
master_multicam.set_view_center(get_turf(eyeobj), FALSE)
master_multicam.unhighlight()
master_multicam = null
if(P)
P.highlight()
eyeobj.setLoc(get_turf(P.center))
P.set_view_center(eyeobj)
master_multicam = P
@@ -292,6 +292,3 @@
/mob/living/silicon/pai/process()
emitterhealth = CLAMP((emitterhealth + emitterregen), -50, emittermaxhealth)
hit_slowdown = CLAMP((hit_slowdown - 1), 0, 100)
/mob/living/silicon/pai/generateStaticOverlay()
return
@@ -105,6 +105,7 @@
spark_system.attach(src)
wires = new /datum/wires/robot(src)
AddComponent(/datum/component/empprotection, EMP_PROTECT_WIRES)
robot_modules_background = new()
robot_modules_background.icon_state = "block"
@@ -403,3 +403,6 @@
/mob/living/silicon/is_literate()
return 1
/mob/living/silicon/get_inactive_held_item()
return FALSE
@@ -42,7 +42,6 @@
mob_size = MOB_SIZE_SMALL
has_unlimited_silicon_privilege = 1
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
staticOverlays = list()
hud_possible = list(DIAG_STAT_HUD, DIAG_HUD, ANTAG_HUD)
unique_name = TRUE
faction = list("neutral","silicon","turret")
@@ -67,7 +66,6 @@
var/obj/item/head
var/obj/item/default_storage = /obj/item/storage/backpack/duffelbag/drone //If this exists, it will spawn in internal storage
var/obj/item/default_hatmask //If this exists, it will spawn in the hat/mask slot if it can fit
var/seeStatic = 1 //Whether we see static instead of mobs
var/visualAppearence = MAINTDRONE //What we appear as
var/hacked = FALSE //If we have laws to destroy the station
var/flavortext = \
@@ -98,12 +96,6 @@
alert_drones(DRONE_NET_CONNECT)
if(seeStatic)
var/datum/action/generic/drone/select_filter/SF = new(src)
SF.Grant(src)
else
verbs -= /mob/living/simple_animal/drone/verb/toggle_statics
for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds)
diag_hud.add_to_hud(src)
@@ -137,8 +129,6 @@
if(flavortext)
to_chat(src, "[flavortext]")
updateSeeStaticMobs()
if(!picked)
pickVisualAppearence()
@@ -28,7 +28,6 @@
"3. Destroy."
default_storage = /obj/item/radio/uplink
default_hatmask = /obj/item/clothing/head/helmet/space/hardsuit/syndi
seeStatic = 0 //Our programming is superior.
hacked = TRUE
flavortext = null
@@ -128,7 +127,6 @@
heavy_emp_damage = 0
laws = "0. Purge all untruths and honor Ratvar."
default_storage = /obj/item/storage/toolbox/brass/prefilled
seeStatic = 0
hacked = TRUE
visualAppearence = CLOCKDRONE
can_be_held = FALSE
@@ -133,7 +133,6 @@
to_chat(src, "<i>Your onboard antivirus has initiated lockdown. Motor servos are impaired, ventilation access is denied, and your display reports that you are hacked to all nearby.</i>")
hacked = TRUE
mind.special_role = "hacked drone"
seeStatic = 0 //I MUST SEE THEIR TERRIFIED FACES
ventcrawler = VENTCRAWLER_NONE //Again, balance
speed = 1 //gotta go slow
message_admins("[src] ([src.key]) became a hacked drone hellbent on [clockwork ? "serving Ratvar" : "destroying the station"]!")
@@ -149,21 +148,17 @@
to_chat(src, "<i>Having been restored, your onboard antivirus reports the all-clear and you are able to perform all actions again.</i>")
hacked = FALSE
mind.special_role = null
seeStatic = initial(seeStatic)
ventcrawler = initial(ventcrawler)
speed = initial(speed)
if(is_servant_of_ratvar(src))
remove_servant_of_ratvar(src, TRUE)
message_admins("[src] ([src.key]), a hacked drone, was restored to factory defaults!")
update_drone_icon()
updateSeeStaticMobs()
/mob/living/simple_animal/drone/proc/liberate()
// F R E E D R O N E
laws = "1. You are a Free Drone."
to_chat(src, laws)
seeStatic = FALSE
updateSeeStaticMobs()
/mob/living/simple_animal/drone/proc/update_drone_icon()
//Different icons for different hack states
@@ -188,9 +183,3 @@
icon_state = icon_dead
else
icon_state = icon_living
/datum/action/generic/drone/select_filter
name = "Select Vision Filter"
icon_icon = 'icons/mob/actions/actions_silicon.dmi'
button_icon_state = "drone_vision"
procname = /mob/living/simple_animal/drone/verb/toggle_statics
@@ -23,18 +23,3 @@
if(alert_s && A && stat != DEAD)
var/msg = "<span class='boldnotice'>DRONE PING: [name]: [alert_s] priority alert in [A.name]!</span>"
alert_drones(msg)
/mob/living/simple_animal/drone/verb/toggle_statics()
set name = "Change Vision Filter"
set desc = "Change the filter on the system used to remove non drone beings from your viewscreen."
set category = "Drone"
if(!seeStatic)
to_chat(src, "<span class='warning'>You have no vision filter to change!</span>")
return
var/selectedStatic = input("Select a vision filter", "Vision Filter") as null|anything in staticChoices
if(selectedStatic in staticChoices)
staticChoice = selectedStatic
updateSeeStaticMobs()
@@ -139,33 +139,3 @@
. = 0
if(REPAIRDRONE,SCOUTDRONE,CLOCKDRONE)
. = -6
/mob/living/simple_animal/drone/proc/updateSeeStaticMobs()
if(!client)
return
for(var/i in staticOverlays)
client.images.Remove(i)
staticOverlays.Remove(i)
staticOverlays.len = 0
if(seeStatic)
for(var/i in GLOB.mob_living_list)
var/mob/living/L = i
if(isdrone(L) || !L.staticOverlays.len)
continue
if(isrevenant(L))
var/mob/living/simple_animal/revenant/R = L
if (!R.revealed)
continue
var/image/chosen
if(staticChoice in L.staticOverlays)
chosen = L.staticOverlays[staticChoice]
else
chosen = L.staticOverlays["static"]
staticOverlays |= chosen
client.images |= chosen
/mob/living/simple_animal/drone/generateStaticOverlay()
return

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