Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into station_traits
This commit is contained in:
@@ -212,6 +212,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
area_flags = BLOBS_ALLOWED | UNIQUE_AREA | CULT_PERMITTED
|
||||
// airlock_wires = /datum/wires/airlock/maint
|
||||
sound_environment = SOUND_AREA_TUNNEL_ENCLOSED
|
||||
minimap_color = "#454545"
|
||||
|
||||
//Maintenance - Departmental
|
||||
|
||||
@@ -435,6 +436,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
/area/hallway
|
||||
nightshift_public_area = NIGHTSHIFT_AREA_PUBLIC
|
||||
sound_environment = SOUND_AREA_STANDARD_STATION
|
||||
minimap_color = "#aaaaaa"
|
||||
|
||||
/area/hallway/primary
|
||||
name = "Primary Hallway"
|
||||
@@ -490,6 +492,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
/area/hallway/secondary/exit
|
||||
name = "Escape Shuttle Hallway"
|
||||
icon_state = "escape"
|
||||
minimap_color = "#baa0a0"
|
||||
|
||||
/area/hallway/secondary/exit/departure_lounge
|
||||
name = "Departure Lounge"
|
||||
@@ -498,6 +501,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
/area/hallway/secondary/entry
|
||||
name = "Arrival Shuttle Hallway"
|
||||
icon_state = "entry"
|
||||
minimap_color = "#a0a0ba"
|
||||
|
||||
/area/hallway/secondary/service
|
||||
name = "Service Hallway"
|
||||
|
||||
@@ -124,6 +124,10 @@
|
||||
/// Color on minimaps, if it's null (which is default) it makes one at random.
|
||||
var/minimap_color
|
||||
|
||||
var/minimap_color2 // if this isn't null, then this will show as a checkerboard pattern mixed in with the above. works even if the above is null (for better or worse)
|
||||
|
||||
var/minimap_show_walls = TRUE
|
||||
|
||||
/**
|
||||
* These two vars allow for multiple unique areas to be linked to a master area
|
||||
* and share some functionalities such as APC powernet nodes, fire alarms etc, without sacrificing
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
ambientsounds = RUINS
|
||||
sound_environment = SOUND_ENVIRONMENT_STONEROOM
|
||||
var/valid_territory = FALSE // hey so what if we did not allow things like cult summons to appear on ruins
|
||||
minimap_color = "#775940"
|
||||
minimap_color2 = "#6b5d48"
|
||||
minimap_show_walls = FALSE
|
||||
|
||||
|
||||
/area/ruin/unpowered
|
||||
|
||||
+16
-5
@@ -518,7 +518,7 @@
|
||||
. = list("[get_examine_string(user, TRUE)].")
|
||||
|
||||
if(desc)
|
||||
. += desc
|
||||
. += "<hr>[desc]"
|
||||
|
||||
if(custom_materials)
|
||||
var/list/materials_list = list()
|
||||
@@ -702,7 +702,7 @@
|
||||
var/blood_id = get_blood_id()
|
||||
if(!(blood_id in GLOB.blood_reagent_types))
|
||||
return
|
||||
return list("color" = BLOOD_COLOR_HUMAN, "ANIMAL DNA" = "Y-")
|
||||
return list("color" = BLOOD_COLOR_HUMAN, "blendmode" = BLEND_MULTIPLY, "ANIMAL DNA" = "Y-")
|
||||
|
||||
/mob/living/carbon/get_blood_dna_list()
|
||||
var/blood_id = get_blood_id()
|
||||
@@ -711,14 +711,16 @@
|
||||
var/list/blood_dna = list()
|
||||
if(dna)
|
||||
blood_dna["color"] = dna.species.exotic_blood_color //so when combined, the list grows with the number of colors
|
||||
blood_dna["blendmode"] = dna.species.exotic_blood_blend_mode
|
||||
blood_dna[dna.unique_enzymes] = dna.blood_type
|
||||
else
|
||||
blood_dna["color"] = BLOOD_COLOR_HUMAN
|
||||
blood_dna["blendmode"] = BLEND_MULTIPLY
|
||||
blood_dna["UNKNOWN DNA"] = "X*"
|
||||
return blood_dna
|
||||
|
||||
/mob/living/carbon/alien/get_blood_dna_list()
|
||||
return list("color" = BLOOD_COLOR_XENO, "UNKNOWN DNA" = "X*")
|
||||
return list("color" = BLOOD_COLOR_XENO, "blendmode" = BLEND_MULTIPLY, "UNKNOWN DNA" = "X*")
|
||||
|
||||
//to add a mob's dna info into an object's blood_DNA list.
|
||||
/atom/proc/transfer_mob_blood_dna(mob/living/L)
|
||||
@@ -737,6 +739,7 @@
|
||||
var/old = blood_DNA["color"]
|
||||
blood_DNA["color"] = BlendRGB(blood_DNA["color"], new_blood_dna["color"])
|
||||
changed = old != blood_DNA["color"]
|
||||
blood_DNA["blendmode"] = new_blood_dna["blendmode"]
|
||||
if(blood_DNA.len == old_length)
|
||||
return FALSE
|
||||
return changed
|
||||
@@ -756,6 +759,7 @@
|
||||
blood_DNA["color"] = blood_dna["color"]
|
||||
else
|
||||
blood_DNA["color"] = BlendRGB(blood_DNA["color"], blood_dna["color"])
|
||||
blood_DNA["blendmode"] = blood_dna["blendmode"]
|
||||
|
||||
//to add blood from a mob onto something, and transfer their dna info
|
||||
/atom/proc/add_mob_blood(mob/living/M)
|
||||
@@ -826,6 +830,11 @@
|
||||
/atom/proc/blood_DNA_to_color()
|
||||
return (blood_DNA && blood_DNA["color"]) || BLOOD_COLOR_HUMAN
|
||||
|
||||
/atom/proc/blood_DNA_to_blend()
|
||||
if(blood_DNA && !isnull(blood_DNA["blendmode"]))
|
||||
return blood_DNA["blendmode"]
|
||||
return BLEND_MULTIPLY
|
||||
|
||||
/atom/proc/clean_blood()
|
||||
. = blood_DNA? TRUE : FALSE
|
||||
blood_DNA = null
|
||||
@@ -1192,6 +1201,8 @@
|
||||
log_mecha(log_text)
|
||||
if(LOG_SHUTTLE)
|
||||
log_shuttle(log_text)
|
||||
if(LOG_ECON)
|
||||
log_econ(log_text)
|
||||
else
|
||||
stack_trace("Invalid individual logging type: [message_type]. Defaulting to [LOG_GAME] (LOG_GAME).")
|
||||
log_game(log_text)
|
||||
@@ -1295,7 +1306,7 @@
|
||||
filters += filter(arglist(arguments))
|
||||
UNSETEMPTY(filter_data)
|
||||
|
||||
/atom/proc/transition_filter(name, time, list/new_params, easing, loop)
|
||||
/atom/proc/transition_filter(name, time, list/new_params, easing, loop, parallel = TRUE)
|
||||
var/filter = get_filter(name)
|
||||
if(!filter)
|
||||
return
|
||||
@@ -1306,7 +1317,7 @@
|
||||
for(var/thing in new_params)
|
||||
params[thing] = new_params[thing]
|
||||
|
||||
animate(filter, new_params, time = time, easing = easing, loop = loop)
|
||||
animate(filter, new_params, time = time, easing = easing, loop = loop, flags = (parallel ? ANIMATION_PARALLEL : 0))
|
||||
for(var/param in params)
|
||||
filter_data[name][param] = params[param]
|
||||
|
||||
|
||||
@@ -64,6 +64,16 @@
|
||||
/// last time we yelled
|
||||
var/last_yell = 0
|
||||
|
||||
// Text-to-bark sounds
|
||||
var/sound/vocal_bark
|
||||
var/vocal_bark_id
|
||||
var/vocal_pitch = 1
|
||||
var/vocal_pitch_range = 0.2 //Actual pitch is (pitch - (vocal_pitch_range*0.5)) to (pitch + (vocal_pitch_range*0.5))
|
||||
var/vocal_volume = 70 //Baseline. This gets modified by yelling and other factors
|
||||
var/vocal_speed = 4 //Lower values are faster, higher values are slower
|
||||
|
||||
var/vocal_current_bark //When barks are queued, this gets passed to the bark proc. If vocal_current_bark doesn't match the args passed to the bark proc (if passed at all), then the bark simply doesn't play. Basic curtailing of spam~
|
||||
|
||||
/atom/movable/Initialize(mapload)
|
||||
. = ..()
|
||||
switch(blocks_emissive)
|
||||
@@ -217,6 +227,10 @@
|
||||
if(NAMEOF(src, glide_size))
|
||||
set_glide_size(var_value)
|
||||
. = TRUE
|
||||
if(NAMEOF(src, vocal_bark))
|
||||
if(isfile(var_value))
|
||||
vocal_bark = sound(var_value) //bark() expects vocal_bark to already be a sound datum, for performance reasons. adminbus QoL!
|
||||
. = TRUE
|
||||
|
||||
if(!isnull(.))
|
||||
datum_flags |= DF_VAR_EDITED
|
||||
@@ -604,11 +618,11 @@
|
||||
if(throwing && !throw_override)
|
||||
return
|
||||
if(on && !(movement_type & FLOATING))
|
||||
animate(src, pixel_y = 2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
|
||||
animate(pixel_y = -2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
|
||||
animate(src, pixel_z = 2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
|
||||
animate(pixel_z = -4, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
|
||||
setMovetype(movement_type | FLOATING)
|
||||
else if (!on && (movement_type & FLOATING))
|
||||
animate(src, pixel_y = initial(pixel_y), time = 10)
|
||||
animate(src, pixel_z = initial(pixel_y), time = 10)
|
||||
setMovetype(movement_type & ~FLOATING)
|
||||
floating_need_update = FALSE // assume it's done
|
||||
|
||||
@@ -696,6 +710,17 @@
|
||||
var/datum/language_holder/LH = get_language_holder()
|
||||
return LH.update_atom_languages(src)
|
||||
|
||||
/// Sets the vocal bark for the atom, using the bark's ID
|
||||
/atom/movable/proc/set_bark(id)
|
||||
if(!id)
|
||||
return FALSE
|
||||
var/datum/bark/B = GLOB.bark_list[id]
|
||||
if(!B)
|
||||
return FALSE
|
||||
vocal_bark = sound(initial(B.soundpath))
|
||||
vocal_bark_id = id
|
||||
return vocal_bark
|
||||
|
||||
/* End language procs */
|
||||
|
||||
|
||||
@@ -774,4 +799,4 @@
|
||||
M.Turn(pick(-30, 30))
|
||||
animate(I, alpha = 175, pixel_x = to_x, pixel_y = to_y, time = 3, transform = M, easing = CUBIC_EASING)
|
||||
sleep(1)
|
||||
animate(I, alpha = 0, transform = matrix(), time = 1)
|
||||
animate(I, alpha = 0, transform = matrix(), time = 1, flags = ANIMATION_PARALLEL)
|
||||
|
||||
@@ -104,6 +104,10 @@ Class Procs:
|
||||
anchored = TRUE
|
||||
interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND | INTERACT_ATOM_UI_INTERACT
|
||||
|
||||
vocal_bark_id = "synth"
|
||||
vocal_pitch = 0.6
|
||||
vocal_volume = 40
|
||||
|
||||
var/stat = 0
|
||||
var/use_power = IDLE_POWER_USE
|
||||
//0 = dont run the auto
|
||||
@@ -312,6 +316,36 @@ Class Procs:
|
||||
|
||||
return TRUE // If we passed all of those checks, woohoo! We can interact with this machine.
|
||||
|
||||
/obj/machinery/proc/can_transact(obj/item/card/id/thecard, allowdepartment, silent)
|
||||
if(!istype(thecard))
|
||||
if(!silent)
|
||||
say("No card found.")
|
||||
return FALSE
|
||||
else if (!thecard.registered_account)
|
||||
if(!silent)
|
||||
say("No account found.")
|
||||
return FALSE
|
||||
else if(!allowdepartment && !thecard.registered_account.account_job)
|
||||
if(!silent)
|
||||
say("Departmental accounts have been blacklisted from personal expenses due to embezzlement.")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/proc/attempt_transact(obj/item/card/id/thecard, transaction_cost)
|
||||
if(!istype(thecard))
|
||||
return FALSE
|
||||
var/datum/bank_account/account = thecard.registered_account
|
||||
if(!istype(account))
|
||||
return FALSE
|
||||
|
||||
if(transaction_cost)
|
||||
if(!account.adjust_money(-transaction_cost))
|
||||
return FALSE
|
||||
var/datum/bank_account/D = SSeconomy.get_dep_account(payment_department)
|
||||
if(D)
|
||||
D.adjust_money(transaction_cost)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/proc/check_nap_violations()
|
||||
if(!SSeconomy.full_ancap)
|
||||
return TRUE
|
||||
|
||||
@@ -62,14 +62,15 @@
|
||||
if(!is_operational())
|
||||
return
|
||||
|
||||
if(shocked && !(stat & NOPOWER))
|
||||
shock(user,50)
|
||||
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "Autolathe", capitalize(src.name))
|
||||
ui.open()
|
||||
|
||||
if(shocked && !(stat & NOPOWER))
|
||||
if(shock(user,50))
|
||||
ui.close() //close the window if they got zapped successfully as to prevent them from getting zapped infinitely.
|
||||
|
||||
/obj/machinery/autolathe/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["materials"] = list()
|
||||
@@ -298,6 +299,16 @@
|
||||
wires.interact(user)
|
||||
return STOP_ATTACK_PROC_CHAIN
|
||||
|
||||
/obj/machinery/autolathe/wirecutter_act(mob/living/user, obj/item/I)
|
||||
. = ..()
|
||||
if(busy)
|
||||
balloon_alert(user, "it's busy!")
|
||||
return STOP_ATTACK_PROC_CHAIN
|
||||
|
||||
if(panel_open)
|
||||
wires.interact(user)
|
||||
return STOP_ATTACK_PROC_CHAIN
|
||||
|
||||
/obj/machinery/autolathe/proc/AfterMaterialInsert(obj/item/item_inserted, id_inserted, amount_inserted)
|
||||
if(istype(item_inserted, /obj/item/stack/ore/bluespace_crystal))
|
||||
use_power(MINERAL_MATERIAL_AMOUNT / 10)
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#define COLORMATE_TINT 1
|
||||
#define COLORMATE_HSV 2
|
||||
#define COLORMATE_MATRIX 3
|
||||
|
||||
/obj/machinery/gear_painter
|
||||
name = "\improper Color Mate"
|
||||
desc = "A machine to give your apparel a fresh new color! Recommended to use with white items for best results."
|
||||
desc = "A machine to give your apparel a fresh new color!"
|
||||
icon = 'icons/obj/vending.dmi'
|
||||
icon_state = "colormate"
|
||||
// light_mask = "colormate-light-mask"
|
||||
@@ -10,7 +14,11 @@
|
||||
var/atom/movable/inserted
|
||||
var/activecolor = "#FFFFFF"
|
||||
var/list/color_matrix_last
|
||||
var/matrix_mode = FALSE
|
||||
var/active_mode = COLORMATE_HSV
|
||||
|
||||
var/build_hue = 0
|
||||
var/build_sat = 1
|
||||
var/build_val = 1
|
||||
/// Allow holder'd mobs
|
||||
var/allow_mobs = TRUE
|
||||
/// Minimum lightness for normal mode
|
||||
@@ -71,8 +79,8 @@
|
||||
return
|
||||
if(!QDELETED(H))
|
||||
H.release()
|
||||
|
||||
insert_mob(victim, user)
|
||||
temp = "[victim] has been inserted."
|
||||
SStgui.update_uis(src)
|
||||
|
||||
if(is_type_in_list(I, allowed_types) && is_operational())
|
||||
@@ -85,7 +93,6 @@
|
||||
|
||||
inserted = I
|
||||
update_icon()
|
||||
temp = "[I] has been inserted."
|
||||
SStgui.update_uis(src)
|
||||
|
||||
else
|
||||
@@ -134,7 +141,7 @@
|
||||
|
||||
/obj/machinery/gear_painter/ui_data(mob/user)
|
||||
. = list()
|
||||
.["matrixactive"] = matrix_mode
|
||||
.["activemode"] = active_mode
|
||||
.["matrixcolors"] = list(
|
||||
"rr" = color_matrix_last[1],
|
||||
"rg" = color_matrix_last[2],
|
||||
@@ -149,6 +156,9 @@
|
||||
"cg" = color_matrix_last[11],
|
||||
"cb" = color_matrix_last[12]
|
||||
)
|
||||
.["buildhue"] = build_hue
|
||||
.["buildsat"] = build_sat
|
||||
.["buildval"] = build_val
|
||||
if(temp)
|
||||
.["temp"] = temp
|
||||
if(inserted)
|
||||
@@ -166,7 +176,7 @@
|
||||
if(inserted)
|
||||
switch(action)
|
||||
if("switch_modes")
|
||||
matrix_mode = text2num(params["mode"])
|
||||
active_mode = text2num(params["mode"])
|
||||
return TRUE
|
||||
if("choose_color")
|
||||
var/chosen_color = input(usr, "Choose a color: ", "Colormate color picking", activecolor) as color|null
|
||||
@@ -174,14 +184,11 @@
|
||||
activecolor = chosen_color
|
||||
return TRUE
|
||||
if("paint")
|
||||
if(!check_valid_color(activecolor, usr))
|
||||
return TRUE
|
||||
inserted.add_atom_colour(activecolor, FIXED_COLOUR_PRIORITY)
|
||||
playsound(src, 'sound/effects/spray3.ogg', 50, 1)
|
||||
do_paint(usr)
|
||||
temp = "Painted Successfully!"
|
||||
return TRUE
|
||||
if("drop")
|
||||
temp = "Ejected \the [inserted]!"
|
||||
temp = ""
|
||||
drop_item()
|
||||
return TRUE
|
||||
if("clear")
|
||||
@@ -192,76 +199,95 @@
|
||||
if("set_matrix_color")
|
||||
color_matrix_last[params["color"]] = params["value"]
|
||||
return TRUE
|
||||
if("matrix_paint")
|
||||
var/list/cm = rgb_construct_color_matrix(
|
||||
text2num(color_matrix_last[1]),
|
||||
text2num(color_matrix_last[2]),
|
||||
text2num(color_matrix_last[3]),
|
||||
text2num(color_matrix_last[4]),
|
||||
text2num(color_matrix_last[5]),
|
||||
text2num(color_matrix_last[6]),
|
||||
text2num(color_matrix_last[7]),
|
||||
text2num(color_matrix_last[8]),
|
||||
text2num(color_matrix_last[9]),
|
||||
text2num(color_matrix_last[10]),
|
||||
text2num(color_matrix_last[11]),
|
||||
text2num(color_matrix_last[12])
|
||||
)
|
||||
if(!check_valid_color(cm, usr))
|
||||
return TRUE
|
||||
inserted.add_atom_colour(cm, FIXED_COLOUR_PRIORITY)
|
||||
playsound(src, 'sound/effects/spray3.ogg', 50, 1)
|
||||
temp = "Matrix Painted Successfully!"
|
||||
if("set_hue")
|
||||
build_hue = clamp(text2num(params["buildhue"]), 0, 360)
|
||||
return TRUE
|
||||
if("set_sat")
|
||||
build_sat = clamp(text2num(params["buildsat"]), -10, 10)
|
||||
return TRUE
|
||||
if("set_val")
|
||||
build_val = clamp(text2num(params["buildval"]), -10, 10)
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/machinery/gear_painter/proc/do_paint(mob/user)
|
||||
var/color_to_use
|
||||
switch(active_mode)
|
||||
if(COLORMATE_TINT)
|
||||
color_to_use = activecolor
|
||||
if(COLORMATE_MATRIX)
|
||||
color_to_use = rgb_construct_color_matrix(
|
||||
text2num(color_matrix_last[1]),
|
||||
text2num(color_matrix_last[2]),
|
||||
text2num(color_matrix_last[3]),
|
||||
text2num(color_matrix_last[4]),
|
||||
text2num(color_matrix_last[5]),
|
||||
text2num(color_matrix_last[6]),
|
||||
text2num(color_matrix_last[7]),
|
||||
text2num(color_matrix_last[8]),
|
||||
text2num(color_matrix_last[9]),
|
||||
text2num(color_matrix_last[10]),
|
||||
text2num(color_matrix_last[11]),
|
||||
text2num(color_matrix_last[12])
|
||||
)
|
||||
if(COLORMATE_HSV)
|
||||
color_to_use = color_matrix_hsv(build_hue, build_sat, build_val)
|
||||
color_matrix_last = color_to_use
|
||||
if(!color_to_use || !check_valid_color(color_to_use, user))
|
||||
to_chat(user, "<span class='notice'>Invalid color.</span>")
|
||||
return FALSE
|
||||
inserted.add_atom_colour(color_to_use, FIXED_COLOUR_PRIORITY)
|
||||
playsound(src, 'sound/effects/spray3.ogg', 50, 1)
|
||||
return TRUE
|
||||
|
||||
|
||||
/// Produces the preview image of the item, used in the UI, the way the color is not stacking is a sin.
|
||||
/obj/machinery/gear_painter/proc/build_preview()
|
||||
if(inserted) //sanity
|
||||
if(matrix_mode)
|
||||
var/list/cm = rgb_construct_color_matrix(
|
||||
text2num(color_matrix_last[1]),
|
||||
text2num(color_matrix_last[2]),
|
||||
text2num(color_matrix_last[3]),
|
||||
text2num(color_matrix_last[4]),
|
||||
text2num(color_matrix_last[5]),
|
||||
text2num(color_matrix_last[6]),
|
||||
text2num(color_matrix_last[7]),
|
||||
text2num(color_matrix_last[8]),
|
||||
text2num(color_matrix_last[9]),
|
||||
text2num(color_matrix_last[10]),
|
||||
text2num(color_matrix_last[11]),
|
||||
text2num(color_matrix_last[12])
|
||||
)
|
||||
if(!check_valid_color(cm, usr))
|
||||
temp = "Failed to generate preview: Invalid color!"
|
||||
return getFlatIcon(inserted, defdir=SOUTH, no_anim=TRUE)
|
||||
var/list/cm
|
||||
switch(active_mode)
|
||||
if(COLORMATE_MATRIX)
|
||||
cm = rgb_construct_color_matrix(
|
||||
text2num(color_matrix_last[1]),
|
||||
text2num(color_matrix_last[2]),
|
||||
text2num(color_matrix_last[3]),
|
||||
text2num(color_matrix_last[4]),
|
||||
text2num(color_matrix_last[5]),
|
||||
text2num(color_matrix_last[6]),
|
||||
text2num(color_matrix_last[7]),
|
||||
text2num(color_matrix_last[8]),
|
||||
text2num(color_matrix_last[9]),
|
||||
text2num(color_matrix_last[10]),
|
||||
text2num(color_matrix_last[11]),
|
||||
text2num(color_matrix_last[12])
|
||||
)
|
||||
if(!check_valid_color(cm, usr))
|
||||
return getFlatIcon(inserted, defdir=SOUTH, no_anim=TRUE)
|
||||
|
||||
var/cur_color = inserted.color
|
||||
inserted.color = null
|
||||
inserted.color = cm
|
||||
var/icon/preview = getFlatIcon(inserted, defdir=SOUTH, no_anim=TRUE)
|
||||
inserted.color = cur_color
|
||||
if(COLORMATE_TINT)
|
||||
if(!check_valid_color(activecolor, usr))
|
||||
return getFlatIcon(inserted, defdir=SOUTH, no_anim=TRUE)
|
||||
|
||||
. = preview
|
||||
if(COLORMATE_HSV)
|
||||
cm = color_matrix_hsv(build_hue, build_sat, build_val)
|
||||
color_matrix_last = cm
|
||||
if(!check_valid_color(cm, usr))
|
||||
return getFlatIcon(inserted, defdir=SOUTH, no_anim=TRUE)
|
||||
|
||||
else
|
||||
if(!check_valid_color(activecolor, usr))
|
||||
temp = "Failed to generate preview: Invalid color!"
|
||||
return getFlatIcon(inserted, defdir=SOUTH, no_anim=TRUE)
|
||||
var/cur_color = inserted.color
|
||||
inserted.color = null
|
||||
inserted.color = (active_mode == COLORMATE_TINT ? activecolor : cm)
|
||||
var/icon/preview = getFlatIcon(inserted, defdir=SOUTH, no_anim=TRUE)
|
||||
inserted.color = cur_color
|
||||
temp = ""
|
||||
|
||||
var/cur_color = inserted.color
|
||||
inserted.color = null
|
||||
inserted.color = activecolor
|
||||
var/icon/preview = getFlatIcon(inserted, defdir=SOUTH, no_anim=TRUE)
|
||||
inserted.color = cur_color
|
||||
|
||||
. = preview
|
||||
. = preview
|
||||
|
||||
/obj/machinery/gear_painter/proc/check_valid_color(list/cm, mob/user)
|
||||
if(!islist(cm)) // normal
|
||||
var/list/HSV = ReadHSV(RGBtoHSV(cm))
|
||||
if(HSV[3] < minimum_normal_lightness)
|
||||
temp = "[cm] is far too dark (min lightness [minimum_normal_lightness]!"
|
||||
temp = "[cm] is too dark (Minimum lightness: [minimum_normal_lightness])"
|
||||
return FALSE
|
||||
return TRUE
|
||||
else // matrix
|
||||
@@ -275,6 +301,6 @@
|
||||
COLORTEST("FFFFFF", cm)
|
||||
#undef COLORTEST
|
||||
if(passed < minimum_matrix_tests)
|
||||
temp = "[english_list(color)] is not allowed (passed [passed] out of 4, minimum [minimum_matrix_tests], minimum lightness [minimum_matrix_lightness])."
|
||||
temp = "Matrix is too dark. (passed [passed] out of [minimum_matrix_tests] required tests. Minimum lightness: [minimum_matrix_lightness])."
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
@@ -6,17 +6,22 @@
|
||||
verb_say = "states"
|
||||
density = TRUE
|
||||
req_one_access = list(ACCESS_BAR, ACCESS_KITCHEN, ACCESS_HYDROPONICS, ACCESS_ENGINE, ACCESS_CARGO, ACCESS_THEATRE)
|
||||
payment_department = ACCOUNT_SRV
|
||||
var/active = FALSE
|
||||
var/list/rangers = list()
|
||||
var/stop = 0
|
||||
var/volume = 70
|
||||
var/datum/track/selection = null
|
||||
var/queuecost = PRICE_CHEAP //Set to -1 to make this jukebox require access for queueing
|
||||
var/datum/track/playing = null
|
||||
var/datum/track/selectedtrack = null
|
||||
var/list/queuedplaylist = list()
|
||||
var/queuecooldown //This var exists solely to prevent accidental repeats of John Mulaney's 'What's New Pussycat?' incident. Intentional, however......
|
||||
|
||||
/obj/machinery/jukebox/disco
|
||||
name = "radiant dance machine mark IV"
|
||||
desc = "The first three prototypes were discontinued after mass casualty incidents."
|
||||
icon_state = "disco"
|
||||
req_access = list(ACCESS_ENGINE)
|
||||
req_one_access = list(ACCESS_ENGINE)
|
||||
anchored = FALSE
|
||||
var/list/spotlights = list()
|
||||
var/list/sparkles = list()
|
||||
@@ -24,7 +29,7 @@
|
||||
/obj/machinery/jukebox/disco/indestructible
|
||||
name = "radiant dance machine mark V"
|
||||
desc = "Now redesigned with data gathered from the extensive disco and plasma research."
|
||||
req_access = null
|
||||
req_one_access = null
|
||||
anchored = TRUE
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
flags_1 = NODECONSTRUCT_1
|
||||
@@ -46,6 +51,16 @@
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/machinery/jukebox/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
obj_flags |= EMAGGED
|
||||
queuecost = PRICE_FREE
|
||||
req_one_access = null
|
||||
to_chat(user, "<span class='notice'>You've bypassed [src]'s audio volume limiter, and enabled free play.</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/jukebox/update_icon_state()
|
||||
if(active)
|
||||
icon_state = "[initial(icon_state)]-active"
|
||||
@@ -56,7 +71,7 @@
|
||||
if(!anchored)
|
||||
to_chat(user,"<span class='warning'>This device must be anchored by a wrench!</span>")
|
||||
return UI_CLOSE
|
||||
if(!allowed(user) && !isobserver(user))
|
||||
if((queuecost < 0 && !allowed(user)) && !isobserver(user))
|
||||
to_chat(user,"<span class='warning'>Error: Access Denied.</span>")
|
||||
user.playsound_local(src, 'sound/misc/compiler-failure.ogg', 25, TRUE)
|
||||
return UI_CLOSE
|
||||
@@ -77,18 +92,21 @@
|
||||
data["active"] = active
|
||||
data["songs"] = list()
|
||||
for(var/datum/track/S in SSjukeboxes.songs)
|
||||
var/list/track_data = list(
|
||||
name = S.song_name
|
||||
)
|
||||
var/list/track_data = list(name = S.song_name)
|
||||
data["songs"] += list(track_data)
|
||||
data["queued_tracks"] = list()
|
||||
for(var/datum/track/S in queuedplaylist)
|
||||
var/list/track_data = list(name = S.song_name)
|
||||
data["queued_tracks"] += list(track_data)
|
||||
data["track_selected"] = null
|
||||
data["track_length"] = null
|
||||
data["track_beat"] = null
|
||||
if(selection)
|
||||
data["track_selected"] = selection.song_name
|
||||
data["track_length"] = DisplayTimeText(selection.song_length)
|
||||
data["track_beat"] = selection.song_beat
|
||||
if(playing)
|
||||
data["track_selected"] = playing.song_name
|
||||
data["track_length"] = DisplayTimeText(playing.song_length)
|
||||
data["volume"] = volume
|
||||
data["is_emagged"] = (obj_flags & EMAGGED)
|
||||
data["cost_for_play"] = queuecost
|
||||
data["has_access"] = allowed(user)
|
||||
return data
|
||||
|
||||
/obj/machinery/jukebox/ui_act(action, list/params)
|
||||
@@ -100,57 +118,91 @@
|
||||
if("toggle")
|
||||
if(QDELETED(src))
|
||||
return
|
||||
if(!active)
|
||||
if(stop > world.time)
|
||||
to_chat(usr, "<span class='warning'>Error: The device is still resetting from the last activation, it will be ready again in [DisplayTimeText(stop-world.time)].</span>")
|
||||
playsound(src, 'sound/misc/compiler-failure.ogg', 50, TRUE)
|
||||
return
|
||||
if(!allowed(usr))
|
||||
return
|
||||
if(!active && !playing)
|
||||
activate_music()
|
||||
START_PROCESSING(SSobj, src)
|
||||
return TRUE
|
||||
else
|
||||
stop = 0
|
||||
return TRUE
|
||||
if("select_track")
|
||||
if(active)
|
||||
to_chat(usr, "<span class='warning'>Error: You cannot change the song until the current one is over.</span>")
|
||||
return TRUE
|
||||
if("add_to_queue")
|
||||
if(QDELETED(src))
|
||||
return
|
||||
if(world.time < queuecooldown)
|
||||
return
|
||||
if(!istype(selectedtrack, /datum/track))
|
||||
return
|
||||
if(!allowed(usr) && queuecost)
|
||||
var/obj/item/card/id/C
|
||||
if(isliving(usr))
|
||||
var/mob/living/L = usr
|
||||
C = L.get_idcard(TRUE)
|
||||
if(!can_transact(C))
|
||||
queuecooldown = world.time + (1 SECONDS)
|
||||
playsound(src, 'sound/misc/compiler-failure.ogg', 25, TRUE)
|
||||
return
|
||||
if(!attempt_transact(C, queuecost))
|
||||
say("Insufficient funds.")
|
||||
queuecooldown = world.time + (1 SECONDS)
|
||||
playsound(src, 'sound/misc/compiler-failure.ogg', 25, TRUE)
|
||||
return
|
||||
to_chat(usr, "<span class='notice'>You spend [queuecost] credits to queue [selectedtrack.song_name].</span>")
|
||||
log_econ("[queuecost] credits were inserted into [src] by [key_name(usr)] (ID: [C.registered_name]) to queue [selectedtrack.song_name].")
|
||||
queuedplaylist += selectedtrack
|
||||
if(active)
|
||||
say("[selectedtrack.song_name] has been added to the queue.")
|
||||
else if(!playing)
|
||||
activate_music()
|
||||
playsound(src, 'sound/machines/ping.ogg', 50, TRUE)
|
||||
queuecooldown = world.time + (3 SECONDS)
|
||||
return TRUE
|
||||
if("select_track")
|
||||
var/list/available = list()
|
||||
for(var/datum/track/S in SSjukeboxes.songs)
|
||||
available[S.song_name] = S
|
||||
var/selected = params["track"]
|
||||
if(QDELETED(src) || !selected || !istype(available[selected], /datum/track))
|
||||
return
|
||||
selection = available[selected]
|
||||
selectedtrack = available[selected]
|
||||
return TRUE
|
||||
if("set_volume")
|
||||
if(!allowed(usr))
|
||||
return
|
||||
var/new_volume = params["volume"]
|
||||
if(new_volume == "reset")
|
||||
volume = initial(volume)
|
||||
return TRUE
|
||||
else if(new_volume == "min")
|
||||
volume = 0
|
||||
return TRUE
|
||||
else if(new_volume == "max")
|
||||
volume = 100
|
||||
return TRUE
|
||||
volume = ((obj_flags & EMAGGED) ? 210 : 100)
|
||||
else if(text2num(new_volume) != null)
|
||||
volume = text2num(new_volume)
|
||||
return TRUE
|
||||
volume = clamp(0, text2num(new_volume), ((obj_flags & EMAGGED) ? 210 : 100))
|
||||
var/wherejuke = SSjukeboxes.findjukeboxindex(src)
|
||||
if(wherejuke)
|
||||
SSjukeboxes.updatejukebox(wherejuke, jukefalloff = volume/35)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/jukebox/proc/activate_music()
|
||||
var/jukeboxslottotake = SSjukeboxes.addjukebox(src, selection, 2)
|
||||
if(playing || !queuedplaylist.len)
|
||||
return FALSE
|
||||
playing = queuedplaylist[1]
|
||||
var/jukeboxslottotake = SSjukeboxes.addjukebox(src, playing, volume/35)
|
||||
if(jukeboxslottotake)
|
||||
active = TRUE
|
||||
update_icon()
|
||||
START_PROCESSING(SSobj, src)
|
||||
stop = world.time + selection.song_length
|
||||
stop = world.time + playing.song_length
|
||||
queuedplaylist.Cut(1, 2)
|
||||
say("Now playing: [playing.song_name]")
|
||||
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, TRUE)
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/jukebox/disco/activate_music()
|
||||
..()
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
dance_setup()
|
||||
lights_spin()
|
||||
|
||||
@@ -243,7 +295,7 @@
|
||||
S.pixel_y = 7
|
||||
S.forceMove(get_turf(src))
|
||||
sleep(7)
|
||||
if(selection.song_name == "Engineering's Ultimate High-Energy Hustle")
|
||||
if(playing.song_name == "Engineering's Ultimate High-Energy Hustle")
|
||||
sleep(280)
|
||||
for(var/obj/reveal in sparkles)
|
||||
reveal.alpha = 255
|
||||
@@ -299,7 +351,7 @@
|
||||
continue
|
||||
if(prob(2)) // Unique effects for the dance floor that show up randomly to mix things up
|
||||
INVOKE_ASYNC(src, .proc/hierofunk)
|
||||
sleep(selection.song_beat)
|
||||
sleep(playing.song_beat)
|
||||
|
||||
#undef DISCO_INFENO_RANGE
|
||||
|
||||
@@ -431,6 +483,7 @@
|
||||
return
|
||||
SSjukeboxes.removejukebox(position)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
playing = null
|
||||
rangers = list()
|
||||
|
||||
/obj/machinery/jukebox/disco/dance_over()
|
||||
@@ -439,12 +492,21 @@
|
||||
QDEL_LIST(sparkles)
|
||||
|
||||
/obj/machinery/jukebox/process()
|
||||
if(active && world.time >= stop)
|
||||
active = FALSE
|
||||
dance_over()
|
||||
playsound(src,'sound/machines/terminal_off.ogg',50,1)
|
||||
update_icon()
|
||||
stop = world.time + 100
|
||||
if(active)
|
||||
if(world.time >= stop)
|
||||
active = FALSE
|
||||
dance_over()
|
||||
if(stop && queuedplaylist.len)
|
||||
activate_music()
|
||||
else
|
||||
playsound(src,'sound/machines/terminal_off.ogg',50,1)
|
||||
update_icon()
|
||||
playing = null
|
||||
stop = 0
|
||||
else if(volume > 140) // BOOM BOOM BOOM BOOM
|
||||
for(var/mob/living/carbon/C in hearers(round(volume/35), src)) // I WANT YOU IN MY ROOM
|
||||
if(istype(C)) // LETS SPEND THE NIGHT TOGETHER
|
||||
C.adjustEarDamage(max((((volume/35) - sqrt(get_dist(C, src) * 4)) - C.get_ear_protection())*0.1, 0)) // FROM NOW UNTIL FOREVER
|
||||
|
||||
|
||||
/obj/machinery/jukebox/disco/process()
|
||||
|
||||
@@ -1356,6 +1356,7 @@
|
||||
/obj/machinery/door/airlock/proc/remove_electrify()
|
||||
secondsElectrified = NOT_ELECTRIFIED
|
||||
unelectrify_timerid = null
|
||||
diag_hud_set_electrified()
|
||||
|
||||
/obj/machinery/door/airlock/proc/set_electrified(seconds, mob/user)
|
||||
secondsElectrified = seconds
|
||||
|
||||
@@ -203,9 +203,13 @@ GLOBAL_LIST_EMPTY(doppler_arrays)
|
||||
point_gain = (BOMB_TARGET_POINTS * 2 * orig_light) / (orig_light + BOMB_TARGET_SIZE)
|
||||
|
||||
/*****The Point Capper*****/
|
||||
if(point_gain > linked_techweb.largest_bomb_value)
|
||||
var/old_tech_largest_bomb_value = linked_techweb.largest_bomb_value //held so we can pull old before we do math
|
||||
linked_techweb.largest_bomb_value = point_gain
|
||||
|
||||
var/list/largest_values = linked_techweb.largest_values
|
||||
if(!(LARGEST_BOMB in largest_values))
|
||||
largest_values[LARGEST_BOMB] = 0
|
||||
if(point_gain > largest_values[LARGEST_BOMB])
|
||||
var/old_tech_largest_bomb_value = largest_values[LARGEST_BOMB] //held so we can pull old before we do math
|
||||
linked_techweb.largest_values[LARGEST_BOMB] = point_gain
|
||||
point_gain -= old_tech_largest_bomb_value
|
||||
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_SCI)
|
||||
if(D)
|
||||
|
||||
@@ -230,13 +230,13 @@
|
||||
|
||||
if(beaker)
|
||||
if(beaker.reagents && beaker.reagents.reagent_list.len)
|
||||
. += "\t<span class='notice'>Attached is \a [beaker] with [beaker.reagents.total_volume] units of liquid.</span>\n"
|
||||
. += "<span class='notice'>Attached is \a [beaker] with [beaker.reagents.total_volume] units of liquid.</span>\n"
|
||||
else
|
||||
. += "\t<span class='notice'>Attached is an empty [beaker.name].</span>\n"
|
||||
. += "<span class='notice'>Attached is an empty [beaker.name].</span>\n"
|
||||
else
|
||||
. += "\t<span class='notice'>No chemicals are attached.</span>\n"
|
||||
. += "<span class='notice'>No chemicals are attached.</span>\n"
|
||||
|
||||
. += "\t<span class='notice'>[attached ? attached : "No one"] is attached.</span>"
|
||||
. += "<span class='notice'>[attached ? attached : "No one"] is attached.</span>"
|
||||
|
||||
/obj/machinery/iv_drip/telescopic
|
||||
name = "telescopic IV drip"
|
||||
|
||||
@@ -13,6 +13,17 @@
|
||||
#define TURRET_FLAG_SHOOT_BORGS (1<<6) // checks if it can shoot cyborgs
|
||||
#define TURRET_FLAG_SHOOT_HEADS (1<<7) // checks if it can shoot at heads of staff
|
||||
|
||||
DEFINE_BITFIELD(turret_flags, list(
|
||||
"TURRET_FLAG_AUTH_WEAPONS" = TURRET_FLAG_AUTH_WEAPONS,
|
||||
"TURRET_FLAG_SHOOT_ALL" = TURRET_FLAG_SHOOT_ALL,
|
||||
"TURRET_FLAG_SHOOT_ALL_REACT" = TURRET_FLAG_SHOOT_ALL_REACT,
|
||||
"TURRET_FLAG_SHOOT_ANOMALOUS" = TURRET_FLAG_SHOOT_ANOMALOUS,
|
||||
"TURRET_FLAG_SHOOT_BORGS" = TURRET_FLAG_SHOOT_BORGS,
|
||||
"TURRET_FLAG_SHOOT_CRIMINALS" = TURRET_FLAG_SHOOT_CRIMINALS,
|
||||
"TURRET_FLAG_SHOOT_HEADS" = TURRET_FLAG_SHOOT_HEADS,
|
||||
"TURRET_FLAG_SHOOT_UNSHIELDED" = TURRET_FLAG_SHOOT_UNSHIELDED,
|
||||
))
|
||||
|
||||
/obj/machinery/porta_turret
|
||||
name = "turret"
|
||||
icon = 'icons/obj/turrets.dmi'
|
||||
|
||||
@@ -29,10 +29,12 @@
|
||||
|
||||
var/obj/effect/overlay/status_display_text/message1_overlay
|
||||
var/obj/effect/overlay/status_display_text/message2_overlay
|
||||
var/mutable_appearance/ai_vtuber_overlay
|
||||
var/current_picture = ""
|
||||
var/current_mode = SD_BLANK
|
||||
var/message1 = ""
|
||||
var/message2 = ""
|
||||
var/mob/living/silicon/ai/master
|
||||
|
||||
/obj/item/wallframe/status_display
|
||||
name = "status display frame"
|
||||
@@ -122,6 +124,10 @@
|
||||
if(overlay && message == overlay.message)
|
||||
return null
|
||||
|
||||
// if an AI is controlling, we don't update the overlay
|
||||
if(master)
|
||||
return
|
||||
|
||||
if(overlay)
|
||||
qdel(overlay)
|
||||
|
||||
@@ -147,6 +153,10 @@
|
||||
remove_messages()
|
||||
return
|
||||
|
||||
if(master)
|
||||
remove_messages()
|
||||
return
|
||||
|
||||
switch(current_mode)
|
||||
if(SD_BLANK)
|
||||
remove_messages()
|
||||
@@ -493,6 +503,42 @@
|
||||
user.emote(initial(emote.key))
|
||||
break
|
||||
|
||||
// ai vtuber moment
|
||||
/obj/machinery/status_display/AICtrlClick(mob/living/silicon/ai/user)
|
||||
if(!isAI(user) || master || (user.current && !istype(user.current, /obj/machinery/status_display))) // don't let two AIs control the same one, don't let AI control two things at once
|
||||
return
|
||||
|
||||
if(!user.client.prefs.custom_holoform_icon)
|
||||
to_chat(user, span_notice("You have no custom holoform set!"))
|
||||
return
|
||||
|
||||
// move AI to the location, set master, update overlays (removes messages)
|
||||
user.current = src
|
||||
user.eyeobj.setLoc(get_turf(src))
|
||||
icon_state = initial(icon_state)
|
||||
user.controlled_display = src
|
||||
master = user
|
||||
update_overlays()
|
||||
update_appearance()
|
||||
|
||||
// we set the avatar here
|
||||
var/icon/I = icon(user.client.prefs.custom_holoform_icon)
|
||||
I.Crop(1,16,32,32)
|
||||
ai_vtuber_overlay = mutable_appearance(I)
|
||||
ai_vtuber_overlay.blend_mode = BLEND_ADD
|
||||
ai_vtuber_overlay.pixel_y = 8
|
||||
update_overlays()
|
||||
add_overlay(ai_vtuber_overlay)
|
||||
|
||||
// tell the user how to speak
|
||||
to_chat(user, span_notice("Use :q to relay messages through the status display."))
|
||||
|
||||
// modified version of how holopads 'hear' and relay to AIs
|
||||
/obj/machinery/status_display/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list())
|
||||
. = ..()
|
||||
if(master && !radio_freq && master.controlled_display == src)
|
||||
master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mods)
|
||||
|
||||
/obj/machinery/status_display/ai/process()
|
||||
if(stat & NOPOWER)
|
||||
update_appearance()
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
desc = "They look bloody and gruesome."
|
||||
icon_state = "gibbl5"
|
||||
layer = LOW_OBJ_LAYER
|
||||
blend_mode = BLEND_DEFAULT
|
||||
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6")
|
||||
mergeable_decal = FALSE
|
||||
bloodiness = 0 //This isn't supposed to be bloody.
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
desc = "It's gooey. Perhaps it's the chef's cooking?"
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
icon_state = "floor1"
|
||||
blend_mode = BLEND_MULTIPLY
|
||||
random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7")
|
||||
blood_state = BLOOD_STATE_BLOOD
|
||||
bloodiness = BLOOD_AMOUNT_PER_DECAL
|
||||
@@ -33,16 +34,20 @@
|
||||
. = ..()
|
||||
if(!fixed_color)
|
||||
add_atom_colour(blood_DNA_to_color(), FIXED_COLOUR_PRIORITY)
|
||||
blend_mode = blood_DNA_to_blend()
|
||||
|
||||
/obj/effect/decal/cleanable/blood/PersistenceSave(list/data)
|
||||
. = ..()
|
||||
data["color"] = color
|
||||
data["blendmode"] = blend_mode
|
||||
|
||||
/obj/effect/decal/cleanable/blood/PersistenceLoad(list/data)
|
||||
. = ..()
|
||||
if(data["color"])
|
||||
fixed_color = TRUE
|
||||
add_atom_colour(data["color"], FIXED_COLOUR_PRIORITY)
|
||||
if(data["blendmode"])
|
||||
blend_mode = data["blendmode"]
|
||||
name = "dried blood"
|
||||
desc = "Looks like it's been here a while. Eew"
|
||||
bloodiness = 0
|
||||
@@ -82,8 +87,8 @@
|
||||
/obj/effect/decal/cleanable/trail_holder //not a child of blood on purpose
|
||||
name = "blood"
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
icon_state = "ltrails_1"
|
||||
desc = "Your instincts say you shouldn't be following these."
|
||||
blend_mode = BLEND_MULTIPLY
|
||||
random_icon_states = null
|
||||
beauty = -50
|
||||
persistent = TRUE
|
||||
@@ -95,6 +100,7 @@
|
||||
. = ..()
|
||||
data["dir"] = dir
|
||||
data["color"] = color
|
||||
data["blendmode"] = blend_mode
|
||||
|
||||
/obj/effect/decal/cleanable/trail_holder/PersistenceLoad(list/data)
|
||||
. = ..()
|
||||
@@ -103,11 +109,14 @@
|
||||
if(data["color"])
|
||||
fixed_color = TRUE
|
||||
add_atom_colour(data["color"], FIXED_COLOUR_PRIORITY)
|
||||
if(data["blendmode"])
|
||||
blend_mode = data["blendmode"]
|
||||
|
||||
/obj/effect/decal/cleanable/trail_holder/update_icon()
|
||||
. = ..()
|
||||
if(!fixed_color)
|
||||
add_atom_colour(blood_DNA_to_color(), FIXED_COLOUR_PRIORITY)
|
||||
blend_mode = blood_DNA_to_blend()
|
||||
|
||||
/obj/effect/cleanable/trail_holder/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/effects/fire.dmi', "fire"))
|
||||
GLOBAL_DATUM_INIT(welding_sparks, /mutable_appearance, mutable_appearance('icons/effects/welding_effect.dmi', "welding_sparks", GASFIRE_LAYER, ABOVE_LIGHTING_PLANE))
|
||||
|
||||
GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
// if true, everyone item when created will have its name changed to be
|
||||
|
||||
@@ -601,11 +601,12 @@
|
||||
H.adjustOxyLoss(H.health - HALFWAYCRITDEATH, 0)
|
||||
else
|
||||
var/overall_damage = total_brute + total_burn + H.getToxLoss() + H.getOxyLoss()
|
||||
var/mobhealth = H.health
|
||||
H.adjustOxyLoss((mobhealth - HALFWAYCRITDEATH) * (H.getOxyLoss() / overall_damage), 0)
|
||||
H.adjustToxLoss((mobhealth - HALFWAYCRITDEATH) * (H.getToxLoss() / overall_damage), 0)
|
||||
H.adjustFireLoss((mobhealth - HALFWAYCRITDEATH) * (total_burn / overall_damage), 0)
|
||||
H.adjustBruteLoss((mobhealth - HALFWAYCRITDEATH) * (total_brute / overall_damage), 0)
|
||||
if(overall_damage)
|
||||
var/mobhealth = H.health
|
||||
H.adjustOxyLoss((mobhealth - HALFWAYCRITDEATH) * (H.getOxyLoss() / overall_damage), 0)
|
||||
H.adjustToxLoss((mobhealth - HALFWAYCRITDEATH) * (H.getToxLoss() / overall_damage), 0)
|
||||
H.adjustFireLoss((mobhealth - HALFWAYCRITDEATH) * (total_burn / overall_damage), 0)
|
||||
H.adjustBruteLoss((mobhealth - HALFWAYCRITDEATH) * (total_brute / overall_damage), 0)
|
||||
H.updatehealth() // Previous "adjust" procs don't update health, so we do it manually.
|
||||
user.visible_message("<span class='notice'>[req_defib ? "[defib]" : "[src]"] pings: Resuscitation successful.</span>")
|
||||
playsound(src, 'sound/machines/defib_success.ogg', 50, 0)
|
||||
|
||||
@@ -145,32 +145,29 @@ GENETICS SCANNER
|
||||
mob_status = "<span class='alert'><b>Deceased</b></span>"
|
||||
oxy_loss = max(rand(1, 40), oxy_loss, (300 - (tox_loss + fire_loss + brute_loss))) // Random oxygen loss
|
||||
|
||||
var/msg = "<span class='info'>*---------*\nAnalyzing results for [M]:\n\tOverall status: [mob_status]"
|
||||
var/msg = "<span class='info'>Analyzing results for [M]:\n<blockquote class='notice'>Overall status: [mob_status]"
|
||||
|
||||
// Damage descriptions
|
||||
if(brute_loss > 10)
|
||||
msg += "\n\t<span class='alert'>[brute_loss > 50 ? "Severe" : "Minor"] tissue damage detected.</span>"
|
||||
msg += "\n<span class='alert'>[brute_loss > 50 ? "Severe" : "Minor"] tissue damage detected.</span>"
|
||||
if(fire_loss > 10)
|
||||
msg += "\n\t<span class='alert'>[fire_loss > 50 ? "Severe" : "Minor"] burn damage detected.</span>"
|
||||
msg += "\n<span class='alert'>[fire_loss > 50 ? "Severe" : "Minor"] burn damage detected.</span>"
|
||||
if(oxy_loss > 10)
|
||||
msg += "\n\t<span class='info'><span class='alert'>[oxy_loss > 50 ? "Severe" : "Minor"] oxygen deprivation detected.</span>"
|
||||
msg += "\n<span class='info'><span class='alert'>[oxy_loss > 50 ? "Severe" : "Minor"] oxygen deprivation detected.</span>"
|
||||
if(tox_loss > 10)
|
||||
msg += "\n\t<span class='alert'>[tox_loss > 50 ? "Severe" : "Minor"] amount of [HAS_TRAIT(M, TRAIT_ROBOTIC_ORGANISM) ? "system corruption" : "toxin damage"] detected.</span>"
|
||||
msg += "\n<span class='alert'>[tox_loss > 50 ? "Severe" : "Minor"] amount of [HAS_TRAIT(M, TRAIT_ROBOTIC_ORGANISM) ? "system corruption" : "toxin damage"] detected.</span>"
|
||||
if(M.getStaminaLoss())
|
||||
msg += "\n\t<span class='alert'>Subject appears to be suffering from fatigue.</span>"
|
||||
msg += "\n<span class='alert'>Subject appears to be suffering from fatigue.</span>"
|
||||
if(advanced)
|
||||
msg += "\n\t<span class='info'>Fatigue Level: [M.getStaminaLoss()]%.</span>"
|
||||
msg += "\n<span class='info'>Fatigue Level: [M.getStaminaLoss()]%.</span>"
|
||||
if (M.getCloneLoss())
|
||||
msg += "\n\t<span class='alert'>Subject appears to have [M.getCloneLoss() > 30 ? "Severe" : "Minor"] cellular damage.</span>"
|
||||
msg += "\n<span class='alert'>Subject appears to have [M.getCloneLoss() > 30 ? "Severe" : "Minor"] cellular damage.</span>"
|
||||
if(advanced)
|
||||
msg += "\n\t<span class='info'>Cellular Damage Level: [M.getCloneLoss()].</span>"
|
||||
msg += "\n<span class='info'>Cellular Damage Level: [M.getCloneLoss()].</span>"
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(advanced && H.has_dna())
|
||||
msg += "\n\t<span class='info'>Genetic Stability: [H.dna.stability]%.</span>"
|
||||
|
||||
to_chat(user, msg)
|
||||
msg = ""
|
||||
msg += "\n<span class='info'>Genetic Stability: [H.dna.stability]%.</span>"
|
||||
|
||||
// Body part damage report
|
||||
var/list/dmgreport = list()
|
||||
@@ -178,7 +175,7 @@ GENETICS SCANNER
|
||||
var/mob/living/carbon/C = M
|
||||
var/list/damaged = C.get_damaged_bodyparts(1,1)
|
||||
if(length(damaged)>0 || oxy_loss>0 || tox_loss>0 || fire_loss>0)
|
||||
dmgreport += "<table style='margin-left:33px'><tr><font face='Verdana'>\
|
||||
dmgreport += "<table><tr><font face='Verdana'>\
|
||||
<td style='width: 90px;'><font color='#0000CC'>Damage:</font></td>\
|
||||
<td style='width: 55px;'><font color='red'><b>Brute</b></font></td>\
|
||||
<td style='width: 45px;'><font color='orange'><b>Burn</b></font></td>\
|
||||
@@ -196,7 +193,7 @@ GENETICS SCANNER
|
||||
<td><font color='red'>[(org.brute_dam > 0) ? "[org.brute_dam]" : "0"]</font></td>\
|
||||
<td><font color='orange'>[(org.burn_dam > 0) ? "[org.burn_dam]" : "0"]</font></td></tr>"
|
||||
dmgreport += "</table>"
|
||||
to_chat(user, dmgreport.Join())
|
||||
msg += "\n[dmgreport.Join()]"
|
||||
|
||||
|
||||
//Organ damages report
|
||||
@@ -317,7 +314,7 @@ GENETICS SCANNER
|
||||
damage_message += " <font color='red'>Minor [O.name] failure detected.</span>"
|
||||
|
||||
if(temp_message || damage_message)
|
||||
msg += "\t<b><span class='info'>[uppertext(O.name)]:</b></span> [damage_message] [temp_message]\n"
|
||||
msg += "\n<b><span class='info'>[uppertext(O.name)]:</b></span> [damage_message] [temp_message]\n"
|
||||
|
||||
|
||||
|
||||
@@ -332,24 +329,24 @@ GENETICS SCANNER
|
||||
var/has_liver = C.dna && !(NOLIVER in C.dna.species.species_traits)
|
||||
var/has_stomach = C.dna && !(NOSTOMACH in C.dna.species.species_traits)
|
||||
if(!M.getorganslot(ORGAN_SLOT_EYES))
|
||||
msg += "\t<span class='alert'><b>Subject does not have eyes.</b></span>\n"
|
||||
msg += "<span class='alert'><b>Subject does not have eyes.</b></span>\n"
|
||||
if(!M.getorganslot(ORGAN_SLOT_EARS))
|
||||
msg += "\t<span class='alert'><b>Subject does not have ears.</b></span>\n"
|
||||
msg += "<span class='alert'><b>Subject does not have ears.</b></span>\n"
|
||||
if(!M.getorganslot(ORGAN_SLOT_BRAIN))
|
||||
msg += "\t<span class='alert'><b>Subject's brain function is non-existent!</b></span>\n"
|
||||
msg += "<span class='alert'><b>Subject's brain function is non-existent!</b></span>\n"
|
||||
if(has_liver && !M.getorganslot(ORGAN_SLOT_LIVER))
|
||||
msg += "\t<span class='alert'><b>Subject's liver is missing!</b></span>\n"
|
||||
msg += "<span class='alert'><b>Subject's liver is missing!</b></span>\n"
|
||||
if(blooded && !M.getorganslot(ORGAN_SLOT_HEART))
|
||||
msg += "\t<span class='alert'><b>Subject's heart is missing!</b></span>\n"
|
||||
msg += "<span class='alert'><b>Subject's heart is missing!</b></span>\n"
|
||||
if(breathes && !M.getorganslot(ORGAN_SLOT_LUNGS))
|
||||
msg += "\t<span class='alert'><b>Subject's lungs have collapsed from trauma!</b></span>\n"
|
||||
msg += "<span class='alert'><b>Subject's lungs have collapsed from trauma!</b></span>\n"
|
||||
if(has_stomach && !M.getorganslot(ORGAN_SLOT_STOMACH))
|
||||
msg += "\t<span class='alert'><b>Subject's stomach is missing!</span>\n"
|
||||
msg += "<span class='alert'><b>Subject's stomach is missing!</span>\n"
|
||||
|
||||
|
||||
if(M.radiation)
|
||||
msg += "\t<span class='alert'>Subject is irradiated.</span>\n"
|
||||
msg += "\t<span class='info'>Radiation Level: [M.radiation] rad</span>\n"
|
||||
msg += "<span class='alert'>Subject is irradiated.</span>\n"
|
||||
msg += "<span class='info'>Radiation Level: [M.radiation] rad</span>\n"
|
||||
|
||||
|
||||
|
||||
@@ -383,11 +380,11 @@ GENETICS SCANNER
|
||||
else if (S.flying_species != initial(S.flying_species))
|
||||
mutant = TRUE
|
||||
|
||||
msg += "\t<span class='info'>Reported Species: [H.spec_trait_examine_font()][H.dna.custom_species ? H.dna.custom_species : S.name]</font></span>\n"
|
||||
msg += "\t<span class='info'>Base Species: [H.spec_trait_examine_font()][S.name]</font></span>\n"
|
||||
msg += "\n<span class='info'>Reported Species: [H.spec_trait_examine_font()][H.dna.custom_species ? H.dna.custom_species : S.name]</font></span>\n"
|
||||
msg += "<span class='info'>Base Species: [H.spec_trait_examine_font()][S.name]</font></span>\n"
|
||||
if(mutant)
|
||||
msg += "\t<span class='info'>Subject has mutations present.</span>\n"
|
||||
msg += "\t<span class='info'>Body temperature: [round(M.bodytemperature-T0C,0.1)] °C ([round(M.bodytemperature*1.8-459.67,0.1)] °F)</span>\n"
|
||||
msg += "<span class='info'>Subject has mutations present.</span>\n"
|
||||
msg += "<span class='info'>Body temperature: [round(M.bodytemperature-T0C,0.1)] °C ([round(M.bodytemperature*1.8-459.67,0.1)] °F)</span>\n"
|
||||
|
||||
// Time of death
|
||||
if(M.tod && (M.stat == DEAD || ((HAS_TRAIT(M, TRAIT_FAKEDEATH)) && !advanced)))
|
||||
@@ -452,14 +449,14 @@ GENETICS SCANNER
|
||||
if(cyberimp_detect)
|
||||
msg += "<span class='notice'>Detected cybernetic modifications:</span>\n"
|
||||
msg += "<span class='notice'>[cyberimp_detect]</span>\n"
|
||||
msg += "<span class='notice'>*---------*</span>"
|
||||
msg += "</blockquote>"
|
||||
to_chat(user, msg)
|
||||
SEND_SIGNAL(M, COMSIG_NANITE_SCAN, user, FALSE)
|
||||
|
||||
/proc/chemscan(mob/living/user, mob/living/M)
|
||||
if(istype(M))
|
||||
if(M.reagents)
|
||||
var/msg = "<span class='info'>*---------*\n"
|
||||
var/msg = "<blockquote class='purple'>"
|
||||
if(M.reagents.reagent_list.len)
|
||||
var/list/datum/reagent/reagents = list()
|
||||
for(var/datum/reagent/R in M.reagents.reagent_list)
|
||||
@@ -498,7 +495,7 @@ GENETICS SCANNER
|
||||
if(95 to INFINITY)
|
||||
msg += "<span class='danger'>Subject contains a extremely dangerous amount of toxic isomers.</span>\n"
|
||||
|
||||
msg += "*---------*</span>"
|
||||
msg += "</blockquote>"
|
||||
to_chat(user, msg)
|
||||
|
||||
/obj/item/healthanalyzer/verb/toggle_mode()
|
||||
@@ -529,12 +526,14 @@ GENETICS SCANNER
|
||||
|
||||
var/render_list = ""
|
||||
for(var/i in patient.get_wounded_bodyparts())
|
||||
if(render_list == "")
|
||||
render_list += "<blockquote class='warning'>"
|
||||
var/obj/item/bodypart/wounded_part = i
|
||||
render_list += "<span class='alert ml-1'><b>Warning: Physical trauma[LAZYLEN(wounded_part.wounds) > 1? "s" : ""] detected in [wounded_part.name]</b>"
|
||||
for(var/k in wounded_part.wounds)
|
||||
var/datum/wound/W = k
|
||||
render_list += "<div class='ml-2'>[W.get_scanner_description()]</div>\n"
|
||||
render_list += "</span>"
|
||||
render_list += "</blockquote>"
|
||||
|
||||
if(render_list == "")
|
||||
if(istype(scanner))
|
||||
|
||||
@@ -205,6 +205,10 @@
|
||||
if(!throw_item(target, I, user))
|
||||
break
|
||||
|
||||
if(user)
|
||||
shake_camera(user, (pressureSetting * 0.75 + 1), (pressureSetting * 0.75))
|
||||
|
||||
|
||||
/obj/item/pneumatic_cannon/proc/throw_item(turf/target, obj/item/I, mob/user)
|
||||
if(!istype(I))
|
||||
return FALSE
|
||||
|
||||
@@ -22,8 +22,8 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
|
||||
new/datum/stack_recipe("spout flask", /obj/item/glasswork/glass_base/spouty, 20), \
|
||||
new/datum/stack_recipe("small bulb flask", /obj/item/glasswork/glass_base/flask_small, 5), \
|
||||
new/datum/stack_recipe("large bottle flask", /obj/item/glasswork/glass_base/flask_large, 15), \
|
||||
new/datum/stack_recipe("tea cup", /obj/item/glasswork/glass_base/tea_plate, 5), \
|
||||
new/datum/stack_recipe("tea plate", /obj/item/glasswork/glass_base/tea_cup, 5), \
|
||||
new/datum/stack_recipe("tea cup", /obj/item/glasswork/glass_base/tea_cup, 5), \
|
||||
new/datum/stack_recipe("tea plate", /obj/item/glasswork/glass_base/tea_plate, 5), \
|
||||
)), \
|
||||
))
|
||||
|
||||
|
||||
@@ -561,4 +561,4 @@
|
||||
singular_name = "catwalk floor tile"
|
||||
desc = "Flooring that shows its contents underneath. Engineers love it!"
|
||||
icon_state = "catwalk_tile"
|
||||
turf_type = /turf/open/floor/plating/catwalk_floor
|
||||
turf_type = /turf/open/floor/catwalk_floor
|
||||
|
||||
@@ -119,6 +119,11 @@
|
||||
dyn_explosion(T, plasmaAmount/5)//20 plasma in a standard welder has a 4 power explosion. no breaches, but enough to kill/dismember holder
|
||||
qdel(src)
|
||||
|
||||
/obj/item/weldingtool/use_tool(atom/target, mob/living/user, delay, amount, volume, datum/callback/extra_checks, skill_gain_mult)
|
||||
target.add_overlay(GLOB.welding_sparks)
|
||||
. = ..()
|
||||
target.cut_overlay(GLOB.welding_sparks)
|
||||
|
||||
/obj/item/weldingtool/attack(mob/living/carbon/human/H, mob/user)
|
||||
if(!istype(H))
|
||||
return ..()
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
var/obj_flags = CAN_BE_HIT
|
||||
var/set_obj_flags // ONLY FOR MAPPING: Sets flags from a string list, handled in Initialize. Usage: set_obj_flags = "EMAGGED;!CAN_BE_HIT" to set EMAGGED and clear CAN_BE_HIT.
|
||||
|
||||
var/minimap_override_color // allows this obj to set its own color on the minimap
|
||||
|
||||
var/damtype = BRUTE
|
||||
var/force = 0
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
/obj/structure/proc/do_climb(atom/movable/A)
|
||||
if(climbable)
|
||||
density = FALSE
|
||||
. = step(A,get_dir(A,src.loc))
|
||||
. = step(A, (A.loc == loc ? dir : get_dir(A,src.loc)))
|
||||
density = TRUE
|
||||
|
||||
/obj/structure/proc/climb_structure(mob/living/user)
|
||||
|
||||
@@ -156,9 +156,10 @@
|
||||
for(var/atom/movable/AM in L)
|
||||
if(AM != src && insert(AM) == -1) // limit reached
|
||||
break
|
||||
// for(var/i in reverseRange(L.GetAllContents()))
|
||||
// var/atom/movable/thing = i
|
||||
// SEND_SIGNAL(thing, COMSIG_TRY_STORAGE_HIDE_ALL)
|
||||
// todo: this should be unnecessary, storage should auto close on move wtf
|
||||
for(var/i in reverseRange(L.GetAllContents()))
|
||||
var/atom/movable/thing = i
|
||||
SEND_SIGNAL(thing, COMSIG_TRY_STORAGE_HIDE_ALL)
|
||||
|
||||
/obj/structure/closet/proc/open(mob/living/user, force = FALSE)
|
||||
if(!can_open(user, force))
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
new /obj/item/clothing/under/rank/security/officer/blueshirt/seccorp/hoscorp(src)
|
||||
new /obj/item/clothing/suit/armor/vest/leather(src)
|
||||
new /obj/item/clothing/suit/armor/hos(src)
|
||||
new /obj/item/clothing/suit/armor/hos/platecarrier(src)
|
||||
new /obj/item/clothing/under/rank/security/head_of_security/skirt(src)
|
||||
new /obj/item/clothing/under/rank/security/head_of_security/alt(src)
|
||||
new /obj/item/clothing/under/rank/security/head_of_security/alt/skirt(src)
|
||||
|
||||
+29
-1
@@ -31,14 +31,42 @@ GLOBAL_LIST_INIT(freqtospan, list(
|
||||
/atom/movable/proc/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
|
||||
SEND_SIGNAL(src, COMSIG_MOVABLE_HEAR, args)
|
||||
|
||||
/atom/movable/proc/bark(list/hearers, distance, volume, pitch, queue_time)
|
||||
if(queue_time && vocal_current_bark != queue_time)
|
||||
return
|
||||
if(SEND_SIGNAL(src, COMSIG_MOVABLE_BARK, hearers, distance, volume, pitch))
|
||||
return //bark interception. this probably counts as some flavor of BDSM
|
||||
if(!vocal_bark)
|
||||
if(!vocal_bark_id || !set_bark(vocal_bark_id)) //just-in-time bark generation
|
||||
return
|
||||
volume = min(volume, 100)
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/mob/M in hearers)
|
||||
M.playsound_local(T, vol = volume, vary = TRUE, frequency = pitch, max_distance = distance, falloff_distance = 0, falloff_exponent = BARK_SOUND_FALLOFF_EXPONENT(distance), S = vocal_bark, distance_multiplier = 1)
|
||||
|
||||
/atom/movable/proc/can_speak()
|
||||
return 1
|
||||
|
||||
/atom/movable/proc/send_speech(message, range = 7, atom/movable/source = src, bubble_type, list/spans, datum/language/message_language = null, message_mode)
|
||||
var/rendered = compose_message(src, message_language, message, , spans, message_mode, source)
|
||||
for(var/_AM in get_hearers_in_view(range, source))
|
||||
var/list/hearers = get_hearers_in_view(range, source)
|
||||
for(var/_AM in hearers)
|
||||
var/atom/movable/AM = _AM
|
||||
AM.Hear(rendered, src, message_language, message, , spans, message_mode, source)
|
||||
if(SEND_SIGNAL(src, COMSIG_MOVABLE_QUEUE_BARK, hearers, args) || vocal_bark || vocal_bark_id)
|
||||
for(var/mob/M in hearers)
|
||||
if(!M.client)
|
||||
continue
|
||||
if(!(M.client.prefs.toggles & SOUND_BARK))
|
||||
hearers -= M
|
||||
var/barks = min(round((LAZYLEN(message) / vocal_speed)) + 1, BARK_MAX_BARKS)
|
||||
var/total_delay
|
||||
vocal_current_bark = world.time //this is juuuuust random enough to reliably be unique every time send_speech() is called, in most scenarios
|
||||
for(var/i in 1 to barks)
|
||||
if(total_delay > BARK_MAX_TIME)
|
||||
break
|
||||
addtimer(CALLBACK(src, .proc/bark, hearers, range, vocal_volume, BARK_DO_VARY(vocal_pitch, vocal_pitch_range), vocal_current_bark), total_delay)
|
||||
total_delay += rand(DS2TICKS(vocal_speed / BARK_SPEED_BASELINE), DS2TICKS(vocal_speed / BARK_SPEED_BASELINE) + DS2TICKS(vocal_speed / BARK_SPEED_BASELINE)) TICKS
|
||||
|
||||
/atom/movable/proc/compose_message(atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode, face_name = FALSE, atom/movable/source)
|
||||
if(!source)
|
||||
|
||||
+11
-4
@@ -110,13 +110,20 @@ distance_multiplier - Can be used to multiply the distance at which the sound is
|
||||
*/
|
||||
|
||||
/mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff_exponent = SOUND_FALLOFF_EXPONENT, channel = 0, pressure_affected = TRUE, sound/S, max_distance,
|
||||
falloff_distance = SOUND_DEFAULT_FALLOFF_DISTANCE, distance_multiplier = SOUND_DEFAULT_DISTANCE_MULTIPLIER, envwet = -10000, envdry = 0)
|
||||
if(!client || !can_hear())
|
||||
falloff_distance = SOUND_DEFAULT_FALLOFF_DISTANCE, distance_multiplier = SOUND_DEFAULT_DISTANCE_MULTIPLIER, envwet = -10000, envdry = 0, virtual_hearer)
|
||||
if(audiovisual_redirect)
|
||||
virtual_hearer = get_turf(src)
|
||||
audiovisual_redirect.playsound_local(turf_source, soundin, vol, vary, frequency, falloff_exponent, channel, pressure_affected, S, max_distance, falloff_distance, distance_multiplier, max(0, envwet), -10000, virtual_hearer)
|
||||
//No return here, as we want to deliberately support the possibility of shenanigans in which mobs with clients can have active AV redirects to completely different players
|
||||
if(!client)
|
||||
return
|
||||
|
||||
if(!S)
|
||||
S = sound(get_sfx(soundin))
|
||||
|
||||
if(!can_hear() && !(S.status & SOUND_UPDATE)) //This is primarily to make sure sound updates still go through when a spaceman's deaf
|
||||
return
|
||||
|
||||
S.wait = 0 //No queue
|
||||
S.channel = channel || SSsounds.random_available_channel()
|
||||
S.volume = vol
|
||||
@@ -131,7 +138,7 @@ distance_multiplier - Can be used to multiply the distance at which the sound is
|
||||
S.frequency = get_rand_frequency()
|
||||
|
||||
if(isturf(turf_source))
|
||||
var/turf/T = get_turf(src)
|
||||
var/turf/T = virtual_hearer || get_turf(src)
|
||||
|
||||
//sound volume falloff with distance
|
||||
var/distance = get_dist(T, turf_source)
|
||||
@@ -173,7 +180,7 @@ distance_multiplier - Can be used to multiply the distance at which the sound is
|
||||
var/dz = turf_source.y - T.y // Hearing from infront/behind
|
||||
S.z = dz * distance_multiplier
|
||||
var/dy = (turf_source.z - T.z) * 5 * distance_multiplier // Hearing from above / below, multiplied by 5 because we assume height is further along coords.
|
||||
S.y = dy + 1
|
||||
S.y = dy + distance_multiplier
|
||||
|
||||
S.falloff = isnull(max_distance)? FALLOFF_SOUNDS : max_distance //use max_distance, else just use 1 as we are a direct sound so falloff isnt relevant.
|
||||
|
||||
|
||||
@@ -73,16 +73,26 @@
|
||||
|
||||
/turf/closed/indestructible/splashscreen
|
||||
name = "Space Station 13"
|
||||
icon = 'icons/blank_title.png'
|
||||
desc = null
|
||||
icon = 'icons/blanks/blank_title.png'
|
||||
icon_state = ""
|
||||
layer = FLY_LAYER
|
||||
plane = SPLASHSCREEN_PLANE
|
||||
bullet_bounce_sound = null
|
||||
|
||||
/turf/closed/indestructible/splashscreen/New()
|
||||
INITIALIZE_IMMEDIATE(/turf/closed/indestructible/splashscreen)
|
||||
|
||||
/turf/closed/indestructible/splashscreen/Initialize(mapload)
|
||||
. = ..()
|
||||
SStitle.splash_turf = src
|
||||
if(SStitle.icon)
|
||||
icon = SStitle.icon
|
||||
..()
|
||||
handle_generic_titlescreen_sizes()
|
||||
|
||||
///helper proc that will center the screen if the icon is changed to a generic width, to make admins have to fudge around with pixel_x less. returns null
|
||||
/turf/closed/indestructible/splashscreen/proc/handle_generic_titlescreen_sizes()
|
||||
var/icon/size_check = icon(SStitle.icon, icon_state)
|
||||
var/width = size_check.Width()
|
||||
pixel_x = (672 - width) * 0.5 //The title screen is mapped with the expectation that it's 672x480. Should probably turn the title screen size into a define some time!
|
||||
|
||||
/turf/closed/indestructible/splashscreen/vv_edit_var(var_name, var_value)
|
||||
. = ..()
|
||||
@@ -90,7 +100,13 @@
|
||||
switch(var_name)
|
||||
if(NAMEOF(src, icon))
|
||||
SStitle.icon = icon
|
||||
handle_generic_titlescreen_sizes()
|
||||
|
||||
/turf/closed/indestructible/start_area
|
||||
name = null
|
||||
desc = null
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
|
||||
/turf/closed/indestructible/riveted
|
||||
icon = 'icons/turf/walls/riveted.dmi'
|
||||
icon_state = "riveted"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* you can crowbar it to interact with the underneath stuff without destroying the tile...
|
||||
* unless you want to!
|
||||
*/
|
||||
/turf/open/floor/plating/catwalk_floor
|
||||
/turf/open/floor/catwalk_floor
|
||||
icon = 'icons/turf/floors/catwalk_plating.dmi'
|
||||
icon_state = "catwalk_below"
|
||||
floor_tile = /obj/item/stack/tile/catwalk
|
||||
@@ -16,29 +16,35 @@
|
||||
barefootstep = FOOTSTEP_CATWALK
|
||||
clawfootstep = FOOTSTEP_CATWALK
|
||||
heavyfootstep = FOOTSTEP_CATWALK
|
||||
intact = FALSE
|
||||
var/covered = TRUE
|
||||
|
||||
/turf/open/floor/plating/catwalk_floor/Initialize(mapload)
|
||||
/turf/open/floor/catwalk_floor/Initialize(mapload)
|
||||
. = ..()
|
||||
layer = CATWALK_LAYER
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
|
||||
/turf/open/floor/plating/catwalk_floor/update_overlays()
|
||||
/turf/open/floor/catwalk_floor/update_overlays()
|
||||
. = ..()
|
||||
var/static/catwalk_overlay
|
||||
var/static/image/catwalk_overlay
|
||||
if(isnull(catwalk_overlay))
|
||||
catwalk_overlay = iconstate2appearance(icon, "catwalk_above")
|
||||
catwalk_overlay = new()
|
||||
catwalk_overlay.icon = icon
|
||||
catwalk_overlay.icon_state = "catwalk_above"
|
||||
catwalk_overlay.plane = GAME_PLANE
|
||||
catwalk_overlay.layer = CATWALK_LAYER
|
||||
catwalk_overlay = catwalk_overlay.appearance
|
||||
if(covered)
|
||||
. += catwalk_overlay
|
||||
|
||||
/turf/open/floor/plating/catwalk_floor/screwdriver_act(mob/living/user, obj/item/tool)
|
||||
/turf/open/floor/catwalk_floor/screwdriver_act(mob/living/user, obj/item/tool)
|
||||
. = ..()
|
||||
covered = !covered
|
||||
user.balloon_alert(user, "[!covered ? "cover removed" : "cover added"]")
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
|
||||
/turf/open/floor/plating/catwalk_floor/pry_tile(obj/item/crowbar, mob/user, silent)
|
||||
/turf/open/floor/catwalk_floor/crowbar_act(mob/user, obj/item/I)
|
||||
if(covered)
|
||||
user.balloon_alert(user, "remove cover first!")
|
||||
return FALSE
|
||||
. = ..()
|
||||
return pry_tile(I, user)
|
||||
|
||||
@@ -117,6 +117,7 @@ GLOBAL_LIST(topic_status_cache)
|
||||
GLOB.world_asset_log = "[GLOB.log_directory]/asset.log"
|
||||
GLOB.world_attack_log = "[GLOB.log_directory]/attack.log"
|
||||
GLOB.world_victim_log = "[GLOB.log_directory]/victim.log"
|
||||
GLOB.world_econ_log = "[GLOB.log_directory]/econ.log"
|
||||
GLOB.world_pda_log = "[GLOB.log_directory]/pda.log"
|
||||
GLOB.world_telecomms_log = "[GLOB.log_directory]/telecomms.log"
|
||||
GLOB.world_manifest_log = "[GLOB.log_directory]/manifest.log"
|
||||
|
||||
Reference in New Issue
Block a user