This commit is contained in:
izac112
2020-08-22 20:07:45 +02:00
339 changed files with 12177 additions and 5535 deletions

View File

@@ -8,6 +8,6 @@ export PHP_VERSION=5.6
# Byond Major
export BYOND_MAJOR=513
# Byond Minor
export BYOND_MINOR=1526
export BYOND_MINOR=1528
# Macro Count
export MACRO_COUNT=4

View File

@@ -128,7 +128,7 @@
return 1
playsound(src, W.usesound, 50, 1)
to_chat(user, "<span class='notice'>You begin to unfasten \the [src]...</span>")
if (do_after(user, 40 * W.toolspeed))
if (do_after(user, 10 * W.toolspeed))
user.visible_message( \
"<span class='notice'>\The [user] unfastens \the [src].</span>", \
"<span class='notice'>You have unfastened \the [src].</span>", \

3
code/__defines/hoses.dm Normal file
View File

@@ -0,0 +1,3 @@
#define HOSE_INPUT "Input"// Only pull liquid.
#define HOSE_OUTPUT "Output"// Only push liquid.
#define HOSE_NEUTRAL "Neutral"// Equalize liquids, not super efficient, can waste reagents due to rounding.

View File

@@ -462,3 +462,16 @@ GLOBAL_LIST_EMPTY(##LIST_NAME);\
#define FONT_HUGE(X) "<font size='4'>[X]</font>"
#define FONT_GIANT(X) "<font size='5'>[X]</font>"
#define VOLUME_CHANNEL_MASTER "Master"
#define VOLUME_CHANNEL_AMBIENCE "Ambience"
#define VOLUME_CHANNEL_ALARMS "Alarms"
#define VOLUME_CHANNEL_VORE "Vore"
// Make sure you update this or clients won't be able to adjust the channel
GLOBAL_LIST_INIT(all_volume_channels, list(
VOLUME_CHANNEL_MASTER,
VOLUME_CHANNEL_AMBIENCE,
VOLUME_CHANNEL_ALARMS,
VOLUME_CHANNEL_VORE,
))

View File

@@ -214,6 +214,13 @@
#define O_AUG_SPINE "spinal augment"
#define O_AUG_PELVIC "pelvic augment"
// FBP components.
#define O_PUMP "hydraulic hub"
#define O_CYCLER "reagent cycler"
#define O_HEATSINK "thermal regulator"
#define O_DIAGNOSTIC "diagnostic controller"
// Non-Standard organs
#define O_MOUTH "mouth"
#define O_CELL "cell"

View File

@@ -3,3 +3,6 @@ GLOBAL_LIST_EMPTY(meteor_list)
/// List of wire colors for each object type of that round. One for airlocks, one for vendors, etc.
GLOBAL_LIST_EMPTY(wire_color_directory) // This is an associative list with the `holder_type` as the key, and a list of colors as the value.
// Reference list for disposal sort junctions. Filled up by sorting junction's New()
GLOBAL_LIST_EMPTY(tagger_locations)

View File

@@ -9,6 +9,7 @@ var/global/list/ai_list = list() //List of all AIs, including clientless
var/global/list/living_mob_list = list() //List of all alive mobs, including clientless. Excludes /mob/new_player
var/global/list/dead_mob_list = list() //List of all dead mobs, including clientless. Excludes /mob/new_player
var/global/list/listening_objects = list() //List of all objects which care about receiving messages (communicators, radios, etc)
var/global/list/cleanbot_reserved_turfs = list() //List of all turfs currently targeted by some cleanbot
var/global/list/cable_list = list() //Index for all cables, so that powernets don't have to look through the entire world all the time
var/global/list/landmarks_list = list() //list of all landmarks created

View File

@@ -454,3 +454,35 @@ proc/TextPreview(var/string,var/len=40)
#define gender2text(gender) capitalize(gender)
/// Used to get a properly sanitized input, of max_length
/// no_trim is self explanatory but it prevents the input from being trimed if you intend to parse newlines or whitespace.
/proc/stripped_input(mob/user, message = "", title = "", default = "", max_length=MAX_MESSAGE_LEN, no_trim=FALSE)
var/name = input(user, message, title, default) as text|null
if(no_trim)
return copytext(html_encode(name), 1, max_length)
else
return trim(html_encode(name), max_length) //trim is "outside" because html_encode can expand single symbols into multiple symbols (such as turning < into &lt;)
// Used to get a properly sanitized multiline input, of max_length
/proc/stripped_multiline_input(mob/user, message = "", title = "", default = "", max_length=MAX_MESSAGE_LEN, no_trim=FALSE)
var/name = input(user, message, title, default) as message|null
if(no_trim)
return copytext(html_encode(name), 1, max_length)
else
return trim(html_encode(name), max_length)
//Adds 'char' ahead of 'text' until there are 'count' characters total
/proc/add_leading(text, count, char = " ")
text = "[text]"
var/charcount = count - length_char(text)
var/list/chars_to_add[max(charcount + 1, 0)]
return jointext(chars_to_add, char) + text
//Adds 'char' behind 'text' until there are 'count' characters total
/proc/add_trailing(text, count, char = " ")
text = "[text]"
var/charcount = count - length_char(text)
var/list/chars_to_add[max(charcount + 1, 0)]
return text + jointext(chars_to_add, char)

View File

@@ -51,6 +51,9 @@
if(modifiers["shift"] && modifiers["ctrl"])
CtrlShiftClickOn(A)
return 1
if(modifiers["shift"] && modifiers["middle"])
ShiftMiddleClickOn(A)
return 1
if(modifiers["middle"])
MiddleClickOn(A)
return 1
@@ -111,12 +114,11 @@
trigger_aiming(TARGET_CAN_CLICK)
return 1
// VOREStation Addition Start: inbelly item interaction
// VOREStation Addition Start: inbelly interaction
if(isbelly(loc) && (loc == A.loc))
if(W)
var/resolved = W.resolve_attackby(A,src)
if(!resolved && A && W)
W.afterattack(A, src, 1, params) // 1: clicking something Adjacent
to_chat(src, "The firm confines prevent that kind of dexterity!") //Only hand-based interactions in bellies
return
else
if(ismob(A)) // No instant mob attacking
setClickCooldown(get_attack_speed())
@@ -230,6 +232,15 @@
return
*/
/*
Shift middle click
Used for pointing.
*/
/mob/proc/ShiftMiddleClickOn(atom/A)
pointed(A)
return
/*
Shift click
For most mobs, examine.
@@ -271,13 +282,16 @@
/atom/proc/AltClick(var/mob/user)
var/turf/T = get_turf(src)
if(T && user.TurfAdjacent(T))
if(user.listed_turf == T)
user.listed_turf = null
else
user.listed_turf = T
user.client.statpanel = "Turf"
user.ToggleTurfTab(T)
return 1
/mob/proc/ToggleTurfTab(var/turf/T)
if(listed_turf == T)
listed_turf = null
else
listed_turf = T
client.statpanel = "Turf"
/mob/proc/TurfAdjacent(var/turf/T)
return T.AdjacentQuick(src)

View File

@@ -20,6 +20,9 @@
if(modifiers["shift"] && modifiers["ctrl"])
CtrlShiftClickOn(A)
return
if(modifiers["shift"] && modifiers["middle"])
ShiftMiddleClickOn(A)
return
if(modifiers["middle"])
MiddleClickOn(A)
return

View File

@@ -33,6 +33,15 @@
return
if(!checkClickCooldown()) return
setClickCooldown(4)
var/list/modifiers = params2list(params)
if(modifiers["shift"])
examinate(A)
return
if(modifiers["alt"]) // alt and alt-gr (rightalt)
var/turf/T = get_turf(A)
if(T && TurfAdjacent(T))
ToggleTurfTab(T)
return
// You are responsible for checking config.ghost_interaction when you override this function
// Not all of them require checking, see below
A.attack_ghost(src)

View File

@@ -237,7 +237,8 @@ var/list/gamemode_cache = list()
var/static/dooc_allowed = 1
var/static/dsay_allowed = 1
var/persistence_enabled = 1
var/persistence_disabled = FALSE
var/persistence_ignore_mapload = FALSE
var/allow_byond_links = 0
var/allow_discord_links = 0
@@ -583,8 +584,11 @@ var/list/gamemode_cache = list()
if("protect_roles_from_antagonist")
config.protect_roles_from_antagonist = 1
if ("persistence_enabled")
config.persistence_enabled = 1
if("persistence_disabled")
config.persistence_disabled = TRUE // Previously this forcibly set persistence enabled in the saves.
if("persistence_ignore_mapload")
config.persistence_ignore_mapload = TRUE
if ("probability")
var/prob_pos = findtext(value, " ")

View File

@@ -19,7 +19,7 @@ SUBSYSTEM_DEF(persistence)
/datum/controller/subsystem/persistence/proc/track_value(var/atom/value, var/track_type)
if(config.persistence_enabled == 0) //if the config is not set to persistent nothing will save or load.
if(config.persistence_disabled) //if the config is set to persistence disabled, nothing will save or load.
return
var/turf/T = get_turf(value)

View File

@@ -6,38 +6,49 @@
name = "water-cooler bottle"
path =/obj/item/weapon/reagent_containers/glass/cooler_bottle
/datum/category_item/autolathe/general/drinkingglass_square
/datum/category_item/autolathe/general/drinkingglass
is_stack = TRUE
/datum/category_item/autolathe/general/drinkingglass/square
name = "half-pint glass"
path =/obj/item/weapon/reagent_containers/food/drinks/glass2/square
/datum/category_item/autolathe/general/drinkingglass_rocks
/datum/category_item/autolathe/general/drinkingglass/rocks
name = "rocks glass"
path =/obj/item/weapon/reagent_containers/food/drinks/glass2/rocks
/datum/category_item/autolathe/general/drinkingglass_shake
/datum/category_item/autolathe/general/drinkingglass/shake
name = "milkshake glass"
path =/obj/item/weapon/reagent_containers/food/drinks/glass2/shake
/datum/category_item/autolathe/general/drinkingglass_cocktail
/datum/category_item/autolathe/general/drinkingglass/cocktail
name = "cocktail glass"
path =/obj/item/weapon/reagent_containers/food/drinks/glass2/cocktail
/datum/category_item/autolathe/general/drinkingglass_shot
/datum/category_item/autolathe/general/drinkingglass/shot
name = "shot glass"
path =/obj/item/weapon/reagent_containers/food/drinks/glass2/shot
/datum/category_item/autolathe/general/drinkingglass_pint
/datum/category_item/autolathe/general/drinkingglass/pint
name = "pint glass"
path =/obj/item/weapon/reagent_containers/food/drinks/glass2/pint
/datum/category_item/autolathe/general/drinkingglass_mug
/datum/category_item/autolathe/general/drinkingglass/mug
name = "glass mug"
path =/obj/item/weapon/reagent_containers/food/drinks/glass2/mug
/datum/category_item/autolathe/general/drinkingglass_wine
/datum/category_item/autolathe/general/drinkingglass/wine
name = "wine glass"
path =/obj/item/weapon/reagent_containers/food/drinks/glass2/wine
/datum/category_item/autolathe/general/drinkingglass/metaglass
name = "metamorphic glass"
path =/obj/item/weapon/reagent_containers/food/drinks/metaglass
/datum/category_item/autolathe/general/drinkingglass/metaglass/metapint
name = "metamorphic pint glass"
path =/obj/item/weapon/reagent_containers/food/drinks/metaglass/metapint
/datum/category_item/autolathe/general/flashlight
name = "flashlight"
path =/obj/item/device/flashlight

View File

@@ -2,40 +2,11 @@
name = "Holo-collar"
path =/obj/item/clothing/accessory/collar/holo
/datum/category_item/autolathe/general/drinkingglass_square
is_stack = TRUE
/datum/category_item/autolathe/general/drinkingglass_rocks
is_stack = TRUE
/datum/category_item/autolathe/general/drinkingglass_shake
is_stack = TRUE
/datum/category_item/autolathe/general/drinkingglass_cocktail
is_stack = TRUE
/datum/category_item/autolathe/general/drinkingglass_shot
is_stack = TRUE
/datum/category_item/autolathe/general/drinkingglass_pint
is_stack = TRUE
/datum/category_item/autolathe/general/drinkingglass_mug
is_stack = TRUE
/datum/category_item/autolathe/general/drinkingglass_wine
is_stack = TRUE
/datum/category_item/autolathe/general/metaglass
name = "metamorphic glass"
path =/obj/item/weapon/reagent_containers/food/drinks/metaglass
is_stack = TRUE
/datum/category_item/autolathe/general/drinkingglass_carafe
/datum/category_item/autolathe/general/drinkingglass/carafe
name = "glass carafe"
path =/obj/item/weapon/reagent_containers/food/drinks/glass2/carafe
/datum/category_item/autolathe/general/drinkingglass_pitcher
/datum/category_item/autolathe/general/drinkingglass/pitcher
name = "plastic pitcher"
path =/obj/item/weapon/reagent_containers/food/drinks/glass2/pitcher

View File

@@ -42,3 +42,15 @@
/datum/category_item/autolathe/tools/welder_industrial
name = "industrial welding tool"
path =/obj/item/weapon/weldingtool/largetank
/datum/category_item/autolathe/tools/spraybottle
name = "spray bottle"
path = /obj/item/weapon/reagent_containers/spray
resources = list(MAT_PLASTIC = 2000)
/datum/category_item/autolathe/tools/spraynozzle
name = "spray nozzle"
path = /obj/item/weapon/reagent_containers/spray
resources = list(MAT_PLASTIC = 5000, DEFAULT_WALL_MATERIAL = 2000)
hidden = 1
man_rating = 2

View File

@@ -6,6 +6,7 @@
var/icon/base_icon = null
var/icon
var/icon_state = "" //icon state of the main segments of the beam
var/beam_color = null // Color of the beam segments
var/max_distance = 0
var/endtime = 0
var/sleep_time = 3
@@ -15,7 +16,7 @@
var/static_beam = 0
var/beam_type = /obj/effect/ebeam //must be subtype
/datum/beam/New(beam_origin,beam_target,beam_icon='icons/effects/beam.dmi',beam_icon_state="b_beam",time=50,maxdistance=10,btype = /obj/effect/ebeam,beam_sleep_time=3)
/datum/beam/New(beam_origin,beam_target,beam_icon='icons/effects/beam.dmi',beam_icon_state="b_beam",time=50,maxdistance=10,btype = /obj/effect/ebeam,beam_sleep_time=3,new_beam_color = null)
endtime = world.time+time
origin = beam_origin
origin_oldloc = get_turf(origin)
@@ -28,6 +29,8 @@
base_icon = new(beam_icon,beam_icon_state)
icon = beam_icon
icon_state = beam_icon_state
if(new_beam_color)
beam_color = new_beam_color
beam_type = btype
/datum/beam/proc/Start()
@@ -68,9 +71,12 @@
var/matrix/rot_matrix = matrix()
rot_matrix.Turn(Angle)
var/turf/T_target = get_turf(target) //Turfs are referenced instead of the objects directly so that beams will link between 2 objects inside other objects.
var/turf/T_origin = get_turf(origin)
//Translation vector for origin and target
var/DX = (32*target.x+target.pixel_x)-(32*origin.x+origin.pixel_x)
var/DY = (32*target.y+target.pixel_y)-(32*origin.y+origin.pixel_y)
var/DX = (32*T_target.x+target.pixel_x)-(32*T_origin.x+origin.pixel_x)
var/DY = (32*T_target.y+target.pixel_y)-(32*T_origin.y+origin.pixel_y)
var/N = 0
var/length = round(sqrt((DX)**2+(DY)**2)) //hypotenuse of the triangle formed by target and origin's displacement
@@ -78,6 +84,10 @@
if(QDELETED(src) || finished)
break
var/obj/effect/ebeam/X = new beam_type(origin_oldloc)
if(beam_color)
X.color = beam_color
X.owner = src
elements |= X
@@ -184,8 +194,8 @@
/atom/proc/Beam(atom/BeamTarget,icon_state="b_beam",icon='icons/effects/beam.dmi',time=50, maxdistance=10,beam_type=/obj/effect/ebeam,beam_sleep_time=3)
var/datum/beam/newbeam = new(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type,beam_sleep_time)
/atom/proc/Beam(atom/BeamTarget,icon_state="b_beam",icon='icons/effects/beam.dmi',time=50, maxdistance=10,beam_type=/obj/effect/ebeam,beam_sleep_time=3,beam_color = null)
var/datum/beam/newbeam = new(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type,beam_sleep_time,beam_color)
spawn(0)
newbeam.Start()
return newbeam

View File

@@ -38,6 +38,7 @@
/obj/item/weapon/storage/box/glasses/shot,
/obj/item/weapon/storage/box/glasses/mug,
/obj/item/weapon/storage/box/glasses/meta,
/obj/item/weapon/storage/box/glasses/meta/metapint,
/obj/item/weapon/reagent_containers/food/drinks/shaker,
/obj/item/weapon/storage/box/glass_extras/straws,
/obj/item/weapon/storage/box/glass_extras/sticks
@@ -57,13 +58,13 @@
group = "Hospitality"
/datum/supply_pack/randomised/hospitality/pizza
num_contained = 5
contains = list(
/obj/item/pizzabox/margherita,
/obj/item/pizzabox/mushroom,
/obj/item/pizzabox/meat,
/obj/item/pizzabox/vegetable,
/obj/item/pizzabox/pineapple
/obj/random/pizzabox,
/obj/random/pizzabox,
/obj/random/pizzabox,
/obj/random/pizzabox,
/obj/random/pizzabox,
/obj/item/weapon/material/knife/plastic
)
name = "Surprise pack of five pizzas"
cost = 15

View File

@@ -29,21 +29,21 @@
name = "BloodPack crate"
contains = list(/obj/item/weapon/storage/box/bloodpacks = 3)
cost = 10
containertype = /obj/structure/closet/crate/nanocare
containertype = /obj/structure/closet/crate/nanomed
containername = "BloodPack crate"
/datum/supply_pack/med/bodybag
name = "Body bag crate"
contains = list(/obj/item/weapon/storage/box/bodybags = 3)
cost = 10
containertype = /obj/structure/closet/crate/nanocare
containertype = /obj/structure/closet/crate/nanomed
containername = "Body bag crate"
/datum/supply_pack/med/cryobag
name = "Stasis bag crate"
contains = list(/obj/item/bodybag/cryobag = 3)
cost = 40
containertype = /obj/structure/closet/crate/nanocare
containertype = /obj/structure/closet/crate/nanomed
containername = "Stasis bag crate"
/datum/supply_pack/med/surgery
@@ -109,7 +109,7 @@
/obj/item/clothing/suit/storage/hooded/wintercoat/medical = 3
)
cost = 10
containertype = /obj/structure/closet/crate/secure/nanocare
containertype = /obj/structure/closet/crate/secure/nanomed
containername = "Medical surplus equipment"
access = access_medical
@@ -133,7 +133,7 @@
/obj/item/weapon/reagent_containers/syringe
)
cost = 50
containertype = /obj/structure/closet/crate/secure/nanocare
containertype = /obj/structure/closet/crate/secure/nanomed
containername = "Chief medical officer equipment"
access = access_cmo
@@ -156,7 +156,7 @@
/obj/item/weapon/reagent_containers/syringe
)
cost = 20
containertype = /obj/structure/closet/crate/secure/nanocare
containertype = /obj/structure/closet/crate/secure/nanomed
containername = "Medical Doctor equipment"
access = access_medical_equip
@@ -179,7 +179,7 @@
/obj/item/weapon/reagent_containers/syringe
)
cost = 20
containertype = /obj/structure/closet/crate/secure/nanocare
containertype = /obj/structure/closet/crate/secure/nanomed
containername = "Chemist equipment"
access = access_chemistry
@@ -207,7 +207,7 @@
/obj/item/clothing/accessory/storage/white_vest
)
cost = 20
containertype = /obj/structure/closet/crate/secure/nanocare
containertype = /obj/structure/closet/crate/secure/nanomed
containername = "Paramedic equipment"
access = access_medical_equip
@@ -226,7 +226,7 @@
/obj/item/weapon/cartridge/medical
)
cost = 20
containertype = /obj/structure/closet/crate/secure/nanocare
containertype = /obj/structure/closet/crate/secure/nanomed
containername = "Psychiatrist equipment"
access = access_psychiatrist
@@ -247,7 +247,7 @@
/obj/item/weapon/storage/box/gloves
)
cost = 10
containertype = /obj/structure/closet/crate/secure/nanocare
containertype = /obj/structure/closet/crate/secure/nanomed
containername = "Medical scrubs crate"
access = access_medical_equip
@@ -291,7 +291,7 @@
/obj/item/weapon/storage/box/gloves
)
cost = 10
containertype = /obj/structure/closet/crate/secure/nanocare
containertype = /obj/structure/closet/crate/secure/nanomed
containername = "Medical uniform crate"
access = access_medical_equip
@@ -309,7 +309,7 @@
/obj/item/weapon/storage/box/gloves
)
cost = 50
containertype = /obj/structure/closet/crate/secure/nanocare
containertype = /obj/structure/closet/crate/secure/nanomed
containername = "Medical biohazard equipment"
access = access_medical_equip

View File

@@ -189,3 +189,12 @@
cost = 40
containertype = /obj/structure/closet/crate/zenghu
containername = "emergency rations"
/datum/supply_pack/misc/reagentpump
name = "Machine - Pump"
contains = list(
/obj/machinery/pump = 1
)
cost = 60
containertype = /obj/structure/closet/crate/large/xion
containername = "pump crate"

View File

@@ -39,7 +39,7 @@
/obj/item/clothing/head/soft/purple,
/obj/item/weapon/storage/belt/janitor,
/obj/item/clothing/shoes/galoshes,
/obj/item/weapon/caution = 4,
/obj/item/clothing/suit/caution = 4,
/obj/item/weapon/storage/bag/trash,
/obj/item/device/lightreplacer,
/obj/item/weapon/reagent_containers/spray/cleaner,

View File

@@ -129,7 +129,7 @@
/obj/item/weapon/tank/oxygen = 2
)
cost = 45
containertype = /obj/structure/closet/crate/secure/nanocare
containertype = /obj/structure/closet/crate/secure/nanomed
containername = "Medical Biohazard voidsuit crate"
access = access_medical_equip

View File

@@ -110,28 +110,6 @@
item_state = "gift"
w_class = ITEMSIZE_LARGE
/obj/item/weapon/caution
desc = "Caution! Wet Floor!"
name = "wet floor sign"
icon = 'icons/obj/janitor.dmi'
icon_state = "caution"
force = 1.0
throwforce = 3.0
throw_speed = 1
throw_range = 5
w_class = ITEMSIZE_SMALL
attack_verb = list("warned", "cautioned", "smashed")
/obj/item/weapon/caution/cone
desc = "This cone is trying to warn you of something!"
name = "warning cone"
icon_state = "cone"
/obj/item/weapon/caution/cone/candy
desc = "This cone is trying to warn you of something! It has been painted to look like candy corn."
name = "candy cone"
icon_state = "candycone"
/*/obj/item/weapon/syndicate_uplink
name = "station bounced radio"
desc = "Remain silent about this..."

View File

@@ -1746,7 +1746,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
temp_closet.locked = 0
temp_closet.icon_state = "closed_unlocked"
for(var/obj/machinery/door_timer/temp_timer in src)
temp_timer.releasetime = 1
temp_timer.timer_duration = 1
..()
/area/security/prison
@@ -1758,7 +1758,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
temp_closet.locked = 0
temp_closet.icon_state = "closed_unlocked"
for(var/obj/machinery/door_timer/temp_timer in src)
temp_timer.releasetime = 1
temp_timer.timer_duration = 1
..()
/area/security/warden

View File

@@ -377,7 +377,10 @@ var/list/mob/living/forced_ambiance_list = new
/area/proc/play_ambience(var/mob/living/L, initial = TRUE)
// Ambience goes down here -- make sure to list each area seperately for ease of adding things in later, thanks! Note: areas adjacent to each other should have the same sounds to prevent cutoff when possible.- LastyScratch
if(!(L && L.is_preference_enabled(/datum/client_preference/play_ambiance))) return
if(!(L && L.is_preference_enabled(/datum/client_preference/play_ambiance)))
return
var/volume_mod = L.get_preference_volume_channel(VOLUME_CHANNEL_AMBIENCE)
// If we previously were in an area with force-played ambiance, stop it.
if((L in forced_ambiance_list) && initial)
@@ -392,6 +395,7 @@ var/list/mob/living/forced_ambiance_list = new
var/sound/chosen_ambiance = pick(forced_ambience)
if(!istype(chosen_ambiance))
chosen_ambiance = sound(chosen_ambiance, repeat = 1, wait = 0, volume = 25, channel = CHANNEL_AMBIENCE_FORCED)
chosen_ambiance.volume *= volume_mod
L << chosen_ambiance
else
L << sound(null, channel = CHANNEL_AMBIENCE_FORCED)
@@ -399,7 +403,7 @@ var/list/mob/living/forced_ambiance_list = new
var/ambience_odds = L?.client.prefs.ambience_chance
if(prob(ambience_odds) && (world.time >= L.client.time_last_ambience_played + 1 MINUTE))
var/sound = pick(ambience)
L << sound(sound, repeat = 0, wait = 0, volume = 50, channel = CHANNEL_AMBIENCE)
L << sound(sound, repeat = 0, wait = 0, volume = 50 * volume_mod, channel = CHANNEL_AMBIENCE)
L.client.time_last_ambience_played = world.time
/area/proc/gravitychange(var/gravitystate = 0)

View File

@@ -196,7 +196,7 @@ var/hadevent = 0
spawn(0) temp_glassairlock.prison_open()
for (var/obj/machinery/door_timer/temp_timer in A)
temp_timer.releasetime = 1
temp_timer.timer_duration = 1
sleep(150)
command_announcement.Announce("Gr3y.T1d3 virus detected in [station_name()] imprisonment subroutines. Recommend station AI involvement.", "Security Alert")

View File

@@ -81,7 +81,7 @@
spawn_positions = 2
supervisors = "the Head of Security"
selection_color = "#601C1C"
access = list(access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels, access_eva, access_external_airlocks)
access = list(access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels, access_eva, access_external_airlocks, access_brig) //Vorestation edit - access_brig
minimal_access = list(access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels, access_eva, access_external_airlocks)
economic_modifier = 5
minimal_player_age = 3

View File

@@ -281,7 +281,7 @@ update_flag
/obj/machinery/portable_atmospherics/canister/tgui_data(mob/user)
var/list/data = list()
data["canLabel"] = can_label ? 1 : 0
data["can_relabel"] = can_label ? 1 : 0
data["connected"] = connected_port ? 1 : 0
data["pressure"] = round(air_contents.return_pressure() ? air_contents.return_pressure() : 0)
data["releasePressure"] = round(release_pressure ? release_pressure : 0)

View File

@@ -442,7 +442,7 @@
<br>\n
<center><b>Comments/Log</b></center><br>"}
for(var/c in active2.fields["comments"])
P.info += "[c]<br>"
P.info += "[c["header"]]<br>[c["text"]]<br>"
else
P.info += "<b>Medical Record Lost!</b><br>"
P.info += "</tt>"

View File

@@ -1,4 +1,8 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
#define SEC_DATA_R_LIST 2 // Record list
#define SEC_DATA_MAINT 3 // Records maintenance
#define SEC_DATA_RECORD 4 // Record
#define FIELD(N, V, E) list(field = N, value = V, edit = E)
/obj/machinery/computer/secure_data//TODO:SANITY
name = "security records console"
@@ -14,15 +18,42 @@
var/screen = null
var/datum/data/record/active1 = null
var/datum/data/record/active2 = null
var/a_id = null
var/temp = null
var/list/temp = null
var/printing = null
var/can_change_id = 0
var/list/Perp
var/tempname = null
//Sorting Variables
var/sortBy = "name"
var/order = 1 // -1 = Descending - 1 = Ascending
// The below are used to make modal generation more convenient
var/static/list/field_edit_questions
var/static/list/field_edit_choices
/obj/machinery/computer/secure_data/Initialize()
..()
field_edit_questions = list(
// General
"name" = "Please enter new name:",
"id" = "Please enter new id:",
"sex" = "Please select new sex:",
"age" = "Please input new age:",
"rank" = "Please enter new rank:",
"fingerprint" = "Please input new fingerprint hash:",
// Security
"brain_type" = "Please select new brain type:",
"criminal" = "Please select new criminal status:",
"mi_crim" = "Please input new minor crime:",
"mi_crim_d" = "Please input minor crime summary.",
"ma_crim" = "Please input new major crime:",
"ma_crim_d" = "Please input new major crime summary.",
"notes" = "Please input new important notes:",
)
field_edit_choices = list(
// General
"sex" = all_genders_text_list,
// Security
"criminal" = list("*Arrest*", "Incarcerated", "Parolled", "Released", "None"),
)
/obj/machinery/computer/secure_data/Destroy()
active1 = null
active2 = null
return ..()
/obj/machinery/computer/secure_data/verb/eject_id()
set category = "Object"
@@ -41,13 +72,14 @@
to_chat(usr, "There is nothing to remove from the console.")
return
/obj/machinery/computer/secure_data/attackby(obj/item/O as obj, user as mob)
if(istype(O, /obj/item/weapon/card/id) && !scan)
usr.drop_item()
/obj/machinery/computer/secure_data/attackby(var/obj/item/O, var/mob/user)
if(istype(O, /obj/item/weapon/card/id) && !scan && user.unEquip(O))
O.loc = src
scan = O
to_chat(user, "You insert [O].")
..()
to_chat(user, "You insert \the [O].")
tgui_interact(user)
else
..()
/obj/machinery/computer/secure_data/attack_ai(mob/user as mob)
return attack_hand(user)
@@ -56,518 +88,380 @@
/obj/machinery/computer/secure_data/attack_hand(mob/user as mob)
if(..())
return
if (using_map && !(src.z in using_map.contact_levels))
to_chat(user, "<span class='warning'>Unable to establish a connection:</span> You're too far away from the station!")
return
var/dat
add_fingerprint(user)
tgui_interact(user)
if (temp)
dat = text("<TT>[]</TT><BR><BR><A href='?src=\ref[];choice=Clear Screen'>Clear Screen</A>", temp, src)
else
dat = text("Confirm Identity: <A href='?src=\ref[];choice=Confirm Identity'>[]</A><HR>", src, (scan ? text("[]", scan.name) : "----------"))
if (authenticated)
switch(screen)
if(1.0)
dat += {"
<p style='text-align:center;'>"}
dat += text("<A href='?src=\ref[];choice=Search Records'>Search Records</A><BR>", src)
dat += text("<A href='?src=\ref[];choice=New Record (General)'>New Record</A><BR>", src)
dat += {"
</p>
<table style="text-align:center;" cellspacing="0" width="100%">
<tr>
<th>Records:</th>
</tr>
</table>
<table style="text-align:center;" border="1" cellspacing="0" width="100%">
<tr>
<th><A href='?src=\ref[src];choice=Sorting;sort=name'>Name</A></th>
<th><A href='?src=\ref[src];choice=Sorting;sort=id'>ID</A></th>
<th><A href='?src=\ref[src];choice=Sorting;sort=rank'>Rank</A></th>
<th><A href='?src=\ref[src];choice=Sorting;sort=fingerprint'>Fingerprints</A></th>
<th>Criminal Status</th>
</tr>"}
if(!isnull(data_core.general))
for(var/datum/data/record/R in sortRecord(data_core.general, sortBy, order))
var/crimstat = ""
for(var/datum/data/record/E in data_core.security)
if ((E.fields["name"] == R.fields["name"] && E.fields["id"] == R.fields["id"]))
crimstat = E.fields["criminal"]
var/background
switch(crimstat)
if("*Arrest*")
background = "'background-color:#DC143C;'"
if("Incarcerated")
background = "'background-color:#CD853F;'"
if("Parolled")
background = "'background-color:#CD853F;'"
if("Released")
background = "'background-color:#3BB9FF;'"
if("None")
background = "'background-color:#00FF7F;'"
if("")
background = "'background-color:#FFFFFF;'"
crimstat = "No Record."
dat += text("<tr style=[]><td><A href='?src=\ref[];choice=Browse Record;d_rec=\ref[]'>[]</a></td>", background, src, R, R.fields["name"])
dat += text("<td>[]</td>", R.fields["id"])
dat += text("<td>[]</td>", R.fields["rank"])
dat += text("<td>[]</td>", R.fields["fingerprint"])
dat += text("<td>[]</td></tr>", crimstat)
dat += "</table><hr width='75%' />"
dat += text("<A href='?src=\ref[];choice=Record Maintenance'>Record Maintenance</A><br><br>", src)
dat += text("<A href='?src=\ref[];choice=Log Out'>{Log Out}</A>",src)
if(2.0)
dat += "<B>Records Maintenance</B><HR>"
dat += "<BR><A href='?src=\ref[src];choice=Delete All Records'>Delete All Records</A><BR><BR><A href='?src=\ref[src];choice=Return'>Back</A>"
if(3.0)
dat += "<CENTER><B>Security Record</B></CENTER><BR>"
if ((istype(active1, /datum/data/record) && data_core.general.Find(active1)))
user << browse_rsc(active1.fields["photo_front"], "front.png")
user << browse_rsc(active1.fields["photo_side"], "side.png")
dat += text("<table><tr><td> \
Name: <A href='?src=\ref[src];choice=Edit Field;field=name'>[active1.fields["name"]]</A><BR> \
ID: <A href='?src=\ref[src];choice=Edit Field;field=id'>[active1.fields["id"]]</A><BR>\n \
Entity Classification: <A href='?src=\ref[src];field=brain_type'>[active1.fields["brain_type"]]</A><BR>\n \
Sex: <A href='?src=\ref[src];choice=Edit Field;field=sex'>[active1.fields["sex"]]</A><BR>\n \
Age: <A href='?src=\ref[src];choice=Edit Field;field=age'>[active1.fields["age"]]</A><BR>\n \
Rank: <A href='?src=\ref[src];choice=Edit Field;field=rank'>[active1.fields["rank"]]</A><BR>\n \
Fingerprint: <A href='?src=\ref[src];choice=Edit Field;field=fingerprint'>[active1.fields["fingerprint"]]</A><BR>\n \
Physical Status: [active1.fields["p_stat"]]<BR>\n \
Mental Status: [active1.fields["m_stat"]]<BR></td> \
<td align = center valign = top>Photo:<br> \
<table><td align = center><img src=front.png height=80 width=80 border=4><BR><A href='?src=\ref[src];choice=Edit Field;field=photo front'>Update front photo</A></td> \
<td align = center><img src=side.png height=80 width=80 border=4><BR><A href='?src=\ref[src];choice=Edit Field;field=photo side'>Update side photo</A></td></table> \
</td></tr></table>")
else
dat += "<B>General Record Lost!</B><BR>"
if ((istype(active2, /datum/data/record) && data_core.security.Find(active2)))
dat += text("<BR>\n<CENTER><B>Security Data</B></CENTER><BR>\nCriminal Status: <A href='?src=\ref[];choice=Edit Field;field=criminal'>[]</A><BR>\n<BR>\nMinor Crimes: <A href='?src=\ref[];choice=Edit Field;field=mi_crim'>[]</A><BR>\nDetails: <A href='?src=\ref[];choice=Edit Field;field=mi_crim_d'>[]</A><BR>\n<BR>\nMajor Crimes: <A href='?src=\ref[];choice=Edit Field;field=ma_crim'>[]</A><BR>\nDetails: <A href='?src=\ref[];choice=Edit Field;field=ma_crim_d'>[]</A><BR>\n<BR>\nImportant Notes:<BR>\n\t<A href='?src=\ref[];choice=Edit Field;field=notes'>[]</A><BR>\n<BR>\n<CENTER><B>Comments/Log</B></CENTER><BR>", src, active2.fields["criminal"], src, active2.fields["mi_crim"], src, active2.fields["mi_crim_d"], src, active2.fields["ma_crim"], src, active2.fields["ma_crim_d"], src, decode(active2.fields["notes"]))
var/counter = 1
while(active2.fields[text("com_[]", counter)])
dat += text("[]<BR><A href='?src=\ref[];choice=Delete Entry;del_c=[]'>Delete Entry</A><BR><BR>", active2.fields[text("com_[]", counter)], src, counter)
counter++
dat += text("<A href='?src=\ref[];choice=Add Entry'>Add Entry</A><BR><BR>", src)
dat += text("<A href='?src=\ref[];choice=Delete Record (Security)'>Delete Record (Security Only)</A><BR><BR>", src)
else
dat += "<B>Security Record Lost!</B><BR>"
dat += text("<A href='?src=\ref[];choice=New Record (Security)'>New Security Record</A><BR><BR>", src)
dat += text("\n<A href='?src=\ref[];choice=Delete Record (ALL)'>Delete Record (ALL)</A><BR><BR>\n<A href='?src=\ref[];choice=Print Record'>Print Record</A><BR>\n<A href='?src=\ref[];choice=Return'>Back</A><BR>", src, src, src)
if(4.0)
if(!Perp.len)
dat += text("ERROR. String could not be located.<br><br><A href='?src=\ref[];choice=Return'>Back</A>", src)
else
dat += {"
<table style="text-align:center;" cellspacing="0" width="100%">
<tr> "}
dat += text("<th>Search Results for '[]':</th>", tempname)
dat += {"
</tr>
</table>
<table style="text-align:center;" border="1" cellspacing="0" width="100%">
<tr>
<th>Name</th>
<th>ID</th>
<th>Rank</th>
<th>Fingerprints</th>
<th>Criminal Status</th>
</tr> "}
for(var/i=1, i<=Perp.len, i += 2)
var/crimstat = ""
var/datum/data/record/R = Perp[i]
if(istype(Perp[i+1],/datum/data/record/))
var/datum/data/record/E = Perp[i+1]
crimstat = E.fields["criminal"]
var/background
switch(crimstat)
if("*Arrest*")
background = "'background-color:#DC143C;'"
if("Incarcerated")
background = "'background-color:#CD853F;'"
if("Parolled")
background = "'background-color:#CD853F;'"
if("Released")
background = "'background-color:#3BB9FF;'"
if("None")
background = "'background-color:#00FF7F;'"
if("")
background = "'background-color:#FFFFFF;'"
crimstat = "No Record."
dat += text("<tr style=[]><td><A href='?src=\ref[];choice=Browse Record;d_rec=\ref[]'>[]</a></td>", background, src, R, R.fields["name"])
dat += text("<td>[]</td>", R.fields["id"])
dat += text("<td>[]</td>", R.fields["rank"])
dat += text("<td>[]</td>", R.fields["fingerprint"])
dat += text("<td>[]</td></tr>", crimstat)
dat += "</table><hr width='75%' />"
dat += text("<br><A href='?src=\ref[];choice=Return'>Return to index.</A>", src)
/obj/machinery/computer/secure_data/tgui_interact(mob/user, datum/tgui/ui = null)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "SecurityRecords", "Security Records") // 800, 380
ui.open()
ui.set_autoupdate(FALSE)
/obj/machinery/computer/secure_data/tgui_data(mob/user)
var/data[0]
data["temp"] = temp
data["scan"] = scan ? scan.name : null
data["authenticated"] = authenticated
data["rank"] = rank
data["screen"] = screen
data["printing"] = printing
data["isAI"] = isAI(user)
data["isRobot"] = isrobot(user)
if(authenticated)
switch(screen)
if(SEC_DATA_R_LIST)
if(!isnull(data_core.general))
var/list/records = list()
data["records"] = records
for(var/datum/data/record/R in sortRecord(data_core.general))
var/color = null
var/criminal = "None"
for(var/datum/data/record/M in data_core.security)
if(M.fields["name"] == R.fields["name"] && M.fields["id"] == R.fields["id"])
switch(M.fields["criminal"])
if("*Arrest*")
color = "bad"
if("Incarcerated")
color = "brown"
if("Parolled", "Released")
color = "average"
if("None")
color = "good"
criminal = M.fields["criminal"]
break
records[++records.len] = list(
"ref" = "\ref[R]",
"id" = R.fields["id"],
"name" = R.fields["name"],
"color" = color,
"criminal" = criminal
)
if(SEC_DATA_RECORD)
var/list/general = list()
data["general"] = general
if(istype(active1, /datum/data/record) && data_core.general.Find(active1))
var/list/fields = list()
general["fields"] = fields
fields[++fields.len] = FIELD("Name", active1.fields["name"], "name")
fields[++fields.len] = FIELD("ID", active1.fields["id"], "id")
fields[++fields.len] = FIELD("Entity Classification", active1.fields["brain_type"], "brain_type")
fields[++fields.len] = FIELD("Sex", active1.fields["sex"], "sex")
fields[++fields.len] = FIELD("Age", active1.fields["age"], "age")
fields[++fields.len] = FIELD("Rank", active1.fields["rank"], "rank")
fields[++fields.len] = FIELD("Fingerprint", active1.fields["fingerprint"], "fingerprint")
fields[++fields.len] = FIELD("Physical Status", active1.fields["p_stat"], null)
fields[++fields.len] = FIELD("Mental Status", active1.fields["m_stat"], null)
var/list/photos = list()
general["photos"] = photos
photos[++photos.len] = active1.fields["photo-south"]
photos[++photos.len] = active1.fields["photo-west"]
general["has_photos"] = (active1.fields["photo-south"] || active1.fields["photo-west"] ? 1 : 0)
general["empty"] = 0
else
else
dat += text("<A href='?src=\ref[];choice=Log In'>{Log In}</A>", src)
user << browse(text("<HEAD><TITLE>Security Records</TITLE></HEAD><TT>[]</TT>", dat), "window=secure_rec;size=600x400")
onclose(user, "secure_rec")
return
general["empty"] = 1
/*Revised /N
I can't be bothered to look more of the actual code outside of switch but that probably needs revising too.
What a mess.*/
/obj/machinery/computer/secure_data/Topic(href, href_list)
var/list/security = list()
data["security"] = security
if(istype(active2, /datum/data/record) && data_core.security.Find(active2))
var/list/fields = list()
security["fields"] = fields
fields[++fields.len] = FIELD("Criminal Status", active2.fields["criminal"], "criminal")
fields[++fields.len] = FIELD("Minor Crimes", active2.fields["mi_crim"], "mi_crim")
fields[++fields.len] = FIELD("Details", active2.fields["mi_crim_d"], "mi_crim_d")
fields[++fields.len] = FIELD("Major Crimes", active2.fields["ma_crim"], "ma_crim")
fields[++fields.len] = FIELD("Details", active2.fields["ma_crim_d"], "ma_crim_d")
fields[++fields.len] = FIELD("Important Notes", active2.fields["notes"], "notes")
if(!active2.fields["comments"] || !islist(active2.fields["comments"]))
active2.fields["comments"] = list()
security["comments"] = active2.fields["comments"]
security["empty"] = 0
else
security["empty"] = 1
data["modal"] = tgui_modal_data(src)
return data
/obj/machinery/computer/secure_data/tgui_act(action, params)
if(..())
return 1
if (!( data_core.general.Find(active1) ))
active1 = null
if (!( data_core.security.Find(active2) ))
active2 = null
if ((usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon)))
usr.set_machine(src)
switch(href_list["choice"])
// SORTING!
if("Sorting")
// Reverse the order if clicked twice
if(sortBy == href_list["sort"])
if(order == 1)
order = -1
else
order = 1
else
// New sorting order!
sortBy = href_list["sort"]
order = initial(order)
//BASIC FUNCTIONS
if("Clear Screen")
temp = null
return TRUE
if ("Return")
screen = 1
if(!data_core.general.Find(active1))
active1 = null
if(!data_core.security.Find(active2))
active2 = null
. = TRUE
if(tgui_act_modal(action, params))
return
switch(action)
if("cleartemp")
temp = null
if("scan")
if(scan)
scan.forceMove(loc)
if(ishuman(usr) && !usr.get_active_hand())
usr.put_in_hands(scan)
scan = null
else
var/obj/item/I = usr.get_active_hand()
if(istype(I, /obj/item/weapon/card/id))
usr.drop_item()
I.forceMove(src)
scan = I
if("login")
var/login_type = text2num(params["login_type"])
if(login_type == LOGIN_TYPE_NORMAL && istype(scan))
if(check_access(scan))
authenticated = scan.registered_name
rank = scan.assignment
else if(login_type == LOGIN_TYPE_AI && isAI(usr))
authenticated = usr.name
rank = "AI"
else if(login_type == LOGIN_TYPE_ROBOT && isrobot(usr))
authenticated = usr.name
var/mob/living/silicon/robot/R = usr
rank = "[R.modtype] [R.braintype]"
if(authenticated)
active1 = null
active2 = null
screen = SEC_DATA_R_LIST
else
. = FALSE
if("Confirm Identity")
if (scan)
if(istype(usr,/mob/living/carbon/human) && !usr.get_active_hand())
if(.)
return
if(authenticated)
. = TRUE
switch(action)
if("logout")
if(scan)
scan.forceMove(loc)
if(ishuman(usr) && !usr.get_active_hand())
usr.put_in_hands(scan)
else
scan.loc = get_turf(src)
scan = null
else
var/obj/item/I = usr.get_active_hand()
if (istype(I, /obj/item/weapon/card/id) && usr.unEquip(I))
I.loc = src
scan = I
if("Log Out")
authenticated = null
screen = null
active1 = null
active2 = null
if("Log In")
if (istype(usr, /mob/living/silicon/ai))
src.active1 = null
src.active2 = null
src.authenticated = usr.name
src.rank = "AI"
src.screen = 1
else if (istype(usr, /mob/living/silicon/robot))
src.active1 = null
src.active2 = null
src.authenticated = usr.name
var/mob/living/silicon/robot/R = usr
src.rank = "[R.modtype] [R.braintype]"
src.screen = 1
else if (istype(scan, /obj/item/weapon/card/id))
active1 = null
active2 = null
if(check_access(scan))
authenticated = scan.registered_name
rank = scan.assignment
screen = 1
//RECORD FUNCTIONS
if("Search Records")
var/t1 = input("Search String: (Partial Name or ID or Fingerprints or Rank)", "Secure. records", null, null) as text
if ((!( t1 ) || usr.stat || !( authenticated ) || usr.restrained() || !in_range(src, usr)))
return
Perp = new/list()
t1 = lowertext(t1)
var/list/components = splittext(t1, " ")
if(components.len > 5)
return //Lets not let them search too greedily.
for(var/datum/data/record/R in data_core.general)
var/temptext = R.fields["name"] + " " + R.fields["id"] + " " + R.fields["fingerprint"] + " " + R.fields["rank"]
for(var/i = 1, i<=components.len, i++)
if(findtext(temptext,components[i]))
var/prelist = new/list(2)
prelist[1] = R
Perp += prelist
for(var/i = 1, i<=Perp.len, i+=2)
for(var/datum/data/record/E in data_core.security)
var/datum/data/record/R = Perp[i]
if ((E.fields["name"] == R.fields["name"] && E.fields["id"] == R.fields["id"]))
Perp[i+1] = E
tempname = t1
screen = 4
if("Record Maintenance")
screen = 2
if("screen")
screen = clamp(text2num(params["screen"]) || 0, SEC_DATA_R_LIST, SEC_DATA_RECORD)
active1 = null
active2 = null
if ("Browse Record")
var/datum/data/record/R = locate(href_list["d_rec"])
var/S = locate(href_list["d_rec"])
if (!( data_core.general.Find(R) ))
temp = "Record Not Found!"
else
for(var/datum/data/record/E in data_core.security)
if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
S = E
active1 = R
active2 = S
screen = 3
/* if ("Search Fingerprints")
var/t1 = input("Search String: (Fingerprint)", "Secure. records", null, null) as text
if ((!( t1 ) || usr.stat || !( authenticated ) || usr.restrained() || (!in_range(src, usr)) && (!istype(usr, /mob/living/silicon))))
return
active1 = null
active2 = null
t1 = lowertext(t1)
for(var/datum/data/record/R in data_core.general)
if (lowertext(R.fields["fingerprint"]) == t1)
active1 = R
if (!( active1 ))
temp = text("Could not locate record [].", t1)
else
for(var/datum/data/record/E in data_core.security)
if ((E.fields["name"] == active1.fields["name"] || E.fields["id"] == active1.fields["id"]))
active2 = E
screen = 3 */
if ("Print Record")
if (!( printing ))
printing = 1
var/datum/data/record/record1 = null
var/datum/data/record/record2 = null
if ((istype(active1, /datum/data/record) && data_core.general.Find(active1)))
record1 = active1
if ((istype(active2, /datum/data/record) && data_core.security.Find(active2)))
record2 = active2
sleep(50)
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( loc )
P.info = "<CENTER><B>Security Record</B></CENTER><BR>"
if (record1)
P.info += text("Name: [] ID: []<BR>\nSex: []<BR>\nAge: []<BR>\nFingerprint: []<BR>\nPhysical Status: []<BR>\nMental Status: []<BR>", record1.fields["name"], record1.fields["id"], record1.fields["sex"], record1.fields["age"], record1.fields["fingerprint"], record1.fields["p_stat"], record1.fields["m_stat"])
P.name = text("Security Record ([])", record1.fields["name"])
else
P.info += "<B>General Record Lost!</B><BR>"
P.name = "Security Record"
if (record2)
P.info += text("<BR>\n<CENTER><B>Security Data</B></CENTER><BR>\nCriminal Status: []<BR>\n<BR>\nMinor Crimes: []<BR>\nDetails: []<BR>\n<BR>\nMajor Crimes: []<BR>\nDetails: []<BR>\n<BR>\nImportant Notes:<BR>\n\t[]<BR>\n<BR>\n<CENTER><B>Comments/Log</B></CENTER><BR>", record2.fields["criminal"], record2.fields["mi_crim"], record2.fields["mi_crim_d"], record2.fields["ma_crim"], record2.fields["ma_crim_d"], decode(record2.fields["notes"]))
var/counter = 1
while(record2.fields[text("com_[]", counter)])
P.info += text("[]<BR>", record2.fields[text("com_[]", counter)])
counter++
else
P.info += "<B>Security Record Lost!</B><BR>"
P.info += "</TT>"
printing = null
updateUsrDialog()
//RECORD DELETE
if ("Delete All Records")
temp = ""
temp += "Are you sure you wish to delete all Security records?<br>"
temp += "<a href='?src=\ref[src];choice=Purge All Records'>Yes</a><br>"
temp += "<a href='?src=\ref[src];choice=Clear Screen'>No</a>"
if ("Purge All Records")
if("del_all")
for(var/datum/data/record/R in data_core.security)
qdel(R)
temp = "All Security records deleted."
if ("Add Entry")
if (!( istype(active2, /datum/data/record) ))
set_temp("All security records deleted.")
if("del_r")
if(active2)
set_temp("Security record deleted.")
qdel(active2)
if("del_r_2")
set_temp("All records for [active1.fields["name"]] deleted.")
if(active1)
for(var/datum/data/record/R in data_core.medical)
if((R.fields["name"] == active1.fields["name"] || R.fields["id"] == active1.fields["id"]))
qdel(R)
qdel(active1)
if(active2)
qdel(active2)
if("d_rec")
var/datum/data/record/general_record = locate(params["d_rec"] || "")
if(!data_core.general.Find(general_record))
set_temp("Record not found.", "danger")
return
var/a2 = active2
var/t1 = sanitize(input("Add Comment:", "Secure. records", null, null) as message)
if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || active2 != a2))
var/datum/data/record/security_record
for(var/datum/data/record/M in data_core.security)
if(M.fields["name"] == general_record.fields["name"] && M.fields["id"] == general_record.fields["id"])
security_record = M
break
active1 = general_record
active2 = security_record
screen = SEC_DATA_RECORD
if("new")
if(istype(active1, /datum/data/record) && !istype(active2, /datum/data/record))
var/datum/data/record/R = new /datum/data/record()
R.fields["name"] = active1.fields["name"]
R.fields["id"] = active1.fields["id"]
R.name = "Security Record #[R.fields["id"]]"
R.fields["brain_type"] = "Unknown"
R.fields["criminal"] = "None"
R.fields["mi_crim"] = "None"
R.fields["mi_crim_d"] = "No minor crime convictions."
R.fields["ma_crim"] = "None"
R.fields["ma_crim_d"] = "No major crime convictions."
R.fields["notes"] = "No notes."
R.fields["notes"] = "No notes."
data_core.security += R
active2 = R
screen = SEC_DATA_RECORD
set_temp("Security record created.", "success")
if("del_c")
var/index = text2num(params["del_c"] || "")
if(!index || !istype(active2, /datum/data/record))
return
var/counter = 1
while(active2.fields[text("com_[]", counter)])
counter++
active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD")] [stationtime2text()], [game_year]<BR>[t1]")
if ("Delete Record (ALL)")
if (active1)
temp = "<h5>Are you sure you wish to delete the record (ALL)?</h5>"
temp += "<a href='?src=\ref[src];choice=Delete Record (ALL) Execute'>Yes</a><br>"
temp += "<a href='?src=\ref[src];choice=Clear Screen'>No</a>"
if ("Delete Record (Security)")
if (active2)
temp = "<h5>Are you sure you wish to delete the record (Security Portion Only)?</h5>"
temp += "<a href='?src=\ref[src];choice=Delete Record (Security) Execute'>Yes</a><br>"
temp += "<a href='?src=\ref[src];choice=Clear Screen'>No</a>"
if ("Delete Entry")
if ((istype(active2, /datum/data/record) && active2.fields[text("com_[]", href_list["del_c"])]))
active2.fields[text("com_[]", href_list["del_c"])] = "<B>Deleted</B>"
//RECORD CREATE
if ("New Record (Security)")
if ((istype(active1, /datum/data/record) && !( istype(active2, /datum/data/record) )))
active2 = data_core.CreateSecurityRecord(active1.fields["name"], active1.fields["id"])
screen = 3
if ("New Record (General)")
active1 = data_core.CreateGeneralRecord()
var/list/comments = active2.fields["comments"]
index = clamp(index, 1, length(comments))
if(comments[index])
comments.Cut(index, index + 1)
if("search")
active1 = null
active2 = null
//FIELD FUNCTIONS
if ("Edit Field")
if (is_not_allowed(usr))
var/t1 = lowertext(params["t1"] || "")
if(!length(t1))
return
var/a1 = active1
var/a2 = active2
switch(href_list["field"])
if("name")
if (istype(active1, /datum/data/record))
var/t1 = sanitizeName(input("Please input name:", "Secure. records", active1.fields["name"], null) as text)
if (!t1 || active1 != a1)
return
active1.fields["name"] = t1
if("id")
if (istype(active2, /datum/data/record))
var/t1 = sanitize(input("Please input id:", "Secure. records", active1.fields["id"], null) as text)
if (!t1 || active1 != a1)
return
active1.fields["id"] = t1
if("fingerprint")
if (istype(active1, /datum/data/record))
var/t1 = sanitize(input("Please input fingerprint hash:", "Secure. records", active1.fields["fingerprint"], null) as text)
if (!t1 || active1 != a1)
return
active1.fields["fingerprint"] = t1
if("sex")
if (istype(active1, /datum/data/record))
if (active1.fields["sex"] == "Male")
active1.fields["sex"] = "Female"
else
active1.fields["sex"] = "Male"
if("age")
if (istype(active1, /datum/data/record))
var/t1 = input("Please input age:", "Secure. records", active1.fields["age"], null) as num
if (!t1 || active1 != a1)
return
active1.fields["age"] = t1
if("mi_crim")
if (istype(active2, /datum/data/record))
var/t1 = sanitize(input("Please input minor disabilities list:", "Secure. records", active2.fields["mi_crim"], null) as text)
if (!t1 || active2 != a2)
return
active2.fields["mi_crim"] = t1
if("mi_crim_d")
if (istype(active2, /datum/data/record))
var/t1 = sanitize(input("Please summarize minor dis.:", "Secure. records", active2.fields["mi_crim_d"], null) as message)
if (!t1 || active2 != a2)
return
active2.fields["mi_crim_d"] = t1
if("ma_crim")
if (istype(active2, /datum/data/record))
var/t1 = sanitize(input("Please input major diabilities list:", "Secure. records", active2.fields["ma_crim"], null) as text)
if (!t1 || active2 != a2)
return
active2.fields["ma_crim"] = t1
if("ma_crim_d")
if (istype(active2, /datum/data/record))
var/t1 = sanitize(input("Please summarize major dis.:", "Secure. records", active2.fields["ma_crim_d"], null) as message)
if (!t1 || active2 != a2)
return
active2.fields["ma_crim_d"] = t1
if("notes")
if (istype(active2, /datum/data/record))
var/t1 = sanitize(input("Please summarize notes:", "Secure. records", html_decode(active2.fields["notes"]), null) as message, extra = 0, max_length = MAX_RECORD_LENGTH)
if (!t1 || active2 != a2)
return
active2.fields["notes"] = t1
if("criminal")
if (istype(active2, /datum/data/record))
temp = "<h5>Criminal Status:</h5>"
temp += "<ul>"
temp += "<li><a href='?src=\ref[src];choice=Change Criminal Status;criminal2=none'>None</a></li>"
temp += "<li><a href='?src=\ref[src];choice=Change Criminal Status;criminal2=arrest'>*Arrest*</a></li>"
temp += "<li><a href='?src=\ref[src];choice=Change Criminal Status;criminal2=incarcerated'>Incarcerated</a></li>"
temp += "<li><a href='?src=\ref[src];choice=Change Criminal Status;criminal2=parolled'>Parolled</a></li>"
temp += "<li><a href='?src=\ref[src];choice=Change Criminal Status;criminal2=released'>Released</a></li>"
temp += "</ul>"
if("rank")
var/list/L = list( "Head of Personnel", "Colony Director", "AI" )
//This was so silly before the change. Now it actually works without beating your head against the keyboard. /N
if ((istype(active1, /datum/data/record) && L.Find(rank)))
temp = "<h5>Rank:</h5>"
temp += "<ul>"
for(var/rank in joblist)
temp += "<li><a href='?src=\ref[src];choice=Change Rank;rank=[rank]'>[rank]</a></li>"
temp += "</ul>"
else
alert(usr, "You do not have the required rank to do this!")
if("species")
if (istype(active1, /datum/data/record))
var/t1 = sanitize(input("Please enter race:", "General records", active1.fields["species"], null) as message)
if (!t1 || active1 != a1)
return
active1.fields["species"] = t1
if("photo front")
var/icon/photo = get_photo(usr)
if(photo)
active1.fields["photo_front"] = photo
if("photo side")
var/icon/photo = get_photo(usr)
if(photo)
active1.fields["photo_side"] = photo
for(var/datum/data/record/R in data_core.security)
if(t1 == lowertext(R.fields["name"]) || t1 == lowertext(R.fields["id"]) || t1 == lowertext(R.fields["b_dna"]))
active2 = R
break
if(!active2)
set_temp("Security record not found. You must enter the person's exact name, ID or DNA.", "danger")
return
for(var/datum/data/record/E in data_core.general)
if(E.fields["name"] == active2.fields["name"] && E.fields["id"] == active2.fields["id"])
active1 = E
break
screen = SEC_DATA_RECORD
if("print_p")
if(!printing)
printing = TRUE
// playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, TRUE)
SStgui.update_uis(src)
addtimer(CALLBACK(src, .proc/print_finish), 5 SECONDS)
if("photo_front")
var/icon/photo = get_photo(usr)
if(photo && active1)
active1.fields["photo_front"] = photo
active1.fields["photo-south"] = "'data:image/png;base64,[icon2base64(photo)]'"
if("photo_side")
var/icon/photo = get_photo(usr)
if(photo && active1)
active1.fields["photo_side"] = photo
active1.fields["photo-west"] = "'data:image/png;base64,[icon2base64(photo)]'"
else
return FALSE
//TEMPORARY MENU FUNCTIONS
else//To properly clear as per clear screen.
temp=null
switch(href_list["choice"])
if ("Change Rank")
if (active1)
active1.fields["rank"] = href_list["rank"]
if(href_list["rank"] in joblist)
active1.fields["real_rank"] = href_list["real_rank"]
if ("Change Criminal Status")
if (active2)
for(var/mob/living/carbon/human/H in player_list)
BITSET(H.hud_updateflag, WANTED_HUD)
switch(href_list["criminal2"])
if("none")
active2.fields["criminal"] = "None"
if("arrest")
active2.fields["criminal"] = "*Arrest*"
if("incarcerated")
active2.fields["criminal"] = "Incarcerated"
if("parolled")
active2.fields["criminal"] = "Parolled"
if("released")
active2.fields["criminal"] = "Released"
if ("Delete Record (Security) Execute")
if (active2)
qdel(active2)
if ("Delete Record (ALL) Execute")
if (active1)
for(var/datum/data/record/R in data_core.medical)
if ((R.fields["name"] == active1.fields["name"] || R.fields["id"] == active1.fields["id"]))
qdel(R)
else
qdel(active1)
if (active2)
qdel(active2)
/**
* Called in tgui_act() to process modal actions
*
* Arguments:
* * action - The action passed by tgui
* * params - The params passed by tgui
*/
/obj/machinery/computer/secure_data/proc/tgui_act_modal(action, params)
. = TRUE
var/id = params["id"] // The modal's ID
var/list/arguments = istext(params["arguments"]) ? json_decode(params["arguments"]) : params["arguments"]
switch(tgui_modal_act(src, action, params))
if(TGUI_MODAL_OPEN)
switch(id)
if("edit")
var/field = arguments["field"]
if(!length(field) || !field_edit_questions[field])
return
var/question = field_edit_questions[field]
var/choices = field_edit_choices[field]
if(length(choices))
tgui_modal_choice(src, id, question, arguments = arguments, value = arguments["value"], choices = choices)
else
temp = "This function does not appear to be working at the moment. Our apologies."
tgui_modal_input(src, id, question, arguments = arguments, value = arguments["value"])
if("add_c")
tgui_modal_input(src, id, "Please enter your message:")
else
return FALSE
if(TGUI_MODAL_ANSWER)
var/answer = params["answer"]
switch(id)
if("edit")
var/field = arguments["field"]
if(!length(field) || !field_edit_questions[field])
return
var/list/choices = field_edit_choices[field]
if(length(choices) && !(answer in choices))
return
add_fingerprint(usr)
updateUsrDialog()
return
if(field == "age")
answer = text2num(answer)
if(field == "rank")
if(answer in joblist)
active1.fields["real_rank"] = answer
if(field == "criminal")
for(var/mob/living/carbon/human/H in player_list)
BITSET(H.hud_updateflag, WANTED_HUD)
if(istype(active2) && (field in active2.fields))
active2.fields[field] = answer
if(istype(active1) && (field in active1.fields))
active1.fields[field] = answer
if("add_c")
if(!length(answer) || !istype(active2) || !length(authenticated))
return
active2.fields["comments"] += list(list(
header = "Made by [authenticated] ([rank]) at [worldtime2stationtime(world.time)]",
text = answer
))
else
return FALSE
else
return FALSE
/**
* Called when the print timer finishes
*/
/obj/machinery/computer/secure_data/proc/print_finish()
var/obj/item/weapon/paper/P = new(loc)
P.info = "<center><b>Security Record</b></center><br>"
if(istype(active1, /datum/data/record) && data_core.general.Find(active1))
P.info += {"Name: [active1.fields["name"]] ID: [active1.fields["id"]]
<br>\nSex: [active1.fields["sex"]]
<br>\nAge: [active1.fields["age"]]
<br>\nFingerprint: [active1.fields["fingerprint"]]
<br>\nPhysical Status: [active1.fields["p_stat"]]
<br>\nMental Status: [active1.fields["m_stat"]]<br>"}
else
P.info += "<b>General Record Lost!</b><br>"
if(istype(active2, /datum/data/record) && data_core.security.Find(active2))
P.info += {"<br>\n<center><b>Security Data</b></center>
<br>\nCriminal Status: [active2.fields["criminal"]]<br>\n
<br>\nMinor Crimes: [active2.fields["mi_crim"]]
<br>\nDetails: [active2.fields["mi_crim_d"]]<br>\n
<br>\nMajor Crimes: [active2.fields["ma_crim"]]
<br>\nDetails: [active2.fields["ma_crim_d"]]<br>\n
<br>\nImportant Notes:
<br>\n\t[active2.fields["notes"]]<br>\n
<br>\n
<center><b>Comments/Log</b></center><br>"}
for(var/c in active2.fields["comments"])
P.info += "[c["header"]]<br>[c["text"]]<br>"
else
P.info += "<b>Security Record Lost!</b><br>"
P.info += "</tt>"
P.name = "paper - 'Security Record: [active1.fields["name"]]'"
printing = FALSE
SStgui.update_uis(src)
/**
* Sets a temporary message to display to the user
*
* Arguments:
* * text - Text to display, null/empty to clear the message from the UI
* * style - The style of the message: (color name), info, success, warning, danger, virus
*/
/obj/machinery/computer/secure_data/proc/set_temp(text = "", style = "info", update_now = FALSE)
temp = list(text = text, style = style)
if(update_now)
SStgui.update_uis(src)
/obj/machinery/computer/secure_data/proc/is_not_allowed(var/mob/user)
return !src.authenticated || user.stat || user.restrained() || (!in_range(src, user) && (!istype(user, /mob/living/silicon)))
@@ -614,3 +508,5 @@ What a mess.*/
/obj/machinery/computer/secure_data/detective_computer
icon_state = "messyfiles"
#undef FIELD

View File

@@ -315,7 +315,7 @@
<br>\n
<center><b>Comments/Log</b></center><br>"}
for(var/c in active1.fields["comments"])
P.info += "[c]<br>"
P.info += "[c["header"]]<br>[c["text"]]<br>"
else
P.info += "<b>General Record Lost!</b><br>"
P.info += "</tt>"

View File

@@ -36,7 +36,7 @@
if(!allowed(user))
return
user.set_machine(src)
ui_interact(user)
tgui_interact(user)
return
/obj/machinery/computer/supplycomp/emag_act(var/remaining_charges, var/mob/user)
@@ -44,24 +44,27 @@
to_chat(user, "<span class='notice'>Special supplies unlocked.</span>")
authorization |= SUP_CONTRABAND
req_access = list()
can_order_contraband = TRUE
return 1
// TGUI
/obj/machinery/computer/supplycomp/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "SupplyConsole", name)
ui.open()
/obj/machinery/computer/supplycomp/ui_interact(mob/user, ui_key = "supply_records", var/datum/nanoui/ui = null, var/force_open = 1, var/key_state = null)
var/data[0]
var/shuttle_status[0] // Supply shuttle status
var/pack_list[0] // List of supply packs within the active_category
var/orders[0]
var/receipts[0]
/obj/machinery/computer/supplycomp/tgui_data(mob/user)
var/list/data = ..()
var/list/shuttle_status = list()
var/datum/shuttle/autodock/ferry/supply/shuttle = SSsupply.shuttle
if(shuttle)
if(shuttle.has_arrive_time())
shuttle_status["location"] = "In transit"
shuttle_status["mode"] = SUP_SHUTTLE_TRANSIT
shuttle_status["time"] = shuttle.eta_minutes()
shuttle_status["time"] = shuttle.eta_seconds()
else
shuttle_status["time"] = 0
@@ -107,149 +110,192 @@
shuttle_status["engine"] = "Engaged"
else
shuttle["mode"] = SUP_SHUTTLE_ERROR
for(var/pack_name in SSsupply.supply_pack)
var/datum/supply_pack/P = SSsupply.supply_pack[pack_name]
if(P.group == active_category)
var/list/pack = list(
"name" = P.name,
"cost" = P.cost,
"contraband" = P.contraband,
"manifest" = uniquelist(P.manifest),
"random" = P.num_contained,
"expand" = 0,
"ref" = "\ref[P]"
)
if(P in expanded_packs)
pack["expand"] = 1
pack_list[++pack_list.len] = pack
shuttle_status["mode"] = SUP_SHUTTLE_ERROR
// Compile user-side orders
// Status determines which menus the entry will display in
// Organized in field-entry list for iterative display
// List is nested so both the list of orders, and the list of elements in each order, can be iterated over
var/list/orders = list()
for(var/datum/supply_order/S in SSsupply.order_history)
orders[++orders.len] = list(
"ref" = "\ref[S]",
"status" = S.status,
"entries" = list(
list("field" = "Supply Pack", "entry" = S.name),
list("field" = "Cost", "entry" = S.cost),
list("field" = "Index", "entry" = S.index),
list("field" = "Reason", "entry" = S.comment),
list("field" = "Ordered by", "entry" = S.ordered_by),
list("field" = "Ordered at", "entry" = S.ordered_at),
list("field" = "Approved by", "entry" = S.approved_by),
list("field" = "Approved at", "entry" = S.approved_at)
)
)
orders.Add(list(list(
"ref" = "\ref[S]",
"status" = S.status,
"cost" = S.cost,
"entries" = list(
list("field" = "Supply Pack", "entry" = S.name),
list("field" = "Cost", "entry" = S.cost),
list("field" = "Index", "entry" = S.index),
list("field" = "Reason", "entry" = S.comment),
list("field" = "Ordered by", "entry" = S.ordered_by),
list("field" = "Ordered at", "entry" = S.ordered_at),
list("field" = "Approved by", "entry" = S.approved_by),
list("field" = "Approved at", "entry" = S.approved_at)
)
)))
// Compile exported crates
var/list/receipts = list()
for(var/datum/exported_crate/E in SSsupply.exported_crates)
receipts[++receipts.len] = list(
"ref" = "\ref[E]",
"contents" = E.contents,
"error" = E.contents["error"],
"title" = list(
list("field" = "Name", "entry" = E.name),
list("field" = "Value", "entry" = E.value)
)
receipts.Add(list(list(
"ref" = "\ref[E]",
"contents" = E.contents,
"error" = E.contents["error"],
"title" = list(
list("field" = "Name", "entry" = E.name),
list("field" = "Value", "entry" = E.value)
)
)))
data["user"] = "\ref[user]"
data["currentTab"] = menu_tab // Communicator compatibility, controls which menu is in use
data["shuttle_auth"] = (authorization & SUP_SEND_SHUTTLE) // Whether this ui is permitted to control the supply shuttle
data["order_auth"] = (authorization & SUP_ACCEPT_ORDERS) // Whether this ui is permitted to accept/deny requested orders
data["shuttle"] = shuttle_status
data["supply_points"] = SSsupply.points
data["categories"] = all_supply_groups
data["active_category"] = active_category
data["supply_packs"] = pack_list
data["orders"] = orders
data["receipts"] = receipts
data["contraband"] = can_order_contraband || (authorization & SUP_CONTRABAND)
data["modal"] = tgui_modal_data(src)
return data
// update the ui if it exists, returns null if no ui is passed/found
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
// the ui does not exist, so we'll create a new() one
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
ui = new(user, src, ui_key, "supply_records.tmpl", "Supply Console", 475, 700, state = key_state)
// when the ui is first opened this is the data it will use
ui.set_initial_data(data)
// open the new ui window
ui.open()
// auto update every 20 Master Controller tick
ui.set_auto_update(20) // Longer term to reduce the rate of data collection and processing
/obj/machinery/computer/supplycomp/tgui_static_data(mob/user)
var/list/data = ..()
var/list/pack_list = list()
for(var/pack_name in SSsupply.supply_pack)
var/datum/supply_pack/P = SSsupply.supply_pack[pack_name]
var/list/pack = list(
"name" = P.name,
"cost" = P.cost,
"group" = P.group,
"contraband" = P.contraband,
"manifest" = uniquelist(P.manifest),
"random" = P.num_contained,
"ref" = "\ref[P]"
)
pack_list.Add(list(pack))
data["supply_packs"] = pack_list
data["categories"] = all_supply_groups
return data
/obj/machinery/computer/supplycomp/Topic(href, href_list)
if(!SSsupply)
to_world_log("## ERROR: The SSsupply datum is missing.")
return
var/datum/shuttle/autodock/ferry/supply/shuttle = SSsupply.shuttle
if (!shuttle)
to_world_log("## ERROR: The supply shuttle datum is missing.")
return
/obj/machinery/computer/supplycomp/tgui_act(action, params)
if(..())
return 1
return TRUE
if(!SSsupply)
log_runtime(EXCEPTION("## ERROR: The SSsupply datum is missing."))
return TRUE
var/datum/shuttle/autodock/ferry/supply/shuttle = SSsupply.shuttle
if(!shuttle)
log_runtime(EXCEPTION("## ERROR: The supply shuttle datum is missing."))
return TRUE
if(isturf(loc) && ( in_range(src, usr) || istype(usr, /mob/living/silicon) ) )
usr.set_machine(src)
if(tgui_modal_act(src, action, params))
return TRUE
// NEW TOPIC
switch(action)
if("view_crate")
var/datum/supply_pack/P = locate(params["crate"])
if(!istype(P))
return FALSE
var/list/payload = list(
"name" = P.name,
"cost" = P.cost,
"manifest" = uniquelist(P.manifest),
"ref" = "\ref[P]",
"random" = P.num_contained,
)
tgui_modal_message(src, action, "", null, payload)
. = TRUE
if("request_crate_multi")
var/datum/supply_pack/S = locate(params["ref"])
// Switch menu
if(href_list["switch_tab"])
menu_tab = href_list["switch_tab"]
// Invalid ref
if(!istype(S))
return FALSE
if(href_list["active_category"])
active_category = href_list["active_category"]
if(href_list["pack_ref"])
var/datum/supply_pack/S = locate(href_list["pack_ref"])
// Invalid ref
if(!istype(S))
return
// Expand the supply pack's contents
if(href_list["expand"])
expanded_packs ^= S
// Make a request for the pack
if(href_list["request"])
var/mob/user = locate(href_list["user"])
if(!istype(user)) // Invalid ref
return
if(S.contraband && !(authorization & SUP_CONTRABAND || can_order_contraband))
return FALSE
if(world.time < reqtime)
visible_message("<span class='warning'>[src]'s monitor flashes, \"[reqtime - world.time] seconds remaining until another requisition form may be printed.\"</span>")
return
return FALSE
var/amount = clamp(input(usr, "How many crates? (0 to 20)") as num|null, 0, 20)
if(!amount)
return FALSE
var/timeout = world.time + 600
var/reason = sanitize(input(user, "Reason:","Why do you require this item?","") as null|text)
var/reason = sanitize(input(usr, "Reason:","Why do you require this item?","") as null|text)
if(world.time > timeout)
to_chat(user, "<span class='warning'>Error. Request timed out.</span>")
return
to_chat(usr, "<span class='warning'>Error. Request timed out.</span>")
return FALSE
if(!reason)
return
return FALSE
SSsupply.create_order(S, user, reason)
for(var/i in 1 to amount)
SSsupply.create_order(S, usr, reason)
var/idname = "*None Provided*"
var/idrank = "*None Provided*"
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(ishuman(usr))
var/mob/living/carbon/human/H = usr
idname = H.get_authentification_name()
idrank = H.get_assignment()
else if(issilicon(user))
idname = user.real_name
else if(issilicon(usr))
idname = usr.real_name
idrank = "Stationbound synthetic"
var/obj/item/weapon/paper/reqform = new /obj/item/weapon/paper(loc)
reqform.name = "Requisition Form - [S.name]"
reqform.info += "<h3>[station_name()] Supply Requisition Form</h3><hr>"
reqform.info += "INDEX: #[SSsupply.ordernum]<br>"
reqform.info += "REQUESTED BY: [idname]<br>"
reqform.info += "RANK: [idrank]<br>"
reqform.info += "REASON: [reason]<br>"
reqform.info += "SUPPLY CRATE TYPE: [S.name]<br>"
reqform.info += "ACCESS RESTRICTION: [get_access_desc(S.access)]<br>"
reqform.info += "AMOUNT: [amount]<br>"
reqform.info += "CONTENTS:<br>"
reqform.info += S.get_html_manifest()
reqform.info += "<hr>"
reqform.info += "STAMP BELOW TO APPROVE THIS REQUISITION:<br>"
reqform.update_icon() //Fix for appearing blank when printed.
reqtime = (world.time + 5) % 1e5
. = TRUE
if("request_crate")
var/datum/supply_pack/S = locate(params["ref"])
// Invalid ref
if(!istype(S))
return FALSE
if(S.contraband && !(authorization & SUP_CONTRABAND || can_order_contraband))
return FALSE
if(world.time < reqtime)
visible_message("<span class='warning'>[src]'s monitor flashes, \"[reqtime - world.time] seconds remaining until another requisition form may be printed.\"</span>")
return FALSE
var/timeout = world.time + 600
var/reason = sanitize(input(usr, "Reason:","Why do you require this item?","") as null|text)
if(world.time > timeout)
to_chat(usr, "<span class='warning'>Error. Request timed out.</span>")
return FALSE
if(!reason)
return FALSE
SSsupply.create_order(S, usr, reason)
var/idname = "*None Provided*"
var/idrank = "*None Provided*"
if(ishuman(usr))
var/mob/living/carbon/human/H = usr
idname = H.get_authentification_name()
idrank = H.get_assignment()
else if(issilicon(usr))
idname = usr.real_name
idrank = "Stationbound synthetic"
var/obj/item/weapon/paper/reqform = new /obj/item/weapon/paper(loc)
@@ -268,24 +314,19 @@
reqform.update_icon() //Fix for appearing blank when printed.
reqtime = (world.time + 5) % 1e5
if(href_list["order_ref"])
var/datum/supply_order/O = locate(href_list["order_ref"])
// Invalid ref
if(!istype(O))
return
var/mob/user = locate(href_list["user"])
if(!istype(user)) // Invalid ref
return
if(href_list["edit"])
var/new_val = sanitize(input(user, href_list["edit"], "Enter the new value for this field:", href_list["default"]) as null|text)
. = TRUE
// Approving Orders
if("edit_order_value")
var/datum/supply_order/O = locate(params["ref"])
if(!istype(O))
return FALSE
if(!(authorization & SUP_ACCEPT_ORDERS))
return FALSE
var/new_val = sanitize(input(usr, params["edit"], "Enter the new value for this field:", params["default"]) as null|text)
if(!new_val)
return
return FALSE
switch(href_list["edit"])
switch(params["edit"])
if("Supply Pack")
O.name = new_val
@@ -313,68 +354,95 @@
if("Approved at")
O.approved_at = new_val
. = TRUE
if("approve_order")
var/datum/supply_order/O = locate(params["ref"])
if(!istype(O))
return FALSE
if(!(authorization & SUP_ACCEPT_ORDERS))
return FALSE
SSsupply.approve_order(O, usr)
. = TRUE
if("deny_order")
var/datum/supply_order/O = locate(params["ref"])
if(!istype(O))
return FALSE
if(!(authorization & SUP_ACCEPT_ORDERS))
return FALSE
SSsupply.deny_order(O, usr)
. = TRUE
if("delete_order")
var/datum/supply_order/O = locate(params["ref"])
if(!istype(O))
return FALSE
if(!(authorization & SUP_ACCEPT_ORDERS))
return FALSE
SSsupply.delete_order(O, usr)
. = TRUE
if("clear_all_requests")
if(!(authorization & SUP_ACCEPT_ORDERS))
return FALSE
SSsupply.deny_all_pending(usr)
. = TRUE
// Exports
if("export_edit_field")
var/datum/exported_crate/E = locate(params["ref"])
// Invalid ref
if(!istype(E))
return FALSE
if(!(authorization & SUP_ACCEPT_ORDERS))
return FALSE
var/list/L = E.contents[params["index"]]
var/field = alert(usr, "Select which field to edit", , "Name", "Quantity", "Value")
if(href_list["approve"])
SSsupply.approve_order(O, user)
if(href_list["deny"])
SSsupply.deny_order(O, user)
if(href_list["delete"])
SSsupply.delete_order(O, user)
if(href_list["clear_all_requests"])
var/mob/user = locate(href_list["user"])
if(!istype(user)) // Invalid ref
return
SSsupply.deny_all_pending(user)
if(href_list["export_ref"])
var/datum/exported_crate/E = locate(href_list["export_ref"])
// Invalid ref
if(!istype(E))
return
var/mob/user = locate(href_list["user"])
if(!istype(user)) // Invalid ref
return
if(href_list["index"])
var/list/L = E.contents[href_list["index"]]
if(href_list["edit"])
var/field = alert(user, "Select which field to edit", , "Name", "Quantity", "Value")
var/new_val = sanitize(input(user, href_list["edit"], "Enter the new value for this field:", href_list["default"]) as null|text)
if(!new_val)
return
switch(field)
if("Name")
L["object"] = new_val
if("Quantity")
var/num = text2num(new_val)
if(num)
L["quantity"] = num
if("Value")
var/num = text2num(new_val)
if(num)
L["value"] = num
if(href_list["delete"])
E.contents.Cut(href_list["index"], href_list["index"] + 1)
// Else clause means they're editing/deleting the whole export report, rather than a specific item in it
else if(href_list["edit"])
var/new_val = sanitize(input(user, href_list["edit"], "Enter the new value for this field:", href_list["default"]) as null|text)
var/new_val = sanitize(input(usr, field, "Enter the new value for this field:", L[lowertext(field)]) as null|text)
if(!new_val)
return
switch(href_list["edit"])
switch(field)
if("Name")
L["object"] = new_val
if("Quantity")
var/num = text2num(new_val)
if(num)
L["quantity"] = num
if("Value")
var/num = text2num(new_val)
if(num)
L["value"] = num
. = TRUE
if("export_delete_field")
var/datum/exported_crate/E = locate(params["ref"])
// Invalid ref
if(!istype(E))
return FALSE
if(!(authorization & SUP_ACCEPT_ORDERS))
return FALSE
E.contents.Cut(params["index"], params["index"] + 1)
. = TRUE
if("export_add_field")
var/datum/exported_crate/E = locate(params["ref"])
// Invalid ref
if(!istype(E))
return FALSE
if(!(authorization & SUP_ACCEPT_ORDERS))
return FALSE
SSsupply.add_export_item(E, usr)
. = TRUE
if("export_edit")
var/datum/exported_crate/E = locate(params["ref"])
// Invalid ref
if(!istype(E))
return FALSE
if(!(authorization & SUP_ACCEPT_ORDERS))
return FALSE
var/new_val = sanitize(input(usr, params["edit"], "Enter the new value for this field:", params["default"]) as null|text)
if(!new_val)
return
switch(params["edit"])
if("Name")
E.name = new_val
@@ -382,39 +450,39 @@
var/num = text2num(new_val)
if(num)
E.value = num
. = TRUE
if("export_delete")
var/datum/exported_crate/E = locate(params["ref"])
// Invalid ref
if(!istype(E))
return FALSE
if(!(authorization & SUP_ACCEPT_ORDERS))
return FALSE
SSsupply.delete_export(E, usr)
. = TRUE
if("send_shuttle")
switch(params["mode"])
if("send_away")
if (shuttle.forbidden_atoms_check())
to_chat(usr, "<span class='warning'>For safety reasons the automated supply shuttle cannot transport live organisms, classified nuclear weaponry or homing beacons.</span>")
else
shuttle.launch(src)
to_chat(usr, "<span class='notice'>Initiating launch sequence.</span>")
else if(href_list["delete"])
SSsupply.delete_export(E, user)
if("send_to_station")
shuttle.launch(src)
to_chat(usr, "<span class='notice'>The supply shuttle has been called and will arrive in approximately [round(SSsupply.movetime/600,1)] minutes.</span>")
else if(href_list["add_item"])
SSsupply.add_export_item(E, user)
if("cancel_shuttle")
shuttle.cancel_launch(src)
switch(href_list["send_shuttle"])
if("send_away")
if (shuttle.forbidden_atoms_check())
to_chat(usr, "<span class='warning'>For safety reasons the automated supply shuttle cannot transport live organisms, classified nuclear weaponry or homing beacons.</span>")
else
shuttle.launch(src)
to_chat(usr, "<span class='notice'>Initiating launch sequence.</span>")
if("send_to_station")
shuttle.launch(src)
to_chat(usr, "<span class='notice'>The supply shuttle has been called and will arrive in approximately [round(SSsupply.movetime/600,1)] minutes.</span>")
if("cancel_shuttle")
shuttle.cancel_launch(src)
if("force_shuttle")
shuttle.force_launch(src)
if("force_shuttle")
shuttle.force_launch(src)
. = TRUE
add_fingerprint(usr)
updateUsrDialog()
return
/obj/machinery/computer/supplycomp/proc/post_signal(var/command)
var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435)
if(!frequency) return

View File

@@ -1,7 +1,12 @@
#define CHARS_PER_LINE 5
#define FONT_SIZE "5pt"
#define FONT_COLOR "#09f"
#define FONT_STYLE "Arial Black"
#define FONT_STYLE "Small Fonts"
#define MAX_TIMER 36000
#define PRESET_SHORT 1 MINUTES
#define PRESET_MEDIUM 5 MINUTES
#define PRESET_LONG 10 MINUTES
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
@@ -19,14 +24,15 @@
icon_state = "frame"
desc = "A remote control for a door."
req_access = list(access_brig)
anchored = 1.0 // can't pick it up
density = 0 // can walk through it.
var/id = null // id of door it controls.
var/releasetime = 0 // when world.timeofday reaches it - release the prisoner
var/timing = 1 // boolean, true/1 timer is on, false/0 means it's not timing
var/picture_state // icon_state of alert picture, if not displaying text/numbers
var/list/obj/machinery/targets
var/timetoset = 0 // Used to set releasetime upon starting the timer
anchored = 1.0 // can't pick it up
density = 0 // can walk through it.
var/id = null // id of door it controls.
var/activation_time = 0
var/timer_duration = 0
var/timing = FALSE // boolean, true/1 timer is on, false/0 means it's not timing
var/list/obj/machinery/targets = list()
maptext_height = 26
maptext_width = 32
@@ -40,15 +46,15 @@
. = ..()
for(var/obj/machinery/door/window/brigdoor/M in machines)
if (M.id == src.id)
if(M.id == id)
LAZYADD(targets,M)
for(var/obj/machinery/flasher/F in machines)
if(F.id == src.id)
if(F.id == id)
LAZYADD(targets,F)
for(var/obj/structure/closet/secure_closet/brig/C in GLOB.all_brig_closets)
if(C.id == src.id)
if(C.id == id)
LAZYADD(targets,C)
if(!LAZYLEN(targets))
@@ -63,213 +69,152 @@
// if it's less than 0, open door, reset timer
// update the door_timer window and the icon
/obj/machinery/door_timer/process()
if(stat & (NOPOWER|BROKEN))
return
if(stat & (NOPOWER|BROKEN)) return
if(src.timing)
// poorly done midnight rollover
// (no seriously there's gotta be a better way to do this)
var/timeleft = timeleft()
if(timeleft > 1e5)
src.releasetime = 0
if(world.timeofday > src.releasetime)
src.timer_end() // open doors, reset timer, clear status screen
src.timing = 0
src.updateUsrDialog()
src.update_icon()
else
timer_end()
return
if(timing)
if(world.time - activation_time >= timer_duration)
timer_end() // open doors, reset timer, clear status screen
update_icon()
// has the door power situation changed, if so update icon.
/obj/machinery/door_timer/power_change()
..()
update_icon()
return
// open/closedoor checks if door_timer has power, if so it checks if the
// linked door is open/closed (by density) then opens it/closes it.
// Closes and locks doors, power check
/obj/machinery/door_timer/proc/timer_start()
if(stat & (NOPOWER|BROKEN)) return 0
if(!LAZYLEN(targets)) return 0
if(stat & (NOPOWER|BROKEN))
return 0
// Set releasetime
releasetime = world.timeofday + timetoset
activation_time = world.time
timing = TRUE
for(var/obj/machinery/door/window/brigdoor/door in targets)
if(door.density) continue
spawn(0)
door.close()
if(door.density)
continue
INVOKE_ASYNC(door, /obj/machinery/door/window/brigdoor.proc/close)
for(var/obj/structure/closet/secure_closet/brig/C in targets)
if(C.broken) continue
if(C.opened && !C.close()) continue
C.locked = 1
if(C.broken)
continue
if(C.opened && !C.close())
continue
C.locked = TRUE
C.icon_state = "closed_locked"
return 1
// Opens and unlocks doors, power check
/obj/machinery/door_timer/proc/timer_end()
if(stat & (NOPOWER|BROKEN)) return 0
if(!LAZYLEN(targets)) return 0
/obj/machinery/door_timer/proc/timer_end(forced = FALSE)
if(stat & (NOPOWER|BROKEN))
return 0
// Reset releasetime
releasetime = 0
timing = FALSE
activation_time = null
set_timer(0)
update_icon()
for(var/obj/machinery/door/window/brigdoor/door in targets)
if(!door.density) continue
spawn(0)
door.open()
if(!door.density)
continue
INVOKE_ASYNC(door, /obj/machinery/door/window/brigdoor.proc/open)
for(var/obj/structure/closet/secure_closet/brig/C in targets)
if(C.broken) continue
if(C.opened) continue
C.locked = 0
if(C.broken)
continue
if(C.opened)
continue
C.locked = FALSE
C.icon_state = "closed_unlocked"
return 1
/obj/machinery/door_timer/proc/time_left(seconds = FALSE)
. = max(0, timer_duration - (activation_time ? (world.time - activation_time) : 0))
if(seconds)
. /= 10
// Check for releasetime timeleft
/obj/machinery/door_timer/proc/timeleft()
. = (releasetime - world.timeofday)/10
if(. < 0)
. = 0
/obj/machinery/door_timer/proc/set_timer(value)
var/new_time = clamp(value, 0, MAX_TIMER)
. = new_time == timer_duration //return 1 on no change
timer_duration = new_time
if(timer_duration && activation_time && timing) // Setting it while active will reset the activation time
activation_time = world.time
// Set timetoset
/obj/machinery/door_timer/proc/timeset(var/seconds)
timetoset = seconds * 10
/obj/machinery/door_timer/attack_hand(mob/user)
if(..())
return TRUE
tgui_interact(user)
if(timetoset <= 0)
timetoset = 0
/obj/machinery/door_timer/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "BrigTimer", name)
ui.open()
return
/obj/machinery/door_timer/tgui_data()
var/list/data = list()
data["time_left"] = time_left()
data["max_time_left"] = MAX_TIMER
data["timing"] = timing
data["flash_found"] = FALSE
data["flash_charging"] = FALSE
data["preset_short"] = PRESET_SHORT
data["preset_medium"] = PRESET_MEDIUM
data["preset_long"] = PRESET_LONG
for(var/obj/machinery/flasher/F in targets)
data["flash_found"] = TRUE
if(F.last_flash && (F.last_flash + 150) > world.time)
data["flash_charging"] = TRUE
break
return data
//Allows AIs to use door_timer, see human attack_hand function below
/obj/machinery/door_timer/attack_ai(var/mob/user as mob)
return src.attack_hand(user)
//Allows humans to use door_timer
//Opens dialog window when someone clicks on door timer
// Allows altering timer and the timing boolean.
// Flasher activation limited to 150 seconds
/obj/machinery/door_timer/attack_hand(var/mob/user as mob)
/obj/machinery/door_timer/tgui_act(action, params)
if(..())
return
. = TRUE
// Used for the 'time left' display
var/second = round(timeleft() % 60)
var/minute = round((timeleft() - second) / 60)
if(!allowed(usr))
to_chat(usr, "<span class='warning'>Access denied.</span>")
return FALSE
// Used for 'set timer'
var/setsecond = round((timetoset / 10) % 60)
var/setminute = round(((timetoset / 10) - setsecond) / 60)
user.set_machine(src)
// dat
var/dat = "<HTML><BODY><TT>"
dat += "<HR>Timer System:</hr>"
dat += " <b>Door [src.id] controls</b><br/>"
// Start/Stop timer
if (src.timing)
dat += "<a href='?src=\ref[src];timing=0'>Stop Timer and open door</a><br/>"
else
dat += "<a href='?src=\ref[src];timing=1'>Activate Timer and close door</a><br/>"
// Time Left display (uses releasetime)
dat += "Time Left: [(minute ? text("[minute]:") : null)][second] <br/>"
dat += "<br/>"
// Set Timer display (uses timetoset)
if(src.timing)
dat += "Set Timer: [(setminute ? text("[setminute]:") : null)][setsecond] <a href='?src=\ref[src];change=1'>Set</a><br/>"
else
dat += "Set Timer: [(setminute ? text("[setminute]:") : null)][setsecond]<br/>"
// Controls
dat += "<a href='?src=\ref[src];tp=-60'>-</a> <a href='?src=\ref[src];tp=-1'>-</a> <a href='?src=\ref[src];tp=1'>+</a> <A href='?src=\ref[src];tp=60'>+</a><br/>"
// Mounted flash controls
if(LAZYLEN(targets))
for(var/obj/machinery/flasher/F in targets)
if(F.last_flash && (F.last_flash + 150) > world.time)
dat += "<br/><A href='?src=\ref[src];fc=1'>Flash Charging</A>"
switch(action)
if("time")
var/real_new_time = 0
var/new_time = params["time"]
var/list/L = splittext(new_time, ":")
if(LAZYLEN(L))
for(var/i in 1 to LAZYLEN(L))
real_new_time += text2num(L[i]) * (60 ** (LAZYLEN(L) - i))
else
dat += "<br/><A href='?src=\ref[src];fc=1'>Activate Flash</A>"
dat += "<br/><br/><a href='?src=\ref[user];mach_close=computer'>Close</a>"
dat += "</TT></BODY></HTML>"
user << browse(dat, "window=computer;size=400x500")
onclose(user, "computer")
return
//Function for using door_timer dialog input, checks if user has permission
// href_list to
// "timing" turns on timer
// "tp" value to modify timer
// "fc" activates flasher
// "change" resets the timer to the timetoset amount while the timer is counting down
// Also updates dialog window and timer icon
/obj/machinery/door_timer/Topic(href, href_list)
if(..())
return
if(!src.allowed(usr))
return
usr.set_machine(src)
if(href_list["timing"])
src.timing = text2num(href_list["timing"])
if(src.timing)
src.timer_start()
real_new_time = text2num(new_time)
if(real_new_time)
set_timer(real_new_time * 10)
if("start")
timer_start()
if("stop")
timer_end(forced = TRUE)
if("flash")
for(var/obj/machinery/flasher/F in targets)
F.flash()
if("preset")
var/preset = params["preset"]
var/preset_time = time_left()
switch(preset)
if("short")
preset_time = PRESET_SHORT
if("medium")
preset_time = PRESET_MEDIUM
if("long")
preset_time = PRESET_LONG
set_timer(timer_duration + preset_time)
if(timing)
activation_time = world.time
else
src.timer_end()
else
if(href_list["tp"]) //adjust timer, close door if not already closed
var/tp = text2num(href_list["tp"])
var/addtime = (timetoset / 10)
addtime += tp
addtime = min(max(round(addtime), 0), 3600)
timeset(addtime)
if(href_list["fc"])
if(LAZYLEN(targets))
for(var/obj/machinery/flasher/F in targets)
F.flash()
if(href_list["change"])
src.timer_start()
src.add_fingerprint(usr)
src.updateUsrDialog()
src.update_icon()
/* if(src.timing)
src.timer_start()
else
src.timer_end() */
return
. = FALSE
//icon update function
@@ -280,53 +225,39 @@
if(stat & (NOPOWER))
icon_state = "frame"
return
if(stat & (BROKEN))
set_picture("ai_bsod")
return
if(src.timing)
if(timing)
var/disp1 = id
var/timeleft = timeleft()
var/disp2 = "[add_zero(num2text((timeleft / 60) % 60),2)]~[add_zero(num2text(timeleft % 60), 2)]"
var/timeleft = time_left(seconds = TRUE)
var/disp2 = "[add_leading(num2text((timeleft / 60) % 60), 2, "0")]:[add_leading(num2text(timeleft % 60), 2, "0")]"
if(length(disp2) > CHARS_PER_LINE)
disp2 = "Error"
update_display(disp1, disp2)
else
if(maptext) maptext = ""
if(maptext)
maptext = ""
return
// Adds an icon in case the screen is broken/off, stolen from status_display.dm
/obj/machinery/door_timer/proc/set_picture(var/state)
picture_state = state
overlays.Cut()
overlays += image('icons/obj/status_display.dmi', icon_state=picture_state)
/obj/machinery/door_timer/proc/set_picture(state)
if(maptext)
maptext = ""
cut_overlays()
add_overlay(mutable_appearance('icons/obj/status_display.dmi', state))
//Checks to see if there's 1 line or 2, adds text-icons-numbers/letters over display
// Stolen from status_display
/obj/machinery/door_timer/proc/update_display(var/line1, var/line2)
/obj/machinery/door_timer/proc/update_display(line1, line2)
line1 = uppertext(line1)
line2 = uppertext(line2)
var/new_text = {"<div style="font-size:[FONT_SIZE];color:[FONT_COLOR];font:'[FONT_STYLE]';text-align:center;" valign="top">[line1]<br>[line2]</div>"}
if(maptext != new_text)
maptext = new_text
//Actual string input to icon display for loop, with 5 pixel x offsets for each letter.
//Stolen from status_display
/obj/machinery/door_timer/proc/texticon(var/tn, var/px = 0, var/py = 0)
var/image/I = image('icons/obj/status_display.dmi', "blank")
var/len = length(tn)
for(var/d = 1 to len)
var/char = copytext(tn, len-d+1, len-d+2)
if(char == " ")
continue
var/image/ID = image('icons/obj/status_display.dmi', icon_state=char)
ID.pixel_x = -(d-1)*5 + px
ID.pixel_y = py
I.overlays += ID
return I
/obj/machinery/door_timer/cell_1
name = "Cell 1"
id = "Cell 1"
@@ -351,7 +282,6 @@
name = "Cell 6"
id = "Cell 6"
/obj/machinery/door_timer/tactical_pet_storage //Vorestation Addition
name = "Tactical Pet Storage"
id = "tactical_pet_storage"

View File

@@ -155,7 +155,7 @@ FIRE ALARM
for(var/obj/machinery/firealarm/FA in area)
fire_alarm.triggerAlarm(loc, FA, duration, hidden = alarms_hidden)
update_icon()
playsound(src, 'sound/machines/airalarm.ogg', 25, 0, 4)
playsound(src, 'sound/machines/airalarm.ogg', 25, 0, 4, volume_channel = VOLUME_CHANNEL_ALARMS)
if(user)
log_game("[user] triggered a fire alarm at [COORD(src)]")

View File

@@ -15,7 +15,6 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense)
anchored = TRUE
circuit = /obj/item/weapon/circuitboard/pointdefense_control
var/list/targets = list() // Targets being engaged by associated batteries
var/ui_template = "pointdefense_control.tmpl"
var/id_tag = null
/obj/machinery/pointdefense_control/Initialize(mapload)
@@ -37,48 +36,42 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense)
if(!id_tag)
. += "[desc_panel_image("multitool")]to set ident tag"
/obj/machinery/pointdefense_control/ui_interact(var/mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
if(ui_template)
var/list/data = build_ui_data()
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, ui_template, name, 400, 600)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/pointdefense_control/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "PointDefenseControl") // 400, 600
ui.open()
/obj/machinery/pointdefense_control/attack_hand(mob/user)
if((. = ..()))
return
if(CanUseTopic(user, global.default_state) > STATUS_CLOSE)
ui_interact(user)
if(..())
return TRUE
tgui_interact(user)
return TRUE
/obj/machinery/pointdefense_control/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
/obj/machinery/pointdefense_control/Topic(var/mob/user, var/href_list)
if((. = ..()))
return
if(href_list["toggle_active"])
var/obj/machinery/power/pointdefense/PD = locate(href_list["toggle_active"])
if(action == "toggle_active")
var/obj/machinery/power/pointdefense/PD = locate(params["target"])
if(!istype(PD))
return TOPIC_NOACTION
return FALSE
//if(!lan || !lan.is_connected(PD))
if(PD.id_tag != id_tag)
return TOPIC_NOACTION
return FALSE
if(!(get_z(PD) in GetConnectedZlevels(get_z(src))))
to_chat(user, "<span class='warning'>[PD] is not within control range.</span>")
return TOPIC_NOACTION
to_chat(usr, "<span class='warning'>[PD] is not within control range.</span>")
return FALSE
if(!PD.Activate()) //Activate() whilst the device is active will return false.
PD.Deactivate()
return TOPIC_REFRESH
return TRUE
/obj/machinery/pointdefense_control/proc/build_ui_data()
/obj/machinery/pointdefense_control/tgui_data(mob/user)
var/list/data = list()
data["id"] = id_tag
data["name"] = name
var/list/turrets = list()
if(id_tag)
var/list/connected_z_levels = GetConnectedZlevels(get_z(src))

View File

@@ -0,0 +1,270 @@
/obj/machinery/pump
name = "fluid pump"
desc = "A fluid pumping machine."
description_info = "A machine that can pump fluid from certain turfs.<br>\
Water can be pumped from any body of water. Certain locations or environmental\
conditions can cause different byproducts to be produced.<br>\
Magma or Lava can be pumped to produce mineralized fluid."
anchored = 0
density = 1
icon = 'icons/obj/machines/reagent.dmi'
icon_state = "pump"
circuit = /obj/item/weapon/circuitboard/fluidpump
var/on = 0
var/obj/item/weapon/cell/cell = null
var/use = 200
var/efficiency = 1
var/reagents_per_cycle = 40
var/unlocked = 0
var/open = 0
var/obj/item/hose_connector/output/Output
// Overlay cache vars.
var/icon/liquid
var/icon/tank
var/icon/powerlow
var/icon/glass
var/icon/open_overlay
var/icon/cell_overlay
/obj/machinery/pump/Initialize()
create_reagents(200)
. = ..()
default_apply_parts()
if(ispath(cell))
cell = new cell(src)
Output = new(src)
RefreshParts()
update_icon()
/obj/machinery/pump/update_icon()
..()
if(!tank)
tank = new/icon(icon, "[icon_state]-volume")
if(!powerlow)
powerlow = new/icon(icon, "[icon_state]-lowpower")
if(!liquid)
var/icon/cutter = new/icon(icon, "[icon_state]-volume")
cutter.Blend(rgb(0, 0, 0,), ICON_MULTIPLY)
liquid = new/icon(icon, "[icon_state]-cutting")
liquid.Blend(cutter,ICON_AND)
if(!glass)
glass = new/icon(icon, "[icon_state]-glass")
glass.Blend(rgb(1,1,1,0.5), ICON_MULTIPLY)
if(!open_overlay)
open_overlay = new/icon(icon, "[icon_state]-open")
if(!cell_overlay)
cell_overlay = new/icon(icon, "[icon_state]-cell")
cut_overlays()
add_overlay(tank)
if(cell && cell.charge < (use * CELLRATE / efficiency))
add_overlay(powerlow)
if(reagents.total_volume >= 1)
var/list/hextorgb = hex2rgb(reagents.get_color())
liquid.GrayScale()
liquid.Blend(rgb(hextorgb[1],hextorgb[2],hextorgb[3]),ICON_MULTIPLY)
add_overlay(liquid)
add_overlay(glass)
if(open)
add_overlay(open_overlay)
if(cell)
add_overlay(cell_overlay)
if(on)
icon_state = "[initial(icon_state)]-running"
else
icon_state = "[initial(icon_state)]"
/obj/machinery/pump/process()
if(Output.get_pairing())
reagents.trans_to_holder(Output.reagents, Output.reagents.maximum_volume)
if(prob(5))
visible_message("<span class='notice'>\The [src] gurgles as it exports fluid.</span>")
if(!on)
return
if(!cell || (cell.charge < (use * CELLRATE / efficiency)))
turn_off(TRUE)
return
handle_pumping()
update_icon()
/obj/machinery/pump/RefreshParts()
for(var/obj/item/weapon/stock_parts/manipulator/SM in component_parts)
efficiency = SM.rating
var/total_bin_rating = 0
for(var/obj/item/weapon/stock_parts/matter_bin/SB in component_parts)
total_bin_rating += SB.rating
reagents.maximum_volume = round(initial(reagents.maximum_volume) + 100 * total_bin_rating)
return
/obj/machinery/pump/power_change()
if(!cell || cell.charge < (use * CELLRATE) || !anchored)
return turn_off(TRUE)
return FALSE
// Returns 0 on failure and 1 on success
/obj/machinery/pump/proc/turn_on(var/loud = 0)
if(!cell)
return 0
if(cell.charge < (use * CELLRATE))
return 0
on = 1
update_icon()
if(loud)
visible_message("<span class='notice'>\The [src] turns on.</span>")
return 1
/obj/machinery/pump/proc/turn_off(var/loud = 0)
on = 0
set_light(0, 0)
update_icon()
if(loud)
visible_message("<span class='notice'>\The [src] shuts down.</span>")
if(!on)
return TRUE
return FALSE
/obj/machinery/pump/attack_ai(mob/user as mob)
if(istype(user, /mob/living/silicon/robot) && Adjacent(user))
return attack_hand(user)
if(on)
turn_off(TRUE)
else
if(!turn_on(1))
to_chat(user, "<span class='notice'>You try to turn on \the [src] but it does not work.</span>")
/obj/machinery/pump/attack_hand(mob/user as mob)
if(open && cell)
if(ishuman(user))
if(!user.get_active_hand())
user.put_in_hands(cell)
cell.loc = user.loc
else
cell.loc = src.loc
cell.add_fingerprint(user)
cell.update_icon()
cell = null
on = 0
set_light(0)
to_chat(user, "<span class='notice'>You remove the power cell.</span>")
update_icon()
return
if(on)
turn_off(TRUE)
else if(anchored)
if(!turn_on(1))
to_chat(user, "<span class='notice'>You try to turn on \the [src] but it does not work.</span>")
update_icon()
/obj/machinery/pump/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(W.is_screwdriver())
if(!open)
if(unlocked)
unlocked = 0
to_chat(user, "<span class='notice'>You screw the battery panel in place.</span>")
else
unlocked = 1
to_chat(user, "<span class='notice'>You unscrew the battery panel.</span>")
else if(W.is_crowbar())
if(unlocked)
if(open)
open = 0
overlays = null
to_chat(user, "<span class='notice'>You crowbar the battery panel in place.</span>")
else
if(unlocked)
open = 1
to_chat(user, "<span class='notice'>You remove the battery panel.</span>")
else if(W.is_wrench())
if(on)
to_chat(user, "<span class='notice'>\The [src] is active. Turn it off before trying to move it!</span>")
return
default_unfasten_wrench(user, W, 2 SECONDS)
else if(istype(W, /obj/item/weapon/cell))
if(open)
if(cell)
to_chat(user, "<span class='notice'>There is a power cell already installed.</span>")
else
user.drop_item()
W.loc = src
cell = W
to_chat(user, "<span class='notice'>You insert the power cell.</span>")
else
..()
RefreshParts()
update_icon()
/obj/machinery/pump/proc/handle_pumping()
var/turf/T = get_turf(src)
if(istype(T, /turf/simulated/floor/water))
cell.use(use * CELLRATE / efficiency)
reagents.add_reagent("water", reagents_per_cycle)
if(T.temperature <= T0C)
reagents.add_reagent("ice", round(reagents_per_cycle / 2, 0.1))
if((istype(T,/turf/simulated/floor/water/pool) || istype(T,/turf/simulated/floor/water/deep/pool)))
reagents.add_reagent("chlorine", round(reagents_per_cycle / 10 * efficiency, 0.1))
else if(istype(T,/turf/simulated/floor/water/contaminated))
reagents.add_reagent("vatstabilizer", round(reagents_per_cycle / 2))
if(T.loc.name == "Sea") // Saltwater.
reagents.add_reagent("sodiumchloride", round(reagents_per_cycle / 10 * efficiency, 0.1))
for(var/turf/simulated/mineral/MT in range(5))
if(MT.mineral)
var/obj/effect/mineral/OR = MT.mineral
reagents.add_reagent(OR.ore_reagent, round(reagents_per_cycle / 20 * efficiency, 0.1))
else if(istype(T, /turf/simulated/floor/lava))
cell.use(use * CELLRATE / efficiency * 4)
reagents.add_reagent("mineralizedfluid", round(reagents_per_cycle * efficiency / 2, 0.1))

View File

@@ -38,7 +38,7 @@ var/list/obj/machinery/requests_console/allConsoles = list()
// 0 = no new message
// 1 = normal priority
// 2 = high priority
var/screen = RCS_MAINMENU
var/screen = RCS_VIEWMSGS
var/silent = 0 // set to 1 for it not to beep all the time
// var/hackState = 0
// 0 = not hacked
@@ -105,10 +105,16 @@ var/list/obj/machinery/requests_console/allConsoles = list()
if(..(user))
return
ui_interact(user)
tgui_interact(user)
/obj/machinery/requests_console/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
/obj/machinery/requests_console/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "RequestConsole", "[department] Request Console")
ui.open()
/obj/machinery/requests_console/tgui_data(mob/user)
var/list/data = ..()
data["department"] = department
data["screen"] = screen
data["message_log"] = message_log
@@ -122,93 +128,103 @@ var/list/obj/machinery/requests_console/allConsoles = list()
data["message"] = message
data["recipient"] = recipient
data["priortiy"] = priority
data["priority"] = priority
data["msgStamped"] = msgStamped
data["msgVerified"] = msgVerified
data["announceAuth"] = announceAuth
return data
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
ui = new(user, src, ui_key, "request_console.tmpl", "[department] Request Console", 520, 410)
ui.set_initial_data(data)
ui.open()
/obj/machinery/requests_console/tgui_act(action, list/params)
if(..())
return TRUE
/obj/machinery/requests_console/Topic(href, href_list)
if(..()) return
usr.set_machine(src)
add_fingerprint(usr)
if(reject_bad_text(href_list["write"]))
recipient = href_list["write"] //write contains the string of the receiving department's name
switch(action)
if("write")
if(reject_bad_text(params["write"]))
recipient = params["write"] //write contains the string of the receiving department's name
var/new_message = sanitize(input("Write your message:", "Awaiting Input", ""))
if(new_message)
message = new_message
screen = RCS_MESSAUTH
switch(href_list["priority"])
if("1") priority = 1
if("2") priority = 2
else priority = 0
else
var/new_message = sanitize(input("Write your message:", "Awaiting Input", ""))
if(new_message)
message = new_message
screen = RCS_MESSAUTH
switch(params["priority"])
if(1)
priority = 1
if(2)
priority = 2
else
priority = 0
else
reset_message(1)
. = TRUE
if("writeAnnouncement")
var/new_message = sanitize(input("Write your message:", "Awaiting Input", ""))
if(new_message)
message = new_message
else
reset_message(1)
. = TRUE
if("sendAnnouncement")
if(!announcementConsole)
return FALSE
announcement.Announce(message, msg_sanitized = 1)
reset_message(1)
. = TRUE
if(href_list["writeAnnouncement"])
var/new_message = sanitize(input("Write your message:", "Awaiting Input", ""))
if(new_message)
message = new_message
else
reset_message(1)
if("department")
if(!message)
return FALSE
var/log_msg = message
var/pass = 0
screen = RCS_SENTFAIL
for(var/obj/machinery/message_server/MS in machines)
if(!MS.active)
continue
MS.send_rc_message(ckey(params["department"]), department, log_msg, msgStamped, msgVerified, priority)
pass = 1
if(pass)
screen = RCS_SENTPASS
message_log += list(list("Message sent to [recipient]", "[message]"))
else
audible_message(text("[bicon(src)] *The Requests Console beeps: 'NOTICE: No server detected!'"),,4)
. = TRUE
if(href_list["sendAnnouncement"])
if(!announcementConsole) return
announcement.Announce(message, msg_sanitized = 1)
reset_message(1)
//Handle printing
if("print")
var/msg = message_log[text2num(params["print"])];
if(msg)
msg = "<b>[msg[1]]:</b><br>[msg[2]]"
msg = replacetext(msg, "<BR>", "\n")
msg = strip_html_properly(msg)
var/obj/item/weapon/paper/R = new(src.loc)
R.name = "[department] Message"
R.info = "<H3>[department] Requests Console</H3><div>[msg]</div>"
. = TRUE
if(href_list["department"] && message)
var/log_msg = message
var/pass = 0
screen = RCS_SENTFAIL
for (var/obj/machinery/message_server/MS in machines)
if(!MS.active) continue
MS.send_rc_message(ckey(href_list["department"]),department,log_msg,msgStamped,msgVerified,priority)
pass = 1
if(pass)
screen = RCS_SENTPASS
message_log += "<B>Message sent to [recipient]</B><BR>[message]"
else
audible_message(text("[bicon(src)] *The Requests Console beeps: 'NOTICE: No server detected!'"),,4)
//Handle screen switching
if("setScreen")
var/tempScreen = text2num(params["setScreen"])
if(tempScreen == RCS_ANNOUNCE && !announcementConsole)
return
if(tempScreen == RCS_VIEWMSGS)
for (var/obj/machinery/requests_console/Console in allConsoles)
if(Console.department == department)
Console.newmessagepriority = 0
Console.icon_state = "req_comp0"
Console.set_light(1)
if(tempScreen == RCS_MAINMENU)
reset_message()
screen = tempScreen
. = TRUE
//Handle printing
if (href_list["print"])
var/msg = message_log[text2num(href_list["print"])];
if(msg)
msg = replacetext(msg, "<BR>", "\n")
msg = strip_html_properly(msg)
var/obj/item/weapon/paper/R = new(src.loc)
R.name = "[department] Message"
R.info = "<H3>[department] Requests Console</H3><div>[msg]</div>"
//Handle screen switching
if(href_list["setScreen"])
var/tempScreen = text2num(href_list["setScreen"])
if(tempScreen == RCS_ANNOUNCE && !announcementConsole)
return
if(tempScreen == RCS_VIEWMSGS)
for (var/obj/machinery/requests_console/Console in allConsoles)
if(Console.department == department)
Console.newmessagepriority = 0
Console.icon_state = "req_comp0"
Console.set_light(1)
if(tempScreen == RCS_MAINMENU)
reset_message()
screen = tempScreen
//Handle silencing the console
if(href_list["toggleSilent"])
silent = !silent
updateUsrDialog()
return
//Handle silencing the console
if("toggleSilent")
silent = !silent
. = TRUE
//err... hacking code, which has no reason for existing... but anyway... it was once supposed to unlock priority 3 messaging on that console (EXTREME priority...), but the code for that was removed.
/obj/machinery/requests_console/attackby(var/obj/item/weapon/O as obj, var/mob/user as mob)
@@ -238,7 +254,7 @@ var/list/obj/machinery/requests_console/allConsoles = list()
if(screen == RCS_MESSAUTH)
var/obj/item/weapon/card/id/T = O
msgVerified = text("<font color='green'><b>Verified by [T.registered_name] ([T.assignment])</b></font>")
updateUsrDialog()
SStgui.update_uis(src)
if(screen == RCS_ANNOUNCE)
var/obj/item/weapon/card/id/ID = O
if(access_RC_announce in ID.GetAccess())
@@ -247,13 +263,13 @@ var/list/obj/machinery/requests_console/allConsoles = list()
else
reset_message()
to_chat(user, "<span class='warning'>You are not authorized to send announcements.</span>")
updateUsrDialog()
SStgui.update_uis(src)
if(istype(O, /obj/item/weapon/stamp))
if(inoperable(MAINT)) return
if(screen == RCS_MESSAUTH)
var/obj/item/weapon/stamp/T = O
msgStamped = text("<font color='blue'><b>Stamped with the [T.name]</b></font>")
updateUsrDialog()
SStgui.update_uis(src)
return
/obj/machinery/requests_console/proc/reset_message(var/mainmenu = 0)

View File

@@ -38,7 +38,7 @@
/obj/machinery/vending/boozeomat
name = "Booze-O-Mat"
desc = "A technological marvel, supposedly able to mix just the mixture you'd like to drink the moment you ask for one."
desc = "A technological marvel, the ads would have you believe this is able to mix just the mixture you'd like to drink the moment you ask for one."
icon_state = "fridge_dark"
products = list(/obj/item/weapon/reagent_containers/food/drinks/glass2/square = 10,
/obj/item/weapon/reagent_containers/food/drinks/glass2/rocks = 10,
@@ -72,7 +72,11 @@
/obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey = 5,
/obj/item/weapon/reagent_containers/food/drinks/bottle/wine = 5,
/obj/item/weapon/reagent_containers/food/drinks/bottle/small/ale = 15,
/obj/item/weapon/reagent_containers/food/drinks/bottle/small/ale/hushedwhisper = 15,
/obj/item/weapon/reagent_containers/food/drinks/bottle/small/beer = 15,
/obj/item/weapon/reagent_containers/food/drinks/bottle/small/beer/silverdragon = 15,
/obj/item/weapon/reagent_containers/food/drinks/bottle/small/beer/meteor = 15,
/obj/item/weapon/reagent_containers/food/drinks/bottle/small/litebeer = 15,
/obj/item/weapon/reagent_containers/food/drinks/bottle/small/cider = 15,
/obj/item/weapon/reagent_containers/food/drinks/bottle/orangejuice = 5,
/obj/item/weapon/reagent_containers/food/drinks/bottle/tomatojuice = 5,
@@ -104,61 +108,144 @@
vending_sound = "machines/vending/vending_cans.ogg"
/obj/machinery/vending/assist
products = list( /obj/item/device/assembly/prox_sensor = 5,/obj/item/device/assembly/igniter = 3,/obj/item/device/assembly/signaler = 4,
/obj/item/weapon/tool/wirecutters = 1, /obj/item/weapon/cartridge/signal = 4)
contraband = list(/obj/item/device/flashlight = 5,/obj/item/device/assembly/timer = 2)
products = list( /obj/item/device/assembly/prox_sensor = 5,
/obj/item/device/assembly/igniter = 3,
/obj/item/device/assembly/signaler = 4,
/obj/item/weapon/tool/wirecutters = 1,
/obj/item/weapon/cartridge/signal = 4)
contraband = list(/obj/item/device/flashlight = 5,
/obj/item/device/assembly/timer = 2)
product_ads = "Only the finest!;Have some tools.;The most robust equipment.;The finest gear in space!"
/obj/machinery/vending/coffee
name = "Hot Drinks machine"
desc = "A vending machine which dispenses hot drinks."
desc = "A Galaksi brand vending machine which dispenses hot drinks."
description_fluff = "The Ward-Takahashi Galaksi Samovar 55 has been reconstituting hot drinks from their powdered forms since... Well, 2555, but the design has hardly changed in a century or so."
product_ads = "Have a drink!;Drink up!;It's good for you!;Would you like a hot joe?;I'd kill for some coffee!;The best beans in the galaxy.;Only the finest brew for you.;Mmmm. Nothing like a coffee.;I like coffee, don't you?;Coffee helps you work!;Try some tea.;We hope you like the best!;Try our new chocolate!;Admin conspiracies"
icon_state = "coffee"
vend_delay = 34
idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan.
vend_power_usage = 85000 //85 kJ to heat a 250 mL cup of coffee
products = list(/obj/item/weapon/reagent_containers/food/drinks/coffee = 25,/obj/item/weapon/reagent_containers/food/drinks/tea = 25,/obj/item/weapon/reagent_containers/food/drinks/h_chocolate = 25)
products = list(/obj/item/weapon/reagent_containers/food/drinks/coffee = 25,
/obj/item/weapon/reagent_containers/food/drinks/decaf = 15,
/obj/item/weapon/reagent_containers/food/drinks/tea = 25,
/obj/item/weapon/reagent_containers/food/drinks/h_chocolate = 25,
/obj/item/weapon/reagent_containers/food/drinks/greentea = 15,
/obj/item/weapon/reagent_containers/food/drinks/chaitea = 15)
contraband = list(/obj/item/weapon/reagent_containers/food/drinks/ice = 10)
prices = list(/obj/item/weapon/reagent_containers/food/drinks/coffee = 2, /obj/item/weapon/reagent_containers/food/drinks/tea = 2, /obj/item/weapon/reagent_containers/food/drinks/h_chocolate = 2) //VOREStation Edit
prices = list(/obj/item/weapon/reagent_containers/food/drinks/coffee = 2,
/obj/item/weapon/reagent_containers/food/drinks/decaf = 3,
/obj/item/weapon/reagent_containers/food/drinks/tea = 2,
/obj/item/weapon/reagent_containers/food/drinks/h_chocolate = 2,
/obj/item/weapon/reagent_containers/food/drinks/greentea = 10,
/obj/item/weapon/reagent_containers/food/drinks/chaitea = 5) // VOREStation Edit - Lowers Coffee/Hot Chocolate/Tea Prices from 3 -> 2.
vending_sound = "machines/vending/vending_coffee.ogg"
/obj/machinery/vending/snack
name = "Getmore Chocolate Corp"
desc = "A snack machine courtesy of the Getmore Chocolate Corporation, based out of Mars."
desc = "A snack machine courtesy of the Getmore Chocolate Corporation, a Centauri Provisions brand."
description_fluff = "Despite its name, the Getmore Chocolate Corporation does not produce chocolate - or any foods at all. The company exists soley to refit Ward-Takahashi's Galaksi brand vending products to accept Centauri Provisions' massive range of snackfoods, and sell them at a significant markup. Generic vendors are not authorized to vend Centauri products, and their popularity forces the market to Getmore or Get Lost."
product_slogans = "Try our new nougat bar!;Twice the calories for half the price!"
product_ads = "The healthiest!;Award-winning chocolate bars!;Mmm! So good!;Oh my god it's so juicy!;Have a snack.;Snacks are good for you!;Have some more Getmore!;Best quality snacks straight from mars.;We love chocolate!;Try our new jerky!"
product_ads = "The healthiest!;Award-winning chocolate bars!;Mmm! So good!;Oh my god it's so juicy!;Have a snack.;Snacks are good for you!;Get More with Getmore!;Best quality snacks from Centauri Provisions.;We love chocolate!;Try our new jerky!"
icon_state = "snack"
products = list(/obj/item/weapon/reagent_containers/food/snacks/candy = 12,/obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 12,/obj/item/weapon/reagent_containers/food/snacks/chips =12,
/obj/item/weapon/reagent_containers/food/snacks/sosjerky = 12,/obj/item/weapon/reagent_containers/food/snacks/no_raisin = 12,/obj/item/weapon/reagent_containers/food/snacks/spacetwinkie = 12,
/obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 12, /obj/item/weapon/reagent_containers/food/snacks/tastybread = 12, /obj/item/weapon/reagent_containers/food/snacks/skrellsnacks = 6)
contraband = list(/obj/item/weapon/reagent_containers/food/snacks/syndicake = 6,/obj/item/weapon/reagent_containers/food/snacks/unajerky = 12,)
prices = list(/obj/item/weapon/reagent_containers/food/snacks/candy = 1,/obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 5,/obj/item/weapon/reagent_containers/food/snacks/chips = 1,
/obj/item/weapon/reagent_containers/food/snacks/sosjerky = 2,/obj/item/weapon/reagent_containers/food/snacks/no_raisin = 1,/obj/item/weapon/reagent_containers/food/snacks/spacetwinkie = 1,
/obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 1, /obj/item/weapon/reagent_containers/food/snacks/tastybread = 2, /obj/item/weapon/reagent_containers/food/snacks/skrellsnacks = 2)
products = list(/obj/item/weapon/reagent_containers/food/snacks/candy = 12,
/obj/item/weapon/reagent_containers/food/snacks/candy/gummy = 12,
/obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 12,
/obj/item/weapon/reagent_containers/food/snacks/chips = 12,
/obj/item/weapon/reagent_containers/food/snacks/chips/bbq = 12,
/obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 12,
/obj/item/weapon/reagent_containers/food/snacks/pistachios = 12,
/obj/item/weapon/reagent_containers/food/snacks/semki = 12,
/obj/item/weapon/reagent_containers/food/snacks/sosjerky = 12,
/obj/item/weapon/reagent_containers/food/snacks/no_raisin = 12,
/obj/item/weapon/reagent_containers/food/snacks/spacetwinkie = 12,
/obj/item/weapon/reagent_containers/food/snacks/tastybread = 12,
/obj/item/weapon/reagent_containers/food/snacks/skrellsnacks = 6,
/obj/item/weapon/reagent_containers/food/snacks/cookiesnack = 6,
/obj/item/weapon/storage/box/gum = 4,
/obj/item/clothing/mask/chewable/candy/lolli = 8,
/obj/item/weapon/storage/box/admints = 4,
/obj/item/weapon/reagent_containers/food/snacks/cb01 = 6,
/obj/item/weapon/reagent_containers/food/snacks/cb02 = 6,
/obj/item/weapon/reagent_containers/food/snacks/cb03 = 6,
/obj/item/weapon/reagent_containers/food/snacks/cb04 = 6,
/obj/item/weapon/reagent_containers/food/snacks/cb05 = 6,
/obj/item/weapon/reagent_containers/food/snacks/cb06 = 6,
/obj/item/weapon/reagent_containers/food/snacks/cb07 = 6,
/obj/item/weapon/reagent_containers/food/snacks/cb08 = 6,
/obj/item/weapon/reagent_containers/food/snacks/cb09 = 6,
/obj/item/weapon/reagent_containers/food/snacks/cb10 = 6,
/obj/item/weapon/reagent_containers/food/snacks/tuna = 2)
contraband = list(/obj/item/weapon/reagent_containers/food/snacks/syndicake = 6,
/obj/item/weapon/reagent_containers/food/snacks/unajerky = 12)
prices = list(/obj/item/weapon/reagent_containers/food/snacks/candy = 1,
/obj/item/weapon/reagent_containers/food/snacks/candy/gummy = 2,
/obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 5,
/obj/item/weapon/reagent_containers/food/snacks/chips = 1,
/obj/item/weapon/reagent_containers/food/snacks/chips/bbq = 1,
/obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 1,
/obj/item/weapon/reagent_containers/food/snacks/pistachios = 1,
/obj/item/weapon/reagent_containers/food/snacks/semki = 1,
/obj/item/weapon/reagent_containers/food/snacks/sosjerky = 2,
/obj/item/weapon/reagent_containers/food/snacks/no_raisin = 1,
/obj/item/weapon/reagent_containers/food/snacks/spacetwinkie = 1,
/obj/item/weapon/reagent_containers/food/snacks/tastybread = 2,
/obj/item/weapon/reagent_containers/food/snacks/skrellsnacks = 4,
/obj/item/weapon/storage/box/gum = 15,
/obj/item/clothing/mask/chewable/candy/lolli = 2,
/obj/item/weapon/storage/box/admints = 5,
/obj/item/weapon/reagent_containers/food/snacks/cookiesnack = 20,
/obj/item/weapon/reagent_containers/food/snacks/cb01 = 5,
/obj/item/weapon/reagent_containers/food/snacks/cb02 = 3,
/obj/item/weapon/reagent_containers/food/snacks/cb03 = 5,
/obj/item/weapon/reagent_containers/food/snacks/cb04 = 4,
/obj/item/weapon/reagent_containers/food/snacks/cb05 = 3,
/obj/item/weapon/reagent_containers/food/snacks/cb06 = 7,
/obj/item/weapon/reagent_containers/food/snacks/cb07 = 4,
/obj/item/weapon/reagent_containers/food/snacks/cb08 = 6,
/obj/item/weapon/reagent_containers/food/snacks/cb09 = 10,
/obj/item/weapon/reagent_containers/food/snacks/cb10 = 8,
/obj/item/weapon/reagent_containers/food/snacks/tuna = 23)
/obj/machinery/vending/cola
name = "Robust Softdrinks"
desc = "A softdrink vendor provided by Robust Industries, LLC."
desc = "A softdrink vendor graciously provided by NanoTrasen's own vending division."
description_fluff = "In a genius sales move, the only vendor authorized to dispense 'outside' beverages (at temperatures lower than 30 degrees celcius) aboard NanoTrasen stations... Is NanoTrasen themselves."
icon_state = "Cola_Machine"
product_slogans = "Robust Softdrinks: More robust than a toolbox to the head!"
product_ads = "Refreshing!;Hope you're thirsty!;Over 1 million drinks sold!;Thirsty? Why not cola?;Please, have a drink!;Drink up!;The best drinks in space."
products = list(/obj/item/weapon/reagent_containers/food/drinks/cans/cola = 10,/obj/item/weapon/reagent_containers/food/drinks/cans/space_mountain_wind = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/dr_gibb = 10,/obj/item/weapon/reagent_containers/food/drinks/cans/starkist = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/waterbottle = 10,/obj/item/weapon/reagent_containers/food/drinks/cans/space_up = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea = 10, /obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/gingerale = 10)
contraband = list(/obj/item/weapon/reagent_containers/food/drinks/cans/thirteenloko = 5, /obj/item/weapon/reagent_containers/food/snacks/liquidfood = 6)
prices = list(/obj/item/weapon/reagent_containers/food/drinks/cans/cola = 1,/obj/item/weapon/reagent_containers/food/drinks/cans/space_mountain_wind = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/dr_gibb = 1,/obj/item/weapon/reagent_containers/food/drinks/cans/starkist = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/waterbottle = 2,/obj/item/weapon/reagent_containers/food/drinks/cans/space_up = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea = 1,/obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/gingerale = 1)
product_ads = "Refreshing!;Hope you're thirsty!;Over 1 million drinks sold!;Thirsty? Why not cola?;Please, have a drink!;Drink up!;The best drinks in the galaxy."
products = list(/obj/item/weapon/reagent_containers/food/drinks/cans/cola = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/space_mountain_wind = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/dr_gibb = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/dr_gibb_diet = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/starkist = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/waterbottle = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/space_up = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/gingerale = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/root_beer = 10)
contraband = list(/obj/item/weapon/reagent_containers/food/drinks/cans/thirteenloko = 5,
/obj/item/weapon/reagent_containers/food/snacks/liquidfood = 6)
prices = list(/obj/item/weapon/reagent_containers/food/drinks/cans/cola = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/space_mountain_wind = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/dr_gibb = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/dr_gibb_diet = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/starkist = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/waterbottle = 2,
/obj/item/weapon/reagent_containers/food/drinks/cans/space_up = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/gingerale = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/root_beer = 1)
idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan.
vending_sound = "machines/vending/vending_cans.ogg"
/obj/machinery/vending/fitness
name = "SweatMAX"
desc = "Fueled by your inner inadequacy!"
description_fluff = "Provided by NanoMed, SweatMAX promises solutions to all of your problems. Premium gains at premium prices. Resale of SweatMAX products is a violation of NanoTrasen guidelines."
icon_state = "fitness"
//VOREStation Edit Start
products = list(/obj/item/weapon/reagent_containers/food/drinks/smallmilk = 16,
@@ -166,6 +253,7 @@
/obj/item/weapon/reagent_containers/food/drinks/glass2/fitnessflask/proteinshake = 8,
/obj/item/weapon/reagent_containers/food/drinks/glass2/fitnessflask = 8,
/obj/item/weapon/reagent_containers/food/snacks/candy/proteinbar = 16,
/obj/item/weapon/reagent_containers/food/snacks/fruitbar = 16,
/obj/item/weapon/reagent_containers/food/snacks/liquidfood = 8,
/obj/item/weapon/reagent_containers/pill/diet = 8,
///obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/glucose = 5, //VOREStation Removal,
@@ -177,6 +265,7 @@
/obj/item/weapon/reagent_containers/food/drinks/glass2/fitnessflask/proteinshake = 15,
/obj/item/weapon/reagent_containers/food/drinks/glass2/fitnessflask = 1,
/obj/item/weapon/reagent_containers/food/snacks/candy/proteinbar = 5,
/obj/item/weapon/reagent_containers/food/snacks/fruitbar = 5,
/obj/item/weapon/reagent_containers/food/snacks/liquidfood = 5,
/obj/item/weapon/reagent_containers/pill/diet = 25,
///obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/glucose = 5,
@@ -201,6 +290,7 @@
/obj/machinery/vending/cigarette
name = "cigarette machine"
desc = "If you want to get cancer, might as well do it in style!"
description_fluff = "As the ease of cancer treatment progressed to the almost routine (if costly) in the 22nd century, the tobacco industry was quick to make sure smoking went back into style. Take your pick, you've got health insurance don't ya, kid?"
product_slogans = "Space cigs taste good like a cigarette should.;I'd rather toolbox than switch.;Smoke!;Don't believe the reports - smoke today!"
product_ads = "Probably not bad for you!;Don't believe the scientists!;It's good for you!;Don't quit, buy more!;Smoke!;Nicotine heaven.;Best cigarettes since 2150.;Award-winning cigs.;Feeling temperamental? Try a Temperamento!;Carcinoma Angels - go fuck yerself!;Don't be so hard on yourself, kid. Smoke a Lucky Star!"
vend_delay = 34
@@ -212,35 +302,76 @@
/obj/item/weapon/storage/fancy/cigarettes/jerichos = 10,
/obj/item/weapon/storage/fancy/cigarettes/menthols = 10,
/obj/item/weapon/storage/rollingpapers = 10,
/obj/item/weapon/storage/chewables/tobacco = 5,
/obj/item/weapon/storage/chewables/tobacco/fine = 5,
/obj/item/weapon/storage/box/matches = 10,
/obj/item/weapon/flame/lighter/random = 4)
/obj/item/weapon/flame/lighter/random = 4,
/obj/item/clothing/mask/smokable/ecig/util = 2,
///obj/item/clothing/mask/smokable/ecig/deluxe = 2,
/obj/item/clothing/mask/smokable/ecig/simple = 2,
/obj/item/weapon/reagent_containers/ecig_cartridge/med_nicotine = 10,
/obj/item/weapon/reagent_containers/ecig_cartridge/high_nicotine = 5,
/obj/item/weapon/reagent_containers/ecig_cartridge/orange = 5,
/obj/item/weapon/reagent_containers/ecig_cartridge/mint = 5,
/obj/item/weapon/reagent_containers/ecig_cartridge/watermelon = 5,
/obj/item/weapon/reagent_containers/ecig_cartridge/grape = 5,
/obj/item/weapon/reagent_containers/ecig_cartridge/lemonlime = 5,
/obj/item/weapon/reagent_containers/ecig_cartridge/coffee = 5,
/obj/item/weapon/reagent_containers/ecig_cartridge/blanknico = 2,
/obj/item/weapon/storage/box/fancy/chewables/tobacco/nico = 5)
contraband = list(/obj/item/weapon/flame/lighter/zippo = 4)
premium = list(/obj/item/weapon/storage/fancy/cigar = 5,
/obj/item/weapon/storage/fancy/cigarettes/carcinomas = 5,
/obj/item/weapon/storage/fancy/cigarettes/professionals = 5)
prices = list(/obj/item/weapon/storage/fancy/cigarettes = 12,
/obj/item/weapon/storage/fancy/cigarettes/dromedaryco = 15,
/obj/item/weapon/storage/fancy/cigarettes/killthroat = 17,
/obj/item/weapon/storage/fancy/cigarettes/dromedaryco = 20,
/obj/item/weapon/storage/fancy/cigarettes/killthroat = 14,
/obj/item/weapon/storage/fancy/cigarettes/luckystars = 17,
/obj/item/weapon/storage/fancy/cigarettes/jerichos = 22,
/obj/item/weapon/storage/fancy/cigarettes/menthols = 18,
/obj/item/weapon/storage/rollingpapers = 10,
/obj/item/weapon/storage/chewables/tobacco = 10,
/obj/item/weapon/storage/chewables/tobacco/fine = 20,
/obj/item/weapon/storage/box/matches = 1,
/obj/item/weapon/flame/lighter/random = 2)
/obj/item/weapon/flame/lighter/random = 2,
/obj/item/clothing/mask/smokable/ecig/util = 100,
///obj/item/clothing/mask/smokable/ecig/deluxe = 300,
/obj/item/clothing/mask/smokable/ecig/simple = 150,
/obj/item/weapon/reagent_containers/ecig_cartridge/med_nicotine = 10,
/obj/item/weapon/reagent_containers/ecig_cartridge/high_nicotine = 15,
/obj/item/weapon/reagent_containers/ecig_cartridge/orange = 15,
/obj/item/weapon/reagent_containers/ecig_cartridge/mint = 15,
/obj/item/weapon/reagent_containers/ecig_cartridge/watermelon = 15,
/obj/item/weapon/reagent_containers/ecig_cartridge/grape = 15,
/obj/item/weapon/reagent_containers/ecig_cartridge/lemonlime = 15,
/obj/item/weapon/reagent_containers/ecig_cartridge/coffee = 15,
/obj/item/weapon/reagent_containers/ecig_cartridge/blanknico = 15,
/obj/item/weapon/storage/box/fancy/chewables/tobacco/nico = 15)
/obj/machinery/vending/medical
name = "NanoMed Plus"
desc = "Medical drug dispenser."
description_fluff = "NanoMed is NanoTrasen's medical science division, and provides almost all of the modern medbay essentials in-house at no extra charge. By using this vending machine, employees accept liability for products that may or may not be temporarily replaced by placebos or experimental treatments."
icon_state = "med"
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?;Ping!"
req_access = list(access_medical)
products = list(/obj/item/weapon/reagent_containers/glass/bottle/antitoxin = 4,/obj/item/weapon/reagent_containers/glass/bottle/inaprovaline = 4,
/obj/item/weapon/reagent_containers/glass/bottle/stoxin = 4,/obj/item/weapon/reagent_containers/glass/bottle/toxin = 4,
/obj/item/weapon/reagent_containers/syringe/antiviral = 4,/obj/item/weapon/reagent_containers/syringe = 12,
/obj/item/device/healthanalyzer = 5,/obj/item/weapon/reagent_containers/glass/beaker = 4, /obj/item/weapon/reagent_containers/dropper = 2,
/obj/item/stack/medical/advanced/bruise_pack = 6, /obj/item/stack/medical/advanced/ointment = 6, /obj/item/stack/medical/splint = 4,
products = list(/obj/item/weapon/reagent_containers/glass/bottle/antitoxin = 4,
/obj/item/weapon/reagent_containers/glass/bottle/inaprovaline = 4,
/obj/item/weapon/reagent_containers/glass/bottle/stoxin = 4,
/obj/item/weapon/reagent_containers/glass/bottle/toxin = 4,
/obj/item/weapon/reagent_containers/syringe/antiviral = 4,
/obj/item/weapon/reagent_containers/syringe = 12,
/obj/item/device/healthanalyzer = 5,
/obj/item/weapon/reagent_containers/glass/beaker = 4,
/obj/item/weapon/reagent_containers/dropper = 2,
/obj/item/stack/medical/advanced/bruise_pack = 6,
/obj/item/stack/medical/advanced/ointment = 6,
/obj/item/stack/medical/splint = 4,
/obj/item/weapon/storage/pill_bottle/carbon = 2)
contraband = list(/obj/item/weapon/reagent_containers/pill/tox = 3,/obj/item/weapon/reagent_containers/pill/stox = 4,/obj/item/weapon/reagent_containers/pill/antitox = 6)
contraband = list(/obj/item/weapon/reagent_containers/pill/tox = 3,
/obj/item/weapon/reagent_containers/pill/stox = 4,
/obj/item/weapon/reagent_containers/pill/antitox = 6)
idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan.
req_log_access = access_cmo
has_logs = 1
@@ -248,20 +379,31 @@
/obj/machinery/vending/phoronresearch
name = "Toximate 3000"
desc = "All the fine parts you need in one vending machine!"
products = list(/obj/item/clothing/under/rank/scientist = 6,/obj/item/clothing/suit/bio_suit = 6,/obj/item/clothing/head/bio_hood = 6,
/obj/item/device/transfer_valve = 6,/obj/item/device/assembly/timer = 6,/obj/item/device/assembly/signaler = 6,
/obj/item/device/assembly/prox_sensor = 6,/obj/item/device/assembly/igniter = 6)
products = list(/obj/item/clothing/under/rank/scientist = 6,
/obj/item/clothing/suit/bio_suit = 6,
/obj/item/clothing/head/bio_hood = 6,
/obj/item/device/transfer_valve = 6,
/obj/item/device/assembly/timer = 6,
/obj/item/device/assembly/signaler = 6,
/obj/item/device/assembly/prox_sensor = 6,
/obj/item/device/assembly/igniter = 6)
req_log_access = access_rd
has_logs = 1
/obj/machinery/vending/wallmed1
name = "NanoMed"
desc = "A wall-mounted version of the NanoMed."
description_fluff = "NanoMed is NanoTrasen's medical science division, and provides almost all of the modern medbay essentials in-house at no extra charge. By using this vending machine, employees accept liability for products that may or may not be temporarily replaced by placebos or experimental treatments."
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"
density = 0 //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/weapon/reagent_containers/hypospray/autoinjector = 4,/obj/item/device/healthanalyzer = 1)
contraband = list(/obj/item/weapon/reagent_containers/syringe/antitoxin = 4,/obj/item/weapon/reagent_containers/syringe/antiviral = 4,/obj/item/weapon/reagent_containers/pill/tox = 1)
products = list(/obj/item/stack/medical/bruise_pack = 2,
/obj/item/stack/medical/ointment = 2,
/obj/item/weapon/reagent_containers/hypospray/autoinjector = 4,
/obj/item/device/healthanalyzer = 1)
contraband = list(/obj/item/weapon/reagent_containers/syringe/antitoxin = 4,
/obj/item/weapon/reagent_containers/syringe/antiviral = 4,
/obj/item/weapon/reagent_containers/pill/tox = 1)
req_log_access = access_cmo
has_logs = 1
can_rotate = 0
@@ -269,10 +411,14 @@
/obj/machinery/vending/wallmed2
name = "NanoMed"
desc = "A wall-mounted version of the NanoMed, containing only vital first aid equipment."
description_fluff = "NanoMed is NanoTrasen's medical science division, and provides almost all of the modern medbay essentials in-house at no extra charge. By using this vending machine, employees accept liability for products that may or may not be temporarily replaced by placebos or experimental treatments."
icon_state = "wallmed"
density = 0 //It is wall-mounted, and thus, not dense. --Superxpdude
products = list(/obj/item/weapon/reagent_containers/hypospray/autoinjector = 5,/obj/item/weapon/reagent_containers/syringe/antitoxin = 3,/obj/item/stack/medical/bruise_pack = 3,
/obj/item/stack/medical/ointment =3,/obj/item/device/healthanalyzer = 3)
products = list(/obj/item/weapon/reagent_containers/hypospray/autoinjector = 5,
/obj/item/weapon/reagent_containers/syringe/antitoxin = 3,
/obj/item/stack/medical/bruise_pack = 3,
/obj/item/stack/medical/ointment =3,
/obj/item/device/healthanalyzer = 3)
contraband = list(/obj/item/weapon/reagent_containers/pill/tox = 3)
req_log_access = access_cmo
has_logs = 1
@@ -281,24 +427,35 @@
/obj/machinery/vending/security
name = "SecTech"
desc = "A security equipment vendor."
description_fluff = "Security vending is kindly provided by the Lawson Arms company, Hephaestus Industries' law enforcement division."
product_ads = "Crack capitalist skulls!;Beat some heads in!;Don't forget - harm is good!;Your weapons are right here.;Handcuffs!;Freeze, scumbag!;Don't tase me bro!;Tase them, bro.;Why not have a donut?"
icon_state = "sec"
req_access = list(access_security)
products = list(/obj/item/weapon/handcuffs = 8,/obj/item/weapon/grenade/flashbang = 4,/obj/item/device/flash = 5,
/obj/item/weapon/reagent_containers/food/snacks/donut/normal = 12,/obj/item/weapon/storage/box/evidence = 6)
contraband = list(/obj/item/clothing/glasses/sunglasses = 2,/obj/item/weapon/storage/box/donut = 2)
products = list(/obj/item/weapon/handcuffs = 8,
/obj/item/weapon/grenade/flashbang = 4,
/obj/item/device/flash = 5,
/obj/item/weapon/reagent_containers/food/snacks/donut/normal = 12,
/obj/item/weapon/storage/box/evidence = 6)
contraband = list(/obj/item/clothing/glasses/sunglasses = 2,
/obj/item/weapon/storage/box/donut = 2)
req_log_access = access_armory
has_logs = 1
/obj/machinery/vending/hydronutrients
name = "NutriMax"
desc = "A plant nutrients vendor."
desc = "A plant nutrients vendor by the NanoPastures company."
product_slogans = "Aren't you glad you don't have to fertilize the natural way?;Now with 50% less stink!;Plants are people too!"
product_ads = "We like plants!;Don't you want some?;The greenest thumbs ever.;We like big plants.;Soft soil..."
icon_state = "nutri_generic"
products = list(/obj/item/weapon/reagent_containers/glass/bottle/eznutrient = 6,/obj/item/weapon/reagent_containers/glass/bottle/left4zed = 4,/obj/item/weapon/reagent_containers/glass/bottle/robustharvest = 3,/obj/item/weapon/plantspray/pests = 20,
/obj/item/weapon/reagent_containers/syringe = 5,/obj/item/weapon/reagent_containers/glass/beaker = 4,/obj/item/weapon/storage/bag/plants = 5)
premium = list(/obj/item/weapon/reagent_containers/glass/bottle/ammonia = 10,/obj/item/weapon/reagent_containers/glass/bottle/diethylamine = 5)
products = list(/obj/item/weapon/reagent_containers/glass/bottle/eznutrient = 6,
/obj/item/weapon/reagent_containers/glass/bottle/left4zed = 4,
/obj/item/weapon/reagent_containers/glass/bottle/robustharvest = 3,
/obj/item/weapon/plantspray/pests = 20,
/obj/item/weapon/reagent_containers/syringe = 5,
/obj/item/weapon/reagent_containers/glass/beaker = 4,
/obj/item/weapon/storage/bag/plants = 5)
premium = list(/obj/item/weapon/reagent_containers/glass/bottle/ammonia = 10,
/obj/item/weapon/reagent_containers/glass/bottle/diethylamine = 5)
idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan.
@@ -309,14 +466,48 @@
product_ads = "We like plants!;Grow some crops!;Grow, baby, growww!;Aw h'yeah son!"
icon_state = "seeds_generic"
products = list(/obj/item/seeds/bananaseed = 3,/obj/item/seeds/berryseed = 3,/obj/item/seeds/carrotseed = 3,/obj/item/seeds/chantermycelium = 3,/obj/item/seeds/chiliseed = 3,
/obj/item/seeds/cornseed = 3, /obj/item/seeds/eggplantseed = 3, /obj/item/seeds/potatoseed = 3, /obj/item/seeds/replicapod = 3,/obj/item/seeds/soyaseed = 3,
/obj/item/seeds/sunflowerseed = 3,/obj/item/seeds/tomatoseed = 3,/obj/item/seeds/towermycelium = 3,/obj/item/seeds/wheatseed = 3,/obj/item/seeds/appleseed = 3,
/obj/item/seeds/poppyseed = 3,/obj/item/seeds/sugarcaneseed = 3,/obj/item/seeds/ambrosiavulgarisseed = 3,/obj/item/seeds/peanutseed = 3,/obj/item/seeds/whitebeetseed = 3,/obj/item/seeds/watermelonseed = 3,/obj/item/seeds/lavenderseed = 3,/obj/item/seeds/limeseed = 3,
/obj/item/seeds/lemonseed = 3,/obj/item/seeds/orangeseed = 3,/obj/item/seeds/grassseed = 3,/obj/item/seeds/cocoapodseed = 3,/obj/item/seeds/plumpmycelium = 2,
/obj/item/seeds/cabbageseed = 3,/obj/item/seeds/grapeseed = 3,/obj/item/seeds/pumpkinseed = 3,/obj/item/seeds/cherryseed = 3,/obj/item/seeds/plastiseed = 3,/obj/item/seeds/riceseed = 3)
contraband = list(/obj/item/seeds/amanitamycelium = 2,/obj/item/seeds/glowshroom = 2,/obj/item/seeds/libertymycelium = 2,/obj/item/seeds/mtearseed = 2,
/obj/item/seeds/nettleseed = 2,/obj/item/seeds/reishimycelium = 2,/obj/item/seeds/reishimycelium = 2,/obj/item/seeds/shandseed = 2,)
products = list(/obj/item/seeds/bananaseed = 3,
/obj/item/seeds/berryseed = 3,
/obj/item/seeds/carrotseed = 3,
/obj/item/seeds/chantermycelium = 3,
/obj/item/seeds/chiliseed = 3,
/obj/item/seeds/cornseed = 3,
/obj/item/seeds/eggplantseed = 3,
/obj/item/seeds/potatoseed = 3,
/obj/item/seeds/replicapod = 3,
/obj/item/seeds/soyaseed = 3,
/obj/item/seeds/sunflowerseed = 3,
/obj/item/seeds/tomatoseed = 3,
/obj/item/seeds/towermycelium = 3,
/obj/item/seeds/wheatseed = 3,
/obj/item/seeds/appleseed = 3,
/obj/item/seeds/poppyseed = 3,
/obj/item/seeds/sugarcaneseed = 3,
/obj/item/seeds/ambrosiavulgarisseed = 3,
/obj/item/seeds/peanutseed = 3,
/obj/item/seeds/whitebeetseed = 3,
/obj/item/seeds/watermelonseed = 3,
/obj/item/seeds/lavenderseed = 3,
/obj/item/seeds/limeseed = 3,
/obj/item/seeds/lemonseed = 3,
/obj/item/seeds/orangeseed = 3,
/obj/item/seeds/grassseed = 3,
/obj/item/seeds/cocoapodseed = 3,
/obj/item/seeds/plumpmycelium = 2,
/obj/item/seeds/cabbageseed = 3,
/obj/item/seeds/grapeseed = 3,
/obj/item/seeds/pumpkinseed = 3,
/obj/item/seeds/cherryseed = 3,
/obj/item/seeds/plastiseed = 3,
/obj/item/seeds/riceseed = 3)
contraband = list(/obj/item/seeds/amanitamycelium = 2,
/obj/item/seeds/glowshroom = 2,
/obj/item/seeds/libertymycelium = 2,
/obj/item/seeds/mtearseed = 2,
/obj/item/seeds/nettleseed = 2,
/obj/item/seeds/reishimycelium = 2,
/obj/item/seeds/reishimycelium = 2,
/obj/item/seeds/shandseed = 2,)
premium = list(/obj/item/weapon/reagent_containers/spray/waterflower = 1)
/**
@@ -357,7 +548,7 @@
/obj/machinery/vending/dinnerware
name = "Dinnerware"
desc = "A kitchen and restaurant equipment vendor."
desc = "A WT Galaksi brand kitchen and restaurant equipment vendor."
product_ads = "Mm, food stuffs!;Food and food accessories.;Get your plates!;You like forks?;I like forks.;Woo, utensils.;You don't really need these..."
icon_state = "dinnerware"
products = list(
@@ -403,11 +594,21 @@
desc = "Tools for tools."
icon_state = "tool"
//req_access = list(access_maint_tunnels) //Maintenance access
products = list(/obj/item/stack/cable_coil/random = 10,/obj/item/weapon/tool/crowbar = 5,/obj/item/weapon/weldingtool = 3,/obj/item/weapon/tool/wirecutters = 5,
/obj/item/weapon/tool/wrench = 5,/obj/item/device/analyzer = 5,/obj/item/device/t_scanner = 5,/obj/item/weapon/tool/screwdriver = 5,
/obj/item/device/flashlight/glowstick = 3, /obj/item/device/flashlight/glowstick/red = 3, /obj/item/device/flashlight/glowstick/blue = 3,
/obj/item/device/flashlight/glowstick/orange =3, /obj/item/device/flashlight/glowstick/yellow = 3)
contraband = list(/obj/item/weapon/weldingtool/hugetank = 2,/obj/item/clothing/gloves/fyellow = 2,)
products = list(/obj/item/stack/cable_coil/random = 10,
/obj/item/weapon/tool/crowbar = 5,
/obj/item/weapon/weldingtool = 3,
/obj/item/weapon/tool/wirecutters = 5,
/obj/item/weapon/tool/wrench = 5,
/obj/item/device/analyzer = 5,
/obj/item/device/t_scanner = 5,
/obj/item/weapon/tool/screwdriver = 5,
/obj/item/device/flashlight/glowstick = 3,
/obj/item/device/flashlight/glowstick/red = 3,
/obj/item/device/flashlight/glowstick/blue = 3,
/obj/item/device/flashlight/glowstick/orange =3,
/obj/item/device/flashlight/glowstick/yellow = 3)
contraband = list(/obj/item/weapon/weldingtool/hugetank = 2,
/obj/item/clothing/gloves/fyellow = 2)
premium = list(/obj/item/clothing/gloves/yellow = 1)
req_log_access = access_ce
has_logs = 1
@@ -417,16 +618,35 @@
desc = "Spare tool vending. What? Did you expect some witty description?"
icon_state = "engivend"
req_access = list(access_engine_equip)
products = list(/obj/item/device/geiger = 4,/obj/item/clothing/glasses/meson = 2,/obj/item/device/multitool = 4,/obj/item/weapon/cell/high = 10,
/obj/item/weapon/airlock_electronics = 10,/obj/item/weapon/module/power_control = 10,
/obj/item/weapon/circuitboard/airalarm = 10,/obj/item/weapon/circuitboard/firealarm = 10,/obj/item/weapon/circuitboard/status_display = 2,
/obj/item/weapon/circuitboard/ai_status_display = 2,/obj/item/weapon/circuitboard/newscaster = 2,/obj/item/weapon/circuitboard/holopad = 2,
/obj/item/weapon/circuitboard/intercom = 4,/obj/item/weapon/circuitboard/security/telescreen/entertainment = 4,
/obj/item/weapon/stock_parts/motor = 2,/obj/item/weapon/stock_parts/spring = 2,/obj/item/weapon/stock_parts/gear = 2,
/obj/item/weapon/circuitboard/atm,/obj/item/weapon/circuitboard/guestpass,/obj/item/weapon/circuitboard/keycard_auth,
/obj/item/weapon/circuitboard/photocopier,/obj/item/weapon/circuitboard/fax,/obj/item/weapon/circuitboard/request,
/obj/item/weapon/circuitboard/microwave,/obj/item/weapon/circuitboard/washing,/obj/item/weapon/circuitboard/scanner_console,
/obj/item/weapon/circuitboard/sleeper_console,/obj/item/weapon/circuitboard/body_scanner,/obj/item/weapon/circuitboard/sleeper,
products = list(/obj/item/device/geiger = 4,
/obj/item/clothing/glasses/meson = 2,
/obj/item/device/multitool = 4,
/obj/item/weapon/cell/high = 10,
/obj/item/weapon/airlock_electronics = 10,
/obj/item/weapon/module/power_control = 10,
/obj/item/weapon/circuitboard/airalarm = 10,
/obj/item/weapon/circuitboard/firealarm = 10,
/obj/item/weapon/circuitboard/status_display = 2,
/obj/item/weapon/circuitboard/ai_status_display = 2,
/obj/item/weapon/circuitboard/newscaster = 2,
/obj/item/weapon/circuitboard/holopad = 2,
/obj/item/weapon/circuitboard/intercom = 4,
/obj/item/weapon/circuitboard/security/telescreen/entertainment = 4,
/obj/item/weapon/stock_parts/motor = 2,
/obj/item/weapon/stock_parts/spring = 2,
/obj/item/weapon/stock_parts/gear = 2,
/obj/item/weapon/circuitboard/atm,
/obj/item/weapon/circuitboard/guestpass,
/obj/item/weapon/circuitboard/keycard_auth,
/obj/item/weapon/circuitboard/photocopier,
/obj/item/weapon/circuitboard/fax,
/obj/item/weapon/circuitboard/request,
/obj/item/weapon/circuitboard/microwave,
/obj/item/weapon/circuitboard/washing,
/obj/item/weapon/circuitboard/scanner_console,
/obj/item/weapon/circuitboard/sleeper_console,
/obj/item/weapon/circuitboard/body_scanner,
/obj/item/weapon/circuitboard/sleeper,
/obj/item/weapon/circuitboard/dna_analyzer)
contraband = list(/obj/item/weapon/cell/potato = 3)
premium = list(/obj/item/weapon/storage/belt/utility = 3)
@@ -439,15 +659,30 @@
desc = "Everything you need for do-it-yourself station repair."
icon_state = "engi"
req_access = list(access_engine_equip)
products = list(/obj/item/clothing/under/rank/chief_engineer = 4,/obj/item/clothing/under/rank/engineer = 4,/obj/item/clothing/shoes/orange = 4,/obj/item/clothing/head/hardhat = 4,
/obj/item/weapon/storage/belt/utility = 4,/obj/item/clothing/glasses/meson = 4,/obj/item/clothing/gloves/yellow = 4, /obj/item/weapon/tool/screwdriver = 12,
/obj/item/weapon/tool/crowbar = 12,/obj/item/weapon/tool/wirecutters = 12,/obj/item/device/multitool = 12,/obj/item/weapon/tool/wrench = 12,/obj/item/device/t_scanner = 12,
/obj/item/stack/cable_coil/heavyduty = 8, /obj/item/weapon/cell = 8, /obj/item/weapon/weldingtool = 8,/obj/item/clothing/head/welding = 8,
/obj/item/weapon/light/tube = 10,/obj/item/clothing/suit/fire = 4, /obj/item/weapon/stock_parts/scanning_module = 5,/obj/item/weapon/stock_parts/micro_laser = 5,
/obj/item/weapon/stock_parts/matter_bin = 5,/obj/item/weapon/stock_parts/manipulator = 5,/obj/item/weapon/stock_parts/console_screen = 5)
// There was an incorrect entry (cablecoil/power). I improvised to cablecoil/heavyduty.
// Another invalid entry, /obj/item/weapon/circuitry. I don't even know what that would translate to, removed it.
// The original products list wasn't finished. The ones without given quantities became quantity 5. -Sayu
products = list(/obj/item/clothing/under/rank/chief_engineer = 4,
/obj/item/clothing/under/rank/engineer = 4,
/obj/item/clothing/shoes/orange = 4,
/obj/item/clothing/head/hardhat = 4,
/obj/item/weapon/storage/belt/utility = 4,
/obj/item/clothing/glasses/meson = 4,
/obj/item/clothing/gloves/yellow = 4,
/obj/item/weapon/tool/screwdriver = 12,
/obj/item/weapon/tool/crowbar = 12,
/obj/item/weapon/tool/wirecutters = 12,
/obj/item/device/multitool = 12,
/obj/item/weapon/tool/wrench = 12,
/obj/item/device/t_scanner = 12,
/obj/item/stack/cable_coil/heavyduty = 8,
/obj/item/weapon/cell = 8,
/obj/item/weapon/weldingtool = 8,
/obj/item/clothing/head/welding = 8,
/obj/item/weapon/light/tube = 10,
/obj/item/clothing/suit/fire = 4,
/obj/item/weapon/stock_parts/scanning_module = 5,
/obj/item/weapon/stock_parts/micro_laser = 5,
/obj/item/weapon/stock_parts/matter_bin = 5,
/obj/item/weapon/stock_parts/manipulator = 5,
/obj/item/weapon/stock_parts/console_screen = 5)
req_log_access = access_ce
has_logs = 1
@@ -456,17 +691,27 @@
desc = "All the tools you need to create your own robot army."
icon_state = "robotics"
req_access = list(access_robotics)
products = list(/obj/item/clothing/suit/storage/toggle/labcoat = 4,/obj/item/clothing/under/rank/roboticist = 4,/obj/item/stack/cable_coil = 4,/obj/item/device/flash = 4,
/obj/item/weapon/cell/high = 12, /obj/item/device/assembly/prox_sensor = 3,/obj/item/device/assembly/signaler = 3,/obj/item/device/healthanalyzer = 3,
/obj/item/weapon/surgical/scalpel = 2,/obj/item/weapon/surgical/circular_saw = 2,/obj/item/weapon/tank/anesthetic = 2,/obj/item/clothing/mask/breath/medical = 5,
/obj/item/weapon/tool/screwdriver = 5,/obj/item/weapon/tool/crowbar = 5)
//everything after the power cell had no amounts, I improvised. -Sayu
products = list(/obj/item/clothing/suit/storage/toggle/labcoat = 4,
/obj/item/clothing/under/rank/roboticist = 4,
/obj/item/stack/cable_coil = 4,
/obj/item/device/flash = 4,
/obj/item/weapon/cell/high = 12,
/obj/item/device/assembly/prox_sensor = 3,
/obj/item/device/assembly/signaler = 3,
/obj/item/device/healthanalyzer = 3,
/obj/item/weapon/surgical/scalpel = 2,
/obj/item/weapon/surgical/circular_saw = 2,
/obj/item/weapon/tank/anesthetic = 2,
/obj/item/clothing/mask/breath/medical = 5,
/obj/item/weapon/tool/screwdriver = 5,
/obj/item/weapon/tool/crowbar = 5)
req_log_access = access_rd
has_logs = 1
/obj/machinery/vending/giftvendor
name = "AlliCo Baubles and Confectionaries"
desc = "For that special someone!"
description_fluff = "AlliCo Ltd. is a NanoTrasen subsidiary focused on the design and licensing of 'cute' products including toys, gifts, stationary and accessories. Their range of original characters feature in all aspects of popular culture, from snacks to animated series."
icon_state = "giftvendor"
vend_delay = 15
products = list(/obj/item/weapon/storage/fancy/heartbox = 5,

View File

@@ -92,7 +92,7 @@
/obj/item/mecha_parts/component/armor/military
name = "military grade mecha plating"
step_delay = 6
step_delay = 4
max_integrity = 100
@@ -121,14 +121,14 @@
typepass = TRUE
if(typepass)
step_delay = 3
step_delay = 0
else
step_delay = initial(step_delay)
/obj/item/mecha_parts/component/armor/marshal
name = "marshal mecha plating"
step_delay = 5
step_delay = 3
max_integrity = 100
@@ -215,7 +215,7 @@
/obj/item/mecha_parts/component/armor/alien
name = "strange mecha plating"
step_delay = 3
step_delay = 2
damage_absorption = list(
"brute"=0.7,
"fire"=0.7,

View File

@@ -9,7 +9,7 @@
var/deflect_coeff = 1.15
var/damage_coeff = 0.8
step_delay = 1
step_delay = 0.5
equip_type = EQUIP_HULL

View File

@@ -9,7 +9,7 @@
var/deflect_coeff = 1.15
var/damage_coeff = 0.8
step_delay = 2
step_delay = 1
equip_type = EQUIP_HULL

View File

@@ -5,6 +5,7 @@
equip_cooldown = 30
energy_drain = 10
force = 15
var/advanced = 0 //Determines if you can pierce the heavens or not. Used in diamond drill.
required_type = list(/obj/mecha/working/ripley)
/obj/item/mecha_parts/mecha_equipment/tool/drill/action(atom/target)
@@ -22,11 +23,17 @@
if(T == chassis.loc && src == chassis.selected)
if(istype(target, /turf/simulated/wall))
var/turf/simulated/wall/W = target
if(W.reinf_material)
if(W.reinf_material && !advanced)//R wall but no good drill
occupant_message("<span class='warning'>[target] is too durable to drill through.</span>")
return
else if((W.reinf_material && advanced) || do_after_cooldown(target))//R wall with good drill
log_message("Drilled through [target]")
target.ex_act(3)
else
log_message("Drilled through [target]")
target.ex_act(2)
else if(istype(target, /turf/simulated/mineral))
if(enable_special)
for(var/turf/simulated/mineral/M in range(chassis,1))
@@ -54,44 +61,7 @@
origin_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 3)
equip_cooldown = 10
force = 15
/obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill/action(atom/target)
if(!action_checks(target)) return
if(isobj(target))
var/obj/target_obj = target
if(target_obj.unacidable) return
set_ready_state(0)
chassis.use_power(energy_drain)
chassis.visible_message("<span class='danger'>[chassis] starts to drill [target]</span>", "<span class='warning'>You hear the drill.</span>")
occupant_message("<span class='danger'>You start to drill [target]</span>")
var/T = chassis.loc
var/C = target.loc //why are these backwards? we may never know -Pete
if(do_after_cooldown(target))
if(T == chassis.loc && src == chassis.selected)
if(istype(target, /turf/simulated/wall))
var/turf/simulated/wall/W = target
if(!W.reinf_material || do_after_cooldown(target))//To slow down how fast mechs can drill through the station
log_message("Drilled through [target]")
target.ex_act(3)
else if(istype(target, /turf/simulated/mineral))
if(enable_special)
for(var/turf/simulated/mineral/M in range(chassis,1))
if(get_dir(chassis,M)&chassis.dir)
M.GetDrilled()
else
var/turf/simulated/mineral/M1 = target
M1.GetDrilled()
log_message("Drilled through [target]")
if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment)
var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo
if(ore_box)
for(var/obj/item/weapon/ore/ore in range(chassis,1))
if(get_dir(chassis,ore)&chassis.dir)
ore.forceMove(ore_box)
else if(target.loc == C)
log_message("Drilled through [target]")
target.ex_act(2)
return 1
advanced = 1
/obj/item/mecha_parts/mecha_equipment/tool/drill/bore
name = "depth bore"

View File

@@ -7,7 +7,7 @@
energy_drain = 20
range = 0
step_delay = 1
step_delay = 0.2
var/obj/item/shield_projector/line/exosuit/my_shield = null
var/my_shield_type = /obj/item/shield_projector/line/exosuit

View File

@@ -9,7 +9,7 @@
energy_drain = OMNI_SHIELD_DRAIN
range = 0
step_delay = 1
step_delay = 0.2
var/obj/item/shield_projector/shields = null
var/shield_type = /obj/item/shield_projector/rectangle/mecha
@@ -48,7 +48,7 @@
log_message("Activated.")
else
set_ready_state(1)
step_delay = 1
step_delay = initial(step_delay)
log_message("Deactivated.")
/obj/item/mecha_parts/mecha_equipment/omni_shield/Topic(href, href_list)

View File

@@ -11,7 +11,7 @@
deviation = 0.7
projectile_energy_cost = 25
step_delay = 2
step_delay = 0.5
origin_tech = list(TECH_MATERIAL = 3, TECH_COMBAT = 4)

View File

@@ -52,7 +52,7 @@
projectile = /obj/item/projectile/beam/heavylaser
fire_sound = 'sound/weapons/lasercannonfire.ogg'
step_delay = 2
step_delay = 1
origin_tech = list(TECH_MATERIAL = 3, TECH_COMBAT = 4, TECH_MAGNET = 4)

View File

@@ -2,7 +2,7 @@
var/missile_speed = 2
var/missile_range = 30
step_delay = 2
step_delay = 0.5
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/Fire(atom/movable/AM, atom/target, turf/aimloc)
AM.throw_at(target,missile_range, missile_speed, chassis)

View File

@@ -7,7 +7,7 @@
energy_drain = 30
step_delay = 2
step_delay = 0.5
projectile = /obj/item/projectile/bullet/incendiary/flamethrower/large
fire_sound = 'sound/weapons/towelwipe.ogg'

View File

@@ -12,7 +12,7 @@
var/auto_rearm = 0 //Does the weapon reload itself after each shot?
required_type = list(/obj/mecha/combat, /obj/mecha/working/hoverpod/combatpod)
step_delay = 1
step_delay = 0.1
equip_type = EQUIP_WEAPON

View File

@@ -674,7 +674,7 @@
break
break
return max(1, round(tally))
return max(1, round(tally, 0.1))
/obj/mecha/proc/dyndomove(direction)
if(!can_move)

View File

@@ -53,7 +53,11 @@ var/global/list/image/splatter_cache=list()
/obj/effect/decal/cleanable/blood/update_icon()
if(basecolor == "rainbow") basecolor = "#[get_random_colour(1)]"
color = basecolor
if(synthblood)
if(basecolor == SYNTH_BLOOD_COLOUR)
name = "oil"
desc = "It's quite oily."
else if(synthblood)
name = "synthetic blood"
desc = "It's quite greasy."
else

View File

@@ -12,12 +12,13 @@ generic_filth = TRUE means when the decal is saved, it will be switched out for
var/age = 0
var/list/random_icon_states = list()
/obj/effect/decal/cleanable/Initialize(var/ml, var/_age)
/obj/effect/decal/cleanable/Initialize(var/mapload, var/_age)
if(!isnull(_age))
age = _age
if(random_icon_states && length(src.random_icon_states) > 0)
src.icon_state = pick(src.random_icon_states)
SSpersistence.track_value(src, /datum/persistent/filth)
if(!mapload || !config.persistence_ignore_mapload)
SSpersistence.track_value(src, /datum/persistent/filth)
. = ..()
/obj/effect/decal/cleanable/Destroy()

View File

@@ -430,11 +430,16 @@ var/list/global/slot_flags_enumeration = list(
return 1
/obj/item/proc/mob_can_unequip(mob/M, slot, disable_warning = 0)
if(!slot) return 0
if(!M) return 0
if(!canremove)
return 0
if(!slot)
if(issilicon(M))
return 1 // for stuff in grippers
return 0
if(!M.slot_is_accessible(slot, src, disable_warning? null : M))
return 0
return 1

View File

@@ -11,6 +11,7 @@ var/list/GPS_list = list()
matter = list(DEFAULT_WALL_MATERIAL = 500)
var/gps_tag = "GEN0"
var/emped = FALSE
var/updating = TRUE // Lets users lock the UI so they don't have to deal with constantly shifting signals
var/tracking = FALSE // Will not show other signals or emit its own signal if false.
var/long_range = FALSE // If true, can see farther, depending on get_map_levels().
var/local_mode = FALSE // If true, only GPS signals of the same Z level are shown.
@@ -66,7 +67,11 @@ var/list/GPS_list = list()
add_overlay("working")
/obj/item/device/gps/attack_self(mob/user)
display(user)
tgui_interact(user)
/obj/item/device/gps/examine(mob/user)
. = ..()
. += display()
// Compiles all the data not available directly from the GPS
// Like the positions and directions to all other GPS units
@@ -117,12 +122,12 @@ var/list/GPS_list = list()
return dat
/obj/item/device/gps/proc/display(mob/user)
/obj/item/device/gps/proc/display()
if(!tracking)
to_chat(user, "The device is off. Alt-click it to turn it on.")
. = "The device is off. Alt-click it to turn it on."
return
if(emped)
to_chat(user, "It's busted!")
. = "It's busted!"
return
var/list/dat = list()
@@ -143,8 +148,7 @@ var/list/GPS_list = list()
else
dat += "No other signals detected."
var/result = dat.Join("<br>")
to_chat(user, result)
. = dat
/obj/item/device/gps/Topic(var/href, var/list/href_list)
if(..())
@@ -168,6 +172,85 @@ var/list/GPS_list = list()
hide_signal = !hide_signal
to_chat(usr, "You set the device to [hide_signal ? "not " : ""]broadcast a signal while scanning for other signals.")
/obj/item/device/gps/tgui_interact(mob/user, datum/tgui/ui)
if(emped)
to_chat(user, "<span class='hear'>[src] fizzles weakly.</span>")
return
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Gps", name)
ui.open()
ui.set_autoupdate(updating)
/obj/item/device/gps/tgui_data(mob/user)
var/list/data = list()
data["power"] = tracking
data["tag"] = gps_tag
data["updating"] = updating
data["globalmode"] = !local_mode
if(!tracking || emped) //Do not bother scanning if the GPS is off or EMPed
return data
var/turf/curr = get_turf(src)
data["currentArea"] = "[get_area_name(curr, TRUE)]"
data["currentCoords"] = list(curr.x, curr.y, curr.z)
data["currentCoordsText"] = "[curr.x], [curr.y], [using_map.get_zlevel_name(curr.z)]"
data["zLevelDetection"] = using_map.get_map_levels(curr.z, long_range)
var/list/signals = list()
data["signals"] = list()
for(var/obj/item/device/gps/G in GPS_list - src)
if(!G.tracking || G.emped || G.hide_signal)
continue
var/turf/T = get_turf(G)
if(!T)
continue
if(local_mode && curr.z != T.z)
continue
if(!(T.z in data["zLevelDetection"]))
continue
var/list/signal = list()
signal["entrytag"] = G.gps_tag //Name or 'tag' of the GPS
signal["coords"] = list(T.x, T.y, T.z)
signal["coordsText"] = "[T.x], [T.y], [using_map.get_zlevel_name(T.z)]"
if(T.z == curr.z) //Distance/Direction calculations for same z-level only
signal["dist"] = max(get_dist(curr, T), 0) //Distance between the src and remote GPS turfs
signal["degrees"] = round(Get_Angle(curr, T)) //0-360 degree directional bearing, for more precision.
signals += list(signal) //Add this signal to the list of signals
data["signals"] = signals
return data
/obj/item/device/gps/tgui_act(action, params)
if(..())
return TRUE
switch(action)
if("rename")
var/a = stripped_input(usr, "Please enter desired tag.", name, gps_tag, 20)
if(!a)
return
gps_tag = a
name = "global positioning system ([gps_tag])"
. = TRUE
if("power")
toggletracking(usr)
. = TRUE
if("updating")
updating = !updating
. = TRUE
if("globalmode")
local_mode = !local_mode
. = TRUE
/obj/item/device/gps/on // Defaults to off to avoid polluting the signal list with a bunch of GPSes without owners. If you need to spawn active ones, use these.
tracking = TRUE
@@ -291,10 +374,10 @@ var/list/GPS_list = list()
/obj/item/device/gps/syndie/display(mob/user)
if(!tracking)
to_chat(user, "The device is off. Alt-click it to turn it on.")
. = "The device is off. Alt-click it to turn it on."
return
if(emped)
to_chat(user, "It's busted!")
. = "It's busted!"
return
var/list/dat = list()
@@ -312,5 +395,4 @@ var/list/GPS_list = list()
else
dat += "No other signals detected."
var/result = dat.Join("<br>")
to_chat(user, result)
. = dat

View File

@@ -0,0 +1,642 @@
/*
* Mech toys (previously labeled prizes, but that's unintuitive)
* Mech toy combat
*/
// Mech battle special attack types.
#define SPECIAL_ATTACK_HEAL 1
#define SPECIAL_ATTACK_DAMAGE 2
#define SPECIAL_ATTACK_UTILITY 3
#define SPECIAL_ATTACK_OTHER 4
// Max length of a mech battle
#define MAX_BATTLE_LENGTH 50
/obj/item/toy/mecha
icon = 'icons/obj/toy.dmi'
icon_state = "ripleytoy"
drop_sound = 'sound/mecha/mechstep.ogg'
reach = 2 // So you can battle across the table!
// Mech Battle Vars
var/timer = 0 // Timer when it'll be off cooldown
var/cooldown = 1.5 SECONDS // Cooldown between play sessions (and interactions)
var/cooldown_multiplier = 20 // Cooldown multiplier after a battle (by default: battle cooldowns are 30 seconds)
var/quiet = FALSE // If it makes noise when played with
var/wants_to_battle = FALSE // TRUE = Offering battle to someone || FALSE = Not offering battle
var/in_combat = FALSE // TRUE = in combat currently || FALSE = Not in combat
var/combat_health = 0 // The mech's health in battle
var/max_combat_health = 0 // The mech's max combat health
var/special_attack_charged = FALSE // TRUE = the special attack is charged || FALSE = not charged
var/special_attack_type = 0 // What type of special attack they use - SPECIAL_ATTACK_DAMAGE, SPECIAL_ATTACK_HEAL, SPECIAL_ATTACK_UTILITY, SPECIAL_ATTACK_OTHER
var/special_attack_type_message = "" // What message their special move gets on examining
var/special_attack_cry = "*flip" // The battlecry when using the special attack
var/special_attack_cooldown = 0 // Current cooldown of their special attack
var/wins = 0 // This mech's win count in combat
var/losses = 0 // ...And their loss count in combat
/obj/item/toy/mecha/Initialize()
. = ..()
desc = "Mini-Mecha action figure! Collect them all! Attack your friends or another mech with one to initiate epic mech combat! [desc]."
combat_health = max_combat_health
switch(special_attack_type)
if(SPECIAL_ATTACK_DAMAGE)
special_attack_type_message = "an aggressive move, which deals bonus damage."
if(SPECIAL_ATTACK_HEAL)
special_attack_type_message = "a defensive move, which grants bonus healing."
if(SPECIAL_ATTACK_UTILITY)
special_attack_type_message = "a utility move, which heals the user and damages the opponent."
if(SPECIAL_ATTACK_OTHER)
special_attack_type_message = "a special move, which [special_attack_type_message]"
else
special_attack_type_message = "a mystery move, even I don't know."
/obj/item/toy/mecha/proc/in_range(source, user) // Modify our in_range proc specifically for mech battles!
if(get_dist(source, user) <= 2)
return 1
return 0 //not in range and not telekinetic
/**
* this proc combines "sleep" while also checking for if the battle should continue
*
* this goes through some of the checks - the toys need to be next to each other to fight!
* if it's player vs themself: They need to be able to "control" both mechs (either must be adjacent or using TK).
* if it's player vs player: Both players need to be able to "control" their mechs (either must be adjacent or using TK).
* if it's player vs mech (suicide): the mech needs to be in range of the player.
* if all the checks are TRUE, it does the sleeps, and returns TRUE. Otherwise, it returns FALSE.
* Arguments:
* * delay - the amount of time the sleep at the end of the check will sleep for
* * attacker - the attacking toy in the battle.
* * attacker_controller - the controller of the attacking toy. there should ALWAYS be an attacker_controller
* * opponent - (optional) the defender controller in the battle, for PvP
*/
/obj/item/toy/mecha/proc/combat_sleep(var/delay, obj/item/toy/mecha/attacker, mob/living/carbon/attacker_controller, mob/living/carbon/opponent)
if(!attacker_controller) // If the attacker for whatever reason is null, don't continue.
return FALSE
if(!attacker) // If there's no attacker, then attacker_controller IS the attacker.
if(!in_range(src, attacker_controller))
attacker_controller.visible_message("<span class='suicide'>[attacker_controller] is running from [src]! The coward!</span>")
return FALSE
else // If there's an attacker, we can procede as normal.
if(!in_range(src, attacker)) // The two toys aren't next to each other, the battle ends.
attacker_controller.visible_message("<span class='notice'> [attacker] and [src] separate, ending the battle. </span>", \
"<span class='notice'> [attacker] and [src] separate, ending the battle. </span>")
return FALSE
// Dead men tell no tales, incapacitated men fight no fights.
if(attacker_controller.incapacitated())
return FALSE
// If the attacker_controller isn't next to the attacking toy (and doesn't have telekinesis), the battle ends.
if(!in_range(attacker, attacker_controller))
attacker_controller.visible_message("<span class='notice'> [attacker_controller.name] seperates from [attacker], ending the battle.</span>", \
"<span class='notice'> You separate from [attacker], ending the battle. </span>")
return FALSE
// If it's PVP and the opponent is not next to the defending(src) toy (and doesn't have telekinesis), the battle ends.
if(opponent)
if(opponent.incapacitated())
return FALSE
if(!in_range(src, opponent))
opponent.visible_message("<span class='notice'> [opponent.name] seperates from [src], ending the battle.</span>", \
"<span class='notice'> You separate from [src], ending the battle. </span>")
return FALSE
// If it's not PVP and the attacker_controller isn't next to the defending toy (and doesn't have telekinesis), the battle ends.
else
if (!in_range(src, attacker_controller))
attacker_controller.visible_message("<span class='notice'> [attacker_controller.name] seperates from [src] and [attacker], ending the battle.</span>", \
"<span class='notice'> You separate [attacker] and [src], ending the battle. </span>")
return FALSE
// If all that is good, then we can sleep peacefully.
sleep(delay)
return TRUE
//all credit to skasi for toy mech fun ideas
/obj/item/toy/mecha/attack_self(mob/user)
if(timer < world.time)
to_chat(user, "<span class='notice'>You play with [src].</span>")
timer = world.time + cooldown
playsound(user, 'sound/mecha/mechstep.ogg', 20, TRUE)
else
. = ..()
/obj/item/toy/mecha/attack_hand(mob/user)
. = ..()
if(.)
return
if(loc == user)
attack_self(user)
/**
* If you attack a mech with a mech, initiate combat between them
*/
/obj/item/toy/mecha/attackby(obj/item/user_toy, mob/living/user)
if(istype(user_toy, /obj/item/toy/mecha))
var/obj/item/toy/mecha/M = user_toy
if(check_battle_start(user, M))
mecha_brawl(M, user)
..()
/**
* Attack is called from the user's toy, aimed at target(another human), checking for target's toy.
*/
/obj/item/toy/mecha/attack(mob/living/carbon/human/target, mob/living/carbon/human/user)
if(target == user)
to_chat(user, "<span class='notice'>Target another toy mech if you want to start a battle with yourself.</span>")
return
else if(user.a_intent != I_HURT)
if(wants_to_battle) //prevent spamming someone with offers
to_chat(user, "<span class='notice'>You already are offering battle to someone!</span>")
return
if(!check_battle_start(user)) //if the user's mech isn't ready, don't bother checking
return
for(var/obj/item/I in target.get_all_held_items())
if(istype(I, /obj/item/toy/mecha)) //if you attack someone with a mech who's also holding a mech, offer to battle them
var/obj/item/toy/mecha/M = I
if(!M.check_battle_start(target, null, user)) //check if the attacker mech is ready
break
//slap them with the metaphorical white glove
if(M.wants_to_battle) //if the target mech wants to battle, initiate the battle from their POV
mecha_brawl(M, target, user) //P = defender's mech / SRC = attacker's mech / target = defender / user = attacker
M.wants_to_battle = FALSE
return
//extend the offer of battle to the other mech
var/datum/gender/T = gender_datums[user.get_visible_gender()]
to_chat(user, "<span class='notice'>You offer battle to [target.name]!</span>")
to_chat(target, "<span class='notice'><b>[user.name] wants to battle with [T.His] [name]!</b> <i>Attack them with a toy mech to initiate combat.</i></span>")
wants_to_battle = TRUE
addtimer(CALLBACK(src, .proc/withdraw_offer, user), 6 SECONDS)
return
..()
/**
* Overrides attack_tk - Sorry, you have to be face to face to initiate a battle, it's good sportsmanship
*/
/obj/item/toy/mecha/attack_tk(mob/user)
if(timer < world.time)
to_chat(user, "<span class='notice'>You telekinetically play with [src].</span>")
timer = world.time + cooldown
playsound(user, 'sound/mecha/mechstep.ogg', 20, TRUE)
/**
* Resets the request for battle.
*
* For use in a timer, this proc resets the wants_to_battle variable after a short period.
* Arguments:
* * user - the user wanting to do battle
*/
/obj/item/toy/mecha/proc/withdraw_offer(mob/living/carbon/user)
if(wants_to_battle)
wants_to_battle = FALSE
to_chat(user, "<span class='notice'>You get the feeling they don't want to battle.</span>")
/**
* Starts a battle, toy mech vs player. Player... doesn't win. Commented out for now as suicide_act is not physically doable.
*/
/obj/item/toy/mecha/suicide_act(mob/living/carbon/user)
if(in_combat)
to_chat(user, "<span class='notice'>[src] is in battle, let it finish first.</span>")
return
var/datum/gender/T = gender_datums[user.get_visible_gender()]
user.visible_message("<span class='suicide'>[user] begins a fight [T.His] can't win with [src]! It looks like [T.His] trying to commit suicide!</span>")
in_combat = TRUE
sleep(1.5 SECONDS)
for(var/i in 1 to 4)
switch(i)
if(1, 3)
SpinAnimation(5, 0)
playsound(src, 'sound/mecha/mechstep.ogg', 30, TRUE)
user.adjustBruteLoss(25)
if(2)
user.SpinAnimation(5, 0)
playsound(user, 'sound/weapons/smash.ogg', 20, TRUE)
combat_health-- //we scratched it!
if(4)
visible_message(special_attack_cry + "!!")
if(!combat_sleep(1 SECONDS, null, user))
visible_message("PATHETIC.")
combat_health = max_combat_health
in_combat = FALSE
return (BRUTELOSS)
sleep(0.5 SECONDS)
user.adjustBruteLoss(450)
in_combat = FALSE
visible_message("AN EASY WIN. MY POWER INCREASES.") // steal a soul, become swole
color= "#ff7373"
max_combat_health = round(max_combat_health*1.5 + 0.1)
combat_health = max_combat_health
wins++
return (BRUTELOSS)
/obj/item/toy/mecha/examine()
. = ..()
. += "<span class='notice'>This toy's special attack is [special_attack_cry], [special_attack_type_message] </span>"
if(in_combat)
. += "<span class='notice'>This toy has a maximum health of [max_combat_health]. Currently, it's [combat_health].</span>"
. += "<span class='notice'>Its special move light is [special_attack_cooldown? "flashing red." : "green and is ready!"]</span>"
else
. += "<span class='notice'>This toy has a maximum health of [max_combat_health].</span>"
if(wins || losses)
. += "<span class='notice'>This toy has [wins] wins, and [losses] losses.</span>"
/**
* The 'master' proc of the mech battle. Processes the entire battle's events and makes sure it start and finishes correctly.
*
* src is the defending toy, and the battle proc is called on it to begin the battle.
* After going through a few checks at the beginning to ensure the battle can start properly, the battle begins a loop that lasts
* until either toy has no more health. During this loop, it also ensures the mechs stay in combat range of each other.
* It will then randomly decide attacks for each toy, occasionally making one or the other use their special attack.
* When either mech has no more health, the loop ends, and it displays the victor and the loser while updating their stats and resetting them.
* Arguments:
* * attacker - the attacking toy, the toy in the attacker_controller's hands
* * attacker_controller - the user, the one who is holding the toys / controlling the fight
* * opponent - optional arg used in Mech PvP battles: the other person who is taking part in the fight (controls src)
*/
/obj/item/toy/mecha/proc/mecha_brawl(obj/item/toy/mecha/attacker, mob/living/carbon/attacker_controller, mob/living/carbon/opponent)
//A GOOD DAY FOR A SWELL BATTLE!
attacker_controller.visible_message("<span class='danger'> [attacker_controller.name] collides [attacker] with [src]! Looks like they're preparing for a brawl! </span>", \
"<span class='danger'> You collide [attacker] into [src], sparking a fierce battle! </span>", \
"<span class='hear'> You hear hard plastic smacking into hard plastic.</span>")
/// Who's in control of the defender (src)?
var/mob/living/carbon/src_controller = (opponent)? opponent : attacker_controller
/// How long has the battle been going?
var/battle_length = 0
in_combat = TRUE
attacker.in_combat = TRUE
//1.5 second cooldown * 20 = 30 second cooldown after a fight
timer = world.time + cooldown*cooldown_multiplier
attacker.timer = world.time + attacker.cooldown*attacker.cooldown_multiplier
sleep(1 SECONDS)
//--THE BATTLE BEGINS--
while(combat_health > 0 && attacker.combat_health > 0 && battle_length < MAX_BATTLE_LENGTH)
if(!combat_sleep(0.5 SECONDS, attacker, attacker_controller, opponent)) //combat_sleep checks everything we need to have checked for combat to continue
break
//before we do anything - deal with charged attacks
if(special_attack_charged)
src_controller.visible_message("<span class='danger'> [src] unleashes its special attack!! </span>", \
"<span class='danger'> You unleash [src]'s special attack! </span>")
special_attack_move(attacker)
else if(attacker.special_attack_charged)
attacker_controller.visible_message("<span class='danger'> [attacker] unleashes its special attack!! </span>", \
"<span class='danger'> You unleash [attacker]'s special attack! </span>")
attacker.special_attack_move(src)
else
//process the cooldowns
if(special_attack_cooldown > 0)
special_attack_cooldown--
if(attacker.special_attack_cooldown > 0)
attacker.special_attack_cooldown--
//combat commences
switch(rand(1,8))
if(1 to 3) //attacker wins
if(attacker.special_attack_cooldown == 0 && attacker.combat_health <= round(attacker.max_combat_health/3)) //if health is less than 1/3 and special off CD, use it
attacker.special_attack_charged = TRUE
attacker_controller.visible_message("<span class='danger'> [attacker] begins charging its special attack!! </span>", \
"<span class='danger'> You begin charging [attacker]'s special attack! </span>")
else //just attack
attacker.SpinAnimation(5, 0)
playsound(attacker, 'sound/mecha/mechstep.ogg', 30, TRUE)
combat_health--
attacker_controller.visible_message("<span class='danger'> [attacker] devastates [src]! </span>", \
"<span class='danger'> You ram [attacker] into [src]! </span>", \
"<span class='hear'> You hear hard plastic smacking hard plastic.</span>")
if(prob(5))
combat_health--
playsound(src, 'sound/effects/meteorimpact.ogg', 20, TRUE)
attacker_controller.visible_message("<span class='boldwarning'> ...and lands a CRIPPLING BLOW! </span>", \
"<span class='boldwarning'> ...and you land a CRIPPLING blow on [src]! </span>", null)
if(4) //both lose
attacker.SpinAnimation(5, 0)
SpinAnimation(5, 0)
combat_health--
attacker.combat_health--
// This is sloppy but we don't have do_sparks.
var/datum/effect/effect/system/spark_spread/sparksrc = new(src)
playsound(src, "sparks", 50, 1)
sparksrc.set_up(2, 0, src)
sparksrc.attach(src)
sparksrc.start()
var/datum/effect/effect/system/spark_spread/sparkatk = new(attacker)
playsound(attacker, "sparks", 50, 1)
sparkatk.set_up(2, 0, attacker)
sparkatk.attach(attacker)
sparkatk.start()
if(prob(50))
attacker_controller.visible_message("<span class='danger'> [attacker] and [src] clash dramatically, causing sparks to fly! </span>", \
"<span class='danger'> [attacker] and [src] clash dramatically, causing sparks to fly! </span>", \
"<span class='hear'> You hear hard plastic rubbing against hard plastic.</span>")
else
src_controller.visible_message("<span class='danger'> [src] and [attacker] clash dramatically, causing sparks to fly! </span>", \
"<span class='danger'> [src] and [attacker] clash dramatically, causing sparks to fly! </span>", \
"<span class='hear'> You hear hard plastic rubbing against hard plastic.</span>")
if(5) //both win
playsound(attacker, 'sound/weapons/parry.ogg', 20, TRUE)
if(prob(50))
attacker_controller.visible_message("<span class='danger'> [src]'s attack deflects off of [attacker]. </span>", \
"<span class='danger'> [src]'s attack deflects off of [attacker]. </span>", \
"<span class='hear'> You hear hard plastic bouncing off hard plastic.</span>")
else
src_controller.visible_message("<span class='danger'> [attacker]'s attack deflects off of [src]. </span>", \
"<span class='danger'> [attacker]'s attack deflects off of [src]. </span>", \
"<span class='hear'> You hear hard plastic bouncing off hard plastic.</span>")
if(6 to 8) //defender wins
if(special_attack_cooldown == 0 && combat_health <= round(max_combat_health/3)) //if health is less than 1/3 and special off CD, use it
special_attack_charged = TRUE
src_controller.visible_message("<span class='danger'> [src] begins charging its special attack!! </span>", \
"<span class='danger'> You begin charging [src]'s special attack! </span>")
else //just attack
SpinAnimation(5, 0)
playsound(src, 'sound/mecha/mechstep.ogg', 30, TRUE)
attacker.combat_health--
src_controller.visible_message("<span class='danger'> [src] smashes [attacker]! </span>", \
"<span class='danger'> You smash [src] into [attacker]! </span>", \
"<span class='hear'> You hear hard plastic smashing hard plastic.</span>")
if(prob(5))
attacker.combat_health--
playsound(attacker, 'sound/effects/meteorimpact.ogg', 20, TRUE)
src_controller.visible_message("<span class='boldwarning'> ...and lands a CRIPPLING BLOW! </span>", \
"<span class='boldwarning'> ...and you land a CRIPPLING blow on [attacker]! </span>", null)
else
attacker_controller.visible_message("<span class='notice'> [src] and [attacker] stand around awkwardly.</span>", \
"<span class='notice'> You don't know what to do next.</span>")
battle_length++
sleep(0.5 SECONDS)
/// Lines chosen for the winning mech
var/list/winlines = list("YOU'RE NOTHING BUT SCRAP!", "I'LL YIELD TO NONE!", "GLORY IS MINE!", "AN EASY FIGHT.", "YOU SHOULD HAVE NEVER FACED ME.", "ROCKED AND SOCKED.")
if(attacker.combat_health <= 0 && combat_health <= 0) //both lose
playsound(src, 'sound/machines/warning-buzzer.ogg', 20, TRUE)
attacker_controller.visible_message("<span class='boldnotice'> MUTUALLY ASSURED DESTRUCTION!! [src] and [attacker] both end up destroyed!</span>", \
"<span class='boldnotice'> Both [src] and [attacker] are destroyed!</span>")
else if(attacker.combat_health <= 0) //src wins
wins++
attacker.losses++
playsound(attacker, 'sound/effects/light_flicker.ogg', 20, TRUE)
attacker_controller.visible_message("<span class='notice'> [attacker] falls apart!</span>", \
"<span class='notice'> [attacker] falls apart!</span>", null)
visible_message("[pick(winlines)]")
src_controller.visible_message("<span class='notice'> [src] destroys [attacker] and walks away victorious!</span>", \
"<span class='notice'> You raise up [src] victoriously over [attacker]!</span>")
else if (combat_health <= 0) //attacker wins
attacker.wins++
losses++
playsound(src, 'sound/effects/light_flicker.ogg', 20, TRUE)
src_controller.visible_message("<span class='notice'> [src] collapses!</span>", \
"<span class='notice'> [src] collapses!</span>", null)
attacker.visible_message("[pick(winlines)]")
attacker_controller.visible_message("<span class='notice'> [attacker] demolishes [src] and walks away victorious!</span>", \
"<span class='notice'> You raise up [attacker] proudly over [src]</span>!")
else //both win?
visible_message("NEXT TIME.")
//don't want to make this a one sided conversation
quiet? attacker.visible_message("I WENT EASY ON YOU.") : attacker.visible_message("OF COURSE.")
in_combat = FALSE
attacker.in_combat = FALSE
combat_health = max_combat_health
attacker.combat_health = attacker.max_combat_health
return
/**
* This proc checks if a battle can be initiated between src and attacker.
*
* Both SRC and attacker (if attacker is included) timers are checked if they're on cooldown, and
* both SRC and attacker (if attacker is included) are checked if they are in combat already.
* If any of the above are true, the proc returns FALSE and sends a message to user (and target, if included) otherwise, it returns TRUE
* Arguments:
* * user: the user who is initiating the battle
* * attacker: optional arg for checking two mechs at once
* * target: optional arg used in Mech PvP battles (if used, attacker is target's toy)
*/
/obj/item/toy/mecha/proc/check_battle_start(mob/living/carbon/user, obj/item/toy/mecha/attacker, mob/living/carbon/target)
var/datum/gender/T
if(target)
T = gender_datums[target.get_visible_gender()] // Doing this because Polaris Code has shitty gender datums and it's clunkier than FUCK.
if(attacker && attacker.in_combat)
to_chat(user, "<span class='notice'>[target ? T.His : "Your" ] [attacker.name] is in combat.</span>")
if(target)
to_chat(target, "<span class='notice'>Your [attacker.name] is in combat.</span>")
return FALSE
if(in_combat)
to_chat(user, "<span class='notice'>Your [name] is in combat.</span>")
if(target)
to_chat(target, "<span class='notice'>[T.His] [name] is in combat.</span>")
return FALSE
if(attacker && attacker.timer > world.time)
to_chat(user, "<span class='notice'>[target?T.His : "Your" ] [attacker.name] isn't ready for battle.</span>")
if(target)
to_chat(target, "<span class='notice'>Your [attacker.name] isn't ready for battle.</span>")
return FALSE
if(timer > world.time)
to_chat(user, "<span class='notice'>Your [name] isn't ready for battle.</span>")
if(target)
to_chat(target, "<span class='notice'>[T.His] [name] isn't ready for battle.</span>")
return FALSE
return TRUE
/**
* Processes any special attack moves that happen in the battle (called in the mechaBattle proc).
*
* Makes the toy shout their special attack cry and updates its cooldown. Then, does the special attack.
* Arguments:
* * victim - the toy being hit by the special move
*/
/obj/item/toy/mecha/proc/special_attack_move(obj/item/toy/mecha/victim)
visible_message(special_attack_cry + "!!")
special_attack_charged = FALSE
special_attack_cooldown = 3
switch(special_attack_type)
if(SPECIAL_ATTACK_DAMAGE) //+2 damage
victim.combat_health-=2
playsound(src, 'sound/weapons/marauder.ogg', 20, TRUE)
if(SPECIAL_ATTACK_HEAL) //+2 healing
combat_health+=2
playsound(src, 'sound/mecha/mech_shield_raise.ogg', 20, TRUE)
if(SPECIAL_ATTACK_UTILITY) //+1 heal, +1 damage
victim.combat_health--
combat_health++
playsound(src, 'sound/mecha/mechmove01.ogg', 30, TRUE)
if(SPECIAL_ATTACK_OTHER) //other
super_special_attack(victim)
else
visible_message("I FORGOT MY SPECIAL ATTACK...")
/**
* Base proc for 'other' special attack moves.
*
* This one is only for inheritance, each mech with an 'other' type move has their procs below.
* Arguments:
* * victim - the toy being hit by the super special move (doesn't necessarily need to be used)
*/
/obj/item/toy/mecha/proc/super_special_attack(obj/item/toy/mecha/victim)
visible_message("<span class='notice'> [src] does a cool flip.</span>")
/obj/random/mech_toy
name = "Random Mech Toy"
desc = "This is a random mech toy."
icon = 'icons/obj/toy.dmi'
icon_state = "ripleytoy"
/obj/random/mech_toy/item_to_spawn()
return pick(typesof(/obj/item/toy/mecha))
/obj/item/toy/mecha/ripley
name = "toy ripley"
desc = "Mini-Mecha action figure! Collect them all! 1/11."
max_combat_health = 4 // 200 integrity
special_attack_type = SPECIAL_ATTACK_DAMAGE
special_attack_cry = "GIGA DRILL BREAK"
/obj/item/toy/mecha/fireripley
name = "toy firefighting ripley"
desc = "Mini-Mecha action figure! Collect them all! 2/11."
icon_state = "fireripleytoy"
max_combat_health = 5 // 250 integrity?
special_attack_type = SPECIAL_ATTACK_UTILITY
special_attack_cry = "FIRE SHIELD"
/obj/item/toy/mecha/deathripley
name = "toy deathsquad ripley"
desc = "Mini-Mecha action figure! Collect them all! 3/11."
icon_state = "deathripleytoy"
max_combat_health = 5 // 250 integrity
special_attack_type = SPECIAL_ATTACK_OTHER
special_attack_type_message = "instantly destroys the opposing mech if its health is less than this mech's health."
special_attack_cry = "KILLER CLAMP"
/obj/item/toy/mecha/deathripley/super_special_attack(obj/item/toy/mecha/victim)
playsound(src, 'sound/weapons/sonic_jackhammer.ogg', 20, TRUE)
if(victim.combat_health < combat_health) // Instantly kills the other mech if it's health is below our's.
visible_message("EXECUTE!!")
victim.combat_health = 0
else // Otherwise, just deal one damage.
victim.combat_health--
/obj/item/toy/mecha/gygax
name = "toy gygax"
desc = "Mini-Mecha action figure! Collect them all! 4/11."
icon_state = "gygaxtoy"
max_combat_health = 5 // 250 integrity
special_attack_type = SPECIAL_ATTACK_UTILITY
special_attack_cry = "SUPER SERVOS"
/obj/item/toy/mecha/durand
name = "toy durand"
desc = "Mini-Mecha action figure! Collect them all! 5/11."
icon_state = "durandtoy"
max_combat_health = 6 // 400 integrity
special_attack_type = SPECIAL_ATTACK_HEAL
special_attack_cry = "SHIELD OF PROTECTION"
/obj/item/toy/mecha/honk
name = "toy H.O.N.K."
desc = "Mini-Mecha action figure! Collect them all! 6/11."
icon_state = "honktoy"
max_combat_health = 4 // 140 integrity
special_attack_type = SPECIAL_ATTACK_OTHER
special_attack_type_message = "puts the opposing mech's special move on cooldown and heals this mech."
special_attack_cry = "MEGA HORN"
/obj/item/toy/mecha/honk/super_special_attack(obj/item/toy/mecha/victim)
playsound(src, 'sound/machines/honkbot_evil_laugh.ogg', 20, TRUE)
victim.special_attack_cooldown += 3 // Adds cooldown to the other mech and gives a minor self heal
combat_health++
/obj/item/toy/mecha/marauder
name = "toy marauder"
desc = "Mini-Mecha action figure! Collect them all! 7/11."
icon_state = "maraudertoy"
max_combat_health = 7 // 500 integrity
special_attack_type = SPECIAL_ATTACK_DAMAGE
special_attack_cry = "BEAM BLAST"
/obj/item/toy/mecha/seraph
name = "toy seraph"
desc = "Mini-Mecha action figure! Collect them all! 8/11."
icon_state = "seraphtoy"
max_combat_health = 8 // 550 integrity
special_attack_type = SPECIAL_ATTACK_DAMAGE
special_attack_cry = "ROCKET BARRAGE"
/obj/item/toy/mecha/mauler
name = "toy mauler"
desc = "Mini-Mecha action figure! Collect them all! 9/11."
icon_state = "maulertoy"
max_combat_health = 7 // 500 integrity
special_attack_type = SPECIAL_ATTACK_DAMAGE
special_attack_cry = "BULLET STORM"
/obj/item/toy/mecha/odysseus
name = "toy odysseus"
desc = "Mini-Mecha action figure! Collect them all! 10/11."
icon_state = "odysseustoy"
max_combat_health = 4 // 120 integrity
special_attack_type = SPECIAL_ATTACK_HEAL
special_attack_cry = "MECHA BEAM"
/obj/item/toy/mecha/phazon
name = "toy phazon"
desc = "Mini-Mecha action figure! Collect them all! 11/11."
icon_state = "phazontoy"
max_combat_health = 6 // 200 integrity
special_attack_type = SPECIAL_ATTACK_UTILITY
special_attack_cry = "NO-CLIP"
/* // TG-Station Added toys, commenting these out until I port 'em later.
/obj/item/toy/mecha/reticence
name = "toy Reticence"
desc = "12/13"
icon_state = "reticencetoy"
quiet = TRUE
max_combat_health = 4 //100 integrity
special_attack_type = SPECIAL_ATTACK_OTHER
special_attack_type_message = "has a lower cooldown than normal special moves, increases the opponent's cooldown, and deals damage."
special_attack_cry = "*wave"
/obj/item/toy/mecha/reticence/super_special_attack(obj/item/toy/mecha/victim)
special_attack_cooldown-- //Has a lower cooldown...
victim.special_attack_cooldown++ //and increases the opponent's cooldown by 1...
victim.combat_health-- //and some free damage.
/obj/item/toy/mecha/clarke
name = "toy Clarke"
desc = "13/13"
icon_state = "clarketoy"
max_combat_health = 4 //200 integrity
special_attack_type = SPECIAL_ATTACK_UTILITY
special_attack_cry = "ROLL OUT"
*/
#undef SPECIAL_ATTACK_HEAL
#undef SPECIAL_ATTACK_DAMAGE
#undef SPECIAL_ATTACK_UTILITY
#undef SPECIAL_ATTACK_OTHER
#undef MAX_BATTLE_LENGTH

View File

@@ -7,7 +7,6 @@
* Toy crossbow
* Toy swords
* Toy bosun's whistle
* Toy mechs
* Snap pops
* Water flower
* Therapy dolls
@@ -400,94 +399,6 @@
playsound(src, 'sound/misc/boatswain.ogg', 20, 1)
cooldown = world.time
/*
* Mech prizes
*/
/obj/item/toy/prize
icon = 'icons/obj/toy.dmi'
icon_state = "ripleytoy"
var/cooldown = 0
drop_sound = 'sound/mecha/mechstep.ogg'
//all credit to skasi for toy mech fun ideas
/obj/item/toy/prize/attack_self(mob/user as mob)
if(cooldown < world.time - 8)
to_chat(user, "<span class='notice'>You play with [src].</span>")
playsound(src, 'sound/mecha/mechstep.ogg', 20, 1)
cooldown = world.time
/obj/item/toy/prize/attack_hand(mob/user as mob)
if(loc == user)
if(cooldown < world.time - 8)
to_chat(user, "<span class='notice'>You play with [src].</span>")
playsound(src, 'sound/mecha/mechturn.ogg', 20, 1)
cooldown = world.time
return
..()
/obj/random/mech_toy
name = "Random Mech Toy"
desc = "This is a random mech toy."
icon = 'icons/obj/toy.dmi'
icon_state = "ripleytoy"
/obj/random/mech_toy/item_to_spawn()
return pick(typesof(/obj/item/toy/prize))
/obj/item/toy/prize/ripley
name = "toy ripley"
desc = "Mini-Mecha action figure! Collect them all! 1/11."
/obj/item/toy/prize/fireripley
name = "toy firefighting ripley"
desc = "Mini-Mecha action figure! Collect them all! 2/11."
icon_state = "fireripleytoy"
/obj/item/toy/prize/deathripley
name = "toy deathsquad ripley"
desc = "Mini-Mecha action figure! Collect them all! 3/11."
icon_state = "deathripleytoy"
/obj/item/toy/prize/gygax
name = "toy gygax"
desc = "Mini-Mecha action figure! Collect them all! 4/11."
icon_state = "gygaxtoy"
/obj/item/toy/prize/durand
name = "toy durand"
desc = "Mini-Mecha action figure! Collect them all! 5/11."
icon_state = "durandprize"
/obj/item/toy/prize/honk
name = "toy H.O.N.K."
desc = "Mini-Mecha action figure! Collect them all! 6/11."
icon_state = "honkprize"
/obj/item/toy/prize/marauder
name = "toy marauder"
desc = "Mini-Mecha action figure! Collect them all! 7/11."
icon_state = "marauderprize"
/obj/item/toy/prize/seraph
name = "toy seraph"
desc = "Mini-Mecha action figure! Collect them all! 8/11."
icon_state = "seraphprize"
/obj/item/toy/prize/mauler
name = "toy mauler"
desc = "Mini-Mecha action figure! Collect them all! 9/11."
icon_state = "maulerprize"
/obj/item/toy/prize/odysseus
name = "toy odysseus"
desc = "Mini-Mecha action figure! Collect them all! 10/11."
icon_state = "odysseusprize"
/obj/item/toy/prize/phazon
name = "toy phazon"
desc = "Mini-Mecha action figure! Collect them all! 11/11."
icon_state = "phazonprize"
/*
* Action figures
*/
@@ -962,7 +873,7 @@
else
user.visible_message("<span class='notice'><b>\The [user]</b> pokes [src].</span>","<span class='notice'>You poke [src].</span>")
playsound(src, 'sound/items/drop/plushie.ogg', 25, 0)
audible_message("[src] says, \"[pokephrase]\"")
visible_message("[src] says, \"[pokephrase]\"")
last_message = world.time
/obj/item/toy/plushie/verb/rename_plushie()

View File

@@ -14,8 +14,9 @@
if(!isnull(_age))
age = _age
/obj/item/trash/Initialize()
SSpersistence.track_value(src, /datum/persistent/filth/trash)
/obj/item/trash/Initialize(mapload)
if(!mapload || !config.persistence_ignore_mapload)
SSpersistence.track_value(src, /datum/persistent/filth/trash)
. = ..()
/obj/item/trash/Destroy()
@@ -27,40 +28,60 @@
icon_state = "4no_raisins"
/obj/item/trash/candy
name = "candy"
name = "hard candy wrapper"
icon_state = "candy"
/obj/item/trash/candy/gums
name = "gummy candy bag"
icon_state = "candy_gums"
/obj/item/trash/candy/proteinbar
name = "protein bar"
name = "protein bar wrapper"
icon_state = "proteinbar"
/obj/item/trash/candy/fruitbar
name = "fruit bar wrapper"
icon_state = "fruitbar"
/obj/item/trash/cheesie
name = "\improper Cheesie Honkers"
name = "\improper Cheesie Honkers bag"
icon_state = "cheesie_honkers"
/obj/item/trash/chips
name = "chips"
name = "chips bag"
icon_state = "chips"
/obj/item/trash/chips/bbq
name = "bbq chips bag"
icon_state = "chips_bbq"
/obj/item/trash/cookiesnack
name = "\improper Carps Ahoy! miniature cookies packet"
icon_state = "cookiesnack"
/obj/item/trash/popcorn
name = "popcorn"
name = "popcorn bag"
icon_state = "popcorn"
/obj/item/trash/tuna
name = "tuna can"
icon_state = "tuna"
/obj/item/trash/sosjerky
name = "Scaredy's Private Reserve Beef Jerky"
name = "Scaredy's Private Reserve Beef Jerky wrapper"
icon_state = "sosjerky"
/obj/item/trash/unajerky
name = "Moghes Imported Sissalik Jerky"
name = "Moghes Imported Sissalik Jerky tin"
icon_state = "unathitinred"
drop_sound = 'sound/items/drop/soda.ogg'
/obj/item/trash/syndi_cakes
name = "syndi cakes"
name = "syndi cakes box"
icon_state = "syndi_cakes"
/obj/item/trash/waffles
name = "waffles"
name = "waffles tray"
icon_state = "waffles"
/obj/item/trash/plate
@@ -72,13 +93,39 @@
icon_state = "snack_bowl"
/obj/item/trash/pistachios
name = "pistachios pack"
name = "pistachios packet"
icon_state = "pistachios_pack"
/obj/item/trash/semki
name = "semki pack"
name = "semki packet"
icon_state = "semki_pack"
/obj/item/trash/koisbar
name = "candy wrapper"
icon_state = "koisbar"
/obj/item/trash/kokobar
name = "candy wrapper"
icon_state = "kokobar"
/obj/item/trash/gumpack
name = "gum packet"
icon_state = "gum_pack"
/obj/item/trash/admints
name = "mint wrapper"
icon_state = "admint_pack"
/obj/item/trash/coffee
name = "empty cup"
icon_state = "coffee_vended"
drop_sound = 'sound/items/drop/papercup.ogg'
/obj/item/trash/ramen
name = "cup ramen"
icon_state = "ramen"
drop_sound = 'sound/items/drop/papercup.ogg'
/obj/item/trash/tray
name = "tray"
icon_state = "tray"
@@ -90,19 +137,19 @@
icon_state = "candle4"
/obj/item/trash/liquidfood
name = "\improper \"LiquidFood\" ration"
name = "\improper \"LiquidFood\" ration packet"
icon_state = "liquidfood"
/obj/item/trash/liquidprotein
name = "\improper \"LiquidProtein\" ration"
name = "\improper \"LiquidProtein\" ration packet"
icon_state = "liquidprotein"
/obj/item/trash/liquidvitamin
name = "\improper \"VitaPaste\" ration"
name = "\improper \"VitaPaste\" ration packet"
icon_state = "liquidvitamin"
/obj/item/trash/tastybread
name = "bread tube"
name = "bread tube wrapper"
icon_state = "tastybread"
// Aurora Food Port
@@ -122,5 +169,26 @@
name = "empty basket"
icon_state = "chipbasket_empty"
/obj/item/trash/spitgum
name = "old gum"
desc = "A disgusting chewed up wad of gum."
icon = 'icons/obj/clothing/masks.dmi'
icon_state = "spit-gum"
drop_sound = 'sound/items/drop/flesh.ogg'
/obj/item/trash/lollibutt
name = "lollipop stick"
desc = "A lollipop stick devoid of pop."
icon = 'icons/obj/clothing/masks.dmi'
icon_state = "pop-stick"
/obj/item/trash/spitwad
name = "spit wad"
desc = "A disgusting spitwad."
icon = 'icons/obj/clothing/masks.dmi'
icon_state = "spit-chew"
drop_sound = 'sound/items/drop/flesh.ogg'
slot_flags = SLOT_EARS | SLOT_MASK
/obj/item/trash/attack(mob/M as mob, mob/living/user as mob)
return

View File

@@ -19,6 +19,7 @@ RSF
var/list/container_types = list(
"metamorphic glass" = /obj/item/weapon/reagent_containers/food/drinks/metaglass,
"metamorphic pint glass" = /obj/item/weapon/reagent_containers/food/drinks/metaglass/metapint,
"half-pint glass" = /obj/item/weapon/reagent_containers/food/drinks/glass2/square,
"rocks glass" = /obj/item/weapon/reagent_containers/food/drinks/glass2/rocks,
"milkshake glass" = /obj/item/weapon/reagent_containers/food/drinks/glass2/shake,

View File

@@ -0,0 +1,233 @@
/obj/item/clothing/mask/chewable
name = "chewable item master"
desc = "If you are seeing this, ahelp it."
icon = 'icons/obj/clothing/masks.dmi'
drop_sound = 'sound/items/drop/food.ogg'
body_parts_covered = 0
var/type_butt = null
var/chem_volume = 0
var/chewtime = 0
var/brand
var/list/filling = list()
var/wrapped = FALSE
/obj/item/clothing/mask/chewable/attack_self(mob/user)
if(wrapped)
wrapped = FALSE
to_chat(user, span("notice", "You unwrap \the [name]."))
playsound(src.loc, 'sound/items/drop/wrapper.ogg', 50, 1)
slot_flags = SLOT_EARS | SLOT_MASK
update_icon()
/obj/item/clothing/mask/chewable/update_icon()
cut_overlays()
if(wrapped)
add_overlay("[initial(icon_state)]_wrapper")
obj/item/clothing/mask/chewable/Initialize()
. = ..()
flags |= NOREACT // so it doesn't react until you light it
create_reagents(chem_volume) // making the cigarrete a chemical holder with a maximum volume of 15
for(var/R in filling)
reagents.add_reagent(R, filling[R])
if(wrapped)
slot_flags = null
/obj/item/clothing/mask/chewable/equipped(var/mob/living/user, var/slot)
..()
if(slot == slot_wear_mask)
var/mob/living/carbon/human/C = user
if(C.check_has_mouth())
START_PROCESSING(SSprocessing, src)
else
to_chat(user, span("notice", "You don't have a mouth, and can't make much use of \the [src]."))
/obj/item/clothing/mask/chewable/dropped()
STOP_PROCESSING(SSprocessing, src)
..()
obj/item/clothing/mask/chewable/Destroy()
. = ..()
STOP_PROCESSING(SSprocessing, src)
/obj/item/clothing/mask/chewable/proc/chew()
chewtime--
if(reagents && reagents.total_volume)
if(ishuman(loc))
var/mob/living/carbon/human/C = loc
if (src == C.wear_mask && C.check_has_mouth())
reagents.trans_to_mob(C, REM, CHEM_INGEST, 0.2)
else
STOP_PROCESSING(SSprocessing, src)
/obj/item/clothing/mask/chewable/process()
chew()
if(chewtime < 1)
spitout()
/obj/item/clothing/mask/chewable/tobacco
name = "wad"
desc = "A chewy wad of tobacco. Cut in long strands and treated with syrup so it doesn't taste like an ash-tray when you stuff it into your face."
throw_speed = 0.5
icon_state = "chew"
type_butt = /obj/item/trash/spitwad
w_class = 1
slot_flags = SLOT_EARS | SLOT_MASK
chem_volume = 50
chewtime = 300
brand = "tobacco"
/obj/item/clothing/mask/chewable/proc/spitout(var/transfer_color = 1, var/no_message = 0)
if(type_butt)
var/obj/item/butt = new type_butt(src.loc)
transfer_fingerprints_to(butt)
if(transfer_color)
butt.color = color
if(brand)
butt.desc += " This one is \a [brand]."
if(ismob(loc))
var/mob/living/M = loc
if(!no_message)
to_chat(M, SPAN_NOTICE("The [name] runs out of flavor."))
if(M.wear_mask)
M.remove_from_mob(src) //un-equip it so the overlays can update
M.update_inv_wear_mask(0)
if(!M.equip_to_slot_if_possible(butt, slot_wear_mask))
M.update_inv_l_hand(0)
M.update_inv_r_hand(1)
M.put_in_hands(butt)
STOP_PROCESSING(SSprocessing, src)
qdel(src)
/obj/item/clothing/mask/chewable/tobacco/cheap
name = "chewing tobacco"
desc = "A chewy wad of tobacco. Cut in long strands and treated with syrup so it tastes less like an ash-tray when you stuff it into your face."
filling = list("nicotine" = 2)
/obj/item/clothing/mask/chewable/tobacco/fine
name = "deluxe chewing tobacco"
desc = "A chewy wad of fine tobacco. Cut in long strands and treated with syrup so it doesn't taste like an ash-tray when you stuff it into your face."
filling = list("nicotine" = 3)
/obj/item/clothing/mask/chewable/tobacco/nico
name = "nicotine gum"
desc = "A chewy wad of synthetic rubber, laced with nicotine. Possibly the least disgusting method of nicotine delivery."
icon_state = "nic_gum"
type_butt = /obj/item/trash/spitgum
wrapped = TRUE
/obj/item/clothing/mask/chewable/tobacco/nico/Initialize()
. = ..()
reagents.add_reagent("nicotine", 2)
color = reagents.get_color()
/obj/item/weapon/storage/chewables
name = "box of chewing wads master"
desc = "A generic brand of Waffle Co Wads, unflavored chews. Why do these exist?"
icon = 'icons/obj/cigarettes.dmi'
icon_state = "cigpacket"
item_state = "cigpacket"
drop_sound = 'sound/items/drop/shovel.ogg'
use_sound = 'sound/items/storage/pillbottle.ogg'
w_class = 2
throwforce = 2
slot_flags = SLOT_BELT
starts_with = list(/obj/item/clothing/mask/chewable/tobacco = 6)
make_exact_fit()
//Tobacco Tins
/obj/item/weapon/storage/chewables/tobacco
name = "tin of Al Mamun Smooth chewing tobacco"
desc = "Packaged and shipped straight from Kishar, popularised by the biosphere farmers of Kanondaga."
icon_state = "chew_generic"
item_state = "cigpacket"
starts_with = list(/obj/item/clothing/mask/chewable/tobacco/cheap = 6)
storage_slots = 6
/obj/item/weapon/storage/chewables/tobacco/fine
name = "tin of Suamalie chewing tobacco"
desc = "Once reserved for the first-class tourists of Oasis, this premium blend has been released for the public to enjoy."
icon_state = "chew_fine"
item_state = "Dpacket"
starts_with = list(/obj/item/clothing/mask/chewable/tobacco/fine = 6)
/obj/item/weapon/storage/box/fancy/chewables/tobacco/nico
name = "box of Nico-Tine gum"
desc = "A government doctor approved brand of nicotine gum. Cut out the middleman for your addiction fix."
icon = 'icons/obj/cigarettes.dmi'
icon_state = "chew_nico"
item_state = "Epacket"
starts_with = list(/obj/item/clothing/mask/chewable/tobacco/nico = 6)
storage_slots = 6
drop_sound = 'sound/items/drop/box.ogg'
use_sound = 'sound/items/storage/box.ogg'
/obj/item/weapon/storage/box/fancy/chewables/tobacco/update_icon()
icon_state = "[initial(icon_state)][contents.len]"
/obj/item/clothing/mask/chewable/candy
name = "wad"
desc = "A chewy wad of wadding material."
throw_speed = 0.5
icon_state = "chew"
type_butt = /obj/item/trash/spitgum
w_class = 1
slot_flags = SLOT_EARS | SLOT_MASK
chem_volume = 50
chewtime = 300
filling = list("sugar" = 2)
/obj/item/clothing/mask/chewable/candy/gum
name = "chewing gum"
desc = "A chewy wad of fine synthetic rubber and artificial flavoring. Be sure to unwrap it, genius."
icon_state = "gum"
item_state = "gum"
wrapped = TRUE
/obj/item/clothing/mask/chewable/candy/gum/Initialize()
. = ..()
reagents.add_reagent(pick("banana","berryjuice","grapejuice","lemonjuice","limejuice","orangejuice","watermelonjuice"),10)
color = reagents.get_color()
update_icon()
/obj/item/weapon/storage/box/gum
name = "\improper Frooty-Choos flavored gum"
desc = "A small pack of chewing gum in various flavors."
description_fluff = "Frooty-Choos is NanoTrasen's top-selling brand of artificially flavoured fruit-adjacent non-swallowable chew-product. This extremely specific definition places sales figures safely away from competing 'gum' brands."
icon = 'icons/obj/food_snacks.dmi'
icon_state = "gum_pack"
item_state = "candy"
slot_flags = SLOT_EARS
w_class = 1
starts_with = list(/obj/item/clothing/mask/chewable/candy/gum = 5)
can_hold = list(/obj/item/clothing/mask/chewable/candy/gum,
/obj/item/trash/spitgum)
use_sound = 'sound/items/drop/paper.ogg'
drop_sound = 'sound/items/drop/wrapper.ogg'
max_storage_space = 5
foldable = null
trash = /obj/item/trash/gumpack
/obj/item/clothing/mask/chewable/candy/lolli
name = "lollipop"
desc = "A simple artificially flavored sphere of sugar on a handle, colloquially known as a sucker. Allegedly one is born every minute. Make sure to unwrap it, genius."
type_butt = /obj/item/trash/lollibutt
icon_state = "lollipop"
item_state = "lollipop"
wrapped = TRUE
/obj/item/clothing/mask/chewable/candy/lolli/process()
chew()
if(chewtime < 1)
spitout(0)
/obj/item/clothing/mask/chewable/candy/lolli/Initialize()
. = ..()
reagents.add_reagent(pick("banana","berryjuice","grapejuice","lemonjuice","limejuice","orangejuice","watermelonjuice"),20)
color = reagents.get_color()
update_icon()

View File

@@ -488,6 +488,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
/obj/item/weapon/rollingpaper
name = "rolling paper"
desc = "A small, thin piece of easily flammable paper, commonly used for rolling and smoking various dried plants."
description_fluff = "The legalization of certain substances propelled the sale of rolling papers through the roof. Now almost every Trans-stellar produces a variety, often of questionable quality."
icon = 'icons/obj/cigarettes.dmi'
icon_state = "cig paper"
@@ -513,6 +514,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
/obj/item/weapon/flame/lighter
name = "cheap lighter"
desc = "A cheap-as-free lighter."
description_fluff = "The 'hand-made in Altair' sticker underneath is a charming way of saying 'Made with prison labour'. It's no wonder the company can sell these things so cheap."
icon = 'icons/obj/items.dmi'
icon_state = "lighter-g"
item_state = "lighter-g"
@@ -527,6 +529,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
/obj/item/weapon/flame/lighter/zippo
name = "\improper Zippo lighter"
desc = "The zippo."
description_fluff = "Still going after all these years."
icon = 'icons/obj/zippo.dmi'
icon_state = "zippo"
item_state = "zippo"

View File

@@ -0,0 +1,14 @@
#ifndef T_BOARD
#error T_BOARD macro is not defined but we need it!
#endif
/obj/item/weapon/circuitboard/fluidpump
name = T_BOARD("fluid pump")
build_path = /obj/machinery/pump
board_type = new /datum/frame/frame_types/machine
origin_tech = list(TECH_DATA = 1)
req_components = list(
/obj/item/weapon/stock_parts/matter_bin = 2,
/obj/item/weapon/stock_parts/motor = 2,
/obj/item/weapon/stock_parts/manipulator = 1)

View File

@@ -1,6 +1,6 @@
/obj/item/clothing/mask/smokable/ecig
name = "electronic cigarette"
desc = "Device with modern approach to smoking."
desc = "For the modern approach to smoking."
icon = 'icons/obj/ecig.dmi'
var/active = 0
//var/obj/item/weapon/cell/ec_cell = /obj/item/weapon/cell/device
@@ -24,6 +24,7 @@
/obj/item/clothing/mask/smokable/ecig/simple
name = "simple electronic cigarette"
desc = "A cheap Lucky 1337 electronic cigarette, styled like a traditional cigarette."
description_fluff = "Produced by the Ward-Takahashi Corporation on behalf of the Lucky Stars cigarette brand, the 1337 is the e-cig of choice for teenage wastrels across the core worlds. Due to a total lack of safety features, this model is banned on most interstellar flights."
icon_state = "ccigoff"
icon_off = "ccigoff"
icon_empty = "ccigoff"
@@ -32,6 +33,7 @@
/obj/item/clothing/mask/smokable/ecig/util
name = "electronic cigarette"
desc = "A popular utilitarian model electronic cigarette, the ONI-55. Comes in a variety of colors."
description_fluff = "Ward-Takahashi's flagship brand of e-cig is a popular fashion accessory in certain circles where open flames are prohibited. Custom casings are sold for almost as much as the device itself, and are practically impossible to DIY."
icon_state = "ecigoff1"
icon_off = "ecigoff1"
icon_empty = "ecigoff1"
@@ -43,6 +45,7 @@
/obj/item/clothing/mask/smokable/ecig/deluxe
name = "deluxe electronic cigarette"
desc = "A premium model eGavana MK3 electronic cigarette, shaped like a cigar."
description_fluff = "The eGavana is a product of Morpheus Cyberkinetics, and comes standard with additional jacks that allow cyborgs and positronics to experience a simulation of soothing artificial oil residues entering their lungs. It's a pretty good cig for meatbags, too."
icon_state = "pcigoff1"
icon_off = "pcigoff1"
icon_empty = "pcigoff2"

View File

@@ -87,17 +87,17 @@
/obj/item/toy/crossbow,
/obj/item/weapon/gun/projectile/revolver/capgun,
/obj/item/toy/katana,
/obj/item/toy/prize/deathripley,
/obj/item/toy/prize/durand,
/obj/item/toy/prize/fireripley,
/obj/item/toy/prize/gygax,
/obj/item/toy/prize/honk,
/obj/item/toy/prize/marauder,
/obj/item/toy/prize/mauler,
/obj/item/toy/prize/odysseus,
/obj/item/toy/prize/phazon,
/obj/item/toy/prize/ripley,
/obj/item/toy/prize/seraph,
/obj/item/toy/mecha/deathripley,
/obj/item/toy/mecha/durand,
/obj/item/toy/mecha/fireripley,
/obj/item/toy/mecha/gygax,
/obj/item/toy/mecha/honk,
/obj/item/toy/mecha/marauder,
/obj/item/toy/mecha/mauler,
/obj/item/toy/mecha/odysseus,
/obj/item/toy/mecha/phazon,
/obj/item/toy/mecha/ripley,
/obj/item/toy/mecha/seraph,
/obj/item/toy/spinningtoy,
/obj/item/toy/sword,
/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiadeus,

View File

@@ -26,6 +26,7 @@
item_state = "syringe_kit"
center_of_mass = list("x" = 13,"y" = 10)
var/foldable = /obj/item/stack/material/cardboard // BubbleWrap - if set, can be folded (when empty) into a sheet of cardboard
var/trash = null // if set, can be crushed into a trash item when empty
max_w_class = ITEMSIZE_SMALL
max_storage_space = INVENTORY_BOX_SPACE
use_sound = 'sound/items/storage/box.ogg'
@@ -35,26 +36,37 @@
/obj/item/weapon/storage/box/attack_self(mob/user as mob)
if(..()) return
//try to fold it.
if ( contents.len )
return
//try to fold it
if(ispath(foldable))
if (contents.len)
return
var/found = 0
// Close any open UI windows first
for(var/mob/M in range(1))
if (M.s_active == src)
close(M)
if (M == user)
found = 1
if (!found) // User is too far away
return
// Now make the cardboard
to_chat(user, "<span class='notice'>You fold [src] flat.</span>")
playsound(src, 'sound/items/storage/boxfold.ogg', 30, 1)
new foldable(get_turf(src))
qdel(src)
//try to crush it
if(ispath(trash))
if(contents.len && user.a_intent == I_HURT) // only crumple with things inside on harmintent.
user.visible_message(SPAN_DANGER("You crush \the [src], spilling its contents everywhere!"), SPAN_DANGER("[user] crushes \the [src], spilling its contents everywhere!"))
spill()
else
to_chat(user, SPAN_NOTICE("You crumple up \the [src].")) //make trash
playsound(src.loc, 'sound/items/drop/wrapper.ogg', 30, 1)
var/obj/item/trash = new src.trash()
qdel(src)
user.put_in_hands(trash)
if ( !ispath(foldable) )
return
var/found = 0
// Close any open UI windows first
for(var/mob/M in range(1))
if (M.s_active == src)
close(M)
if ( M == user )
found = 1
if ( !found ) // User is too far away
return
// Now make the cardboard
to_chat(user, "<span class='notice'>You fold [src] flat.</span>")
playsound(src, 'sound/items/storage/boxfold.ogg', 30, 1)
new foldable(get_turf(src))
qdel(src)
/obj/item/weapon/storage/box/survival
name = "emergency supply box"

View File

@@ -265,14 +265,16 @@
/obj/item/weapon/storage/fancy/cigarettes/dromedaryco
name = "\improper DromedaryCo packet"
desc = "A packet of six imported DromedaryCo cancer sticks. A label on the packaging reads, \"Wouldn't a slow death make a change?\""
desc = "A packet of six Earth-export DromedaryCo cancer sticks. A label on the packaging reads, \"Wouldn't a slow death make a change?\""
description_fluff = "DromedaryCo is one of Sol's oldest cigarette brands, and takes pride in having sourced tobcacco from the same Indian plantations since 2044. Popular with those willing to pay extra for a little nostalgia."
icon_state = "Dpacket"
brand = "\improper Dromedary Co. cigarette"
/obj/item/weapon/storage/fancy/cigarettes/killthroat
name = "\improper AcmeCo packet"
desc = "A packet of six AcmeCo cigarettes. For those who somehow want to obtain the record for the most amount of cancerous tumors."
icon_state = "Bpacket"
desc = "A packet of six AcmeCo cigarettes. For those who want to obtain a record for the most cancerous tumors on a budget."
description_fluff = "Available anywhere people breathe and want to breathe less, AcmeCo is the cheapest, most widespread cigarette brand in the galaxy. They taste like trash, but when you're keeping them inside your jumpsuit on a 16 hour shift, you're probably not too concerned with flavour."
icon_state = "Apacket"
brand = "\improper Acme Co. cigarette"
// New exciting ways to kill your lungs! - Earthcrusher //
@@ -280,36 +282,41 @@
/obj/item/weapon/storage/fancy/cigarettes/luckystars
name = "\improper pack of Lucky Stars"
desc = "A mellow blend made from synthetic, pod-grown tobacco. The commercial jingle is guaranteed to get stuck in your head."
description_fluff = "Lucky Stars are some of the most prolific advertisers in the business, with Gilthari Exports plastering the name and slogan on everything from workplace safety videos to racing bikes. 'Feel the gentle warmth of your Lucky Star'."
icon_state = "LSpacket"
brand = "\improper Lucky Star"
/obj/item/weapon/storage/fancy/cigarettes/jerichos
name = "\improper pack of Jerichos"
desc = "Typically seen dangling from the lips of Martian soldiers and border world hustlers. Tastes like hickory smoke, feels like warm liquid death down your lungs."
desc = "Typically seen dangling from the lips of Fleet veterans and border world hustlers. Tastes like hickory smoke, feels like warm liquid death down your lungs."
description_fluff = "The Jericho brand has carefully cultivated its 'rugged' image ever since its completely accidental association with the SolGov-Hegemony war due to their sizable corporate presence in the region. Prior to the war, Jerichos were considered the realm of drunks and sad divorcees."
icon_state = "Jpacket"
brand = "\improper Jericho"
/obj/item/weapon/storage/fancy/cigarettes/menthols
name = "\improper pack of Temperamento Menthols"
desc = "With a sharp and natural organic menthol flavor, these Temperamentos are a favorite of NDV crews. Hardly anyone knows they make 'em in non-menthol!"
desc = "With a sharp and natural organic menthol flavor, these Temperamentos are a favorite of science vessel crews. Hardly anyone knows they make 'em in non-menthol!"
description_fluff = "Temperamento Menthols are a product of the Aether Atmospherics and Recycling company, and the 'smooth' menthol taste is rumoured to be the chemical by-product of some far more profitable industrial synthesis."
icon_state = "TMpacket"
brand = "\improper Temperamento Menthol"
/obj/item/weapon/storage/fancy/cigarettes/carcinomas
name = "\improper pack of Carcinoma Angels"
desc = "This unknown brand was slated for the chopping block, until they were publicly endorsed by an old Earthling gonzo journalist. The rest is history. They sell a variety for cats, too."
icon_state = "CApacket"
desc = "This previously unknown brand was slated for the chopping block, until they were publicly endorsed by an old Earthling gonzo journalist. The rest is history. They sell a variety for cats, too."
description_fluff = "The bitter taste of a Carcinoma Angel is considered desirable by many equally bitter wash-ups who consider themselves to be 'hard-boiled'. The smell is practically inseparable from urban security offices, and old men with exonet radio shows."
brand = "\improper Carcinoma Angel"
/obj/item/weapon/storage/fancy/cigarettes/professionals
name = "\improper pack of Professional 120s"
desc = "Let's face it - if you're smoking these, you're either trying to look upper-class or you're 80 years old. That's the only excuse. They are, however, very good quality."
description_fluff = "Grown and rolled in a meticulously maintained biosphere orbitting Love, P120 tobacco is marketed as 'probably the best in the galaxy'. The premium price point, and the fact that the vast majority of consumers couldn't really tell the difference between this and the next leading brand."
icon_state = "P100packet"
brand = "\improper Professional 120"
/obj/item/weapon/storage/fancy/cigar
name = "cigar case"
desc = "A case for holding your cigars when you are not smoking them."
description_fluff = "The tastefully engraved palm tree tells you that these 'Corona Grande' premium cigars are only sold on the luxury cruises and resorts of Oasis, though ten separate companies produce them for that purpose galaxy-wide. The standard is however very high."
icon_state = "cigarcase"
icon = 'icons/obj/cigarettes.dmi'
w_class = ITEMSIZE_TINY

View File

@@ -8,19 +8,21 @@
toolspeed = 2 //It is now used in surgery as a not awful, but probably dangerous option, due to speed.
/obj/item/weapon/tape_roll/proc/can_place(var/mob/living/carbon/human/H, var/mob/user)
if(istype(user, /mob/living/silicon/robot) || user == H)
return TRUE
for (var/obj/item/weapon/grab/G in H.grabbed_by)
if (G.loc == user && G.state >= GRAB_AGGRESSIVE)
return TRUE
return FALSE
/obj/item/weapon/tape_roll/attack(var/mob/living/carbon/human/H, var/mob/user)
if(istype(H))
if(user.a_intent == I_HELP)
return
var/can_place = 0
if(istype(user, /mob/living/silicon/robot))
can_place = 1
else
for (var/obj/item/weapon/grab/G in H.grabbed_by)
if (G.loc == user && G.state >= GRAB_AGGRESSIVE)
can_place = 1
break
if(!can_place)
if(!can_place(H, user))
to_chat(user, "<span class='danger'>You need to have a firm grip on [H] before you can use \the [src]!</span>")
return
else
@@ -43,16 +45,7 @@
if(!do_after(user, 30))
return
can_place = 0
if(istype(user, /mob/living/silicon/robot))
can_place = 1
else
for (var/obj/item/weapon/grab/G in H.grabbed_by)
if (G.loc == user && G.state >= GRAB_AGGRESSIVE)
can_place = 1
if(!can_place)
if(!can_place(H, user))
return
if(!H || !src || !H.organs_by_name[BP_HEAD] || !H.has_eyes() || H.glasses || (H.head && (H.head.body_parts_covered & FACE)))
@@ -81,16 +74,7 @@
if(!do_after(user, 30))
return
can_place = 0
if(istype(user, /mob/living/silicon/robot))
can_place = 1
else
for (var/obj/item/weapon/grab/G in H.grabbed_by)
if (G.loc == user && G.state >= GRAB_AGGRESSIVE)
can_place = 1
if(!can_place)
if(!can_place(H, user))
return
if(!H || !src || !H.organs_by_name[BP_HEAD] || !H.check_has_mouth() || (H.head && (H.head.body_parts_covered & FACE)))
@@ -103,16 +87,7 @@
playsound(src, 'sound/effects/tape.ogg',25)
else if(user.zone_sel.selecting == "r_hand" || user.zone_sel.selecting == "l_hand")
can_place = 0
if(istype(user, /mob/living/silicon/robot))
can_place = 1
else
for (var/obj/item/weapon/grab/G in H.grabbed_by)
if (G.loc == user && G.state >= GRAB_AGGRESSIVE)
can_place = 1
if(!can_place)
if(!can_place(H, user))
return
var/obj/item/weapon/handcuffs/cable/tape/T = new(user)

View File

@@ -101,8 +101,8 @@ something, make sure it's not in one of the other lists.*/
prob(1);/obj/item/clothing/under/tactical,
prob(3);/obj/item/clothing/accessory/storage/webbing,
prob(3);/obj/item/weapon/camera_assembly,
prob(4);/obj/item/weapon/caution,
prob(3);/obj/item/weapon/caution/cone,
prob(4);/obj/item/clothing/suit/caution,
prob(3);/obj/item/clothing/head/cone,
prob(1);/obj/item/weapon/card/emag_broken,
prob(2);/obj/item/device/camera,
prob(3);/obj/item/device/pda,

View File

@@ -520,17 +520,17 @@
/obj/item/weapon/reagent_containers/spray/waterflower,
/obj/item/toy/eight_ball,
/obj/item/toy/eight_ball/conch,
/obj/item/toy/prize/ripley,
/obj/item/toy/prize/fireripley,
/obj/item/toy/prize/deathripley,
/obj/item/toy/prize/gygax,
/obj/item/toy/prize/durand,
/obj/item/toy/prize/honk,
/obj/item/toy/prize/marauder,
/obj/item/toy/prize/seraph,
/obj/item/toy/prize/mauler,
/obj/item/toy/prize/odysseus,
/obj/item/toy/prize/phazon)
/obj/item/toy/mecha/ripley,
/obj/item/toy/mecha/fireripley,
/obj/item/toy/mecha/deathripley,
/obj/item/toy/mecha/gygax,
/obj/item/toy/mecha/durand,
/obj/item/toy/mecha/honk,
/obj/item/toy/mecha/marauder,
/obj/item/toy/mecha/seraph,
/obj/item/toy/mecha/mauler,
/obj/item/toy/mecha/odysseus,
/obj/item/toy/mecha/phazon)
/obj/random/mouseremains
name = "random mouseremains"

View File

@@ -64,7 +64,7 @@
/obj/item/clothing/head/soft/purple,
/obj/item/clothing/head/beret/purple,
/obj/item/device/flashlight,
/obj/item/weapon/caution = 4,
/obj/item/clothing/suit/caution = 4,
/obj/item/device/lightreplacer,
/obj/item/weapon/storage/bag/trash,
/obj/item/weapon/storage/belt/janitor,

View File

@@ -407,8 +407,8 @@
desc = "A crate emblazoned with the NanoThreads Garments livery, a subsidary of the NanoTrasen Corporation."
closet_appearance = /decl/closet_appearance/crate/nanotrasenclothing
/obj/structure/closet/crate/nanocare
desc = "A crate emblazoned with the NanoCare Medical livery, a subsidary of the NanoTrasen Corporation."
/obj/structure/closet/crate/nanomed
desc = "A crate emblazoned with the NanoMed Medical livery, a subsidary of the NanoTrasen Corporation."
closet_appearance = /decl/closet_appearance/crate/nanotrasenmedical
/obj/structure/closet/crate/oculum
@@ -522,8 +522,8 @@
desc = "A secure crate emblazoned with the standard NanoTrasen livery."
closet_appearance = /decl/closet_appearance/crate/secure/nanotrasen
/obj/structure/closet/crate/secure/nanocare
desc = "A secure crate emblazoned with the NanoCare Medical livery, a subsidary of the NanoTrasen Corporation."
/obj/structure/closet/crate/secure/nanomed
desc = "A secure crate emblazoned with the NanoMed Medical livery, a subsidary of the NanoTrasen Corporation."
closet_appearance = /decl/closet_appearance/crate/secure/nanotrasenmedical
/obj/structure/closet/crate/secure/scg

View File

@@ -93,7 +93,7 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart)
to_chat(user, "<span class='notice'>You put [I] into [src].</span>")
return 1
else if(istype(I, /obj/item/weapon/caution))
else if(istype(I, /obj/item/clothing/suit/caution))
if(signs < 4)
user.unEquip(I, 0, src)
signs++
@@ -192,7 +192,7 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart)
myreplacer = null
if("sign")
if(signs)
var/obj/item/weapon/caution/Sign = locate() in src
var/obj/item/clothing/suit/caution/Sign = locate() in src
if(Sign)
user.put_in_hands(Sign)
to_chat(user, "<span class='notice'>You take \a [Sign] from [src].</span>")
@@ -258,7 +258,7 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart)
mybucket = null
if (signs)
for (var/obj/item/weapon/caution/Sign in src)
for (var/obj/item/clothing/suit/caution/Sign in src)
if (prob(min((chance*2),100)))
signs--
Sign.forceMove(dropspot)

View File

@@ -192,8 +192,8 @@ Loot piles can be depleted, if loot_depleted is turned on. Note that players wh
/obj/item/weapon/spacecash/c10,
/obj/item/weapon/spacecash/c20,
/obj/item/weapon/camera_assembly,
/obj/item/weapon/caution,
/obj/item/weapon/caution/cone,
/obj/item/clothing/suit/caution,
/obj/item/clothing/head/cone,
/obj/item/weapon/card/emag_broken,
/obj/item/device/camera,
/obj/item/device/pda,
@@ -227,8 +227,10 @@ Loot piles can be depleted, if loot_depleted is turned on. Note that players wh
/obj/item/trash/candle,
/obj/item/trash/candy,
/obj/item/trash/candy/proteinbar,
/obj/item/trash/candy/gums,
/obj/item/trash/cheesie,
/obj/item/trash/chips,
/obj/item/trash/chips/bbq,
/obj/item/trash/liquidfood,
/obj/item/trash/pistachios,
/obj/item/trash/plate,
@@ -239,6 +241,7 @@ Loot piles can be depleted, if loot_depleted is turned on. Note that players wh
/obj/item/trash/sosjerky,
/obj/item/trash/syndi_cakes,
/obj/item/trash/tastybread,
/obj/item/trash/coffee,
/obj/item/trash/tray,
/obj/item/trash/unajerky,
/obj/item/trash/waffles,

View File

@@ -141,7 +141,7 @@
prob(4);/obj/item/clothing/shoes/leather,
prob(4);/obj/item/clothing/suit/storage/hazardvest,
prob(4);/obj/item/clothing/under/color/grey,
prob(4);/obj/item/weapon/caution,
prob(4);/obj/item/clothing/suit/caution,
prob(4);/obj/item/weapon/cell,
prob(4);/obj/item/weapon/cell/device,
prob(4);/obj/item/weapon/reagent_containers/food/snacks/liquidfood,
@@ -165,7 +165,7 @@
prob(3);/obj/item/device/radio/headset,
prob(3);/obj/item/seeds/lustflower,
prob(3);/obj/item/weapon/camera_assembly,
prob(3);/obj/item/weapon/caution/cone,
prob(3);/obj/item/clothing/head/cone,
prob(3);/obj/item/weapon/cell/high,
prob(3);/obj/item/weapon/spacecash/c10,
prob(3);/obj/item/weapon/spacecash/c20,

View File

@@ -1,4 +1,4 @@
/proc/playsound(atom/source, soundin, vol as num, vary, extrarange as num, falloff, is_global, frequency = null, channel = 0, pressure_affected = TRUE, ignore_walls = TRUE, preference = null)
/proc/playsound(atom/source, soundin, vol as num, vary, extrarange as num, falloff, is_global, frequency = null, channel = 0, pressure_affected = TRUE, ignore_walls = TRUE, preference = null, volume_channel = null)
if(isarea(source))
throw EXCEPTION("playsound(): source is an area")
return
@@ -23,9 +23,9 @@
if(distance <= maxdistance)
if(T && T.z == turf_source.z)
M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, is_global, channel, pressure_affected, S, preference)
M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, is_global, channel, pressure_affected, S, preference, volume_channel)
/mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff, is_global, channel = 0, pressure_affected = TRUE, sound/S, preference)
/mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff, is_global, channel = 0, pressure_affected = TRUE, sound/S, preference, volume_channel = null)
if(!client || ear_deaf > 0)
return
if(preference && !client.is_preference_enabled(preference))
@@ -36,6 +36,11 @@
S.wait = 0 //No queue
S.channel = channel || open_sound_channel()
// I'm not sure if you can modify S.volume, but I'd rather not try to find out what
// horrible things lurk in BYOND's internals, so we're just gonna do vol *=
vol *= client.get_preference_volume_channel(volume_channel)
vol *= client.get_preference_volume_channel(VOLUME_CHANNEL_MASTER)
S.volume = vol
if(vary)

View File

@@ -8,5 +8,8 @@
new /obj/item/weapon/reagent_containers/food/snacks/worm(src)
else
to_chat(user, "<span class='notice'>You decide to not finish digging in \the [src].</span>")
else if(istype(S, /obj/item/stack/tile/floor))
ChangeTurf(/turf/simulated/floor, preserve_outdoors = TRUE)
return
else
..()

View File

@@ -49,6 +49,7 @@
/turf/Destroy()
. = QDEL_HINT_IWILLGC
cleanbot_reserved_turfs -= src
..()
/turf/ex_act(severity)

View File

@@ -108,7 +108,7 @@ var/world_topic_spam_protect_time = world.timeofday
s["version"] = game_version
s["mode"] = master_mode
s["respawn"] = config.abandon_allowed
s["persistance"] = config.persistence_enabled
s["persistance"] = config.persistence_disabled
s["enter"] = config.enter_allowed
s["vote"] = config.allow_vote_mode
s["ai"] = config.allow_ai
@@ -529,7 +529,9 @@ var/world_topic_spam_protect_time = world.timeofday
features += config.abandon_allowed ? "respawn" : "no respawn"
features += config.persistence_enabled ? "persistence enabled" : "persistence disabled"
features += config.persistence_disabled ? "persistence disabled" : "persistence enabled"
features += config.persistence_ignore_mapload ? "persistence mapload disabled" : "persistence mapload enabled"
if (config && config.allow_vote_mode)
features += "vote"

View File

@@ -130,9 +130,6 @@ var/custom_event_msg = null
var/DBConnection/dbcon = new() // Feedback database (New database)
var/DBConnection/dbcon_old = new() // /tg/station database (Old database) -- see the files in the SQL folder for information on what goes where.
// Reference list for disposal sort junctions. Filled up by sorting junction's New()
/var/list/tagger_locations = list()
// Added for Xenoarchaeology, might be useful for other stuff.
var/global/list/alphabet_uppercase = list("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z")

View File

@@ -937,16 +937,30 @@ var/datum/announcement/minor/admin_min_announcer = new
set category = "Server"
set desc="Whether persistent data will be saved from now on."
set name="Toggle Persistent Data"
config.persistence_enabled = !(config.persistence_enabled)
if(config.persistence_enabled)
config.persistence_disabled = !(config.persistence_disabled)
if(!config.persistence_disabled)
to_world("<B>Persistence is now enabled..</B>")
else
to_world("<B>Persistence is no longer enabled.</B>")
message_admins("<font color='blue'>[key_name_admin(usr)] toggled persistence to [config.persistence_enabled ? "On" : "Off"].</font>", 1)
log_admin("[key_name(usr)] toggled persistence to [config.persistence_enabled ? "On" : "Off"].")
message_admins("<font color='blue'>[key_name_admin(usr)] toggled persistence to [config.persistence_disabled ? "Off" : "On"].</font>", 1)
log_admin("[key_name(usr)] toggled persistence to [config.persistence_disabled ? "Off" : "On"].")
world.update_status()
feedback_add_details("admin_verb","TPD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/admins/proc/togglemaploadpersistence()
set category = "Server"
set desc="Whether mapload persistent data will be saved from now on."
set name="Toggle Mapload Persistent Data"
config.persistence_ignore_mapload = !(config.persistence_ignore_mapload)
if(!config.persistence_ignore_mapload)
to_world("<B>Persistence is now enabled..</B>")
else
to_world("<B>Persistence is no longer enabled.</B>")
message_admins("<font color='blue'>[key_name_admin(usr)] toggled persistence to [config.persistence_ignore_mapload ? "Off" : "On"].</font>", 1)
log_admin("[key_name(usr)] toggled persistence to [config.persistence_ignore_mapload ? "Off" : "On"].")
world.update_status()
feedback_add_details("admin_verb","TMPD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/admins/proc/toggle_aliens()
set category = "Server"
set desc="Toggle alien mobs"

View File

@@ -183,7 +183,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
var/admin_number_present = send2irc_adminless_only(initiator_ckey, name)
log_admin("Ticket #[id]: [key_name(initiator)]: [name] - heard by [admin_number_present] non-AFK admins who have +BAN.")
if(admin_number_present <= 0)
to_chat(C, "<span class='notice'>No active admins are online, your adminhelp was sent to the admin irc.</span>")
to_chat(C, "<span class='notice'>No active admins are online, your adminhelp was sent to the admin discord.</span>") //VOREStation Edit
send2adminchat() //VOREStation Add
//YW EDIT START
var/list/adm = get_admin_counts()

View File

@@ -32,6 +32,8 @@
else
targets["(No Mob) - [T]"] = T
var/target = input(src,"To whom shall we send a message?","Admin PM",null) as null|anything in sortList(targets)
if(!target) //Admin canceled
return
cmd_admin_pm(targets[target],null)
feedback_add_details("admin_verb","Admin PM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!

View File

@@ -24,6 +24,7 @@
var/time_died_as_mouse = null //when the client last died as a mouse
var/datum/tooltip/tooltips = null
var/datum/chatOutput/chatOutput
var/datum/volume_panel/volume_panel = null // Initialized by /client/verb/volume_panel()
var/chatOutputLoadedAt
var/adminhelped = 0

View File

@@ -35,8 +35,8 @@
pref.client_fps = sanitize_integer(pref.client_fps, 0, MAX_CLIENT_FPS, initial(pref.client_fps))
pref.ambience_freq = sanitize_integer(pref.ambience_freq, 0, 60, initial(pref.ambience_freq)) // No more than once per hour.
pref.ambience_chance = sanitize_integer(pref.ambience_chance, 0, 100, initial(pref.ambience_chance)) // 0-100 range.
pref.tgui_fancy = sanitize_integer(pref.tgui_fancy, 0, 1, initial(pref.tgui_fancy))
pref.tgui_lock = sanitize_integer(pref.tgui_lock, 0, 1, initial(pref.tgui_lock))
pref.tgui_fancy = sanitize_integer(pref.tgui_fancy, 0, 1, initial(pref.tgui_fancy))
pref.tgui_lock = sanitize_integer(pref.tgui_lock, 0, 1, initial(pref.tgui_lock))
/datum/category_item/player_setup_item/player_global/ui/content(var/mob/user)
. = "<b>UI Style:</b> <a href='?src=\ref[src];select_style=1'><b>[pref.UI_style]</b></a><br>"

View File

@@ -303,6 +303,14 @@
character_name = list("Yikatihaki")
allowed_roles = list("Explorer")
/datum/gear/fluff/suit/storage/flintlock
path = /obj/item/clothing/suit/storage/flintlock
display_name = "Flintlock's jacket"
slot = slot_wear_suit
ckeywhitelist = list("flintlockdafox")
character_name = list("Flintlock Sharpsman")
// G CKEYS
// H CKEYS

View File

@@ -134,11 +134,6 @@
cloaks[initial(cloak_type.name)] = cloak_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(cloaks))
/datum/gear/mask/ipc_monitor
display_name = "display monitor (Full Body Prosthetic)"
path = /obj/item/clothing/mask/monitor
sort_category = "Xenowear"
/datum/gear/uniform/harness
display_name = "gear harness (Full Body Prosthetic, Diona)"
path = /obj/item/clothing/under/harness

View File

@@ -76,6 +76,7 @@
. = list()
. += "<tt><center>"
. += "<b>Choose occupation chances</b><br>Unavailable occupations are crossed out.<br>"
. += "<script type='text/javascript'>function setJobPrefRedirect(level, rank) { window.location.href='?src=\ref[src];level=' + level + ';set_job=' + encodeURIComponent(rank); return false; }</script>"
. += "<table width='100%' cellpadding='1' cellspacing='0'><tr><td width='20%' valign='top'>" // Table within a table for alignment, also allows you to easily add more columns.
. += "<table width='100%' cellpadding='1' cellspacing='0'>"
var/index = -1
@@ -162,7 +163,32 @@
. += "</td><td width='40%'>"
. += "<a href='?src=\ref[src];set_job=[rank]'>"
var/prefLevelLabel = "ERROR"
var/prefLevelColor = "pink"
var/prefUpperLevel = -1 // level to assign on left click
var/prefLowerLevel = -1 // level to assign on right click
if(pref.GetJobDepartment(job, 1) & job.flag)
prefLevelLabel = "High"
prefLevelColor = "55cc55"
prefUpperLevel = 4
prefLowerLevel = 2
else if(pref.GetJobDepartment(job, 2) & job.flag)
prefLevelLabel = "Medium"
prefLevelColor = "eecc22"
prefUpperLevel = 1
prefLowerLevel = 3
else if(pref.GetJobDepartment(job, 3) & job.flag)
prefLevelLabel = "Low"
prefLevelColor = "cc5555"
prefUpperLevel = 2
prefLowerLevel = 4
else
prefLevelLabel = "NEVER"
prefLevelColor = "black"
prefUpperLevel = 3
prefLowerLevel = 1
. += "<a href='?src=\ref[src];set_job=[rank];level=[prefUpperLevel]' oncontextmenu='javascript:return setJobPrefRedirect([prefLowerLevel], \"[rank]\");'>"
if(job.type == /datum/job/assistant)//Assistant is special
if(pref.job_civilian_low & ASSISTANT)
@@ -174,14 +200,7 @@
. += "</a></td></tr>"
continue
if(pref.GetJobDepartment(job, 1) & job.flag)
. += " <font color=55cc55>\[High]</font>"
else if(pref.GetJobDepartment(job, 2) & job.flag)
. += " <font color=eecc22>\[Medium]</font>"
else if(pref.GetJobDepartment(job, 3) & job.flag)
. += " <font color=cc5555>\[Low]</font>"
else
. += " <font color=black>\[NEVER]</font>"
. += " <font color=[prefLevelColor]>\[[prefLevelLabel]]</font>"
if(LAZYLEN(job.alt_titles))
. += "</a></td></tr><tr bgcolor='[lastJob.selection_color]'><td width='60%' align='center'>&nbsp</td><td><a href='?src=\ref[src];select_alt_title=\ref[job]'>\[[pref.GetPlayerAltTitle(job)]\]</a></td></tr>"
. += "</a></td></tr>"
@@ -222,8 +241,8 @@
return (pref.equip_preview_mob ? TOPIC_REFRESH_UPDATE_PREVIEW : TOPIC_REFRESH)
else if(href_list["set_job"])
if(SetJob(user, href_list["set_job"])) return (pref.equip_preview_mob ? TOPIC_REFRESH_UPDATE_PREVIEW : TOPIC_REFRESH)
if(SetJob(user, href_list["set_job"], text2num(href_list["level"])))
return (pref.equip_preview_mob ? TOPIC_REFRESH_UPDATE_PREVIEW : TOPIC_REFRESH)
else if(href_list["job_info"])
var/rank = href_list["job_info"]
@@ -272,7 +291,7 @@
if(job.title != new_title)
pref.player_alt_titles[job.title] = new_title
/datum/category_item/player_setup_item/occupation/proc/SetJob(mob/user, role)
/datum/category_item/player_setup_item/occupation/proc/SetJob(mob/user, role, level)
var/datum/job/job = job_master.GetJob(role)
if(!job)
return 0
@@ -284,67 +303,74 @@
pref.job_civilian_low |= job.flag
return 1
if(pref.GetJobDepartment(job, 1) & job.flag)
SetJobDepartment(job, 1)
else if(pref.GetJobDepartment(job, 2) & job.flag)
SetJobDepartment(job, 2)
else if(pref.GetJobDepartment(job, 3) & job.flag)
SetJobDepartment(job, 3)
else//job = Never
SetJobDepartment(job, 4)
SetJobDepartment(job, level)
return 1
/datum/category_item/player_setup_item/occupation/proc/reset_jobhigh()
pref.job_civilian_med |= pref.job_civilian_high
pref.job_medsci_med |= pref.job_medsci_high
pref.job_engsec_med |= pref.job_engsec_high
pref.job_civilian_high = 0
pref.job_medsci_high = 0
pref.job_engsec_high = 0
// Level is equal to the desired new level of the job. So for a value of 4, we want to disable the job.
/datum/category_item/player_setup_item/occupation/proc/SetJobDepartment(var/datum/job/job, var/level)
if(!job || !level) return 0
switch(level)
if(1)//Only one of these should ever be active at once so clear them all here
pref.job_civilian_high = 0
pref.job_medsci_high = 0
pref.job_engsec_high = 0
pref.job_talon_high = 0 //VOREStation Add
return 1
if(2)//Set current highs to med, then reset them
pref.job_civilian_med |= pref.job_civilian_high
pref.job_medsci_med |= pref.job_medsci_high
pref.job_engsec_med |= pref.job_engsec_high
pref.job_talon_med |= pref.job_talon_high //VOREStation Add
pref.job_civilian_high = 0
pref.job_medsci_high = 0
pref.job_engsec_high = 0
pref.job_talon_high = 0 //VOREStation Add
if(!job || !level)
return 0
switch(job.department_flag)
if(CIVILIAN)
pref.job_civilian_low &= ~job.flag
pref.job_civilian_med &= ~job.flag
pref.job_civilian_high &= ~job.flag
switch(level)
if(2)
if(1)
reset_jobhigh()
pref.job_civilian_high = job.flag
pref.job_civilian_med &= ~job.flag
if(3)
if(2)
pref.job_civilian_med |= job.flag
pref.job_civilian_low &= ~job.flag
else
if(3)
pref.job_civilian_low |= job.flag
if(MEDSCI)
pref.job_medsci_low &= ~job.flag
pref.job_medsci_med &= ~job.flag
pref.job_medsci_high &= ~job.flag
switch(level)
if(2)
if(1)
reset_jobhigh()
pref.job_medsci_high = job.flag
pref.job_medsci_med &= ~job.flag
if(3)
if(2)
pref.job_medsci_med |= job.flag
pref.job_medsci_low &= ~job.flag
else
if(3)
pref.job_medsci_low |= job.flag
if(ENGSEC)
pref.job_engsec_low &= ~job.flag
pref.job_engsec_med &= ~job.flag
pref.job_engsec_high &= ~job.flag
switch(level)
if(2)
if(1)
reset_jobhigh()
pref.job_engsec_high = job.flag
pref.job_engsec_med &= ~job.flag
if(3)
if(2)
pref.job_engsec_med |= job.flag
pref.job_engsec_low &= ~job.flag
else
if(3)
pref.job_engsec_low |= job.flag
/*/VOREStation Add //YW COMMENT OUT
if(TALON)
pref.job_talon_low &= ~job.flag
pref.job_talon_med &= ~job.flag
pref.job_talon_high &= ~job.flag
switch(level)
if(1)
reset_jobhigh()
pref.job_talon_high = job.flag
if(2)
pref.job_talon_med |= job.flag
if(3)
pref.job_talon_low |= job.flag
VOREStation Add End*/
return 1
/datum/category_item/player_setup_item/occupation/proc/ResetJobs()

View File

@@ -0,0 +1,106 @@
/datum/category_group/player_setup_category/volume_sliders
name = "Sound"
sort_order = 7
category_item_type = /datum/category_item/player_setup_item/volume_sliders
/datum/category_item/player_setup_item/volume_sliders/volume
name = "General Volume"
sort_order = 1
/datum/category_item/player_setup_item/volume_sliders/volume/load_preferences(var/savefile/S)
S["volume_channels"] >> pref.volume_channels
/datum/category_item/player_setup_item/volume_sliders/volume/save_preferences(var/savefile/S)
S["volume_channels"] << pref.volume_channels
/datum/category_item/player_setup_item/volume_sliders/volume/sanitize_preferences()
if(isnull(pref.volume_channels))
pref.volume_channels = list()
for(var/channel in pref.volume_channels)
if(!(channel in GLOB.all_volume_channels))
// Channel no longer exists, yeet
pref.volume_channels.Remove(channel)
for(var/channel in GLOB.all_volume_channels)
if(!(channel in pref.volume_channels))
pref.volume_channels["[channel]"] = 1
else
pref.volume_channels["[channel]"] = clamp(pref.volume_channels["[channel]"], 0, 2)
/datum/category_item/player_setup_item/volume_sliders/volume/content(var/mob/user)
. += "<b>Volume Settings</b><br>"
for(var/channel in pref.volume_channels)
. += "[channel]: <a href='?src=\ref[src];change_volume=[channel];'><b>[pref.volume_channels[channel] * 100]%</b></a><br>"
. += "<br>"
/datum/category_item/player_setup_item/volume_sliders/volume/OnTopic(var/href, var/list/href_list, var/mob/user)
if(href_list["change_volume"])
if(CanUseTopic(user))
var/channel = href_list["change_volume"]
if(!(channel in pref.volume_channels))
pref.volume_channels["[channel]"] = 1
var/value = input("Choose your volume for [channel] (0-200%)", "[channel] volume", (pref.volume_channels[channel] * 100))
if(isnum(value))
value = CLAMP(value, 0, 200)
pref.volume_channels["[channel]"] = (value / 100)
return TOPIC_REFRESH
return ..()
/mob/proc/get_preference_volume_channel(volume_channel)
if(!client)
return 0
return client.get_preference_volume_channel(volume_channel)
/client/proc/get_preference_volume_channel(volume_channel)
if(!volume_channel || !prefs)
return 1
if(!(volume_channel in prefs.volume_channels))
prefs.volume_channels["[volume_channel]"] = 1
return prefs.volume_channels["[volume_channel]"]
// Neat little volume adjuster thing in case you don't wanna touch preferences by hand you lazy fuck
/datum/volume_panel
/datum/volume_panel/tgui_state(mob/user)
return GLOB.tgui_always_state
/datum/volume_panel/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "VolumePanel", "Volume Panel")
ui.open()
/datum/volume_panel/tgui_data(mob/user)
if(!user.client || !user.client.prefs)
return list("error" = TRUE)
var/list/data = ..()
data["volume_channels"] = user.client.prefs.volume_channels
return data
/datum/volume_panel/tgui_act(action, params)
if(..())
return TRUE
if(!usr?.client?.prefs)
return TRUE
var/datum/preferences/P = usr.client.prefs
switch(action)
if("adjust_volume")
var/channel = params["channel"]
if(channel in P.volume_channels)
P.volume_channels["[channel]"] = clamp(params["vol"], 0, 2)
SScharacter_setup.queue_preferences_save(P)
return TRUE
/client/verb/volume_panel()
set name = "Volume Panel"
set category = "Preferences"
set desc = "Allows you to adjust volume levels on the fly."
if(!volume_panel)
volume_panel = new(src)
volume_panel.tgui_interact(mob)

View File

@@ -2,23 +2,23 @@
var/media_volume = 1
var/media_player = 2 // 0 = VLC, 1 = WMP, 2 = HTML5, 3+ = unassigned
/datum/category_item/player_setup_item/player_global/media
/datum/category_item/player_setup_item/volume_sliders/media
name = "Media"
sort_order = 5
sort_order = 2
/datum/category_item/player_setup_item/player_global/media/load_preferences(var/savefile/S)
/datum/category_item/player_setup_item/volume_sliders/media/load_preferences(var/savefile/S)
S["media_volume"] >> pref.media_volume
S["media_player"] >> pref.media_player
/datum/category_item/player_setup_item/player_global/media/save_preferences(var/savefile/S)
/datum/category_item/player_setup_item/volume_sliders/media/save_preferences(var/savefile/S)
S["media_volume"] << pref.media_volume
S["media_player"] << pref.media_player
/datum/category_item/player_setup_item/player_global/media/sanitize_preferences()
/datum/category_item/player_setup_item/volume_sliders/media/sanitize_preferences()
pref.media_volume = isnum(pref.media_volume) ? CLAMP(pref.media_volume, 0, 1) : initial(pref.media_volume)
pref.media_player = sanitize_inlist(pref.media_player, list(0, 1, 2), initial(pref.media_player))
/datum/category_item/player_setup_item/player_global/media/content(var/mob/user)
/datum/category_item/player_setup_item/volume_sliders/media/content(var/mob/user)
. += "<b>Jukebox Volume:</b>"
. += "<a href='?src=\ref[src];change_media_volume=1'><b>[round(pref.media_volume * 100)]%</b></a><br>"
. += "<b>Media Player Type:</b> Depending on you operating system, one of these might work better. "
@@ -30,7 +30,7 @@
. += (pref.media_player == 0) ? "<span class='linkOn'><b>VLC</b></span> " : "<a href='?src=\ref[src];set_media_player=0'>VLC</a> "
. += "<br>"
/datum/category_item/player_setup_item/player_global/media/OnTopic(var/href, var/list/href_list, var/mob/user)
/datum/category_item/player_setup_item/volume_sliders/media/OnTopic(var/href, var/list/href_list, var/mob/user)
if(href_list["change_media_volume"])
if(CanUseTopic(user))
var/value = input("Choose your Jukebox volume (0-100%)", "Jukebox volume", round(pref.media_volume * 100))

View File

@@ -1,7 +1,7 @@
// Global stuff that will put us on the map
/datum/category_group/player_setup_category/vore
name = "VORE"
sort_order = 7
sort_order = 8
category_item_type = /datum/category_item/player_setup_item/vore
// Define a place to save appearance in character setup

View File

@@ -14,6 +14,7 @@
var/traits_cheating = 0 //Varedit by admins allows saving new maximums on people who apply/etc
var/starting_trait_points = STARTING_SPECIES_POINTS
var/max_traits = MAX_SPECIES_TRAITS
var/dirty_synth = 0 //Are you a synth
// Definition of the stuff for Ears
/datum/category_item/player_setup_item/vore/traits
@@ -82,6 +83,10 @@
/datum/category_item/player_setup_item/vore/traits/copy_to_mob(var/mob/living/carbon/human/character)
character.custom_species = pref.custom_species
var/datum/species/selected_species = GLOB.all_species[pref.species]
if(character.isSynthetic()) //Checking if we have a synth on our hands, boys.
pref.dirty_synth = 1
if(selected_species.selects_bodytype)
var/datum/species/custom/CS = character.species
var/S = pref.custom_base ? pref.custom_base : "Human"
@@ -255,6 +260,14 @@
var/conflict = FALSE
user.isSynthetic() //Recheck just to be sure
if(pref.dirty_synth && instance.not_for_synths)//if you are a synth you can't take this trait.
alert("You cannot take this trait as a SYNTH.\
Please remove that trait, or pick another trait to add.","Error")
pref.dirty_synth = 0 //Just to be sure
return TOPIC_REFRESH
if(trait_choice in pref.pos_traits + pref.neu_traits + pref.neg_traits)
conflict = instance.name

View File

@@ -153,6 +153,8 @@ datum/preferences
var/examine_text_mode = 0 // Just examine text, include usage (description_info), switch to examine panel.
var/multilingual_mode = 0 // Default behaviour, delimiter-key-space, delimiter-key-delimiter, off
var/list/volume_channels = list()
/datum/preferences/New(client/C)
player_setup = new(src)

View File

@@ -111,7 +111,7 @@
. = FALSE
if(LAZYLEN(accessories))
for(var/obj/item/clothing/C in accessories)
if(C.handle_low_temperature(tempcheck))
if(C.handle_high_temperature(tempcheck))
. = TRUE
if(max_heat_protection_temperature && max_heat_protection_temperature >= tempcheck)

View File

@@ -7,6 +7,7 @@
* Kitty ears
* Holiday hats
Crown of Wrath
Warning cone
*/
/*
@@ -288,3 +289,19 @@
/obj/item/clothing/head/psy_crown/gluttony/activate_ability(var/mob/living/wearer)
..()
wearer.add_modifier(/datum/modifier/gluttonyregeneration, 45 SECONDS)
/obj/item/clothing/head/cone
name = "warning cone"
desc = "This cone is trying to warn you of something!"
description_info = "It looks like you can wear it in your head slot."
icon_state = "cone"
item_state = "cone"
drop_sound = 'sound/items/drop/shoes.ogg'
force = 1
throwforce = 3
throw_speed = 2
throw_range = 5
w_class = 2
body_parts_covered = HEAD
attack_verb = list("warned", "cautioned", "smashed")
armor = list("melee" = 5, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)

View File

@@ -342,7 +342,7 @@
piece.armor["bio"] = 100
else
piece.armor["bio"] = src.armor["bio"]
playsound(src, "[!seal_target ? 'sound/machines/boltsdown.ogg' : 'sound/machines/boltsup.ogg']", 10, FALSE)
playsound(src,'sound/machines/rig/rigservo.ogg', 10, FALSE)
else
failed_to_seal = 1
@@ -707,7 +707,7 @@
if(istype(holder))
if(use_obj && check_slot == use_obj)
to_chat(H, "<span class='notice'><b>Your [use_obj.name] [use_obj.gender == PLURAL ? "retract" : "retracts"] swiftly.</b></span>")
playsound(src, 'sound/machines/boltsup.ogg', 10, FALSE)
playsound(src, 'sound/machines/rig/rigservo.ogg', 10, FALSE)
use_obj.canremove = 1
holder.drop_from_inventory(use_obj)
use_obj.forceMove(get_turf(src))
@@ -726,7 +726,7 @@
return
else
to_chat(H, "<span class='notice'>Your [use_obj.name] [use_obj.gender == PLURAL ? "deploy" : "deploys"] swiftly.</span>")
playsound(src, 'sound/machines/boltsdown.ogg', 10, FALSE)
playsound(src, 'sound/machines/rig/rigservo.ogg', 10, FALSE)
if(piece == "helmet" && helmet)
helmet.update_light(H)

View File

@@ -900,3 +900,38 @@ obj/item/clothing/suit/kamishimo
name = "science snowsuit"
icon_state = "snowsuit_science"
*/
/obj/item/clothing/suit/caution
name = "wet floor sign"
desc = "Caution! Wet Floor!"
description_fluff = "Used by the janitor to passive-aggressively point at when you eventually slip on one of their mopped floors."
description_info = "Alt-click, or click in-hand to toggle the caution lights. It looks like you can wear it in your suit slot."
icon_state = "caution"
drop_sound = 'sound/items/drop/shoes.ogg'
force = 1
throwforce = 3
throw_speed = 2
throw_range = 5
w_class = 2
body_parts_covered = UPPER_TORSO|LOWER_TORSO
attack_verb = list("warned", "cautioned", "smashed")
armor = list("melee" = 5, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
/obj/item/clothing/suit/caution/attack_self()
toggle()
/obj/item/clothing/suit/caution/AltClick()
toggle()
/obj/item/clothing/suit/caution/proc/toggle()
if(!usr || usr.stat || usr.lying || usr.restrained() || !Adjacent(usr)) return
else if(src.icon_state == "caution")
src.icon_state = "caution_blinking"
src.item_state = "caution_blinking"
usr.show_message("You turn the wet floor sign on.")
playsound(src.loc, 'sound/machines/button.ogg', 30, 1)
else
src.icon_state = "caution"
src.item_state = "caution"
usr.show_message("You turn the wet floor sign off.")
update_clothing_icon()

View File

@@ -3,29 +3,32 @@
/obj/item/clothing/under/nanotrasen
name = "NanoTrasen uniform"
desc = "A comfortable turtleneck and black trousers sporting nanotrasen symbols."
icon_state = "navyutility"
worn_state = "navyutility"
icon = 'icons/obj/clothing/uniforms_solgov.dmi'
icon_override = 'icons/mob/uniform_solgov.dmi'
item_icons = list(slot_w_uniform_str = 'icons/mob/uniform_solgov.dmi', slot_r_hand_str = "black", slot_l_hand_str = "black")
icon_state = "blackutility"
worn_state = "blackutility"
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0)
siemens_coefficient = 0.9
/obj/item/clothing/under/nanotrasen/security
name = "NanoTrasen security uniform"
desc = "The security uniform of NanoTrasen's security. It looks sturdy and well padded"
icon_state = "navyutility_sec"
worn_state = "navyutility_sec"
icon_state = "blackutility_crew"
worn_state = "blackutility_crew"
armor = list(melee = 10, bullet = 5, laser = 5, energy = 5, bomb = 5, bio = 0, rad = 0)
/obj/item/clothing/under/nanotrasen/security/warden
name = "NanoTrasen warden uniform"
desc = "The uniform of the NanoTrasen's prison wardens. It looks sturdy and well padded. This one has gold cuffs."
icon_state = "navyutility_com"
worn_state = "navyutility_com"
icon_state = "blackutility_com"
worn_state = "blackutility_com"
/obj/item/clothing/under/nanotrasen/security/commander
name = "NanoTrasen security command uniform"
desc = "The uniform of the NanoTrasen's security commanding officers. It looks sturdy and well padded. This one has gold trim and red blazes."
icon_state = "blackutility_seccom"
worn_state = "blackutility_seccom"
icon_state = "blackutility_com"
worn_state = "blackutility_com"
//Head Gear
@@ -42,7 +45,7 @@
/obj/item/clothing/head/beret/nanotrasen
name = "NanoTrasen security beret"
desc = "A NT blue beret belonging to the NanoTrasen security forces. For personnel that are more inclined towards style than safety."
icon_state = "beret_navy"
icon_state = "beret_navy_security"
//Armor

View File

@@ -37,6 +37,22 @@
name = "small command dress"
icon_state = "seromi_dress_cap"
/obj/item/clothing/under/seromi/smock/dress/science
name = "small research dress"
icon_state = "seromi_dress_science"
/obj/item/clothing/under/seromi/smock/dress/security
name = "small security dress"
icon_state = "seromi_dress_security"
/obj/item/clothing/under/seromi/smock/dress/engine
name = "small engineering dress"
icon_state = "seromi_dress_engine"
/obj/item/clothing/under/seromi/smock/dress/medical
name = "small medical dress"
icon_state = "seromi_dress_medical"
/obj/item/clothing/under/seromi/smock/uniform
name = "small command uniform"
icon_state = "seromi_captain"

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