Deconflict

This commit is contained in:
Arkatos1
2019-08-26 18:53:55 +02:00
476 changed files with 11894 additions and 7105 deletions

View File

@@ -123,8 +123,12 @@
#define TANK_RUPTURE_PRESSURE (40.*ONE_ATMOSPHERE) //Tank spills all contents into atmosphere
#define TANK_FRAGMENT_PRESSURE (50.*ONE_ATMOSPHERE) //Boom 3x3 base explosion
#define TANK_FRAGMENT_SCALE (10.*ONE_ATMOSPHERE) //+1 for each SCALE kPa aboe threshold
#define TANK_DEFAULT_RELEASE_PRESSURE 16
// Atmos alarm defines
#define ATMOS_ALARM_NONE 0
#define ATMOS_ALARM_WARNING 1
#define ATMOS_ALARM_DANGER 2
//LAVALAND
#define LAVALAND_EQUIPMENT_EFFECT_PRESSURE 50 //what pressure you have to be under to increase the effect of equipment meant for lavaland

View File

@@ -57,6 +57,89 @@
#define MAX_STACK_AMOUNT_GLASS 50
#define MAX_STACK_AMOUNT_RODS 60
//Colors
#define COLOR_RED "#FF0000"
#define COLOR_GREEN "#00FF00"
#define COLOR_BLUE "#0000FF"
#define COLOR_CYAN "#00FFFF"
#define COLOR_PINK "#FF00FF"
#define COLOR_YELLOW "#FFFF00"
#define COLOR_ORANGE "#FF9900"
#define COLOR_WHITE "#FFFFFF"
#define COLOR_GRAY "#808080"
#define COLOR_BLACK "#000000"
#define COLOR_NAVY_BLUE "#000080"
#define COLOR_LIGHT_GREEN "#008000"
#define COLOR_DARK_GRAY "#404040"
#define COLOR_MAROON "#800000"
#define COLOR_PURPLE "#800080"
#define COLOR_VIOLET "#9933ff"
#define COLOR_OLIVE "#808000"
#define COLOR_BROWN_ORANGE "#824b28"
#define COLOR_DARK_ORANGE "#b95a00"
#define COLOR_GRAY40 "#666666"
#define COLOR_GRAY20 "#333333"
#define COLOR_GRAY15 "#151515"
#define COLOR_SEDONA "#cc6600"
#define COLOR_DARK_BROWN "#917448"
#define COLOR_DEEP_SKY_BLUE "#00e1ff"
#define COLOR_LIME "#00ff00"
#define COLOR_TEAL "#33cccc"
#define COLOR_PALE_PINK "#bf89ba"
#define COLOR_YELLOW_GRAY "#c9a344"
#define COLOR_PALE_YELLOW "#c1bb7a"
#define COLOR_WARM_YELLOW "#b3863c"
#define COLOR_RED_GRAY "#aa5f61"
#define COLOR_BROWN "#b19664"
#define COLOR_GREEN_GRAY "#8daf6a"
#define COLOR_DARK_GREEN_GRAY "#54654c"
#define COLOR_BLUE_GRAY "#6a97b0"
#define COLOR_DARK_BLUE_GRAY "#3e4855"
#define COLOR_SUN "#ec8b2f"
#define COLOR_PURPLE_GRAY "#a2819e"
#define COLOR_BLUE_LIGHT "#33ccff"
#define COLOR_RED_LIGHT "#ff3333"
#define COLOR_BEIGE "#ceb689"
#define COLOR_BABY_BLUE "#89cff0"
#define COLOR_PALE_GREEN_GRAY "#aed18b"
#define COLOR_PALE_RED_GRAY "#cc9090"
#define COLOR_PALE_PURPLE_GRAY "#bda2ba"
#define COLOR_PALE_BLUE_GRAY "#8bbbd5"
#define COLOR_LUMINOL "#66ffff"
#define COLOR_SILVER "#c0c0c0"
#define COLOR_GRAY80 "#cccccc"
#define COLOR_OFF_WHITE "#eeeeee"
#define COLOR_GOLD "#6d6133"
#define COLOR_NT_RED "#9d2300"
#define COLOR_BOTTLE_GREEN "#1f6b4f"
#define COLOR_PALE_BTL_GREEN "#57967f"
#define COLOR_GUNMETAL "#545c68"
#define COLOR_WALL_GUNMETAL "#353a42"
#define COLOR_STEEL "#a8b0b2"
#define COLOR_MUZZLE_FLASH "#ffffb2"
#define COLOR_CHESTNUT "#996633"
#define COLOR_BEASTY_BROWN "#663300"
#define COLOR_WHEAT "#ffff99"
#define COLOR_CYAN_BLUE "#3366cc"
#define COLOR_LIGHT_CYAN "#66ccff"
#define COLOR_PAKISTAN_GREEN "#006600"
#define COLOR_HULL "#436b8e"
#define COLOR_AMBER "#ffbf00"
#define COLOR_COMMAND_BLUE "#46698c"
#define COLOR_SKY_BLUE "#5ca1cc"
#define COLOR_PALE_ORANGE "#b88a3b"
#define COLOR_CIVIE_GREEN "#b7f27d"
#define COLOR_TITANIUM "#d1e6e3"
#define COLOR_DARK_GUNMETAL "#4c535b"
#define COLOR_BRONZE "#8c7853"
#define COLOR_BRASS "#b99d71"
#define COLOR_INDIGO "#4b0082"
#define COLOR_ALUMINIUM "#bbbbbb"
#define COLOR_CRYSTAL "#00c8a5"
#define COLOR_ASTEROID_ROCK "#735555"
#define COLOR_NULLGLASS "#ff6088"
#define COLOR_DIAMOND "#d8d4ea"
//FONTS:
// Used by Paper and PhotoCopier (and PaperBin once a year).
// Used by PDA's Notekeeper.
@@ -270,6 +353,8 @@
#define TRIGGER_GUARD_NONE 0
#define TRIGGER_GUARD_NORMAL 1
#define CLIENT_FROM_VAR(I) (ismob(I) ? I:client : (istype(I, /client) ? I : (istype(I, /datum/mind) ? I:current?:client : null)))
// Macro to get the current elapsed round time, rather than total world runtime
#define ROUND_TIME (SSticker.round_start_time ? (world.time - SSticker.round_start_time) : 0)
@@ -305,6 +390,8 @@
#define BLOODY_FOOTPRINT_BASE_ALPHA 150
#define BLOOD_GAIN_PER_STEP 100
#define BLOOD_LOSS_PER_STEP 5
#define BLOOD_LOSS_IN_SPREAD 20
#define BLOOD_AMOUNT_PER_DECAL 20
//Bloody shoe blood states
#define BLOOD_STATE_HUMAN "blood"
@@ -320,7 +407,7 @@
#define INVESTIGATE_BOMB "bombs"
// The SQL version required by this version of the code
#define SQL_VERSION 8
#define SQL_VERSION 9
// Vending machine stuff
#define CAT_NORMAL 1
@@ -402,4 +489,15 @@
#define DICE_NOT_RIGGED 1
#define DICE_BASICALLY_RIGGED 2
#define DICE_TOTALLY_RIGGED 3
#define DICE_TOTALLY_RIGGED 3
// Parallax
#define PARALLAX_DELAY_DEFAULT world.tick_lag
#define PARALLAX_DELAY_MED 1
#define PARALLAX_DELAY_LOW 2
#define PARALLAX_LOOP_TIME 25
// Engine types
#define ENGTYPE_SING "Singularity"
#define ENGTYPE_SM "Supermatter"
#define ENGTYPE_TESLA "Tesla"

View File

@@ -187,6 +187,7 @@
#define isswarmer(A) (istype((A), /mob/living/simple_animal/hostile/swarmer))
#define isguardian(A) (istype((A), /mob/living/simple_animal/hostile/guardian))
#define isnymph(A) (istype((A), /mob/living/simple_animal/diona))
#define ishostile(A) (istype(A, /mob/living/simple_animal/hostile))
#define issilicon(A) (istype((A), /mob/living/silicon))
#define isAI(A) (istype((A), /mob/living/silicon/ai))

View File

@@ -63,3 +63,12 @@
#define EXP_TYPE_WHITELIST "Whitelist"
#define EXP_DEPT_TYPE_LIST list(EXP_TYPE_SERVICE, EXP_TYPE_MEDICAL, EXP_TYPE_ENGINEERING, EXP_TYPE_SCIENCE, EXP_TYPE_SECURITY, EXP_TYPE_COMMAND, EXP_TYPE_SILICON, EXP_TYPE_SPECIAL)
// Defines just for parallax because its levels make storing it in the regular prefs a pain in the ass
// These dont need to be bitflags because there isnt going to be more than one at a time of these active
// But its gonna piss off my OCD if it isnt bitflags, so deal with it, -affected
#define PARALLAX_DISABLE 1
#define PARALLAX_LOW 2
#define PARALLAX_MED 4
#define PARALLAX_HIGH 8
#define PARALLAX_INSANE 16

View File

@@ -32,3 +32,10 @@
#define SECHUD 1
#define MEDHUD 2
#define ANTAGHUD 3
//for clothing visor toggles, these determine which vars to toggle
#define VISOR_FLASHPROTECT (1<<0)
#define VISOR_TINT (1<<1)
#define VISOR_VISIONFLAGS (1<<2) //all following flags only matter for glasses
#define VISOR_DARKNESSVIEW (1<<3)
#define VISOR_INVISVIEW (1<<4)

View File

@@ -41,6 +41,7 @@
#define SHUTTLE_STRANDED 4
#define SHUTTLE_ESCAPE 5
#define SHUTTLE_ENDGAME 6
#define SHUTTLE_IGNITING 7
// Shuttle return values
#define SHUTTLE_CAN_DOCK "can_dock"

View File

@@ -26,7 +26,7 @@
//#define STATUS_EFFECT_WISH_GRANTERS_GIFT /datum/status_effect/wish_granters_gift //If you're currently resurrecting with the Wish Granter
//#define STATUS_EFFECT_BLOODDRUNK /datum/status_effect/blooddrunk //Stun immunity and greatly reduced damage taken
#define STATUS_EFFECT_BLOODDRUNK /datum/status_effect/blooddrunk //Stun immunity and greatly reduced damage taken
/////////////
// DEBUFFS //
@@ -52,7 +52,7 @@
#define STATUS_EFFECT_SUMMONEDGHOST /datum/status_effect/cultghost //is a cult ghost and can't use manifest runes
//#define STATUS_EFFECT_CRUSHERMARK /datum/status_effect/crusher_mark //if struck with a proto-kinetic crusher, takes a ton of damage
#define STATUS_EFFECT_CRUSHERMARK /datum/status_effect/crusher_mark //if struck with a proto-kinetic crusher, takes a ton of damage
#define STATUS_EFFECT_SAWBLEED /datum/status_effect/saw_bleed //if the bleed builds up enough, takes a ton of damage
@@ -74,6 +74,6 @@
//#define STATUS_EFFECT_SIGILMARK /datum/status_effect/sigil_mark
//#define STATUS_EFFECT_CRUSHERDAMAGETRACKING /datum/status_effect/crusher_damage //tracks total kinetic crusher damage on a target
#define STATUS_EFFECT_CRUSHERDAMAGETRACKING /datum/status_effect/crusher_damage //tracks total kinetic crusher damage on a target
//#define STATUS_EFFECT_SYPHONMARK /datum/status_effect/syphon_mark //tracks kills for the KA death syphon module
#define STATUS_EFFECT_SYPHONMARK /datum/status_effect/syphon_mark //tracks kills for the KA death syphon module

View File

@@ -79,7 +79,8 @@
#define INIT_ORDER_NANOMOB -23
#define INIT_ORDER_SQUEAK -40
#define INIT_ORDER_PATH -50
#define INIT_ORDER_PERSISTENCE -100
#define INIT_ORDER_PERSISTENCE -95
#define INIT_ORDER_CHAT -100 //Should be last to ensure chat remains smooth during init.
// Subsystem fire priority, from lowest to highest priority
// If the subsystem isn't listed here it's either DEFAULT or PROCESS (if it's a processing subsystem child)
@@ -111,6 +112,7 @@
#define FIRE_PRIORITY_MOBS 100
#define FIRE_PRIORITY_NANOUI 110
#define FIRE_PRIORITY_TICKER 200
#define FIRE_PRIORITY_CHAT 400
#define FIRE_PRIORITY_OVERLAYS 500
#define FIRE_PRIORITY_INPUT 1000 // This must always always be the max highest priority. Player input must never be lost.

View File

@@ -19,6 +19,12 @@
return A
return 0
/proc/get_location_name(atom/X, format_text = FALSE)
var/area/A = isarea(X) ? X : get_area(X)
if(!A)
return null
return format_text ? format_text(A.name) : A.name
/proc/get_areas_in_range(dist=0, atom/center=usr)
if(!dist)
var/turf/T = get_turf(center)
@@ -429,6 +435,17 @@
/proc/GetBluePart(const/hexa)
return hex2num(copytext(hexa, 6, 8))
/proc/lavaland_equipment_pressure_check(turf/T)
. = FALSE
if(!istype(T))
return
var/datum/gas_mixture/environment = T.return_air()
if(!istype(environment))
return
var/pressure = environment.return_pressure()
if(pressure <= LAVALAND_EQUIPMENT_EFFECT_PRESSURE)
. = TRUE
/proc/GetHexColors(const/hexa)
return list(
GetRedPart(hexa),

View File

@@ -153,29 +153,33 @@
/turf/simulated/wall/diagonal_smooth(adjacencies)
adjacencies = reverse_ndir(..())
if(adjacencies)
var/list/U = list()
var/mutable_appearance/underlay_appearance = mutable_appearance(layer = TURF_LAYER, plane = FLOOR_PLANE)
var/list/U = list(underlay_appearance)
if(fixed_underlay)
if(fixed_underlay["space"])
U += image('icons/turf/space.dmi', SPACE_ICON_STATE, layer=TURF_LAYER)
underlay_appearance.icon = 'icons/turf/space.dmi'
underlay_appearance.icon_state = SPACE_ICON_STATE
underlay_appearance.plane = PLANE_SPACE
else
U += image(fixed_underlay["icon"], fixed_underlay["icon_state"], layer=TURF_LAYER)
underlay_appearance.icon = fixed_underlay["icon"]
underlay_appearance.icon_state = fixed_underlay["icon_state"]
else
var/turf/T = get_step(src, turn(adjacencies, 180))
if(T && (T.density || T.smooth))
var/turned_adjacency = turn(adjacencies, 180)
var/turf/T = get_step(src, turned_adjacency)
if(!T.get_smooth_underlay_icon(underlay_appearance, src, turned_adjacency))
T = get_step(src, turn(adjacencies, 135))
if(T && (T.density || T.smooth))
if(!T.get_smooth_underlay_icon(underlay_appearance, src, turned_adjacency))
T = get_step(src, turn(adjacencies, 225))
if(istype(T, /turf/space) && !istype(T, /turf/space/transit))
U += image('icons/turf/space.dmi', SPACE_ICON_STATE, layer=TURF_LAYER)
else if(T && !T.density && !T.smooth)
U += T
else if(baseturf && !initial(baseturf.density) && !initial(baseturf.smooth))
U += image(initial(baseturf.icon), initial(baseturf.icon_state), layer=TURF_LAYER)
else
U += DEFAULT_UNDERLAY_IMAGE
//if all else fails, ask our own turf
if(!T.get_smooth_underlay_icon(underlay_appearance, src, turned_adjacency) && !get_smooth_underlay_icon(underlay_appearance, src, turned_adjacency))
underlay_appearance.icon = DEFAULT_UNDERLAY_ICON
underlay_appearance.icon_state = DEFAULT_UNDERLAY_ICON_STATE
underlays = U
// Drop posters which were previously placed on this wall.
for(var/obj/structure/sign/poster/P in src)
P.roll_and_drop(src)
/proc/cardinal_smooth(atom/A, adjacencies)
//NW CORNER
var/nw = "1-i"

View File

@@ -545,6 +545,43 @@ proc/checkhtml(var/t)
text = copytext(text, 1, MAX_PAPER_MESSAGE_LEN)
return text
/proc/convert_pencode_arg(text, tag, arg)
arg = sanitize_simple(html_encode(arg), list("''"="","\""="", "?"=""))
// https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#rule-4---css-escape-and-strictly-validate-before-inserting-untrusted-data-into-html-style-property-values
var/list/style_attacks = list("javascript:", "expression", "byond:", "file:")
for(var/style_attack in style_attacks)
if(findtext(arg, style_attack))
// Do not attempt to render dangerous things
return text
if(tag == "class")
return "<span class='[arg]'>"
if(tag == "style")
return "<span style='[arg]'>"
if(tag == "img")
var/list/img_props = splittext(arg, ";")
if(img_props.len == 3)
return "<img src='[img_props[1]]' width='[img_props[2]]' height='[img_props[3]]'>"
if(img_props.len == 2)
return "<img src='[img_props[1]]' width='[img_props[2]]'>"
return "<img src='[arg]'>"
return text
/proc/admin_pencode_to_html()
var/text = pencode_to_html(arglist(args))
var/regex/R = new(@"\[(.*?) (.*?)\]", "ge")
text = R.Replace(text, /proc/convert_pencode_arg)
text = replacetext(text, "\[/class\]", "</span>")
text = replacetext(text, "\[/style\]", "</span>")
text = replacetext(text, "\[/img\]", "</img>")
return text
/proc/html_to_pencode(text)
text = replacetext(text, "<BR>", "\n")
text = replacetext(text, "<center>", "\[center\]")

View File

@@ -47,4 +47,6 @@ GLOBAL_LIST_INIT(active_diseases, list()) //List of Active disease in all mob
GLOBAL_LIST_EMPTY(mob_spawners) // All mob_spawn objects
GLOBAL_LIST_EMPTY(explosive_walls)
GLOBAL_LIST_EMPTY(explosive_walls)
GLOBAL_LIST_EMPTY(engine_beacon_list)

View File

@@ -209,11 +209,13 @@
/atom/proc/AIMiddleClick()
return
/obj/machinery/door/airlock/AIMiddleClick() // Toggles door bolt lights.
if(!src.lights)
Topic(src, list("src" = UID(), "command"="lights", "activate" = "1"), 1) // 1 meaning no window (consistency!)
/obj/machinery/door/airlock/AIMiddleClick() // Toggles door safety.
if(safe)
Topic(src, list("src" = UID(), "command"="safeties", "activate" = "1"), 1) // 1 meaning no window (consistency!)
to_chat(usr, "The door safeties have been overridden.")
else
Topic(src, list("src" = UID(), "command"="lights", "activate" = "0"), 1)
Topic(src, list("src" = UID(), "command"="safeties", "activate" = "0"), 1)
to_chat(usr, "The door safeties have been reset.")
return
/obj/machinery/ai_slipper/AICtrlClick() //Turns liquid dispenser on or off

View File

@@ -107,14 +107,20 @@
#define ui_healthdoll "EAST-1:28,CENTER-1:15"
#define ui_health "EAST-1:28,CENTER:17"
#define ui_internal "EAST-1:28,CENTER+1:19"
//borgs
//borgs
#define ui_borg_health "EAST-1:28,CENTER-1:15" //borgs have the health display where humans have the pressure damage indicator.
//aliens
#define ui_alien_health "EAST-1:28,CENTER-1:15" //aliens have the health display where humans have the pressure damage indicator.
//constructs
#define ui_construct_pull "EAST-1:28,SOUTH+1:10" //above the zone_sel icon
#define ui_construct_health "EAST,CENTER:15" //same height as humans, hugging the right border
//slimes
#define ui_slime_health "EAST,CENTER:15" //same as borgs, constructs and humans
//Pop-up inventory
#define ui_shoes "WEST+1:8,SOUTH:5"

View File

@@ -2,6 +2,25 @@
var/datum/action/linked_action
screen_loc = null
/obj/screen/movable/action_button/MouseDrop(over_object)
if((istype(over_object, /obj/screen/movable/action_button) && !istype(over_object, /obj/screen/movable/action_button/hide_toggle)))
if(locked)
to_chat(usr, "<span class='warning'>Action button \"[name]\" is locked, unlock it first.</span>")
closeToolTip(usr)
return
var/obj/screen/movable/action_button/B = over_object
var/list/actions = usr.actions
actions.Swap(actions.Find(linked_action), actions.Find(B.linked_action))
moved = FALSE
B.moved = FALSE
closeToolTip(usr)
usr.update_action_buttons()
else if(istype(over_object, /obj/screen/movable/action_button/hide_toggle))
closeToolTip(usr)
else
closeToolTip(usr)
return ..()
/obj/screen/movable/action_button/Click(location,control,params)
var/list/modifiers = params2list(params)
if(modifiers["shift"])
@@ -29,6 +48,13 @@
icon_state = "bg_default"
var/hidden = 0
/obj/screen/movable/action_button/hide_toggle/MouseDrop(over_object)
if(istype(over_object, /obj/screen/movable/action_button))
closeToolTip(usr)
else
closeToolTip(usr)
return ..()
/obj/screen/movable/action_button/hide_toggle/Click(location,control,params)
var/list/modifiers = params2list(params)
if(modifiers["shift"])
@@ -83,9 +109,9 @@
var/image/img = image(icon, src, hidden ? "show" : "hide")
overlays += img
/obj/screen/movable/action_button/MouseEntered(location,control,params)
openToolTip(usr,src,params,title = name,content = desc)
/obj/screen/movable/action_button/MouseEntered(location, control, params)
if(!QDELETED(src))
openToolTip(usr, src, params, title = name, content = desc)
/obj/screen/movable/action_button/MouseExited()
closeToolTip(usr)

View File

@@ -256,4 +256,10 @@
//Add multicamera camera
using = new /obj/screen/ai/add_multicam()
using.screen_loc = ui_ai_add_multicam
static_inventory += using
static_inventory += using
//Intent
using = new /obj/screen/act_intent/robot/AI()
using.icon_state = mymob.a_intent
static_inventory += using
action_intent = using

View File

@@ -49,8 +49,8 @@
/obj/screen/blob/Blobbernaut
icon_state = "ui_blobbernaut"
name = "Produce Blobbernaut (20)"
desc = "Produces a strong, but dumb blobbernaut from a factory blob for 20 resources.<br>The factory blob will be destroyed in the process."
name = "Produce Blobbernaut (60)"
desc = "Produces a strong, intelligent blobbernaut from a factory blob for 60 resources.<br>The factory blob will be destroyed in the process."
/obj/screen/blob/Blobbernaut/Click()
if(isovermind(usr))

View File

@@ -59,3 +59,8 @@
using = new /obj/screen/ghost/teleport()
using.screen_loc = ui_ghost_teleport
static_inventory += using
/datum/hud/ghost/show_hud()
mymob.client.screen = list()
mymob.client.screen += static_inventory
..()

View File

@@ -99,6 +99,7 @@
/datum/hud/proc/show_hud(version = 0)
if(!ismob(mymob))
return FALSE
if(!mymob.client)
return FALSE
@@ -172,6 +173,7 @@
mymob.update_action_buttons(1)
reorganize_alerts()
reload_fullscreen()
update_parallax_pref(mymob)
plane_masters_update()
/datum/hud/proc/plane_masters_update()

View File

@@ -0,0 +1,319 @@
/client
var/list/parallax_layers
var/list/parallax_layers_cached
var/static/list/parallax_static_layers_tail = newlist(/obj/screen/parallax_pmaster, /obj/screen/parallax_space_whitifier)
var/atom/movable/movingmob
var/turf/previous_turf
var/dont_animate_parallax //world.time of when we can state animate()ing parallax again
var/last_parallax_shift //world.time of last update
var/parallax_throttle = 0 //ds between updates
var/parallax_movedir = 0
var/parallax_layers_max = 3
var/parallax_animate_timer
/datum/hud/proc/create_parallax()
var/client/C = mymob.client
if(!apply_parallax_pref())
return
if(!length(C.parallax_layers_cached))
C.parallax_layers_cached = list()
C.parallax_layers_cached += new /obj/screen/parallax_layer/layer_1(null, C.view)
C.parallax_layers_cached += new /obj/screen/parallax_layer/layer_2(null, C.view)
C.parallax_layers_cached += new /obj/screen/parallax_layer/planet(null, C.view)
C.parallax_layers_cached += new /obj/screen/parallax_layer/layer_3(null, C.view)
C.parallax_layers = C.parallax_layers_cached.Copy()
if(length(C.parallax_layers) > C.parallax_layers_max)
C.parallax_layers.len = C.parallax_layers_max
C.screen |= (C.parallax_layers + C.parallax_static_layers_tail)
/datum/hud/proc/remove_parallax()
var/client/C = mymob.client
C.screen -= (C.parallax_layers_cached + C.parallax_static_layers_tail)
C.parallax_layers = null
/datum/hud/proc/apply_parallax_pref()
var/client/C = mymob.client
if(C.prefs)
var/pref = C.prefs.parallax
if (isnull(pref))
pref = PARALLAX_HIGH
switch(C.prefs.parallax)
if (PARALLAX_INSANE)
C.parallax_throttle = FALSE
C.parallax_layers_max = 4
return TRUE
if (PARALLAX_MED)
C.parallax_throttle = PARALLAX_DELAY_MED
C.parallax_layers_max = 2
return TRUE
if (PARALLAX_LOW)
C.parallax_throttle = PARALLAX_DELAY_LOW
C.parallax_layers_max = 1
return TRUE
if (PARALLAX_DISABLE)
return FALSE
C.parallax_throttle = PARALLAX_DELAY_DEFAULT
C.parallax_layers_max = 3
return TRUE
/datum/hud/proc/update_parallax_pref()
remove_parallax()
create_parallax()
update_parallax()
// This sets which way the current shuttle is moving (returns true if the shuttle has stopped moving so the caller can append their animation)
// Well, it would if our shuttle code had dynamic areas
/datum/hud/proc/set_parallax_movedir(new_parallax_movedir, skip_windups)
. = FALSE
var/client/C = mymob.client
if(new_parallax_movedir == C.parallax_movedir)
return
var/animatedir = new_parallax_movedir
if(new_parallax_movedir == FALSE)
var/animate_time = 0
for(var/thing in C.parallax_layers)
var/obj/screen/parallax_layer/L = thing
L.icon_state = initial(L.icon_state)
L.update_o(C.view)
var/T = PARALLAX_LOOP_TIME / L.speed
if(T > animate_time)
animate_time = T
C.dont_animate_parallax = world.time + min(animate_time, PARALLAX_LOOP_TIME)
animatedir = C.parallax_movedir
var/matrix/newtransform
switch(animatedir)
if(NORTH)
newtransform = matrix(1, 0, 0, 0, 1, 480)
if(SOUTH)
newtransform = matrix(1, 0, 0, 0, 1,-480)
if(EAST)
newtransform = matrix(1, 0, 480, 0, 1, 0)
if(WEST)
newtransform = matrix(1, 0,-480, 0, 1, 0)
var/shortesttimer
for(var/thing in C.parallax_layers)
var/obj/screen/parallax_layer/L = thing
var/T = PARALLAX_LOOP_TIME / L.speed
if(isnull(shortesttimer))
shortesttimer = T
if(T < shortesttimer)
shortesttimer = T
L.transform = newtransform
animate(L, transform = matrix(), time = T, easing = QUAD_EASING | (new_parallax_movedir ? EASE_IN : EASE_OUT), flags = ANIMATION_END_NOW)
if(new_parallax_movedir)
L.transform = newtransform
animate(transform = matrix(), time = T) //queue up another animate so lag doesn't create a shutter
C.parallax_movedir = new_parallax_movedir
if(C.parallax_animate_timer)
deltimer(C.parallax_animate_timer)
var/datum/callback/CB = CALLBACK(src, .proc/update_parallax_motionblur, C, animatedir, new_parallax_movedir, newtransform)
if(skip_windups)
CB.Invoke()
else
C.parallax_animate_timer = addtimer(CB, min(shortesttimer, PARALLAX_LOOP_TIME), TIMER_CLIENT_TIME|TIMER_STOPPABLE)
/datum/hud/proc/update_parallax_motionblur(client/C, animatedir, new_parallax_movedir, matrix/newtransform)
C.parallax_animate_timer = FALSE
for(var/thing in C.parallax_layers)
var/obj/screen/parallax_layer/L = thing
if(!new_parallax_movedir)
animate(L)
continue
var/newstate = initial(L.icon_state)
if(animatedir)
if(animatedir == NORTH || animatedir == SOUTH)
newstate += "_vertical"
else
newstate += "_horizontal"
var/T = PARALLAX_LOOP_TIME / L.speed
if(newstate in icon_states(L.icon))
L.icon_state = newstate
L.update_o(C.view)
L.transform = newtransform
animate(L, transform = matrix(), time = T, loop = -1, flags = ANIMATION_END_NOW)
/datum/hud/proc/update_parallax()
var/client/C = mymob.client
var/turf/posobj = get_turf(C.eye)
if(!posobj)
return
var/area/areaobj = posobj.loc
// Update the movement direction of the parallax if necessary (for shuttles)
var/area/shuttle/SA = areaobj
if(!SA || !SA.moving)
set_parallax_movedir(0)
else
set_parallax_movedir(SA.parallax_movedir)
var/force
if(!C.previous_turf || (C.previous_turf.z != posobj.z))
C.previous_turf = posobj
force = TRUE
if(!force && world.time < C.last_parallax_shift+C.parallax_throttle)
return
//Doing it this way prevents parallax layers from "jumping" when you change Z-Levels.
var/offset_x = posobj.x - C.previous_turf.x
var/offset_y = posobj.y - C.previous_turf.y
if(!offset_x && !offset_y && !force)
return
var/last_delay = world.time - C.last_parallax_shift
last_delay = min(last_delay, C.parallax_throttle)
C.previous_turf = posobj
C.last_parallax_shift = world.time
for(var/thing in C.parallax_layers)
var/obj/screen/parallax_layer/L = thing
L.update_status(mymob)
if(L.view_sized != C.view)
L.update_o(C.view)
var/change_x
var/change_y
if(L.absolute)
L.offset_x = -(posobj.x - SSparallax.planet_x_offset) * L.speed
L.offset_y = -(posobj.y - SSparallax.planet_y_offset) * L.speed
else
change_x = offset_x * L.speed
L.offset_x -= change_x
change_y = offset_y * L.speed
L.offset_y -= change_y
if(L.offset_x > 240)
L.offset_x -= 480
if(L.offset_x < -240)
L.offset_x += 480
if(L.offset_y > 240)
L.offset_y -= 480
if(L.offset_y < -240)
L.offset_y += 480
if(!(areaobj.parallax_movedir && areaobj.moving) && C.dont_animate_parallax <= world.time && (offset_x || offset_y) && abs(offset_x) <= max(C.parallax_throttle/world.tick_lag+1,1) && abs(offset_y) <= max(C.parallax_throttle/world.tick_lag+1,1) && (round(abs(change_x)) > 1 || round(abs(change_y)) > 1))
L.transform = matrix(1, 0, offset_x*L.speed, 0, 1, offset_y*L.speed)
animate(L, transform=matrix(), time = last_delay)
L.screen_loc = "CENTER-7:[round(L.offset_x,1)],CENTER-7:[round(L.offset_y,1)]"
/atom/movable/proc/update_parallax_contents()
if(length(client_mobs_in_contents))
for(var/thing in client_mobs_in_contents)
var/mob/M = thing
if(M && M.client && M.hud_used && length(M.client.parallax_layers))
M.hud_used.update_parallax()
/obj/screen/parallax_layer
icon = 'icons/effects/parallax.dmi'
var/speed = 1
var/offset_x = 0
var/offset_y = 0
var/view_sized
var/absolute = FALSE
blend_mode = BLEND_ADD
plane = PLANE_SPACE_PARALLAX
screen_loc = "CENTER-7,CENTER-7"
mouse_opacity = 0
/obj/screen/parallax_layer/New(view)
..()
if(!view)
view = world.view
update_o(view)
/obj/screen/parallax_layer/proc/update_o(view)
if(!view)
view = world.view
var/list/new_overlays = list()
var/count = Ceiling(view/(480/world.icon_size))+1
for(var/x in -count to count)
for(var/y in -count to count)
if(x == 0 && y == 0)
continue
var/mutable_appearance/texture_overlay = mutable_appearance(icon, icon_state)
texture_overlay.transform = matrix(1, 0, x*480, 0, 1, y*480)
new_overlays += texture_overlay
overlays = new_overlays
view_sized = view
/obj/screen/parallax_layer/proc/update_status(mob/M)
return
/obj/screen/parallax_layer/layer_1
icon_state = "layer1"
speed = 0.6
layer = 1
/obj/screen/parallax_layer/layer_2
icon_state = "layer2"
speed = 1
layer = 2
/obj/screen/parallax_layer/layer_3
icon_state = "layer3"
speed = 1.4
layer = 3
/obj/screen/parallax_layer/planet
icon_state = "planet"
blend_mode = BLEND_OVERLAY
absolute = TRUE //Status of seperation
speed = 3
layer = 30
/obj/screen/parallax_layer/planet/update_status(mob/M)
var/turf/T = get_turf(M)
if(is_station_level(T.z))
invisibility = 0
else
invisibility = INVISIBILITY_ABSTRACT
/obj/screen/parallax_layer/planet/update_o()
return //Shit wont move
/obj/screen/parallax_pmaster
appearance_flags = PLANE_MASTER
plane = PLANE_SPACE_PARALLAX
blend_mode = BLEND_MULTIPLY
mouse_opacity = FALSE
screen_loc = "CENTER-7,CENTER-7"
/obj/screen/parallax_space_whitifier
appearance_flags = PLANE_MASTER
plane = PLANE_SPACE
color = list(
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
1, 1, 1, 1,
0, 0, 0, 0
)
screen_loc = "CENTER-7,CENTER-7"
#undef LOOP_NONE
#undef LOOP_NORMAL
#undef LOOP_REVERSE
#undef LOOP_TIME

View File

@@ -95,6 +95,9 @@
icon = 'icons/mob/screen_robot.dmi'
screen_loc = ui_borg_intents
/obj/screen/act_intent/robot/AI
screen_loc = "EAST-1:32,SOUTH:70"
/obj/screen/mov_intent
name = "run/walk toggle"
icon_state = "running"
@@ -453,6 +456,12 @@
/obj/screen/healths/corgi
icon = 'icons/mob/screen_corgi.dmi'
/obj/screen/healths/slime
icon = 'icons/mob/screen_slime.dmi'
icon_state = "slime_health0"
screen_loc = ui_slime_health
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
/obj/screen/healths/guardian
name = "summoner health"
icon = 'icons/mob/guardian.dmi'

View File

@@ -0,0 +1,18 @@
/mob/living/carbon/slime/create_mob_hud()
if(client && !hud_used)
hud_used = new /datum/hud/slime(src)
/mob/living/simple_animal/slime/create_mob_hud()
if(client && !hud_used)
hud_used = new /datum/hud/slime(src)
/datum/hud/slime/New(mob/owner)
..()
mymob.healths = new /obj/screen/healths/slime()
infodisplay += mymob.healths
mymob.pullin = new /obj/screen/pull()
mymob.pullin.icon = 'icons/mob/screen_slime.dmi'
mymob.pullin.update_icon(mymob)
mymob.pullin.screen_loc = ui_construct_pull
hotkeybuttons += mymob.pullin

View File

@@ -17,6 +17,7 @@
else
following = null
forceMove(get_turf(A))
update_parallax_contents()
/mob/dead/observer/ClickOn(var/atom/A, var/params)
if(client.click_intercept)
@@ -58,6 +59,14 @@
/atom/proc/attack_ghost(mob/user as mob)
return
// health + cyborg analyzer for ghosts
/mob/living/attack_ghost(mob/dead/observer/user)
if(user.client && user.health_scan)
if(issilicon(src) || ismachine(src))
robot_healthscan(user, src)
else if(ishuman(src))
healthscan(user, src, 1, TRUE)
// ---------------------------------------
// And here are some good things for free:
// Now you can click through portals, wormholes, gateways, and teleporters while observing. -Sayu

View File

@@ -0,0 +1,65 @@
SUBSYSTEM_DEF(chat)
name = "Chat"
flags = SS_TICKER|SS_NO_INIT
wait = 1
priority = FIRE_PRIORITY_CHAT
init_order = INIT_ORDER_CHAT
var/list/payload = list()
/datum/controller/subsystem/chat/fire()
for(var/i in payload)
var/client/C = i
C << output(payload[C], "browseroutput:output")
payload -= C
if(MC_TICK_CHECK)
return
/datum/controller/subsystem/chat/proc/queue(target, message, flag)
if(!target || !message)
return
if(!istext(message))
stack_trace("to_chat called with invalid input type")
return
if(target == world)
target = GLOB.clients
//Some macros remain in the string even after parsing and fuck up the eventual output
message = replacetext(message, "\improper", "")
message = replacetext(message, "\proper", "")
message += "<br>"
//url_encode it TWICE, this way any UTF-8 characters are able to be decoded by the Javascript.
//Do the double-encoding here to save nanoseconds
var/twiceEncoded = url_encode(url_encode(message))
if(islist(target))
for(var/I in target)
var/client/C = CLIENT_FROM_VAR(I) //Grab us a client if possible
if(!C?.chatOutput || C.chatOutput.broken) //A player who hasn't updated his skin file.
continue
if(!C.chatOutput.loaded) //Client still loading, put their messages in a queue
C.chatOutput.messageQueue += message
continue
payload[C] += twiceEncoded
else
var/client/C = CLIENT_FROM_VAR(target) //Grab us a client if possible
if(!C?.chatOutput || C.chatOutput.broken) //A player who hasn't updated his skin file.
return
if(!C.chatOutput.loaded) //Client still loading, put their messages in a queue
C.chatOutput.messageQueue += message
return
payload[C] += twiceEncoded

View File

@@ -0,0 +1,44 @@
SUBSYSTEM_DEF(parallax)
name = "Parallax"
wait = 2
flags = SS_POST_FIRE_TIMING | SS_BACKGROUND
priority = FIRE_PRIORITY_PARALLAX
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
var/list/currentrun
var/planet_x_offset = 128
var/planet_y_offset = 128
/datum/controller/subsystem/parallax/Initialize(timeofday)
. = ..()
planet_y_offset = rand(100, 160)
planet_x_offset = rand(100, 160)
/datum/controller/subsystem/parallax/fire(resumed = 0)
if(!resumed)
src.currentrun = GLOB.clients.Copy()
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
while(length(currentrun))
var/client/C = currentrun[currentrun.len]
currentrun.len--
if(!C || !C.eye)
if(MC_TICK_CHECK)
return
continue
var/atom/movable/A = C.eye
if(!istype(A))
continue
for (A; isloc(A.loc) && !isturf(A.loc); A = A.loc);
if(A != C.movingmob)
if(C.movingmob != null)
C.movingmob.client_mobs_in_contents -= C.mob
UNSETEMPTY(C.movingmob.client_mobs_in_contents)
LAZYINITLIST(A.client_mobs_in_contents)
A.client_mobs_in_contents += C.mob
C.movingmob = A
if(MC_TICK_CHECK)
return
currentrun = null

View File

@@ -196,6 +196,14 @@
/datum/action/item_action/toggle_helmet_light
name = "Toggle Helmet Light"
/datum/action/item_action/toggle_welding_screen/plasmaman
name = "Toggle Welding Screen"
/datum/action/item_action/toggle_welding_screen/plasmaman/Trigger()
var/obj/item/clothing/head/helmet/space/plasmaman/H = target
if(istype(H))
H.toggle_welding_screen(owner)
/datum/action/item_action/toggle_helmet_mode
name = "Toggle Helmet Mode"

View File

@@ -0,0 +1,31 @@
/datum/component/spraycan_paintable
var/current_paint
/datum/component/spraycan_paintable/Initialize()
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/Repaint)
/datum/component/spraycan_paintable/Destroy()
RemoveCurrentCoat()
return ..()
/datum/component/spraycan_paintable/proc/RemoveCurrentCoat()
var/atom/A = parent
A.remove_atom_colour(FIXED_COLOUR_PRIORITY, current_paint)
/datum/component/spraycan_paintable/proc/Repaint(datum/source, obj/item/toy/crayon/spraycan/spraycan, mob/living/user)
if(!istype(spraycan) || user.a_intent == INTENT_HARM)
return
. = COMPONENT_NO_AFTERATTACK
if(spraycan.capped)
to_chat(user, "<span class='warning'>Take the cap off first!</span>")
return
if(spraycan.uses < 2)
to_chat(user, "<span class ='warning'>There is not enough paint in the can!")
return
RemoveCurrentCoat()
var/colour = spraycan.colour
current_paint = colour
var/atom/A = parent
A.add_atom_colour(colour, FIXED_COLOUR_PRIORITY)
playsound(spraycan, 'sound/effects/spray.ogg', 5, 1, 5)
to_chat(user, "<span class='notice'>You spray [spraycan] on [A], painting it.</span>")

View File

@@ -1269,7 +1269,12 @@
return
src.debug_variables(DAT)
return
if(href_list["copyoutfit"])
if(!check_rights(R_EVENT))
return
var/mob/living/carbon/human/H = locateUID(href_list["copyoutfit"])
if(istype(H))
H.copy_outfit()
/client/proc/view_var_Topic_list(href, href_list, hsrc)
if(href_list["VarsList"])

View File

@@ -30,11 +30,11 @@ Bonus
if(prob(SYMPTOM_ACTIVATION_PROB))
var/mob/living/carbon/M = A.affected_mob
to_chat(M, "<span class='warning'>[pick("You feel cold.", "You start shivering.")]</span>")
if(M.bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT)
if(M.bodytemperature > BODYTEMP_COLD_DAMAGE_LIMIT)
Chill(M, A)
return
/datum/symptom/shivering/proc/Chill(mob/living/M, datum/disease/advance/A)
var/get_cold = (sqrtor0(16+A.totalStealth()*2))+(sqrtor0(21+A.totalResistance()*2))
M.bodytemperature = min(M.bodytemperature - (get_cold * A.stage), BODYTEMP_COLD_DAMAGE_LIMIT + 1)
return 1
M.bodytemperature = max(M.bodytemperature - (get_cold * A.stage), BODYTEMP_COLD_DAMAGE_LIMIT + 1)
return 1

View File

@@ -100,15 +100,20 @@
height = 400
immediate_submit = TRUE
/datum/async_input/ranked/New()
..()
popup.add_script("rankedInput.js", 'html/browser/rankedInput.js')
popup.add_head_content("<title>Drag and drop or use the buttons to reorder</title>")
/datum/async_input/ranked/render_choices()
var/dat = "<div>"
dat += "<table style='margin: auto; text-align: left;'>"
dat += "<table id='choices' uid=[UID()] style='margin: auto; text-align: left;'>"
for(var/i = 1, i <= choices.len, i++)
var/choice = choices[i]
dat += "<tr>"
dat += "<td>[button("+", i != 1 ? "upvote=[i]" : "", , i == 1)]</td>"
dat += "<td>[button("-", i != choices.len ? "downvote=[i]" : "", , i == choices.len)]</td>"
dat += "<td>[i]. [choice]</td>"
dat += "<td style='cursor: move;' index='[i]' ondrop='drop(event)' ondragover='allowDrop(event)' draggable='true' ondragstart='drag(event)'>[i]. [choice]</td>"
dat += "</tr>"
dat += "</table>"
dat += "</div>"
@@ -131,6 +136,15 @@
show()
return
if(href_list["cut"] && href_list["insert"])
var/cut = text2num(href_list["cut"])
var/insert = text2num(href_list["insert"])
var/choice = choices[cut]
choices.Cut(cut, cut + 1)
choices.Insert(insert, choice)
show()
return
..()
/datum/async_input/autocomplete

View File

@@ -19,14 +19,20 @@
var/suit_store = null
var/l_hand = null
var/r_hand = null
/// Should the toggle helmet proc be called on the helmet during equip
var/toggle_helmet = TRUE
var/pda = null
var/internals_slot = null //ID of slot containing a gas tank
var/list/backpack_contents = list() // In the list(path=count,otherpath=count) format
var/list/implants = null
var/list/cybernetic_implants = null
var/box // Internals box. Will be inserted at the start of backpack_contents
var/list/implants = list()
var/list/cybernetic_implants = list()
var/list/accessories = list()
var/list/chameleon_extras //extra types for chameleon outfit changes, mostly guns
var/can_be_admin_equipped = TRUE // Set to FALSE if your outfit requires runtime parameters
/datum/outfit/proc/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
//to be overriden for customization depending on client prefs,species etc
return
@@ -82,12 +88,24 @@
if(pda)
equip_item(H, pda, slot_wear_pda)
if(uniform)
for(var/path in accessories)
var/obj/item/clothing/accessory/A = new path()
var/obj/item/clothing/under/U = uniform
U.attach_accessory(A, H)
if(!visualsOnly) // Items in pockets or backpack don't show up on mob's icon.
if(l_pocket)
equip_item(H, l_pocket, slot_l_store)
if(r_pocket)
equip_item(H, r_pocket, slot_r_store)
if(box)
if(!backpack_contents)
backpack_contents = list()
backpack_contents.Insert(1, box)
backpack_contents[box] = 1
for(var/path in backpack_contents)
var/number = backpack_contents[path]
for(var/i in 1 to number)
@@ -97,6 +115,10 @@
var/obj/item/organ/internal/O = new path(H)
O.insert(H)
if(!H.head && toggle_helmet && istype(H.wear_suit, /obj/item/clothing/suit/space/hardsuit))
var/obj/item/clothing/suit/space/hardsuit/HS = H.wear_suit
HS.ToggleHelmet()
post_equip(H, visualsOnly)
if(!visualsOnly)
@@ -159,3 +181,97 @@
types += chameleon_extras
listclearnulls(types)
return types
/datum/outfit/proc/save_to_file(mob/admin)
var/stored_data = get_json_data()
var/json = json_encode(stored_data)
// Kinda annoying but as far as I can tell you need to make actual file.
var/f = file("data/TempOutfitUpload")
fdel(f)
WRITE_FILE(f, json)
admin << ftp(f, "[name].json")
/datum/outfit/proc/load_from(list/outfit_data)
// This could probably use more strict validation.
name = outfit_data["name"]
uniform = text2path(outfit_data["uniform"])
suit = text2path(outfit_data["suit"])
toggle_helmet = text2path(outfit_data["toggle_helmet"])
back = text2path(outfit_data["back"])
belt = text2path(outfit_data["belt"])
gloves = text2path(outfit_data["gloves"])
shoes = text2path(outfit_data["shoes"])
head = text2path(outfit_data["head"])
mask = text2path(outfit_data["mask"])
l_ear = text2path(outfit_data["l_ear"])
r_ear = text2path(outfit_data["r_ear"])
glasses = text2path(outfit_data["glasses"])
id = text2path(outfit_data["id"])
pda = text2path(outfit_data["pda"])
l_pocket = text2path(outfit_data["l_pocket"])
r_pocket = text2path(outfit_data["r_pocket"])
suit_store = text2path(outfit_data["suit_store"])
r_hand = text2path(outfit_data["r_hand"])
l_hand = text2path(outfit_data["l_hand"])
internals_slot = text2path(outfit_data["internals_slot"])
var/list/backpack = outfit_data["backpack_contents"]
backpack_contents = list()
for(var/item in backpack)
var/itype = text2path(item)
if(itype)
backpack_contents[itype] = backpack[item]
box = text2path(outfit_data["box"])
var/list/impl = outfit_data["implants"]
implants = list()
for(var/I in impl)
var/imptype = text2path(I)
if(imptype)
implants += imptype
var/list/cybernetic_impl = outfit_data["cybernetic_implants"]
cybernetic_implants = list()
for(var/I in cybernetic_impl)
var/cybtype = text2path(I)
if(cybtype)
cybernetic_implants += cybtype
var/list/accessories = outfit_data["accessories"]
accessories = list()
for(var/A in accessories)
var/accessorytype = text2path(A)
if(accessorytype)
accessories += accessorytype
return TRUE
/datum/outfit/proc/get_json_data()
. = list()
.["outfit_type"] = type
.["name"] = name
.["uniform"] = uniform
.["suit"] = suit
.["toggle_helmet"] = toggle_helmet
.["back"] = back
.["belt"] = belt
.["gloves"] = gloves
.["shoes"] = shoes
.["head"] = head
.["mask"] = mask
.["l_ear"] = l_ear
.["r_ear"] = r_ear
.["glasses"] = glasses
.["id"] = id
.["pda"] = pda
.["l_pocket"] = l_pocket
.["r_pocket"] = r_pocket
.["suit_store"] = suit_store
.["r_hand"] = r_hand
.["l_hand"] = l_hand
.["internals_slot"] = internals_slot
.["backpack_contents"] = backpack_contents
.["box"] = box
.["implants"] = implants
.["cybernetic_implants"] = cybernetic_implants
.["accessories"] = accessories

View File

@@ -78,7 +78,6 @@
suit = /obj/item/clothing/suit/space/hardsuit/syndi
belt = /obj/item/storage/belt/military
head = /obj/item/clothing/head/helmet/space/hardsuit/syndi
mask = /obj/item/clothing/mask/gas/syndicate
l_ear = /obj/item/radio/headset/syndicate/alt
glasses = /obj/item/clothing/glasses/night
@@ -110,7 +109,6 @@
/datum/outfit/admin/syndicate/operative/freedom
name = "Syndicate Freedom Operative"
suit = /obj/item/clothing/suit/space/hardsuit/syndi/freedom
head = /obj/item/clothing/head/helmet/space/hardsuit/syndi/freedom
/datum/outfit/admin/syndicate_strike_team
@@ -794,41 +792,34 @@
/datum/outfit/admin/hardsuit/engineer
name = "Engineer Hardsuit"
suit = /obj/item/clothing/suit/space/hardsuit
head = /obj/item/clothing/head/helmet/space/hardsuit
suit = /obj/item/clothing/suit/space/hardsuit/engine
/datum/outfit/admin/hardsuit/ce
name = "CE Hardsuit"
suit = /obj/item/clothing/suit/space/hardsuit/elite
head = /obj/item/clothing/head/helmet/space/hardsuit/elite
suit = /obj/item/clothing/suit/space/hardsuit/engine/elite
shoes = /obj/item/clothing/shoes/magboots/advance
/datum/outfit/admin/hardsuit/mining
name = "Mining Hardsuit"
suit = /obj/item/clothing/suit/space/hardsuit/mining
head = /obj/item/clothing/head/helmet/space/hardsuit/mining
/datum/outfit/admin/hardsuit/syndi
name = "Syndi Hardsuit"
suit = /obj/item/clothing/suit/space/hardsuit/syndi
head = /obj/item/clothing/head/helmet/space/hardsuit/syndi
shoes = /obj/item/clothing/shoes/magboots/syndie
/datum/outfit/admin/hardsuit/wizard
name = "Wizard Hardsuit"
suit = /obj/item/clothing/suit/space/hardsuit/wizard
head = /obj/item/clothing/head/helmet/space/hardsuit/wizard
shoes = /obj/item/clothing/shoes/magboots
/datum/outfit/admin/hardsuit/medical
name = "Medical Hardsuit"
suit = /obj/item/clothing/suit/space/hardsuit/medical
head = /obj/item/clothing/head/helmet/space/hardsuit/medical
/datum/outfit/admin/hardsuit/atmos
name = "Atmos Hardsuit"
suit = /obj/item/clothing/suit/space/hardsuit/atmos
head = /obj/item/clothing/head/helmet/space/hardsuit/atmos
suit = /obj/item/clothing/suit/space/hardsuit/engine/atmos
/datum/outfit/admin/tournament
@@ -963,7 +954,6 @@
belt = /obj/item/claymore/ceremonial
gloves = /obj/item/clothing/gloves/combat
shoes = /obj/item/clothing/shoes/magboots
head = /obj/item/clothing/head/helmet/space/hardsuit/singuloth
mask = /obj/item/clothing/mask/breath
l_ear = /obj/item/radio/headset/ert
glasses = /obj/item/clothing/glasses/meson/cyber
@@ -1111,7 +1101,6 @@
backpack_contents = list(
/obj/item/storage/box/engineer = 1,
/obj/item/clothing/suit/space/hardsuit/wizard = 1,
/obj/item/clothing/head/helmet/space/hardsuit/wizard = 1,
/obj/item/clothing/shoes/magboots = 1,
/obj/item/kitchen/knife/ritual = 1,
/obj/item/clothing/suit/wizrobe/red = 1,

View File

@@ -0,0 +1,178 @@
/datum/outfit/plasmaman
name = "Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman
uniform = /obj/item/clothing/under/plasmaman
r_hand = /obj/item/tank/plasma/plasmaman/belt/full
mask = /obj/item/clothing/mask/breath
/datum/outfit/plasmaman/bar
name = "Bartender Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/white
uniform = /obj/item/clothing/under/plasmaman/enviroslacks
/datum/outfit/plasmaman/chef
name = "Chef Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/chef
uniform = /obj/item/clothing/under/plasmaman/chef
/datum/outfit/plasmaman/botany
name = "Botany Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/botany
uniform = /obj/item/clothing/under/plasmaman/botany
/datum/outfit/plasmaman/librarian
name = "Librarian Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/librarian
uniform = /obj/item/clothing/under/plasmaman/librarian
/datum/outfit/plasmaman/chaplain
name = "Chaplain Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/chaplain
uniform = /obj/item/clothing/under/plasmaman/chaplain
/datum/outfit/plasmaman/janitor
name = "Janitor Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/janitor
uniform = /obj/item/clothing/under/plasmaman/janitor
/datum/outfit/plasmaman/security
name = "Security Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/security
uniform = /obj/item/clothing/under/plasmaman/security
/datum/outfit/plasmaman/detective
name = "Detective Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/white
uniform = /obj/item/clothing/under/plasmaman/enviroslacks
l_ear = /obj/item/radio/headset/headset_sec
/datum/outfit/plasmaman/warden
name = "Warden Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/security/warden
uniform = /obj/item/clothing/under/plasmaman/security/warden
/datum/outfit/plasmaman/hos
name = "Head of Security Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/security/hos
uniform = /obj/item/clothing/under/plasmaman/security/hos
/datum/outfit/plasmaman/cargo
name = "Cargo Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/cargo
uniform = /obj/item/clothing/under/plasmaman/cargo
/datum/outfit/plasmaman/mining
name = "Mining Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/mining
uniform = /obj/item/clothing/under/plasmaman/mining
/datum/outfit/plasmaman/medical
name = "Medical Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/medical
uniform = /obj/item/clothing/under/plasmaman/medical
/datum/outfit/plasmaman/cmo
name = "Chief Medical Officer Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/cmo
uniform = /obj/item/clothing/under/plasmaman/cmo
/datum/outfit/plasmaman/viro
name = "Virology Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/viro
uniform = /obj/item/clothing/under/plasmaman/viro
/datum/outfit/plasmaman/chemist
name = "Chemist Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/chemist
uniform = /obj/item/clothing/under/plasmaman/chemist
/datum/outfit/plasmaman/genetics
name = "Genetics Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/genetics
uniform = /obj/item/clothing/under/plasmaman/genetics
/datum/outfit/plasmaman/science
name = "Science Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/science
uniform = /obj/item/clothing/under/plasmaman/science
/datum/outfit/plasmaman/rd
name = "Research Director Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/rd
uniform = /obj/item/clothing/under/plasmaman/rd
/datum/outfit/plasmaman/robotics
name = "Robotics Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/robotics
uniform = /obj/item/clothing/under/plasmaman/robotics
/datum/outfit/plasmaman/engineering
name = "Engineering Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/engineering
uniform = /obj/item/clothing/under/plasmaman/engineering
/datum/outfit/plasmaman/ce
name = "Chief Engineer Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/engineering/ce
uniform = /obj/item/clothing/under/plasmaman/engineering/ce
/datum/outfit/plasmaman/atmospherics
name = "Atmospherics Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/atmospherics
uniform = /obj/item/clothing/under/plasmaman/atmospherics
/datum/outfit/plasmaman/mime
name = "Plasmamime"
head = /obj/item/clothing/head/helmet/space/plasmaman/mime
uniform = /obj/item/clothing/under/plasmaman/mime
mask = /obj/item/clothing/mask/gas/mime
/datum/outfit/plasmaman/clown
name = "Plasmaclown"
head = /obj/item/clothing/head/helmet/space/plasmaman/clown
uniform = /obj/item/clothing/under/plasmaman/clown
mask = /obj/item/clothing/mask/gas/clown_hat
/datum/outfit/plasmaman/hop
name = "Head of Personnel Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/hop
uniform = /obj/item/clothing/under/plasmaman/hop
/datum/outfit/plasmaman/captain
name = "Captain Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/captain
uniform = /obj/item/clothing/under/plasmaman/captain
/datum/outfit/plasmaman/blueshield
name = "Blueshield Plasmaman"
head = /obj/item/clothing/head/helmet/space/plasmaman/blueshield
uniform = /obj/item/clothing/under/plasmaman/blueshield

View File

@@ -0,0 +1,190 @@
// This outfit preserves varedits made on the items
// Created from admin helpers.
/datum/outfit/varedit
var/list/vv_values
var/list/stored_access
var/update_id_name = FALSE //If the name of the human is same as the name on the id they're wearing we'll update provided id when equipping
/datum/outfit/varedit/pre_equip(mob/living/carbon/human/H, visualsOnly)
H.delete_equipment() //Applying VV to wrong objects is not reccomended.
. = ..()
/datum/outfit/varedit/proc/set_equipment_by_slot(slot, item_path)
switch(slot)
if(slot_w_uniform)
uniform = item_path
if(slot_back)
back = item_path
if(slot_wear_suit)
suit = item_path
if(slot_belt)
belt = item_path
if(slot_gloves)
gloves = item_path
if(slot_shoes)
shoes = item_path
if(slot_head)
head = item_path
if(slot_wear_mask)
mask = item_path
if(slot_l_ear)
l_ear = item_path
if(slot_r_ear)
r_ear = item_path
if(slot_glasses)
glasses = item_path
if(slot_wear_id)
id = item_path
if(slot_wear_pda)
pda = item_path
if(slot_s_store)
suit_store = item_path
if(slot_l_store)
l_pocket = item_path
if(slot_r_store)
r_pocket = item_path
/proc/collect_vv(obj/item/I)
//Temporary/Internal stuff, do not copy these.
var/static/list/ignored_vars = list("vars","x","y","z","plane","layer","override","animate_movement","pixel_step_size","screen_loc","fingerprintslast","tip_timer")
if(istype(I))
var/list/vedits = list()
for(var/varname in I.vars)
if(!I.can_vv_get(varname))
continue
if(varname in ignored_vars)
continue
var/vval = I.vars[varname]
//Does it even work ?
if(vval == initial(I.vars[varname]))
continue
//Only text/numbers and icons variables to make it less weirdness prone.
if(!istext(vval) && !isnum(vval) && !isicon(vval))
continue
vedits[varname] = I.vars[varname]
return vedits
/mob/living/carbon/human/proc/copy_outfit()
var/datum/outfit/varedit/O = new
//Copy equipment
var/list/result = list()
var/list/slots_to_check = list(slot_w_uniform, slot_back, slot_wear_suit, slot_belt, slot_gloves, slot_shoes, slot_head, slot_wear_mask, slot_l_ear, slot_r_ear, slot_glasses, slot_wear_id, slot_wear_pda, slot_s_store, slot_l_store, slot_r_store)
for(var/s in slots_to_check)
var/obj/item/I = get_item_by_slot(s)
var/vedits = collect_vv(I)
if(vedits)
result["[s]"] = vedits
if(istype(I))
O.set_equipment_by_slot(s, I.type)
//Copy access
O.stored_access = list()
var/obj/item/id_slot = get_item_by_slot(slot_wear_id)
if(id_slot)
O.stored_access |= id_slot.GetAccess()
var/obj/item/card/id/ID = id_slot.GetID()
if(ID && ID.registered_name == real_name)
O.update_id_name = TRUE
//Copy hands
if(l_hand || r_hand) //Not in the mood to let outfits transfer amputees
var/obj/item/left_hand = l_hand
var/obj/item/right_hand = r_hand
if(istype(left_hand))
O.l_hand = left_hand.type
var/vedits = collect_vv(left_hand)
if(vedits)
result["LHAND"] = vedits
if(istype(right_hand))
O.r_hand = right_hand.type
var/vedits = collect_vv(left_hand)
if(vedits)
result["RHAND"] = vedits
O.vv_values = result
//Copy backpack contents if exist.
var/obj/item/backpack = get_item_by_slot(slot_back)
if(istype(backpack) && LAZYLEN(backpack.contents) > 0)
var/list/typecounts = list()
for(var/obj/item/I in backpack)
if(typecounts[I.type])
typecounts[I.type] += 1
else
typecounts[I.type] = 1
O.backpack_contents = typecounts
//TODO : Copy varedits from backpack stuff too.
//Copy implants
O.implants = list()
for(var/obj/item/implant/I in contents)
if(istype(I))
O.implants |= I.type
// Copy cybernetic implants
O.cybernetic_implants = list()
for(var/obj/item/organ/internal/CI in contents)
if(istype(CI))
O.cybernetic_implants |= CI.type
// Copy accessories
var/obj/item/clothing/under/uniform_slot = get_item_by_slot(slot_w_uniform)
if(uniform_slot)
O.accessories = list()
for(var/obj/item/clothing/accessory/A in uniform_slot.accessories)
if(istype(A))
O.accessories |= A
//Copy to outfit cache
var/outfit_name = stripped_input(usr, "Enter the outfit name")
O.name = outfit_name
GLOB.custom_outfits += O
to_chat(usr, "Outfit registered, use select equipment to equip it.")
/datum/outfit/varedit/post_equip(mob/living/carbon/human/H, visualsOnly)
. = ..()
//Apply VV
for(var/slot in vv_values)
var/list/edits = vv_values[slot]
var/obj/item/I
switch(slot)
if("LHAND")
I = H.l_hand
if("RHAND")
I = H.r_hand
else
I = H.get_item_by_slot(text2num(slot))
for(var/vname in edits)
I.vv_edit_var(vname,edits[vname])
//Apply access
var/obj/item/id_slot = H.get_item_by_slot(slot_wear_id)
if(id_slot)
var/obj/item/card/id/card = id_slot.GetID()
if(istype(card))
card.access |= stored_access
if(update_id_name)
card.registered_name = H.real_name
card.update_label()
/datum/outfit/varedit/get_json_data()
. = .. ()
.["stored_access"] = stored_access
.["update_id_name"] = update_id_name
var/list/stripped_vv = list()
for(var/slot in vv_values)
var/list/vedits = vv_values[slot]
var/list/stripped_edits = list()
for(var/edit in vedits)
if(istext(vedits[edit]) || isnum(vedits[edit]) || isnull(vedits[edit]))
stripped_edits[edit] = vedits[edit]
if(stripped_edits.len)
stripped_vv[slot] = stripped_edits
.["vv_values"] = stripped_vv
/datum/outfit/varedit/load_from(list/outfit_data)
. = ..()
stored_access = outfit_data["stored_access"]
vv_values = outfit_data["vv_values"]
update_id_name = outfit_data["update_id_name"]

View File

@@ -36,7 +36,7 @@
return
var/obj/item/clothing/mask/horsehead/magichead = new /obj/item/clothing/mask/horsehead
magichead.flags |= NODROP //curses!
magichead.flags |= NODROP | DROPDEL //curses!
magichead.flags_inv = null //so you can still see their face
magichead.voicechange = 1 //NEEEEIIGHH
target.visible_message( "<span class='danger'>[target]'s face lights up in fire, and after the event a horse's head takes its place!</span>", \

View File

@@ -40,6 +40,132 @@
playsound(owner, 'sound/weapons/bite.ogg', 50, 1)
owner.adjustBruteLoss(3)
/datum/status_effect/blooddrunk
id = "blooddrunk"
duration = 10
tick_interval = 0
alert_type = /obj/screen/alert/status_effect/blooddrunk
var/last_health = 0
var/last_bruteloss = 0
var/last_fireloss = 0
var/last_toxloss = 0
var/last_oxyloss = 0
var/last_cloneloss = 0
var/last_staminaloss = 0
/obj/screen/alert/status_effect/blooddrunk
name = "Blood-Drunk"
desc = "You are drunk on blood! Your pulse thunders in your ears! Nothing can harm you!" //not true, and the item description mentions its actual effect
icon_state = "blooddrunk"
/datum/status_effect/blooddrunk/on_apply()
. = ..()
if(.)
owner.maxHealth *= 10
owner.bruteloss *= 10
owner.fireloss *= 10
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
for(var/X in H.bodyparts)
var/obj/item/organ/external/BP = X
BP.max_damage *= 10
BP.min_broken_damage *= 10
BP.brute_dam *= 10
BP.burn_dam *= 10
owner.toxloss *= 10
owner.oxyloss *= 10
owner.cloneloss *= 10
owner.staminaloss *= 10
owner.updatehealth()
last_health = owner.health
last_bruteloss = owner.getBruteLoss()
last_fireloss = owner.getFireLoss()
last_toxloss = owner.getToxLoss()
last_oxyloss = owner.getOxyLoss()
last_cloneloss = owner.getCloneLoss()
last_staminaloss = owner.getStaminaLoss()
add_attack_logs(owner, owner, "gained blood-drunk stun immunity")
var/status = CANSTUN | CANWEAKEN | CANPARALYSE | IGNORESLOWDOWN
owner.status_flags &= ~status
owner.playsound_local(get_turf(owner), 'sound/effects/singlebeat.ogg', 40, 1)
/datum/status_effect/blooddrunk/tick() //multiply the effect of healing by 10
if(owner.health > last_health)
var/needs_health_update = FALSE
var/new_bruteloss = owner.getBruteLoss()
if(new_bruteloss < last_bruteloss)
var/heal_amount = (new_bruteloss - last_bruteloss) * 10
owner.adjustBruteLoss(heal_amount, updating_health = FALSE)
new_bruteloss = owner.getBruteLoss()
needs_health_update = TRUE
last_bruteloss = new_bruteloss
var/new_fireloss = owner.getFireLoss()
if(new_fireloss < last_fireloss)
var/heal_amount = (new_fireloss - last_fireloss) * 10
owner.adjustFireLoss(heal_amount, updating_health = FALSE)
new_fireloss = owner.getFireLoss()
needs_health_update = TRUE
last_fireloss = new_fireloss
var/new_toxloss = owner.getToxLoss()
if(new_toxloss < last_toxloss)
var/heal_amount = (new_toxloss - last_toxloss) * 10
owner.adjustToxLoss(heal_amount, updating_health = FALSE)
new_toxloss = owner.getToxLoss()
needs_health_update = TRUE
last_toxloss = new_toxloss
var/new_oxyloss = owner.getOxyLoss()
if(new_oxyloss < last_oxyloss)
var/heal_amount = (new_oxyloss - last_oxyloss) * 10
owner.adjustOxyLoss(heal_amount, updating_health = FALSE)
new_oxyloss = owner.getOxyLoss()
needs_health_update = TRUE
last_oxyloss = new_oxyloss
var/new_cloneloss = owner.getCloneLoss()
if(new_cloneloss < last_cloneloss)
var/heal_amount = (new_cloneloss - last_cloneloss) * 10
owner.adjustCloneLoss(heal_amount, updating_health = FALSE)
new_cloneloss = owner.getCloneLoss()
needs_health_update = TRUE
last_cloneloss = new_cloneloss
var/new_staminaloss = owner.getStaminaLoss()
if(new_staminaloss < last_staminaloss)
var/heal_amount = (new_staminaloss - last_staminaloss) * 10
owner.adjustStaminaLoss(heal_amount, updating_health = FALSE)
new_staminaloss = owner.getStaminaLoss()
needs_health_update = TRUE
last_staminaloss = new_staminaloss
if(needs_health_update)
owner.updatehealth()
owner.playsound_local(get_turf(owner), 'sound/effects/singlebeat.ogg', 40, 1)
last_health = owner.health
/datum/status_effect/blooddrunk/on_remove()
tick()
owner.maxHealth *= 0.1
owner.bruteloss *= 0.1
owner.fireloss *= 0.1
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
for(var/X in H.bodyparts)
var/obj/item/organ/external/BP = X
BP.brute_dam *= 0.1
BP.burn_dam *= 0.1
BP.max_damage /= 10
BP.min_broken_damage /= 10
owner.toxloss *= 0.1
owner.oxyloss *= 0.1
owner.cloneloss *= 0.1
owner.staminaloss *= 0.1
owner.updatehealth()
add_attack_logs(owner, owner, "lost blood-drunk stun immunity")
owner.status_flags |= CANSTUN | CANWEAKEN | CANPARALYSE | IGNORESLOWDOWN
/datum/status_effect/exercised
id = "Exercised"
duration = 1200

View File

@@ -9,6 +9,39 @@
if(owner.reagents)
owner.reagents.del_reagent("holywater") //can't be deconverted
/datum/status_effect/crusher_mark
id = "crusher_mark"
duration = 300 //if you leave for 30 seconds you lose the mark, deal with it
status_type = STATUS_EFFECT_REPLACE
alert_type = null
var/mutable_appearance/marked_underlay
var/obj/item/twohanded/kinetic_crusher/hammer_synced
/datum/status_effect/crusher_mark/on_creation(mob/living/new_owner, obj/item/twohanded/kinetic_crusher/new_hammer_synced)
. = ..()
if(.)
hammer_synced = new_hammer_synced
/datum/status_effect/crusher_mark/on_apply()
if(owner.mob_size >= MOB_SIZE_LARGE)
marked_underlay = mutable_appearance('icons/effects/effects.dmi', "shield2")
marked_underlay.pixel_x = -owner.pixel_x
marked_underlay.pixel_y = -owner.pixel_y
owner.underlays += marked_underlay
return TRUE
return FALSE
/datum/status_effect/crusher_mark/Destroy()
hammer_synced = null
if(owner)
owner.underlays -= marked_underlay
QDEL_NULL(marked_underlay)
return ..()
/datum/status_effect/crusher_mark/be_replaced()
owner.underlays -= marked_underlay //if this is being called, we should have an owner at this point.
..()
/datum/status_effect/saw_bleed
id = "saw_bleed"
duration = -1 //removed under specific conditions

View File

@@ -1,5 +1,43 @@
//entirely neutral or internal status effects go here
/datum/status_effect/crusher_damage //tracks the damage dealt to this mob by kinetic crushers
id = "crusher_damage"
duration = -1
status_type = STATUS_EFFECT_UNIQUE
alert_type = null
var/total_damage = 0
/datum/status_effect/syphon_mark
id = "syphon_mark"
duration = 50
status_type = STATUS_EFFECT_MULTIPLE
alert_type = null
on_remove_on_mob_delete = TRUE
var/obj/item/borg/upgrade/modkit/bounty/reward_target
/datum/status_effect/syphon_mark/on_creation(mob/living/new_owner, obj/item/borg/upgrade/modkit/bounty/new_reward_target)
. = ..()
if(.)
reward_target = new_reward_target
/datum/status_effect/syphon_mark/on_apply()
if(owner.stat == DEAD)
return FALSE
return ..()
/datum/status_effect/syphon_mark/proc/get_kill()
if(!QDELETED(reward_target))
reward_target.get_kill(owner)
/datum/status_effect/syphon_mark/tick()
if(owner.stat == DEAD)
get_kill()
qdel(src)
/datum/status_effect/syphon_mark/on_remove()
get_kill()
. = ..()
/datum/status_effect/high_five
id = "high_five"
duration = 40

View File

@@ -160,12 +160,16 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
containername = "vox life support supplies crate"
/datum/supply_packs/emergency/plasmamansupport
name = "Plasmaman Life Support Supplies"
contains = list(/obj/item/clothing/mask/breath,
/obj/item/tank/emergency_oxygen/plasma,
/obj/item/clothing/suit/space/eva/plasmaman,
/obj/item/clothing/head/helmet/space/eva/plasmaman)
cost = 75
name = "Plasmaman Supply Kit"
contains = list(/obj/item/clothing/under/plasmaman,
/obj/item/clothing/under/plasmaman,
/obj/item/tank/plasma/plasmaman/belt/full,
/obj/item/tank/plasma/plasmaman/belt/full,
/obj/item/clothing/mask/breath,
/obj/item/clothing/mask/breath,
/obj/item/clothing/head/helmet/space/plasmaman,
/obj/item/clothing/head/helmet/space/plasmaman)
cost = 20
containertype = /obj/structure/closet/crate/secure/plasma
containername = "plasmaman life support supplies crate"
access = access_eva

View File

@@ -207,6 +207,14 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 10
job = list("Mime")
/datum/uplink_item/jobspecific/pressure_mod
name = "Kinetic Accelerator Pressure Mod"
desc = "A modification kit which allows Kinetic Accelerators to do greatly increased damage while indoors. Occupies 35% mod capacity."
reference = "KPM"
item = /obj/item/borg/upgrade/modkit/indoors
cost = 5 //you need two for full damage, so total of 10 for maximum damage
job = list("Shaft Miner")
//Chef
/datum/uplink_item/jobspecific/specialsauce
name = "Chef Excellence's Special Sauce"
@@ -892,6 +900,13 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 3
surplus = 10
/datum/uplink_item/stealthy_weapons/false_briefcase
name = "False Bottomed Briefcase"
desc = "A modified briefcase capable of storing and firing a gun under a false bottom. Use a screwdriver to pry away the false bottom and make modifications. Distinguishable upon close examination due to the added weight."
reference = "FBBC"
item = /obj/item/storage/briefcase/false_bottomed
cost = 3
/datum/uplink_item/stealthy_weapons/soap
name = "Syndicate Soap"
desc = "A sinister-looking surfactant used to clean blood stains to hide murders and prevent DNA analysis. You can also drop it underfoot to slip people."
@@ -1107,10 +1122,10 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 2
/datum/uplink_item/stealthy_tools/thermal
name = "Thermal Imaging Glasses"
desc = "These glasses are thermals disguised as engineers' optical meson scanners. They allow you to see organisms through walls by capturing the upper portion of the infra-red light spectrum, emitted as heat and light by objects. Hotter objects, such as warm bodies, cybernetic organisms and artificial intelligence cores emit more of this light than cooler objects like walls and airlocks."
name = "Thermal Chameleon Glasses"
desc = "These glasses are thermals with Syndicate chameleon technology built into them. They allow you to see organisms through walls by capturing the upper portion of the infra-red light spectrum, emitted as heat and light by objects. Hotter objects, such as warm bodies, cybernetic organisms and artificial intelligence cores emit more of this light than cooler objects like walls and airlocks."
reference = "THIG"
item = /obj/item/clothing/glasses/thermal/syndi
item = /obj/item/clothing/glasses/chameleon/thermal
cost = 6
/datum/uplink_item/stealthy_tools/traitor_belt
@@ -1305,7 +1320,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/datum/uplink_item/suits/hardsuit/elite
name = "Elite Syndicate Hardsuit"
desc = "An advanced hardsuit with superior armor and mobility to the standard Syndicate Hardsuit."
item = /obj/item/storage/box/syndie_kit/elite_hardsuit
item = /obj/item/clothing/suit/space/hardsuit/syndi/elite
cost = 8
reference = "ESHS"
excludefrom = list()
@@ -1314,7 +1329,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/datum/uplink_item/suits/hardsuit/shielded
name = "Shielded Hardsuit"
desc = "An advanced hardsuit with built in energy shielding. The shields will rapidly recharge when not under fire."
item = /obj/item/storage/box/syndie_kit/shielded_hardsuit
item = /obj/item/clothing/suit/space/hardsuit/shielded/syndi
cost = 30
reference = "SHS"
excludefrom = list()

View File

@@ -100,9 +100,11 @@ var/list/ghostteleportlocs = list()
requires_power = FALSE
valid_territory = FALSE
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
parallax_movedir = NORTH
/area/shuttle/arrival
name = "\improper Arrival Shuttle"
parallax_movedir = EAST
/area/shuttle/arrival/pre_game
icon_state = "shuttle2"
@@ -136,12 +138,14 @@ var/list/ghostteleportlocs = list()
music = "music/escape.ogg"
icon_state = "shuttle"
nad_allowed = TRUE
parallax_movedir = EAST
/area/shuttle/pod_4
name = "\improper Escape Pod Four"
music = "music/escape.ogg"
icon_state = "shuttle"
nad_allowed = TRUE
parallax_movedir = EAST
/area/shuttle/escape_pod1
name = "\improper Escape Pod One"
@@ -207,6 +211,7 @@ var/list/ghostteleportlocs = list()
/area/shuttle/transport
icon_state = "shuttle"
name = "\improper Transport Shuttle"
parallax_movedir = EAST
/area/shuttle/transport1
icon_state = "shuttle"
@@ -247,6 +252,7 @@ var/list/ghostteleportlocs = list()
/area/shuttle/specops
name = "\improper Special Ops Shuttle"
icon_state = "shuttlered"
parallax_movedir = EAST
/area/shuttle/specops/centcom
name = "\improper Special Ops Shuttle"
@@ -260,6 +266,7 @@ var/list/ghostteleportlocs = list()
name = "\improper Syndicate Elite Shuttle"
icon_state = "shuttlered"
nad_allowed = TRUE
parallax_movedir = SOUTH
/area/shuttle/syndicate_elite/mothership
name = "\improper Syndicate Elite Shuttle"
@@ -273,6 +280,7 @@ var/list/ghostteleportlocs = list()
name = "\improper Syndicate SIT Shuttle"
icon_state = "shuttlered"
nad_allowed = TRUE
parallax_movedir = SOUTH
/area/shuttle/assault_pod
name = "Steel Rain"
@@ -281,6 +289,7 @@ var/list/ghostteleportlocs = list()
/area/shuttle/administration
name = "\improper Nanotrasen Vessel"
icon_state = "shuttlered"
parallax_movedir = EAST
/area/shuttle/administration/centcom
name = "\improper Nanotrasen Vessel Centcom"
@@ -380,6 +389,7 @@ var/list/ghostteleportlocs = list()
/area/shuttle/salvage/abandoned_ship
name = "\improper Abandoned Ship"
icon_state = "yellow"
parallax_movedir = WEST
/area/shuttle/salvage/clown_asteroid
name = "\improper Clown Asteroid"
@@ -412,6 +422,7 @@ var/list/ghostteleportlocs = list()
/area/shuttle/trade/sol
name = "Sol Freighter"
parallax_movedir = EAST
/area/shuttle/freegolem
name = "Free Golem Ship"
@@ -1859,6 +1870,7 @@ var/list/ghostteleportlocs = list()
/area/shuttle/constructionsite
name = "\improper Construction Site Shuttle"
icon_state = "yellow"
parallax_movedir = EAST
/area/shuttle/constructionsite/station
name = "\improper Construction Site Shuttle"

View File

@@ -67,6 +67,9 @@
var/can_get_auto_cryod = TRUE
var/hide_attacklogs = FALSE // For areas such as thunderdome, lavaland syndiebase, etc which generate a lot of spammy attacklogs. Reduces log priority.
var/parallax_movedir = 0
var/moving = FALSE
/area/Initialize(mapload)
GLOB.all_areas += src
icon_state = ""

View File

@@ -26,7 +26,7 @@
var/inertia_move_delay = 5
var/moving_diagonally = 0 //0: not doing a diagonal move. 1 and 2: doing the first/second step of the diagonal move
var/list/client_mobs_in_contents
var/area/areaMaster
/atom/movable/New()
@@ -215,6 +215,8 @@
if(!inertia_moving)
inertia_next_move = world.time + inertia_move_delay
newtonian_move(Dir)
if(length(client_mobs_in_contents))
update_parallax_contents()
return TRUE
// Previously known as HasEntered()

View File

@@ -163,10 +163,10 @@
icon_state = "blobbernaut"
icon_living = "blobbernaut"
icon_dead = "blobbernaut_dead"
health = 240
maxHealth = 240
melee_damage_lower = 20
melee_damage_upper = 20
health = 200
maxHealth = 200
melee_damage_lower = 10
melee_damage_upper = 15
obj_damage = 60
attacktext = "hits"
attack_sound = 'sound/effects/blobattack.ogg'
@@ -175,18 +175,48 @@
maxbodytemp = 360
force_threshold = 10
mob_size = MOB_SIZE_LARGE
environment_smash = ENVIRONMENT_SMASH_RWALLS
environment_smash = ENVIRONMENT_SMASH_STRUCTURES
pressure_resistance = 100 //100 kPa difference required to push
throw_pressure_limit = 120 //120 kPa difference required to throw
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
/mob/living/simple_animal/hostile/blob/blobbernaut/Life(seconds, times_fired)
if(stat != DEAD && (getBruteLoss() || getFireLoss())) // Heal on blob structures
if(locate(/obj/structure/blob) in get_turf(src))
adjustBruteLoss(-0.25)
adjustFireLoss(-0.25)
else
adjustBruteLoss(0.2) // If you are at full health, you won't lose health. You'll need it. However the moment anybody sneezes on you, the decaying will begin.
adjustFireLoss(0.2)
/mob/living/simple_animal/hostile/blob/blobbernaut/blob_act()
return
/mob/living/simple_animal/hostile/blob/blobbernaut/New()
..()
if(name == "blobbernaut")
name = text("blobbernaut ([rand(1, 1000)])")
/mob/living/simple_animal/hostile/blob/blobbernaut/death(gibbed)
// Only execute the below if we successfully died
. = ..()
if(!.)
return FALSE
flick("blobbernaut_death", src)
/mob/living/simple_animal/hostile/blob/blobbernaut/verb/communicate_overmind()
set category = "Blobbernaut"
set name = "Blob Telepathy"
set desc = "Send a message to the Overmind"
if(stat != DEAD)
blob_talk()
/mob/living/simple_animal/hostile/blob/blobbernaut/proc/blob_talk()
var/message = input(src, "Announce to the overmind", "Blob Telepathy")
var/rendered = "<font color=\"#EE4000\"><i><span class='game say'>Blob Telepathy, <span class='name'>[name]([overmind])</span> <span class='message'>states, \"[message]\"</span></span></i></font>"
if(message)
for(var/mob/M in GLOB.mob_list)
if(isovermind(M) || isobserver(M) || istype((M), /mob/living/simple_animal/hostile/blob/blobbernaut))
M.show_message(rendered, 2)

View File

@@ -84,7 +84,7 @@
var/rendered = "<font color=\"#EE4000\"><i><span class='game say'>Blob Telepathy, <span class='name'>[name]([blob_reagent_datum.name])</span> <span class='message'>[verb] \"[message]\"</span></span></i></font>"
for(var/mob/M in GLOB.mob_list)
if(isovermind(M) || isobserver(M))
if(isovermind(M) || isobserver(M) || istype((M), /mob/living/simple_animal/hostile/blob/blobbernaut))
M.show_message(rendered, 2)
/mob/camera/blob/emote(act, m_type = 1, message = null, force)

View File

@@ -25,7 +25,8 @@
if(blob_nodes.len)
var/list/nodes = list()
for(var/i = 1; i <= blob_nodes.len; i++)
nodes["Blob Node #[i]"] = blob_nodes[i]
var/obj/structure/blob/node/B = blob_nodes[i]
nodes["Blob Node #[i] ([get_location_name(B)])"] = B
var/node_name = input(src, "Choose a node to jump to.", "Node Jump") in nodes
var/obj/structure/blob/node/chosen_node = nodes[node_name]
if(chosen_node)
@@ -207,7 +208,7 @@
/mob/camera/blob/verb/create_blobbernaut()
set category = "Blob"
set name = "Create Blobbernaut (20)"
set name = "Create Blobbernaut (60)"
set desc = "Create a powerful blob-being, a Blobbernaut"
var/turf/T = get_turf(src)
@@ -224,7 +225,7 @@
to_chat(src, "Unable to use this blob, find a factory blob.")
return
if(!can_buy(20))
if(!can_buy(60))
return
var/mob/living/simple_animal/hostile/blob/blobbernaut/blobber = new /mob/living/simple_animal/hostile/blob/blobbernaut (get_turf(B))
@@ -233,6 +234,14 @@
blobber.color = blob_reagent_datum.complementary_color
blobber.overmind = src
blob_mobs.Add(blobber)
spawn()
var/list/candidates = pollCandidates("Do you want to play as a blobbernaut?", ROLE_BLOB, 1, 150)
if(candidates.len)
var/mob/C = pick(candidates)
if(C)
blobber.key = C.key
to_chat(blobber, "<span class='biggerdanger'>You are a blobbernaut! You must assist all blob lifeforms in their mission to consume everything!</span>")
to_chat(blobber, "<span class='danger'>You heal while standing on blob structures, however you will decay slowly if you are damaged outside of the blob.</span>")
return

View File

@@ -1,4 +1,4 @@
/datum/action/changeling/headcrab
/datum/action/changeling/headslug
name = "Last Resort"
desc = "We sacrifice our current body in a moment of need, placing us in control of a vessel that can plant our likeness in a new host. Costs 20 chemicals."
helptext = "We will be placed in control of a small, fragile creature. We may attack a corpse like this to plant an egg which will slowly mature into a new form for us."
@@ -7,12 +7,12 @@
dna_cost = 1
req_human = 1
/datum/action/changeling/headcrab/try_to_sting(mob/user, mob/target)
/datum/action/changeling/headslug/try_to_sting(mob/user, mob/target)
if(alert("Are you sure you wish to do this? This action cannot be undone.",,"Yes","No")=="No")
return
..()
/datum/action/changeling/headcrab/sting_action(mob/user)
/datum/action/changeling/headslug/sting_action(mob/user)
var/datum/mind/M = user.mind
var/list/organs = user.get_organs_zone("head", 1)
@@ -33,7 +33,7 @@
S.Weaken(3)
var/new_location = user.drop_location()
spawn(5) // So it's not killed in explosion
var/mob/living/simple_animal/hostile/headcrab/crab = new(new_location)
var/mob/living/simple_animal/hostile/headslug/crab = new(new_location)
for(var/obj/item/organ/internal/I in organs)
I.loc = crab
crab.origin = M

View File

@@ -29,7 +29,7 @@ var/global/list/all_cults = list()
return 1
/proc/is_sacrifice_target(datum/mind/mind)
if(istype(SSticker.mode.name, "cult"))
if(SSticker.mode.name == "cult")
var/datum/game_mode/cult/cult_mode = SSticker.mode
if(mind == cult_mode.sacrifice_target)
return 1

View File

@@ -344,21 +344,6 @@
else
to_chat(C, "<span class='danger'>The veil cannot be torn here!</span>")
/obj/item/clothing/suit/space/eva/plasmaman/cultist
name = "plasmaman cultist armor"
icon_state = "plasmaman_cult"
item_state = "plasmaman_cult"
desc = "A bulky suit of armour, menacing with red energy. It looks like it would fit a plasmaman."
slowdown = 1
armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30)
/obj/item/clothing/head/helmet/space/eva/plasmaman/cultist
name = "plasmaman cultist helmet"
icon_state = "plasmamanCult_helmet0"
base_state = "plasmamanCult_helmet"
desc = "A helmet designed by cultists. It glows menacingly with unearthly flames."
armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30)
/obj/item/melee/cultblade/ghost
name = "eldritch sword"
force = 15

View File

@@ -163,6 +163,16 @@
possible_sac_targets += player.mind
return possible_sac_targets
// Handles the updating of sacrifice objectives after the sacrifice target goes to cryo and ghosts
/datum/game_mode/cult/proc/update_sac_objective(previous_target, previous_role)
for(var/datum/mind/cult_mind in cult)
if(cult_mind)
var/updated_memory = cult_mind.memory
updated_memory = replacetext("[cult_mind.memory]", "[previous_target]", "[sacrifice_target]")
updated_memory = replacetext("[updated_memory]", "[previous_role]", "[sacrifice_target.assigned_role]")
cult_mind.memory = updated_memory
/datum/game_mode/cult/proc/pick_objective()
var/list/possible_objectives = list()

View File

@@ -1,4 +1,5 @@
/obj/item/paper/talisman
icon = 'icons/obj/paper.dmi'
icon_state = "paper_talisman"
var/cultist_name = "talisman"
var/cultist_desc = "A basic talisman. It serves no purpose."
@@ -7,6 +8,9 @@
var/uses = 1
var/health_cost = 0 //The amount of health taken from the user when invoking the talisman
/obj/item/paper/talisman/update_icon()//overriding this so the update_icon doesn't turn them into normal looking paper
SEND_SIGNAL(src, COMSIG_OBJ_UPDATE_ICON)
/obj/item/paper/talisman/examine(mob/user)
if(iscultist(user) || user.stat == DEAD)
to_chat(user, "<b>Name:</b> [cultist_name]")
@@ -49,6 +53,7 @@
//Supply Talisman: Has a few unique effects. Granted only to starter cultists.
/obj/item/paper/talisman/supply
cultist_name = "Supply Talisman"
icon_state = "supply"
cultist_desc = "A multi-use talisman that can create various objects. Intended to increase the cult's strength early on."
invocation = null
uses = 3
@@ -117,6 +122,7 @@
//Rite of Translocation: Same as rune
/obj/item/paper/talisman/teleport
cultist_name = "Talisman of Teleportation"
icon_state = "teleport"
cultist_desc = "A single-use talisman that will teleport a user to a random rune of the same keyword."
invocation = "Sas'so c'arta forbici!"
health_cost = 5
@@ -159,6 +165,7 @@
/obj/item/paper/talisman/summon_tome
cultist_name = "Talisman of Tome Summoning"
icon_state = "tome"
cultist_desc = "A one-use talisman that will call an untranslated tome from the archives of a cult."
invocation = "N'ath reth sh'yro eth d'raggathnor!"
health_cost = 1
@@ -173,6 +180,7 @@
/obj/item/paper/talisman/true_sight
cultist_name = "Talisman of Veiling"
icon_state = "veil"
cultist_desc = "A multi-use talisman that hides nearby runes. On its second use, will reveal nearby runes."
invocation = "Kla'atu barada nikt'o!"
health_cost = 1
@@ -197,6 +205,7 @@
//Rite of False Truths: Same as rune
/obj/item/paper/talisman/make_runes_fake
cultist_name = "Talisman of Disguising"
icon_state = "disguising"
cultist_desc = "A talisman that will make nearby runes appear fake."
invocation = "By'o nar'nar!"
@@ -212,6 +221,7 @@
//Rite of Disruption: Weaker than rune
/obj/item/paper/talisman/emp
cultist_name = "Talisman of Electromagnetic Pulse"
icon_state = "emp"
cultist_desc = "A talisman that will cause a moderately-sized electromagnetic pulse."
invocation = "Ta'gh fara'qha fel d'amar det!"
health_cost = 5
@@ -226,6 +236,7 @@
//Rite of Disorientation: Stuns and inhibit speech on a single target for quite some time
/obj/item/paper/talisman/stun
cultist_name = "Talisman of Stunning"
icon_state = "stunning"
cultist_desc = "A talisman that will stun and inhibit speech on a single target. To use, attack target directly."
invocation = "Dream sign:Evil sealing talisman!"
health_cost = 10
@@ -271,6 +282,7 @@
//Rite of Arming: Equips cultist armor on the user, where available
/obj/item/paper/talisman/armor
cultist_name = "Talisman of Arming"
icon_state = "arming"
cultist_desc = "A talisman that will equip the invoker with cultist equipment if there is a slot to equip it to."
invocation = "N'ath reth sh'yro eth draggathnor!"
@@ -279,11 +291,8 @@
var/mob/living/carbon/human/H = user
user.visible_message("<span class='warning'>Otherworldly armor suddenly appears on [user]!</span>", \
"<span class='cultitalic'>You speak the words of the talisman, arming yourself!</span>")
if(isplasmaman(H))
H.equip_to_slot(new /obj/item/clothing/suit/space/eva/plasmaman/cultist(H), slot_wear_suit)
H.equip_to_slot(new /obj/item/clothing/head/helmet/space/eva/plasmaman/cultist(H), slot_head)
else
H.equip_to_slot_or_del(new /obj/item/clothing/suit/hooded/cultrobes/alt(user), slot_wear_suit)
H.equip_to_slot_or_del(new /obj/item/clothing/suit/hooded/cultrobes/alt(user), slot_wear_suit)
H.equip_to_slot_or_del(new /obj/item/storage/backpack/cultpack(user), slot_back)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/cult(user), slot_shoes)
H.put_in_hands(new /obj/item/melee/cultblade(user))
@@ -301,6 +310,7 @@
//Talisman of Horrors: Breaks the mind of the victim with nightmarish hallucinations
/obj/item/paper/talisman/horror
cultist_name = "Talisman of Horrors"
icon_state = "horror"
cultist_desc = "A talisman that will break the mind of the victim with nightmarish hallucinations."
invocation = "Lo'Nab Na'Dm!"
@@ -316,6 +326,7 @@
//Talisman of Fabrication: Creates a construct shell out of 25 metal sheets.
/obj/item/paper/talisman/construction
cultist_name = "Talisman of Construction"
icon_state = "construction"
cultist_desc = "Use this talisman on at least twenty-five metal sheets to create an empty construct shell or on plasteel to make runed metal"
invocation = "Ethra p'ni dedol!"
uses = 25
@@ -360,6 +371,7 @@
//Talisman of Shackling: Applies special cuffs directly from the talisman
/obj/item/paper/talisman/shackle
cultist_name = "Talisman of Shackling"
icon_state = "shackling"
cultist_desc = "Use this talisman on a victim to handcuff them with dark bindings."
invocation = "In'totum Lig'abis!"
uses = 4

View File

@@ -291,11 +291,9 @@ proc/issyndicate(mob/living/M as mob)
if("Plasmaman")
synd_mob.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/syndicate(synd_mob), slot_wear_mask)
synd_mob.equip_to_slot(new /obj/item/clothing/suit/space/eva/plasmaman/nuclear(synd_mob), slot_wear_suit)
synd_mob.equip_to_slot(new /obj/item/clothing/head/helmet/space/eva/plasmaman/nuclear(synd_mob), slot_head)
synd_mob.equip_or_collect(new /obj/item/tank/plasma/plasmaman(synd_mob), slot_s_store)
synd_mob.equip_or_collect(new /obj/item/plasmensuit_cartridge(synd_mob), slot_in_backpack)
synd_mob.equip_or_collect(new /obj/item/plasmensuit_cartridge(synd_mob), slot_in_backpack)
synd_mob.equip_or_collect(new /obj/item/extinguisher_refill(synd_mob), slot_in_backpack)
synd_mob.equip_or_collect(new /obj/item/extinguisher_refill(synd_mob), slot_in_backpack)
synd_mob.internal = synd_mob.get_item_by_slot(slot_s_store)
synd_mob.update_action_buttons_icon()

View File

@@ -76,14 +76,19 @@ var/bomb_set
if(panel_open && (istype(O, /obj/item/multitool) || istype(O, /obj/item/wirecutters)))
return attack_hand(user)
if(extended)
if(istype(O, /obj/item/disk/nuclear))
usr.drop_item()
O.loc = src
if(istype(O, /obj/item/disk/nuclear))
if(extended)
if(!user.drop_item())
to_chat(user, "<span class='notice'>\The [O] is stuck to your hand!</span>")
return
O.forceMove(src)
auth = O
add_fingerprint(user)
return attack_hand(user)
else
to_chat(user, "<span class='notice'>You need to deploy \the [src] first. Right click on the sprite, select 'Make Deployable' then click on \the [src] with an empty hand.</span>")
return
if(anchored)
switch(removal_stage)

View File

@@ -297,23 +297,23 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
to_chat(owner, "<span class='warning'>They've got no blood left to give.</span>")
break
if(H.stat < DEAD)
if(!issmall(H) || H.ckey)
if(H.ckey || H.player_ghosted) //Requires ckey regardless if monkey or humanoid, or the body has been ghosted before it died
blood = min(20, H.blood_volume) // if they have less than 20 blood, give them the remnant else they get 20 blood
bloodtotal += blood / 2 //divide by 2 to counted the double suction since removing cloneloss -Melandor0
bloodusable += blood / 2
else
if(!issmall(H) || H.ckey)
if(H.ckey || H.player_ghosted)
blood = min(5, H.blood_volume) // The dead only give 5 blood
bloodtotal += blood
if(old_bloodtotal != bloodtotal)
if(!issmall(H) || H.ckey) // not small OR has a ckey, monkeys with ckeys can be sucked, humanized monkeys can be sucked monkeys without ckeys cannot be sucked
if(H.ckey || H.player_ghosted) // Requires ckey regardless if monkey or human, and has not ghosted, otherwise no power
to_chat(owner, "<span class='notice'><b>You have accumulated [bloodtotal] [bloodtotal > 1 ? "units" : "unit"] of blood[bloodusable != old_bloodusable ? ", and have [bloodusable] left to use" : ""].</b></span>")
check_vampire_upgrade()
H.blood_volume = max(H.blood_volume - 25, 0)
if(ishuman(owner))
var/mob/living/carbon/human/V = owner
if(issmall(H) && !H.ckey)
to_chat(V, "<span class='notice'><b>Feeding on [H] reduces your hunger, but you get no usable blood from it.</b></span>")
if(!H.ckey && !H.player_ghosted)//Only runs if there is no ckey and the body has not being ghosted while alive
to_chat(V, "<span class='notice'><b>Feeding on [H] reduces your thirst, but you get no usable blood from them.</b></span>")
V.nutrition = min(NUTRITION_LEVEL_WELL_FED, V.nutrition + 5)
else
V.nutrition = min(NUTRITION_LEVEL_WELL_FED, V.nutrition + (blood / 2))
@@ -402,7 +402,14 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
if(T.density)
return
vamp_burn(1)
if(bloodusable >= 10) //burn through your blood to tank the light for a little while
to_chat(owner, "<span class='warning'>The starlight saps your strength!</span>")
bloodusable -= 10
vamp_burn(10)
else //You're in trouble, get out of the sun NOW
to_chat(owner, "<span class='userdanger'>Your body is turning to ash, get out of the light now!</span>")
owner.adjustCloneLoss(10) //I'm melting!
vamp_burn(85)
/datum/vampire/proc/handle_vampire()
if(owner.hud_used)
@@ -419,7 +426,7 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
if(istype(owner.loc, /turf/space))
check_sun()
if(istype(owner.loc.loc, /area/chapel) && !get_ability(/datum/vampire_passive/full))
vamp_burn(0)
vamp_burn(7)
nullified = max(0, nullified - 1)
/datum/vampire/proc/handle_vampire_cloak()
@@ -442,8 +449,7 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
else
owner.alpha = round((255 * 0.80))
/datum/vampire/proc/vamp_burn(severe_burn)
var/burn_chance = severe_burn ? 35 : 8
/datum/vampire/proc/vamp_burn(burn_chance)
if(prob(burn_chance) && owner.health >= 50)
switch(owner.health)
if(75 to 100)

View File

@@ -139,7 +139,6 @@
new /obj/item/gun/magic/staff/door(get_turf(H))
if("armor")
new /obj/item/clothing/suit/space/hardsuit/wizard(get_turf(H))
new /obj/item/clothing/head/helmet/space/hardsuit/wizard(get_turf(H))
if("scrying")
new /obj/item/scrying(get_turf(H))
if(!(XRAY in H.mutations))

View File

@@ -446,7 +446,6 @@
if(.)
new /obj/item/clothing/shoes/magboots/wizard(get_turf(user))
new /obj/item/clothing/gloves/color/purple(get_turf(user)) // To complete the outfit
new /obj/item/clothing/head/helmet/space/hardsuit/wizard(get_turf(user))
/datum/spellbook_entry/item/mjolnir
name = "Mjolnir"
@@ -934,7 +933,7 @@
if(istype(user, /mob/living/carbon/human))
to_chat(user, "<font size='15' color='red'><b>HOR-SIE HAS RISEN</b></font>")
var/obj/item/clothing/mask/horsehead/magichead = new /obj/item/clothing/mask/horsehead
magichead.flags |= NODROP //curses!
magichead.flags |= NODROP | DROPDEL //curses!
magichead.flags_inv = null //so you can still see their face
magichead.voicechange = 1 //NEEEEIIGHH
if(!user.unEquip(user.wear_mask))

View File

@@ -7,7 +7,8 @@
required_players = 20
required_enemies = 1
recommended_enemies = 1
var/use_huds = 0
var/use_huds = 1
var/finished = 0
var/but_wait_theres_more = 0
@@ -157,22 +158,30 @@
wizard_mob.gene_stability += DEFAULT_GENE_STABILITY //magic
return 1
// Checks if the game should end due to all wizards and apprentices being dead, or MMI'd/Borged
/datum/game_mode/wizard/check_finished()
var/wizards_alive = 0
var/traitors_alive = 0
// Wizards
for(var/datum/mind/wizard in wizards)
if(!istype(wizard.current,/mob/living/carbon))
continue
if(wizard.current.stat==DEAD)
continue
if(istype(wizard.current, /obj/item/mmi)) // wizard is in an MMI, don't count them as alive
continue
wizards_alive++
// Apprentices - classified as "traitors"
if(!wizards_alive)
for(var/datum/mind/traitor in traitors)
if(!istype(traitor.current,/mob/living/carbon))
continue
if(traitor.current.stat==DEAD)
continue
if(istype(traitor.current, /obj/item/mmi)) // apprentice is in an MMI, don't count them as alive
continue
traitors_alive++
if(wizards_alive || traitors_alive || but_wait_theres_more)

View File

@@ -146,7 +146,7 @@
var/backpack = /obj/item/storage/backpack
var/satchel = /obj/item/storage/backpack/satchel_norm
var/dufflebag = /obj/item/storage/backpack/duffel
var/box = /obj/item/storage/box/survival
box = /obj/item/storage/box/survival
var/tmp/list/gear_leftovers = list()
@@ -168,12 +168,8 @@
else
back = backpack //Department backpack
if(box)
var/spawnbox = box
if(H.dna.species.speciesbox)
spawnbox = H.dna.species.speciesbox
backpack_contents.Insert(1, spawnbox) // Box always takes a first slot in backpack
backpack_contents[spawnbox] = 1
if(box && H.dna.species.speciesbox)
box = H.dna.species.speciesbox
if(allow_loadout && H.client && (H.client.prefs.gear && H.client.prefs.gear.len))
for(var/gear in H.client.prefs.gear)

View File

@@ -175,23 +175,24 @@
name = "Shaft Miner"
jobtype = /datum/job/mining
uniform = /obj/item/clothing/under/rank/miner/lavaland
gloves = /obj/item/clothing/gloves/color/black
shoes = /obj/item/clothing/shoes/workboots/mining
l_ear = /obj/item/radio/headset/headset_cargo/mining
id = /obj/item/card/id/supply
shoes = /obj/item/clothing/shoes/workboots/mining
gloves = /obj/item/clothing/gloves/color/black
uniform = /obj/item/clothing/under/rank/miner/lavaland
l_pocket = /obj/item/reagent_containers/hypospray/autoinjector/survival
r_pocket = /obj/item/flashlight/seclite
r_pocket = /obj/item/storage/bag/ore
id = /obj/item/card/id/supply
pda = /obj/item/pda/shaftminer
backpack_contents = list(
/obj/item/storage/bag/ore=1,\
/obj/item/flashlight/seclite=1,\
/obj/item/kitchen/knife/combat/survival=1,\
/obj/item/mining_voucher=1,\
/obj/item/stack/marker_beacon/ten=1
)
backpack = /obj/item/storage/backpack/explorer
satchel = /obj/item/storage/backpack/explorer
satchel = /obj/item/storage/backpack/satchel/explorer
box = /obj/item/storage/box/survival_mining
/datum/outfit/job/mining/equipped
name = "Shaft Miner"
@@ -210,9 +211,6 @@
/obj/item/stack/marker_beacon/ten=1
)
backpack = /obj/item/storage/backpack/explorer
satchel = /obj/item/storage/backpack/explorer
/datum/outfit/job/miner/equipped/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
..()
if(visualsOnly)

View File

@@ -8,6 +8,7 @@
idle_power_usage = 5
active_power_usage = 60
power_channel = EQUIP
pass_flags = PASSTABLE
var/obj/item/stock_parts/cell/charging = null
var/chargelevel = -1

View File

@@ -178,6 +178,12 @@
if(occupant && occupant.stat != DEAD)
to_chat(user, "Current clone cycle is [round(get_completion())]% complete.")
/obj/machinery/clonepod/return_air() //non-reactive air
var/datum/gas_mixture/GM = new
GM.nitrogen = MOLES_O2STANDARD + MOLES_N2STANDARD
GM.temperature = T20C
return GM
/obj/machinery/clonepod/proc/get_completion()
. = (100 * ((occupant.health + 100) / (heal_level + 100)))

View File

@@ -460,6 +460,12 @@
desc = "Here's your chance, do your dance at the Space Jam."
w_class = WEIGHT_CLASS_BULKY //Stops people from hiding it in their bags/pockets
/obj/item/beach_ball/holoball/baseball
icon_state = "baseball"
name = "baseball"
item_state = "baseball"
desc = "Take me out to the ball game."
/obj/structure/holohoop
name = "basketball hoop"
desc = "Boom, Shakalaka!"

View File

@@ -330,6 +330,14 @@ to destroy them and players will be able to make replacements.
name = "circuit board (Freezer)"
to_chat(user, "<span class='notice'>You set the board to cooling.</span>")
/obj/item/circuitboard/recharger
name = "circuit board (Recharger)"
build_path = /obj/machinery/recharger
board_type = "machine"
origin_tech = "powerstorage=3;materials=2"
frame_desc = "Requires 1 Capacitor"
req_components = list(/obj/item/stock_parts/capacitor = 1)
/obj/item/circuitboard/snow_machine
name = "circuit board (snow machine)"
build_path = /obj/machinery/snow_machine
@@ -591,6 +599,16 @@ to destroy them and players will be able to make replacements.
/obj/item/stock_parts/micro_laser = 1,
/obj/item/stock_parts/console_screen = 1)
/obj/item/circuitboard/reagentgrinder
name = "circuit board (All-In-One Grinder)"
build_path = /obj/machinery/reagentgrinder/empty
board_type = "machine"
origin_tech = "materials=2;engineering=2;biotech=2"
frame_desc = "Requires 2 Manipulators and 1 Matter Bin."
req_components = list(
/obj/item/stock_parts/manipulator = 2,
/obj/item/stock_parts/matter_bin = 1)
//Almost the same recipe as destructive analyzer to give people choices.
/obj/item/circuitboard/experimentor
name = "circuit board (E.X.P.E.R.I-MENTOR)"

View File

@@ -371,6 +371,8 @@
for(var/datum/mind/H in SSticker.mode.cult)
if(H.current)
to_chat(H.current, "<span class='danger'>[SSticker.cultdat.entity_name]</span> murmurs, <span class='cultlarge'>[occupant] is beyond your reach. Sacrifice [cult_mode.sacrifice_target.current] instead...</span></span>")
H.current << 'sound/ambience/alarm4.ogg'
cult_mode.update_sac_objective(occupant.mind, occupant.mind.assigned_role)
else
cult_mode.bypass_phase()

View File

@@ -181,12 +181,6 @@ About the new airlock wires panel:
/obj/machinery/door/airlock/bumpopen(mob/living/simple_animal/user)
..(user)
/obj/machinery/door/airlock/autoclose()
autoclose_timer = 0
if(!QDELETED(src) && !density && !operating && !locked && !welded && autoclose)
close()
return
/obj/machinery/door/airlock/proc/isElectrified()
if(electrified_until != 0)
return 1
@@ -311,6 +305,7 @@ About the new airlock wires panel:
/obj/machinery/door/airlock/update_icon(state=0, override=0)
if(operating && !override)
return
check_unres()
icon_state = density ? "closed" : "open"
switch(state)
if(0)
@@ -333,7 +328,6 @@ About the new airlock wires panel:
var/image/sparks_overlay
var/image/note_overlay
var/notetype = note_type()
switch(state)
if(AIRLOCK_CLOSED)
frame_overlay = get_airlock_overlay("closed", icon)
@@ -516,6 +510,7 @@ About the new airlock wires panel:
else
to_chat(user, "There's a [note.name] pinned to the front...")
note.examine(user)
to_chat(user, "<span class='notice'>Use an empty hand on the airlock on grab mode to remove [note.name].</span>")
if(panel_open)
switch(security_level)
@@ -621,6 +616,31 @@ About the new airlock wires panel:
if(user)
attack_ai(user)
/obj/machinery/door/airlock/proc/check_unres() //unrestricted sides. This overlay indicates which directions the player can access even without an ID
if(hasPower() && unres_sides)
if(unres_sides & NORTH)
var/image/I = image(icon='icons/obj/doors/airlocks/station/overlays.dmi', icon_state="unres_n") //layer=src.layer+1
I.pixel_y = 32
set_light(l_range = 1, l_power = 1, l_color = "#00FF00")
add_overlay(I)
if(unres_sides & SOUTH)
var/image/I = image(icon='icons/obj/doors/airlocks/station/overlays.dmi', icon_state="unres_s") //layer=src.layer+1
I.pixel_y = -32
set_light(l_range = 1, l_power = 1, l_color = "#00FF00")
add_overlay(I)
if(unres_sides & EAST)
var/image/I = image(icon='icons/obj/doors/airlocks/station/overlays.dmi', icon_state="unres_e") //layer=src.layer+1
I.pixel_x = 32
set_light(l_range = 1, l_power = 1, l_color = "#00FF00")
add_overlay(I)
if(unres_sides & WEST)
var/image/I = image(icon='icons/obj/doors/airlocks/station/overlays.dmi', icon_state="unres_w") //layer=src.layer+1
I.pixel_x = -32
set_light(l_range = 1, l_power = 1, l_color = "#00FF00")
add_overlay(I)
else
set_light(0)
/obj/machinery/door/airlock/CanPass(atom/movable/mover, turf/target, height=0)
if(isElectrified() && density && istype(mover, /obj/item))
var/obj/item/I = mover
@@ -1078,6 +1098,10 @@ About the new airlock wires panel:
playsound(loc, doorOpen, 30, 1)
if(closeOther != null && istype(closeOther, /obj/machinery/door/airlock/) && !closeOther.density)
closeOther.close()
if(autoclose)
autoclose_in(normalspeed ? auto_close_time : auto_close_time_dangerous)
if(!density)
return TRUE
operating = TRUE
@@ -1092,10 +1116,6 @@ About the new airlock wires panel:
layer = OPEN_DOOR_LAYER
update_icon(AIRLOCK_OPEN, 1)
operating = FALSE
// The `addtimer` system has the advantage of being cancelable
if(autoclose)
autoclose_timer = addtimer(CALLBACK(src, .proc/autoclose), normalspeed ? auto_close_time : auto_close_time_dangerous, TIMER_UNIQUE | TIMER_STOPPABLE)
return TRUE
/obj/machinery/door/airlock/close(forced=0, override = 0)
@@ -1112,7 +1132,8 @@ About the new airlock wires panel:
for(var/turf/turf in locs)
for(var/atom/movable/M in turf)
if(M.density && M != src) //something is blocking the door
addtimer(CALLBACK(src, .proc/autoclose), 60)
autoclose_in(60)
return
use_power(360) //360 W seems much more appropriate for an actuator moving an industrial door capable of crushing people
if(forced)

View File

@@ -11,6 +11,8 @@
var/list/conf_access = null
var/one_access = 0 //if set to 1, door would receive req_one_access instead of req_access
var/const/max_brain_damage = 60 // Maximum brain damage a mob can have until it can't use the electronics
var/unres_sides = 0
var/unres_direction = null
/obj/item/airlock_electronics/attack_self(mob/user)
if(!ishuman(user) && !isrobot(user))
@@ -23,14 +25,22 @@
return
var/t1 = text("<B>Access control</B><br>\n")
t1 += "<hr>"
t1 += "<B> Unrestricted Access Settings</B><br>"
var/list/Directions = list("North","South",,"East",,,,"West")
for(var/direction in cardinal)
if (unres_direction && unres_direction == direction)
t1 += "<a style='color: red' href='?src=[UID()];unres_direction=[direction]'>[Directions[direction]]</a><br>"
else
t1 += "<a href='?src=[UID()];unres_direction=[direction]'>[Directions[direction]]</a><br>"
t1 += "<hr>"
t1 += "Access requirement is set to "
t1 += one_access ? "<a style='color: green' href='?src=[UID()];one_access=1'>ONE</a><hr>" : "<a style='color: red' href='?src=[UID()];one_access=1'>ALL</a><hr>"
t1 += conf_access == null ? "<font color=red>All</font><br>" : "<a href='?src=[UID()];access=all'>All</a><br>"
t1 += "<br>"
var/list/accesses = get_all_accesses()
for(var/acc in accesses)
var/aname = get_access_desc(acc)
@@ -64,6 +74,14 @@
if(href_list["access"])
toggle_access(href_list["access"])
if(href_list["unres_direction"])
unres_direction = text2num(href_list["unres_direction"])
if (unres_sides == unres_direction)
unres_sides = 0
unres_direction = null
else
unres_sides = unres_direction
attack_self(usr)

View File

@@ -14,21 +14,20 @@
var/visible = 1
var/operating = FALSE
var/autoclose = 0
var/autoclose_timer
var/safe = TRUE //whether the door detects things and mobs in its way and reopen or crushes them.
var/locked = FALSE //whether the door is bolted or not.
var/glass = FALSE
var/welded = FALSE
var/normalspeed = 1
var/auto_close_time = 150
var/auto_close_time_dangerous = 5
var/auto_close_time_dangerous = 15
var/assemblytype //the type of door frame to drop during deconstruction
var/datum/effect_system/spark_spread/spark_system
var/damage_deflection = 10
var/real_explosion_block //ignore this, just use explosion_block
var/heat_proof = FALSE // For rglass-windowed airlocks and firedoors
var/emergency = FALSE
var/unres_sides = 0 //Unrestricted sides. A bitflag for which direction (if any) can open the door with no access
//Multi-tile doors
var/width = 1
@@ -55,6 +54,10 @@
..()
update_dir()
/obj/machinery/door/power_change()
..()
update_icon()
/obj/machinery/door/proc/update_dir()
if(width > 1)
if(dir in list(EAST, WEST))
@@ -73,9 +76,6 @@
air_update_turf(1)
update_freelook_sight()
GLOB.airlocks -= src
if(autoclose_timer)
deltimer(autoclose_timer)
autoclose_timer = 0
QDEL_NULL(spark_system)
return ..()
@@ -175,10 +175,15 @@
/obj/machinery/door/allowed(mob/M)
if(emergency)
return TRUE
if(unrestricted_side(M))
return TRUE
if(!requiresID())
return FALSE // Intentional. machinery/door/requiresID() always == 1. airlocks, however, == 0 if ID scan is disabled. Yes, this var is poorly named.
return ..()
/obj/machinery/door/proc/unrestricted_side(mob/M) //Allows for specific side of airlocks to be unrestrected (IE, can exit maint freely, but need access to enter)
return get_dir(src, M) & unres_sides
/obj/machinery/door/proc/try_to_weld(obj/item/weldingtool/W, mob/user)
return
@@ -273,11 +278,8 @@
operating = FALSE
air_update_turf(1)
update_freelook_sight()
// The `addtimer` system has the advantage of being cancelable
if(autoclose)
autoclose_timer = addtimer(CALLBACK(src, .proc/autoclose), normalspeed ? auto_close_time : auto_close_time_dangerous, TIMER_UNIQUE | TIMER_STOPPABLE)
autoclose_in(normalspeed ? auto_close_time : auto_close_time_dangerous)
return TRUE
/obj/machinery/door/proc/close()
@@ -286,18 +288,15 @@
if(operating || welded)
return
if(safe)
for(var/atom/movable/M in get_turf(src))
if(M.density && M != src) //something is blocking the door
if(autoclose)
addtimer(CALLBACK(src, .proc/autoclose), 60)
return
for(var/turf/turf in locs)
for(var/atom/movable/M in turf)
if(M.density && M != src) //something is blocking the door
if(autoclose)
autoclose_in(60)
return
operating = TRUE
if(autoclose_timer)
deltimer(autoclose_timer)
autoclose_timer = 0
do_animate("closing")
layer = closingLayer
sleep(5)
@@ -345,10 +344,12 @@
return !(stat & NOPOWER)
/obj/machinery/door/proc/autoclose()
autoclose_timer = 0
if(!QDELETED(src) && !density && !operating && !locked && !welded && autoclose)
close()
/obj/machinery/door/proc/autoclose_in(wait)
addtimer(CALLBACK(src, .proc/autoclose), wait, TIMER_UNIQUE | TIMER_NO_HASH_WAIT | TIMER_OVERRIDE)
/obj/machinery/door/proc/update_freelook_sight()
if(!glass && cameranet)
cameranet.updateVisibility(src, 0)

View File

@@ -160,8 +160,8 @@
var/obj/item/stack/cable_coil/C = W
to_chat(user, "You start adding cables to \the [src]...")
playsound(get_turf(src), C.usesound, 50, 1)
if(do_after(user, 20 * C.toolspeed, target = src) && (C.amount >= 3) && (build == 2))
C.use(3)
if(do_after(user, 20 * C.toolspeed, target = src) && (C.amount >= 2) && (build == 2))
C.use(2)
to_chat(user, "<span class='notice'>You've added cables to \the [src].</span>")
build++
update_icon()
@@ -169,7 +169,7 @@
if(istype(W, /obj/item/wirecutters))
to_chat(user, "You begin to remove the wiring from \the [src].")
if(do_after(user, 10 * W.toolspeed, target = src) && (build == 3))
new /obj/item/stack/cable_coil(loc,3)
new /obj/item/stack/cable_coil(loc,2)
playsound(get_turf(src), W.usesound, 50, 1)
to_chat(user, "<span class='notice'>You've removed the cables from \the [src].</span>")
build--
@@ -179,8 +179,8 @@
var/obj/item/stack/rods/R = W
to_chat(user, "You begin to complete \the [src]...")
playsound(get_turf(src), R.usesound, 50, 1)
if(do_after(user, 20 * R.toolspeed, target = src) && (R.amount >= 3) && (build == 3))
R.use(3)
if(do_after(user, 20 * R.toolspeed, target = src) && (R.amount >= 2) && (build == 3))
R.use(2)
to_chat(user, "<span class='notice'>You've added the grille to \the [src].</span>")
build++
update_icon()

View File

@@ -6,7 +6,8 @@
anchored = 1
use_power = IDLE_POWER_USE
idle_power_usage = 4
active_power_usage = 250
active_power_usage = 200
pass_flags = PASSTABLE
var/obj/item/charging = null
var/using_power = FALSE
var/list/allowed_devices = list(/obj/item/gun/energy, /obj/item/melee/baton, /obj/item/modular_computer, /obj/item/rcs, /obj/item/bodyanalyzer)
@@ -14,6 +15,18 @@
var/icon_state_charged = "recharger2"
var/icon_state_charging = "recharger1"
var/icon_state_idle = "recharger0"
var/recharge_coeff = 1
/obj/machinery/recharger/New()
..()
component_parts = list()
component_parts += new /obj/item/circuitboard/recharger(null)
component_parts += new /obj/item/stock_parts/capacitor(null)
RefreshParts()
/obj/machinery/recharger/RefreshParts()
for(var/obj/item/stock_parts/capacitor/C in component_parts)
recharge_coeff = C.rating
/obj/machinery/recharger/attackby(obj/item/G, mob/user, params)
if(iswrench(G))
@@ -54,8 +67,16 @@
else
to_chat(user, "<span class='notice'>[src] isn't connected to anything!</span>")
return 1
else
return ..()
if(anchored && !charging)
if(default_deconstruction_screwdriver(user, "rechargeropen", "recharger0", G))
return
if(panel_open && istype(G, /obj/item/crowbar))
default_deconstruction_crowbar(G)
return
return ..()
/obj/machinery/recharger/attack_hand(mob/user)
if(issilicon(user))
@@ -87,10 +108,11 @@
if(istype(charging, /obj/item/gun/energy))
var/obj/item/gun/energy/E = charging
if(E.power_supply.charge < E.power_supply.maxcharge)
E.power_supply.give(E.power_supply.chargerate)
E.power_supply.give(E.power_supply.chargerate * recharge_coeff)
use_power(250)
using_power = TRUE
if(istype(charging, /obj/item/melee/baton))
var/obj/item/melee/baton/B = charging
if(B.bcell)

View File

@@ -62,8 +62,7 @@
/obj/machinery/suit_storage_unit/engine
name = "engineering suit storage unit"
suit_type = /obj/item/clothing/suit/space/hardsuit/engineering
helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/engineering
suit_type = /obj/item/clothing/suit/space/hardsuit/engine
mask_type = /obj/item/clothing/mask/breath
magboots_type = /obj/item/clothing/shoes/magboots
req_access = list(access_engine_equip)
@@ -73,8 +72,7 @@
/obj/machinery/suit_storage_unit/ce
name = "chief engineer's suit storage unit"
suit_type = /obj/item/clothing/suit/space/hardsuit/elite
helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/elite
suit_type = /obj/item/clothing/suit/space/hardsuit/engine/elite
mask_type = /obj/item/clothing/mask/gas
magboots_type = /obj/item/clothing/shoes/magboots/advance
req_access = list(access_ce)
@@ -85,7 +83,6 @@
/obj/machinery/suit_storage_unit/security
name = "security suit storage unit"
suit_type = /obj/item/clothing/suit/space/hardsuit/security
helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/security
mask_type = /obj/item/clothing/mask/gas/sechailer
magboots_type = /obj/item/clothing/shoes/magboots
req_access = list(access_security)
@@ -98,8 +95,7 @@
/obj/machinery/suit_storage_unit/atmos
name = "atmospherics suit storage unit"
suit_type = /obj/item/clothing/suit/space/hardsuit/atmos
helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/atmos
suit_type = /obj/item/clothing/suit/space/hardsuit/engine/atmos
mask_type = /obj/item/clothing/mask/gas
magboots_type = /obj/item/clothing/shoes/magboots
req_access = list(access_atmospherics)
@@ -110,7 +106,6 @@
/obj/machinery/suit_storage_unit/mining
name = "mining suit storage unit"
suit_type = /obj/item/clothing/suit/space/hardsuit/mining
helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/mining
mask_type = /obj/item/clothing/mask/breath
req_access = list(access_mining_station)
@@ -125,7 +120,6 @@
/obj/machinery/suit_storage_unit/cmo
suit_type = /obj/item/clothing/suit/space/hardsuit/medical
helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/medical
mask_type = /obj/item/clothing/mask/breath
req_access = list(access_cmo)
@@ -159,7 +153,6 @@
/obj/machinery/suit_storage_unit/syndicate
name = "syndicate suit storage unit"
suit_type = /obj/item/clothing/suit/space/hardsuit/syndi
helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/syndi
mask_type = /obj/item/clothing/mask/gas/syndicate
magboots_type = /obj/item/clothing/shoes/magboots/syndie
storage_type = /obj/item/tank/jetpack/oxygen/harness
@@ -174,7 +167,6 @@
/obj/machinery/suit_storage_unit/ert/command
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/commander
helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/ert/commander
mask_type = /obj/item/clothing/mask/breath
storage_type = /obj/item/tank/emergency_oxygen/double
@@ -183,7 +175,6 @@
/obj/machinery/suit_storage_unit/ert/security
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/security
helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/ert/security
mask_type = /obj/item/clothing/mask/breath
storage_type = /obj/item/tank/emergency_oxygen/double
@@ -192,7 +183,6 @@
/obj/machinery/suit_storage_unit/ert/engineer
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/engineer
helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/ert/engineer
mask_type = /obj/item/clothing/mask/breath
storage_type = /obj/item/tank/emergency_oxygen/double
@@ -201,7 +191,6 @@
/obj/machinery/suit_storage_unit/ert/medical
suit_type = /obj/item/clothing/suit/space/hardsuit/ert/medical
helmet_type = /obj/item/clothing/head/helmet/space/hardsuit/ert/medical
mask_type = /obj/item/clothing/mask/breath
storage_type = /obj/item/tank/emergency_oxygen/double
@@ -699,7 +688,7 @@
else
mask.forceMove(loc)
mask = null
/obj/machinery/suit_storage_unit/proc/dispense_magboots(mob/user as mob)
if(!magboots)
return

View File

@@ -201,6 +201,9 @@
return FALSE
if(!Adjacent(user))
return FALSE
if(!allowed(user))
to_chat(user, "<span class='warning'>Access denied!</span>")
return FALSE
return TRUE
/obj/machinery/syndicatebomb/proc/activate()
@@ -273,6 +276,7 @@
/obj/machinery/syndicatebomb/self_destruct
name = "self destruct device"
desc = "Do not taunt. Warranty invalid if exposed to high temperature. Not suitable for agents under 3 years of age."
req_access = list(access_syndicate)
payload = /obj/item/bombcore/large
can_unanchor = FALSE
var/explosive_wall_group = EXPLOSIVE_WALL_GROUP_SYNDICATE_BASE // If set, this bomb will also cause explosive walls in the same group to explode

View File

@@ -1132,7 +1132,6 @@
product_ads = "Go save some lives!;The best stuff for your medbay.;Only the finest tools.;Natural chemicals!;This stuff saves lives.;Don't you want some?"
icon_state = "wallmed"
icon_deny = "wallmed-deny"
req_access = list(access_medical)
density = FALSE //It is wall-mounted, and thus, not dense. --Superxpdude
products = list(/obj/item/stack/medical/bruise_pack = 2, /obj/item/stack/medical/ointment = 2, /obj/item/reagent_containers/hypospray/autoinjector = 4, /obj/item/healthanalyzer = 1)
contraband = list(/obj/item/reagent_containers/syringe/charcoal = 4, /obj/item/reagent_containers/syringe/antiviral = 4, /obj/item/reagent_containers/food/pill/tox = 1)
@@ -1143,7 +1142,6 @@
desc = "Wall-mounted Medical Equipment dispenser."
icon_state = "wallmed"
icon_deny = "wallmed-deny"
req_access = list(access_medical)
density = FALSE //It is wall-mounted, and thus, not dense. --Superxpdude
products = list(/obj/item/reagent_containers/hypospray/autoinjector = 5, /obj/item/reagent_containers/syringe/charcoal = 3, /obj/item/stack/medical/bruise_pack = 3,
/obj/item/stack/medical/ointment = 3, /obj/item/healthanalyzer = 3)

View File

@@ -171,10 +171,8 @@
/obj/mecha/working/ripley/proc/update_pressure()
var/turf/T = get_turf(loc)
var/datum/gas_mixture/environment = T.return_air()
var/pressure = environment.return_pressure()
if(pressure < 20)
if(lavaland_equipment_pressure_check(T))
step_in = 3
for(var/obj/item/mecha_parts/mecha_equipment/drill/drill in equipment)
drill.equip_cooldown = initial(drill.equip_cooldown)/2

View File

@@ -3,7 +3,7 @@
desc = "It's green and acidic. It looks like... <i>blood?</i>"
icon = 'icons/effects/blood.dmi'
basecolor = "#05EE05"
bloodiness = MAX_SHOE_BLOODINESS
bloodiness = BLOOD_AMOUNT_PER_DECAL
blood_state = BLOOD_STATE_XENO
/obj/effect/decal/cleanable/blood/xeno/splatter

View File

@@ -17,12 +17,22 @@ var/global/list/image/splatter_cache = list()
blood_DNA = list()
var/base_icon = 'icons/effects/blood.dmi'
var/blood_state = BLOOD_STATE_HUMAN
var/bloodiness = MAX_SHOE_BLOODINESS
bloodiness = BLOOD_AMOUNT_PER_DECAL
var/basecolor = "#A10808" // Color when wet.
var/amount = 5
var/dry_timer = 0
var/off_floor = FALSE
/obj/effect/decal/cleanable/blood/replace_decal(obj/effect/decal/cleanable/blood/C)
if(C.blood_DNA)
blood_DNA |= C.blood_DNA.Copy()
if(bloodiness)
if(C.bloodiness < MAX_SHOE_BLOODINESS)
C.bloodiness += bloodiness
return ..()
/obj/effect/decal/cleanable/blood/Initialize()
. = ..()
update_icon()
@@ -87,46 +97,6 @@ var/global/list/image/splatter_cache = list()
/obj/effect/decal/cleanable/blood/can_bloodcrawl_in()
return TRUE
//Add "bloodiness" of this blood's type, to the human's shoes
/obj/effect/decal/cleanable/blood/Crossed(atom/movable/O, oldloc)
if(!off_floor && ishuman(O))
var/mob/living/carbon/human/H = O
var/obj/item/organ/external/l_foot = H.get_organ("l_foot")
var/obj/item/organ/external/r_foot = H.get_organ("r_foot")
var/hasfeet = TRUE
if(!l_foot && !r_foot)
hasfeet = FALSE
if(H.shoes && blood_state && bloodiness)
var/obj/item/clothing/shoes/S = H.shoes
var/add_blood = 0
if(bloodiness >= BLOOD_GAIN_PER_STEP)
add_blood = BLOOD_GAIN_PER_STEP
else
add_blood = bloodiness
bloodiness -= add_blood
S.bloody_shoes[blood_state] = min(MAX_SHOE_BLOODINESS, S.bloody_shoes[blood_state] + add_blood)
if(blood_DNA && blood_DNA.len)
S.add_blood(H.blood_DNA, basecolor)
S.blood_state = blood_state
S.blood_color = basecolor
update_icon()
H.update_inv_shoes()
else if(hasfeet && blood_state && bloodiness)//Or feet
var/add_blood = 0
if(bloodiness >= BLOOD_GAIN_PER_STEP)
add_blood = BLOOD_GAIN_PER_STEP
else
add_blood = bloodiness
bloodiness -= add_blood
H.bloody_feet[blood_state] = min(MAX_SHOE_BLOODINESS, H.bloody_feet[blood_state] + add_blood)
if(!H.feet_blood_DNA)
H.feet_blood_DNA = list()
H.blood_state = blood_state
H.feet_blood_DNA |= blood_DNA.Copy()
H.feet_blood_color = basecolor
update_icon()
H.update_inv_shoes()
/obj/effect/decal/cleanable/blood/splatter
random_icon_states = list("mgibbl1", "mgibbl2", "mgibbl3", "mgibbl4", "mgibbl5")
amount = 2
@@ -191,6 +161,8 @@ var/global/list/image/splatter_cache = list()
icon_state = "gibbl5"
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6")
no_clear = TRUE
mergeable_decal = FALSE
var/fleshcolor = "#FFFFFF"
/obj/effect/decal/cleanable/blood/gibs/update_icon()

View File

@@ -16,6 +16,7 @@
icon_state = "ash"
anchored = TRUE
scoop_reagents = list("ash" = 10)
mergeable_decal = FALSE
/obj/effect/decal/cleanable/dirt
name = "dirt"
@@ -97,7 +98,8 @@
gender = NEUTER
icon = 'icons/effects/effects.dmi'
icon_state = "molten"
mergeable_decal = FALSE
/obj/effect/decal/cleanable/molten_object/large
name = "big gooey grey mass"
icon_state = "big_molten"

View File

@@ -5,7 +5,8 @@
icon_state = "gib1"
basecolor = "#030303"
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7")
bloodiness = MAX_SHOE_BLOODINESS
bloodiness = BLOOD_AMOUNT_PER_DECAL
mergeable_decal = FALSE
/obj/effect/decal/cleanable/blood/gibs/robot/can_bloodcrawl_in()
return FALSE

View File

@@ -30,6 +30,7 @@ var/global/list/image/fluidtrack_cache = list()
/obj/effect/decal/cleanable/blood/footprints/Crossed(atom/movable/O, oldloc)
..()
if(ishuman(O))
var/mob/living/carbon/human/H = O
var/obj/item/clothing/shoes/S = H.shoes
@@ -40,19 +41,22 @@ var/global/list/image/fluidtrack_cache = list()
hasfeet = FALSE
if(S && S.bloody_shoes[blood_state] && S.blood_color == basecolor)
S.bloody_shoes[blood_state] = max(S.bloody_shoes[blood_state] - BLOOD_LOSS_PER_STEP, 0)
entered_dirs |= H.dir
if(!S.blood_DNA)
S.blood_DNA = list()
S.blood_DNA |= blood_DNA.Copy()
if(!(entered_dirs & H.dir))
entered_dirs |= H.dir
update_icon()
else if(hasfeet && H.bloody_feet[blood_state] && H.feet_blood_color == basecolor)//Or feet //This will need to be changed.
H.bloody_feet[blood_state] = max(H.bloody_feet[blood_state] - BLOOD_LOSS_PER_STEP, 0)
entered_dirs |= H.dir
if(!H.feet_blood_DNA)
H.feet_blood_DNA = list()
H.feet_blood_DNA |= blood_DNA.Copy()
update_icon()
if(!(entered_dirs & H.dir))
entered_dirs |= H.dir
update_icon()
/obj/effect/decal/cleanable/blood/footprints/Uncrossed(atom/movable/O)
..()
if(ishuman(O))
var/mob/living/carbon/human/H = O
var/obj/item/clothing/shoes/S = H.shoes
@@ -63,17 +67,20 @@ var/global/list/image/fluidtrack_cache = list()
hasfeet = FALSE
if(S && S.bloody_shoes[blood_state] && S.blood_color == basecolor)
S.bloody_shoes[blood_state] = max(S.bloody_shoes[blood_state] - BLOOD_LOSS_PER_STEP, 0)
exited_dirs |= H.dir
if(!S.blood_DNA)
S.blood_DNA = list()
S.blood_DNA |= blood_DNA.Copy()
if(!(exited_dirs & H.dir))
exited_dirs |= H.dir
update_icon()
else if(hasfeet && H.bloody_feet[blood_state] && H.feet_blood_color == basecolor)//Or feet
H.bloody_feet[blood_state] = max(H.bloody_feet[blood_state] - BLOOD_LOSS_PER_STEP, 0)
exited_dirs |= H.dir
if(!H.feet_blood_DNA)
H.feet_blood_DNA = list()
H.feet_blood_DNA |= blood_DNA.Copy()
update_icon()
if(!(exited_dirs & H.dir))
exited_dirs |= H.dir
update_icon()
/obj/effect/decal/cleanable/blood/footprints/update_icon()
@@ -108,14 +115,14 @@ var/global/list/image/fluidtrack_cache = list()
if(ishuman(A))
var/mob/living/carbon/human/H = A
FP.blood_state = H.blood_state
FP.bloodiness = H.bloody_feet[H.blood_state]
FP.bloodiness = H.bloody_feet[H.blood_state] - BLOOD_LOSS_IN_SPREAD
FP.basecolor = H.feet_blood_color
if(H.blood_DNA)
FP.blood_DNA = H.blood_DNA.Copy()
else if(istype(A, /obj/item/clothing/shoes))
var/obj/item/clothing/shoes/S = A
FP.blood_state = S.blood_state
FP.bloodiness = S.bloody_shoes[S.blood_state]
FP.bloodiness = S.bloody_shoes[S.blood_state] - BLOOD_LOSS_IN_SPREAD
FP.basecolor = S.blood_color
if(S.blood_DNA)
FP.blood_DNA = S.blood_DNA.Copy()
@@ -123,3 +130,8 @@ var/global/list/image/fluidtrack_cache = list()
FP.update_icon()
return FP
/obj/effect/decal/cleanable/blood/footprints/replace_decal(obj/effect/decal/cleanable/blood/footprints/C)
if(blood_state != C.blood_state) //We only replace footprints of the same type as us
return
..()

View File

@@ -1,11 +1,65 @@
/obj/effect/decal/cleanable
anchored = TRUE
var/list/random_icon_states = list()
var/bloodiness = 0 //0-100, amount of blood in this decal, used for making footprints and affecting the alpha of bloody footprints
var/mergeable_decal = TRUE //when two of these are on a same tile or do we need to merge them into just one?
/obj/effect/decal/cleanable/proc/replace_decal(obj/effect/decal/cleanable/C) // Returns true if we should give up in favor of the pre-existing decal
if(mergeable_decal)
return TRUE
//Add "bloodiness" of this blood's type, to the human's shoes
//This is on /cleanable because fuck this ancient mess
/obj/effect/decal/cleanable/blood/Crossed(atom/movable/O)
..()
if(!off_floor && ishuman(O))
var/mob/living/carbon/human/H = O
var/obj/item/organ/external/l_foot = H.get_organ("l_foot")
var/obj/item/organ/external/r_foot = H.get_organ("r_foot")
var/hasfeet = TRUE
if(!l_foot && !r_foot)
hasfeet = FALSE
if(H.shoes && blood_state && bloodiness)
var/obj/item/clothing/shoes/S = H.shoes
var/add_blood = 0
if(bloodiness >= BLOOD_GAIN_PER_STEP)
add_blood = BLOOD_GAIN_PER_STEP
else
add_blood = bloodiness
bloodiness -= add_blood
S.bloody_shoes[blood_state] = min(MAX_SHOE_BLOODINESS, S.bloody_shoes[blood_state] + add_blood)
if(blood_DNA && blood_DNA.len)
S.add_blood(H.blood_DNA, basecolor)
S.blood_state = blood_state
S.blood_color = basecolor
update_icon()
H.update_inv_shoes()
else if(hasfeet && blood_state && bloodiness)//Or feet
var/add_blood = 0
if(bloodiness >= BLOOD_GAIN_PER_STEP)
add_blood = BLOOD_GAIN_PER_STEP
else
add_blood = bloodiness
bloodiness -= add_blood
H.bloody_feet[blood_state] = min(MAX_SHOE_BLOODINESS, H.bloody_feet[blood_state] + add_blood)
if(!H.feet_blood_DNA)
H.feet_blood_DNA = list()
H.blood_state = blood_state
H.feet_blood_DNA |= blood_DNA.Copy()
H.feet_blood_color = basecolor
update_icon()
H.update_inv_shoes()
/obj/effect/decal/cleanable/proc/can_bloodcrawl_in()
return FALSE
/obj/effect/decal/cleanable/New()
/obj/effect/decal/cleanable/Initialize(mapload)
. = ..()
if(loc && isturf(loc))
for(var/obj/effect/decal/cleanable/C in loc)
if(C != src && C.type == type && !QDELETED(C))
if(replace_decal(C))
return INITIALIZE_HINT_QDEL
if(random_icon_states && length(src.random_icon_states) > 0)
src.icon_state = pick(src.random_icon_states)
if(smooth)

View File

@@ -67,6 +67,23 @@
/obj/effect/mapping_helpers/no_lava
icon_state = "no_lava"
/obj/effect/mapping_helpers/airlock
layer = DOOR_HELPER_LAYER
/obj/effect/mapping_helpers/airlock/unres
name = "airlock unresctricted side helper"
icon_state = "airlock_unres_helper"
/obj/effect/mapping_helpers/airlock/unres/Initialize(mapload)
if(!mapload)
log_world("### MAP WARNING, [src] spawned outside of mapload!")
return
var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in src.loc
if(airlock)
airlock.unres_sides ^= dir
else
log_world("### MAP WARNING, [src] failed to find an airlock at [AREACOORD(src)]")
..()
/obj/effect/mapping_helpers/no_lava/New()
var/turf/T = get_turf(src)
T.flags |= NO_LAVA_GEN

View File

@@ -141,7 +141,7 @@
new /obj/effect/hallucination/delusion(victim.loc, victim, force_kind = "demon", duration = duration, skip_nearby = 0)
var/obj/item/twohanded/required/chainsaw/doomslayer/chainsaw = new(victim.loc)
chainsaw.flags |= NODROP
chainsaw.flags |= NODROP | DROPDEL
victim.drop_l_hand()
victim.drop_r_hand()
victim.put_in_hands(chainsaw)

View File

@@ -140,6 +140,20 @@
..()
animate(src, alpha = 0, time = duration)
/obj/effect/temp_visual/fire
icon = 'icons/goonstation/effects/fire.dmi'
icon_state = "3"
light_range = LIGHT_RANGE_FIRE
light_color = LIGHT_COLOR_FIRE
duration = 10
layer = MASSIVE_OBJ_LAYER
alpha = 250
blend_mode = BLEND_ADD
/obj/effect/temp_visual/fire/New(loc)
color = heat2color(FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
..()
/obj/effect/temp_visual/revenant
name = "spooky lights"
icon_state = "purplesparkles"
@@ -289,4 +303,33 @@
/obj/effect/temp_visual/dir_setting/firing_effect/magic
icon_state = "shieldsparkles"
duration = 3
duration = 3
/obj/effect/temp_visual/impact_effect
icon_state = "impact_bullet"
duration = 5
/obj/effect/temp_visual/impact_effect/Initialize(mapload, x, y)
pixel_x = x
pixel_y = y
return ..()
/obj/effect/temp_visual/impact_effect/red_laser
icon_state = "impact_laser"
duration = 4
/obj/effect/temp_visual/impact_effect/blue_laser
icon_state = "impact_laser_blue"
duration = 4
/obj/effect/temp_visual/impact_effect/green_laser
icon_state = "impact_laser_green"
duration = 4
/obj/effect/temp_visual/impact_effect/purple_laser
icon_state = "impact_laser_purple"
duration = 4
/obj/effect/temp_visual/impact_effect/ion
icon_state = "shieldsparkles"
duration = 6

View File

@@ -87,6 +87,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
If index term exists and icon_override is not set, this sprite sheet will be used.
*/
var/list/sprite_sheets = null
var/list/sprite_sheets_inhand = null //Used to override inhand items. Use a single .dmi and suffix the icon states inside with _l and _r for each hand.
var/icon_override = null //Used to override hardcoded clothing dmis in human clothing proc.
var/sprite_sheets_obj = null //Used to override hardcoded clothing inventory object dmis in human clothing proc.
@@ -331,7 +332,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
else
return ..()
/obj/item/proc/hit_reaction(mob/living/carbon/human/owner, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
/obj/item/proc/hit_reaction(mob/living/carbon/human/owner, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, atom/movable/AM)
SEND_SIGNAL(src, COMSIG_ITEM_HIT_REACT, args)
if(prob(final_block_chance))
owner.visible_message("<span class='danger'>[owner] blocks [attack_text] with [src]!</span>")
@@ -347,6 +348,8 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
A.Remove(user)
if(flags & DROPDEL)
qdel(src)
if((flags & NODROP) && !(initial(flags) & NODROP)) //Remove NODROP is dropped
flags &= ~NODROP
in_inventory = FALSE
SEND_SIGNAL(src, COMSIG_ITEM_DROPPED,user)

View File

@@ -4,6 +4,7 @@
/obj/item/storage/pill_bottle/happy
name = "Happy pills"
desc = "Highly illegal drug. When you want to see the rainbow."
wrapper_color = COLOR_PINK
/obj/item/storage/pill_bottle/happy/New()
..()
@@ -18,6 +19,7 @@
/obj/item/storage/pill_bottle/zoom
name = "Zoom pills"
desc = "Highly illegal drug. Trade brain for speed."
wrapper_color = COLOR_BLUE
/obj/item/storage/pill_bottle/zoom/New()
..()
@@ -49,15 +51,12 @@
adulterants--
reagents.add_reagent(pick_list("chemistry_tools.json", "CYBERPUNK_drug_adulterants"), 3)
/obj/item/storage/pill_bottle/random_drug_bottle
name = "pill bottle (???)"
desc = "Huh."
allow_wrap = FALSE
/obj/item/storage/pill_bottle/random_drug_bottle/New()
..()
for(var/i in 1 to 5)
new /obj/item/reagent_containers/food/pill/random_drugs(src)

View File

@@ -0,0 +1,96 @@
/*
//////////
Item meant to spawn one of the three (Tesla / Singularity / Supermatter) engines on-station at round-start.
Should be found in the CE's office. Not access-restricted.
//////////
*/
/obj/item/enginepicker
name = "Bluespace Engine Delivery Device"
desc = "A per-station bluespace-based delivery system for a unique engine Engineering Department's choice. Only one option can be chosen. Device self-destructs on use."
icon = 'icons/obj/device.dmi'
icon_state = "enginepicker"
var/list/list_enginebeacons = list()
var/isactive = FALSE
/obj/item/enginepicker/attack_self(mob/living/carbon/user)
if(usr.stat || !usr.canmove || usr.restrained())
return
if(!isactive)
isactive = TRUE //Self-attack spam exploit prevention
else
return
locatebeacons()
var/default = null
var/E = input("Select the station's Engine:", "[src]", default) as null|anything in list_enginebeacons
if(E)
processchoice(E, user)
else
isactive = FALSE
return
//This proc re-assigns all of engine beacons in the global list to a local list.
/obj/item/enginepicker/proc/locatebeacons()
LAZYCLEARLIST(list_enginebeacons)
for(var/obj/item/radio/beacon/engine/B in GLOB.engine_beacon_list)
if(B && !QDELETED(B)) //This ensures that the input pop-up won't have any qdeleted beacons
list_enginebeacons += B
//Spawns and logs / announces the appropriate engine based on the choice made
/obj/item/enginepicker/proc/processchoice(var/obj/item/radio/beacon/engine/choice, mob/living/carbon/user)
var/issuccessful = FALSE //Check for a successful choice
var/engtype //Engine type
var/G //Generator that will be spawned
var/turf/T = get_turf(choice)
if(choice.enginetype.len > 1) //If the beacon has multiple engine types
var/default = null
var/E = input("You have selected a combined beacon, which option would you prefer?", "[src]", default) as null|anything in choice.enginetype
if(E)
engtype = E
issuccessful = TRUE
else
isactive = FALSE
return
if(!engtype) //If it has only one type
engtype = DEFAULTPICK(choice.enginetype, null) //This should(?) account for a possibly scrambled list with a single entry
switch(engtype)
if(ENGTYPE_TESLA)
G = /obj/machinery/the_singularitygen/tesla
if(ENGTYPE_SING)
G = /obj/machinery/the_singularitygen
if(G) //This can only be not-null if the switch operation was successful
issuccessful = TRUE
if(issuccessful)
clearturf(T) //qdels all items / gibs all mobs on the turf. Let's not have an SM shard spawn on top of a poor sod.
new G(T) //Spawns the switch-selected engine on the chosen beacon's turf
var/ailist[] = list()
for(var/mob/living/silicon/ai/A in GLOB.living_mob_list)
ailist += A
if(ailist.len)
var/mob/living/silicon/ai/announcer = pick(ailist)
announcer.say(";Engine delivery detected. Type: [engtype].") //Let's announce the terrible choice to everyone
visible_message("<span class='notice'>\The [src] begins to violently vibrate and hiss, then promptly disintegrates!</span>")
qdel(src) //Self-destructs to prevent crew from spawning multiple engines.
else
visible_message("<span class='notice'>\The [src] buzzes! No beacon found or selected!</span>")
isactive = FALSE
return
//Deletes objects and mobs from the beacon's turf.
/obj/item/enginepicker/proc/clearturf(var/turf/T)
for(var/obj/item/I in T)
I.visible_message("\The [I] gets crushed to dust!")
qdel(I)
for(var/mob/living/M in T)
M.visible_message("\The [M] gets obliterated!")
M.gib()

View File

@@ -49,8 +49,7 @@
/obj/item/radio/beacon/bacon //Probably a better way of doing this, I'm lazy.
/obj/item/radio/beacon/bacon/proc/digest_delay()
spawn(600)
qdel(src)
QDEL_IN(src, 600)
// SINGULO BEACON SPAWNER
/obj/item/radio/beacon/syndicate
@@ -85,3 +84,23 @@
playsound(src, 'sound/effects/pop.ogg', 100, 1, 1)
qdel(src)
return
/obj/item/radio/beacon/engine
desc = "A label on it reads: <i>Warning: This device is used for transportation of high-density objects used for high-yield power generation. Stay away!</i>."
anchored = 1 //Let's not move these around. Some folk might get the idea to use these for assassinations
var/list/enginetype = list()
/obj/item/radio/beacon/engine/Initialize()
LAZYADD(GLOB.engine_beacon_list, src)
/obj/item/radio/beacon/engine/tesling
name = "Engine Beacon for Tesla and Singularity"
enginetype = list(ENGTYPE_TESLA, ENGTYPE_SING)
/obj/item/radio/beacon/engine/tesla
name = "Engine Beacon for Tesla"
enginetype = list(ENGTYPE_TESLA)
/obj/item/radio/beacon/engine/sing
name = "Engine Beacon for Singularity"
enginetype = list(ENGTYPE_SING)

View File

@@ -4,6 +4,10 @@
var/radio_desc = ""
icon_state = "headset"
item_state = "headset"
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/ears.dmi',
"Vox Armalis" = 'icons/mob/species/armalis/ears.dmi'
) //We read you loud and skree-er.
materials = list(MAT_METAL=75)
subspace_transmission = TRUE
canhear_range = 0 // can't hear headsets from very far away

View File

@@ -135,8 +135,13 @@ REAGENT SCANNER
user.show_message("<span class='notice'>Key: Suffocation/Toxin/Burns/Brute</span>", 1)
user.show_message("<span class='notice'>Body Temperature: ???</span>", 1)
return
user.visible_message("<span class='notice'>[user] has analyzed [M]'s vitals.</span>","<span class='notice'> You have analyzed [M]'s vitals.</span>")
user.visible_message("<span class='notice'>[user] has analyzed [M]'s vitals.</span>","<span class='notice'> You have analyzed [M]'s vitals.</span>")
healthscan(user, M, mode, upgraded)
add_fingerprint(user)
proc/healthscan(mob/user, mob/living/M, mode = 1, upgraded = FALSE)
if(!ishuman(M) || M.isSynthetic())
//these sensors are designed for organic life
user.show_message("<span class='notice'>Analyzing Results for ERROR:\n\t Overall Status: ERROR</span>")
@@ -271,8 +276,9 @@ REAGENT SCANNER
user.show_message("<span class='warning'>Subject's genes are showing minor signs of instability.</span>")
else
user.show_message("<span class='notice'>Subject's genes are stable.</span>")
add_fingerprint(user)
/obj/item/healthanalyzer/attack_self(mob/user)
toggle_mode()
/obj/item/healthanalyzer/verb/toggle_mode()
set name = "Switch Verbosity"

View File

@@ -123,6 +123,7 @@
/obj/item/storage/pill_bottle/random_meds
name = "unlabelled pillbottle"
desc = "The sheer recklessness of this bottle's existence astounds you."
allow_wrap = FALSE
var/labelled = FALSE
/obj/item/storage/pill_bottle/random_meds/New()

View File

@@ -133,12 +133,9 @@ var/global/list/datum/stack_recipe/sinew_recipes = list ( \
can_strengthen_clothing = typecacheof(list(
/obj/item/clothing/suit/space/hardsuit/mining,
/obj/item/clothing/head/helmet/space/hardsuit/mining,
/obj/item/clothing/suit/space/eva/plasmaman/miner,
/obj/item/clothing/head/helmet/space/eva/plasmaman/miner,
/obj/item/clothing/suit/hooded/explorer,
/obj/item/clothing/head/hooded/explorer,
/obj/item/clothing/suit/space/eva/plasmaman/explorer,
/obj/item/clothing/head/helmet/space/eva/plasmaman/explorer
/obj/item/clothing/head/helmet/space/plasmaman/mining
))
/obj/item/stack/sheet/animalhide/goliath_hide/afterattack(atom/target, mob/user, proximity_flag)

View File

@@ -178,8 +178,12 @@ var/global/list/datum/stack_recipe/wood_recipes = list(
new /datum/stack_recipe("wooden buckler", /obj/item/shield/riot/buckler, 20, time = 40),
new /datum/stack_recipe("apiary", /obj/structure/beebox, 40, time = 50),
new /datum/stack_recipe("honey frame", /obj/item/honey_frame, 5, time = 10),
new /datum/stack_recipe("wooden bucket", /obj/item/reagent_containers/glass/bucket/wooden, 3, time = 10),
new /datum/stack_recipe("rake", /obj/item/cultivator/rake, 5, time = 10),
new /datum/stack_recipe("ore box", /obj/structure/ore_box, 4, time = 50, one_per_turf = TRUE, on_floor = TRUE),
new /datum/stack_recipe("baseball bat", /obj/item/melee/baseball_bat, 5, time = 15),
new /datum/stack_recipe("fermenting barrel", /obj/structure/fermenting_barrel, 30, time = 50)
new /datum/stack_recipe("fermenting barrel", /obj/structure/fermenting_barrel, 30, time = 50),
new /datum/stack_recipe("firebrand", /obj/item/match/firebrand, 2, time = 100)
)
/obj/item/stack/sheet/wood

View File

@@ -45,7 +45,7 @@
/obj/item/defibrillator/examine(mob/user)
..(user)
to_chat(user,"<span class='notice'>Ctrl-click to remove the paddles from the defibrillator.")
to_chat(user, "<span class='notice'>Ctrl-click to remove the paddles from the defibrillator.</span>")
/obj/item/defibrillator/proc/update_power()
if(bcell)

View File

@@ -4,6 +4,7 @@
icon = 'icons/obj/dice.dmi'
icon_state = "dicebag"
can_hold = list(/obj/item/dice)
allow_wrap = FALSE
/obj/item/storage/pill_bottle/dice/New()
..()

View File

@@ -115,7 +115,8 @@
throw_range = 6
materials = list(MAT_METAL=12000)
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
sharp = 1
sharp = TRUE
var/bayonet = FALSE //Can this be attached to a gun?
/obj/item/kitchen/knife/suicide_act(mob/user)
user.visible_message(pick("<span class='suicide'>[user] is slitting [user.p_their()] wrists with the [src.name]! It looks like [user.p_theyre()] trying to commit suicide.</span>", \
@@ -164,6 +165,7 @@
throwforce = 20
origin_tech = "materials=3;combat=4"
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "cut")
bayonet = TRUE
/obj/item/kitchen/knife/combat/survival
name = "survival knife"

View File

@@ -224,3 +224,13 @@
var/mask_item = M.get_item_by_slot(slot_wear_mask)
if(istype(mask_item, /obj/item/clothing/mask/cigarette))
return mask_item
/obj/item/match/firebrand
name = "firebrand"
desc = "An unlit firebrand. It makes you wonder why it's not just called a stick."
smoketime = 20 //40 seconds
/obj/item/match/firebrand/New()
..()
matchignite()

View File

@@ -18,8 +18,10 @@
burn_state = FLAMMABLE
burntime = 20
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/back.dmi'
)
"Vox" = 'icons/mob/species/vox/back.dmi',
"Vox Armalis" = 'icons/mob/species/armalis/back.dmi',
"Grey" = 'icons/mob/species/grey/back.dmi'
) //For Armalis anything but this and the nitrogen tank will use the default backpack icon.
/obj/item/storage/backpack/attackby(obj/item/W as obj, mob/user as mob, params)
playsound(src.loc, "rustle", 50, 1, -5)
@@ -398,7 +400,7 @@
new /obj/item/gun/projectile/automatic/shotgun/bulldog(src)
new /obj/item/ammo_box/magazine/m12g(src)
new /obj/item/ammo_box/magazine/m12g(src)
new /obj/item/clothing/glasses/thermal/syndi(src)
new /obj/item/clothing/glasses/chameleon/thermal(src)
/obj/item/storage/backpack/duffel/syndie/med/medicalbundle
desc = "A large duffel bag containing a tactical medkit, a Donksoft machine gun and a big jumbo box of riot darts."

View File

@@ -113,7 +113,7 @@
New()
..()
contents = list()
new /obj/item/clothing/mask/breath(src)
new /obj/item/clothing/mask/gas/explorer(src)
new /obj/item/tank/emergency_oxygen/engi(src)
new /obj/item/crowbar/red(src)
new /obj/item/reagent_containers/hypospray/autoinjector(src)
@@ -372,6 +372,20 @@
new /obj/item/implantpad(src)
new /obj/item/locator(src)
/obj/item/storage/box/minertracker
name = "boxed tracking implant kit"
desc = "For finding those who have died on the accursed lavaworld."
icon_state = "implant"
/obj/item/storage/box/minertracker/New()
..()
new /obj/item/implantcase/tracking(src)
new /obj/item/implantcase/tracking(src)
new /obj/item/implantcase/tracking(src)
new /obj/item/implanter(src)
new /obj/item/implantpad(src)
new /obj/item/locator(src)
/obj/item/storage/box/chemimp
name = "chemical implant kit"
desc = "Box of stuff used to implant chemicals."
@@ -1082,15 +1096,6 @@
new /obj/item/stock_parts/micro_laser/quadultra(src)
new /obj/item/stock_parts/matter_bin/bluespace(src)
/obj/item/storage/box/mininghardsuit
name = "Boxed Mining Hardsuit"
desc = "Contains a mining hardsuit and helmet. For mining."
/obj/item/storage/box/mininghardsuit/New()
..()
new /obj/item/clothing/suit/space/hardsuit/mining(src)
new /obj/item/clothing/head/helmet/space/hardsuit/mining(src)
/obj/item/storage/box/hug
name = "box of hugs"
desc = "A special box for sensitive people."

View File

@@ -5,7 +5,7 @@
item_state = "briefcase"
flags = CONDUCT
hitsound = "swing_hit"
force = 8.0
force = 8
throw_speed = 2
throw_range = 4
w_class = WEIGHT_CLASS_BULKY
@@ -20,10 +20,69 @@
force = 10
/obj/item/storage/briefcase/sniperbundle/New()
..()
..()
new /obj/item/gun/projectile/automatic/sniper_rifle/syndicate(src)
new /obj/item/clothing/accessory/red(src)
new /obj/item/clothing/under/syndicate/sniper(src)
new /obj/item/ammo_box/magazine/sniper_rounds/soporific(src)
new /obj/item/ammo_box/magazine/sniper_rounds/soporific(src)
new /obj/item/suppressor/specialoffer(src)
new /obj/item/suppressor/specialoffer(src)
/obj/item/storage/briefcase/false_bottomed
max_w_class = WEIGHT_CLASS_SMALL
max_combined_w_class = 10
var/busy_hunting = FALSE
var/bottom_open = FALSE //is the false bottom open?
var/obj/item/stored_item = null //what's in the false bottom. If it's a gun, we can fire it
/obj/item/storage/briefcase/false_bottomed/Destroy()
if(stored_item)//since the stored_item isn't in the briefcase' contents we gotta remind the game to delete it here.
QDEL_NULL(stored_item)
return ..()
/obj/item/storage/briefcase/false_bottomed/afterattack(atom/A, mob/user, flag, params)
..()
if(stored_item && istype(stored_item, /obj/item/gun) && !Adjacent(A))
var/obj/item/gun/stored_gun = stored_item
stored_gun.afterattack(A, user, flag, params)
/obj/item/storage/briefcase/false_bottomed/attackby(var/obj/item/I, mob/user)
if(isscrewdriver(I))
if(!bottom_open && !busy_hunting)
to_chat(user, "You begin to hunt around the rim of the [src]...")
busy_hunting = TRUE
if(do_after(user, 20, target = src))
if(user)
to_chat(user, "You pry open the false bottom!")
bottom_open = TRUE
busy_hunting = FALSE
else if(bottom_open)
to_chat(user, "You push the false bottom down and close it with a click[stored_item ? ", with the [stored_item] snugly inside." : "."]")
bottom_open = FALSE
else if(bottom_open)
if(stored_item)
to_chat(user, "<span class='warning'>There's already something in the false bottom!</span>")
return
if(I.w_class > WEIGHT_CLASS_NORMAL)
to_chat(user, "<span class='warning'>The [I] is too big to fit in the false bottom!</span>")
return
if(!user.drop_item(I))
user << "<span class='warning'>The [I] is stuck to your hands!</span>"
return
stored_item = I
max_w_class = WEIGHT_CLASS_NORMAL - stored_item.w_class
I.forceMove(null) //null space here we go - to stop it showing up in the briefcase
to_chat(user, "You place the [I] into the false bottom of the briefcase.")
else
return ..()
/obj/item/storage/briefcase/false_bottomed/attack_hand(mob/user)
if(bottom_open && stored_item)
user.put_in_hands(stored_item)
to_chat(user, "You pull out the [stored_item] from the [src]'s false bottom.")
stored_item = null
max_w_class = initial(max_w_class)
else
return ..()

View File

@@ -254,10 +254,21 @@
var/applying_meds = FALSE //To Prevent spam clicking and generating runtimes from apply a deleting pill multiple times.
var/rapid_intake_message = "unscrews the cap on the pill bottle and begins dumping the entire contents down their throat!"
var/rapid_post_instake_message = "downs the entire bottle of pills in one go!"
var/allow_wrap = TRUE
var/wrapper_color = null
/obj/item/storage/pill_bottle/New()
..()
base_name = name
if(allow_wrap)
apply_wrap()
/obj/item/storage/pill_bottle/proc/apply_wrap()
if(wrapper_color)
overlays.Cut()
var/image/I = image(icon, "pillbottle_wrap")
I.color = wrapper_color
overlays += I
/obj/item/storage/pill_bottle/attack(mob/M, mob/user)
if(iscarbon(M) && contents.len)
@@ -274,6 +285,9 @@
else
return ..()
/obj/item/storage/pill_bottle/ert
wrapper_color = COLOR_MAROON
/obj/item/storage/pill_bottle/ert/New()
..()
new /obj/item/reagent_containers/food/pill/salicylic(src)
@@ -319,15 +333,18 @@
/obj/item/storage/pill_bottle/patch_pack
name = "Patch Pack"
desc = "It's a container for storing medical patches."
icon_state = "patch_pack"
can_hold = list(/obj/item/reagent_containers/food/pill/patch)
cant_hold = list()
rapid_intake_message = "flips the lid of the Patch Pack open and begins rapidly stamping patches on themselves!"
rapid_post_instake_message = "stamps the entire contents of the Patch Pack all over their entire body!"
allow_wrap = FALSE
/obj/item/storage/pill_bottle/charcoal
name = "Pill bottle (Charcoal)"
desc = "Contains pills used to counter toxins."
wrapper_color = COLOR_GREEN
New()
..()
@@ -342,6 +359,7 @@
/obj/item/storage/pill_bottle/painkillers
name = "Pill Bottle (Salicylic Acid)"
desc = "Contains various pills for minor pain relief."
wrapper_color = COLOR_RED
/obj/item/storage/pill_bottle/painkillers/New()
..()
@@ -354,8 +372,11 @@
new /obj/item/reagent_containers/food/pill/salicylic(src)
new /obj/item/reagent_containers/food/pill/salicylic(src)
/obj/item/storage/pill_bottle/fakedeath
allow_wrap = FALSE
/obj/item/storage/pill_bottle/fakedeath/New()
..()
new /obj/item/reagent_containers/food/pill/fakedeath(src)
new /obj/item/reagent_containers/food/pill/fakedeath(src)
new /obj/item/reagent_containers/food/pill/fakedeath(src)
new /obj/item/reagent_containers/food/pill/fakedeath(src)

View File

@@ -20,7 +20,7 @@
if("thief") // 40TC
new /obj/item/gun/energy/kinetic_accelerator/crossbow(src) // 12TC
new /obj/item/chameleon(src) // 8TC
new /obj/item/clothing/glasses/thermal/syndi(src) // 6TC
new /obj/item/clothing/glasses/chameleon/thermal(src) // 6TC
new /obj/item/clothing/gloves/color/black/thief(src) // 6TC
new /obj/item/card/id/syndicate(src) // 2TC
new /obj/item/clothing/shoes/chameleon/noslip(src) // 2TC
@@ -108,7 +108,7 @@
new /obj/item/gun/projectile/automatic/sniper_rifle/syndicate/penetrator(src) // 16TC
new /obj/item/ammo_box/magazine/sniper_rounds/penetrator(src) // 5TC
new /obj/item/ammo_box/magazine/sniper_rounds/soporific(src) // 3TC
new /obj/item/clothing/glasses/thermal/syndi/sunglasses(src) // 6TC
new /obj/item/clothing/glasses/chameleon/thermal(src) // 6TC
new /obj/item/clothing/gloves/combat(src) // 0 TC
new /obj/item/clothing/under/suit_jacket/really_black(src) // 0 TC
new /obj/item/clothing/suit/storage/lawyer/blackjacket/armored(src) // 0TC
@@ -136,36 +136,14 @@
/obj/item/storage/box/syndie_kit/hardsuit
name = "Boxed Blood Red Suit and Helmet"
can_hold = list(/obj/item/clothing/suit/space/hardsuit/syndi, /obj/item/clothing/head/helmet/space/hardsuit/syndi, /obj/item/tank/emergency_oxygen/syndi, /obj/item/clothing/mask/gas/syndicate)
can_hold = list(/obj/item/clothing/suit/space/hardsuit/syndi, /obj/item/tank/emergency_oxygen/syndi, /obj/item/clothing/mask/gas/syndicate)
max_w_class = WEIGHT_CLASS_NORMAL
/obj/item/storage/box/syndie_kit/hardsuit/New()
..()
new /obj/item/clothing/suit/space/hardsuit/syndi(src)
new /obj/item/clothing/head/helmet/space/hardsuit/syndi(src)
new /obj/item/clothing/mask/gas/syndicate(src)
new /obj/item/tank/emergency_oxygen/syndi(src)
return
/obj/item/storage/box/syndie_kit/elite_hardsuit
name = "Boxed Elite Syndicate Hardsuit and Helmet"
can_hold = list(/obj/item/clothing/suit/space/hardsuit/syndi/elite, /obj/item/clothing/head/helmet/space/hardsuit/syndi/elite)
max_w_class = WEIGHT_CLASS_NORMAL
/obj/item/storage/box/syndie_kit/elite_hardsuit/New()
..()
new /obj/item/clothing/suit/space/hardsuit/syndi/elite(src)
new /obj/item/clothing/head/helmet/space/hardsuit/syndi/elite(src)
/obj/item/storage/box/syndie_kit/shielded_hardsuit
name = "Boxed Shielded Syndicate Hardsuit and Helmet"
can_hold = list(/obj/item/clothing/suit/space/hardsuit/shielded/syndi, /obj/item/clothing/head/helmet/space/hardsuit/shielded/syndi)
max_w_class = WEIGHT_CLASS_BULKY
/obj/item/storage/box/syndie_kit/shielded_hardsuit/New()
..()
new /obj/item/clothing/suit/space/hardsuit/shielded/syndi(src)
new /obj/item/clothing/head/helmet/space/hardsuit/shielded/syndi(src)
/obj/item/storage/box/syndie_kit/conversion
name = "box (CK)"

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