i think it works

MAJOR antag backend update
- you cannot bruteforce the pen anymore
- uplink now uses bitflag to lock purchases
- poplock is handled entirely by the buyable uplink items
- tgui antag intro (for selected ones)
This commit is contained in:
LetterN
2021-10-30 11:45:50 +08:00
parent f7b898a2a9
commit 99019166e4
117 changed files with 3049 additions and 1868 deletions

View File

@@ -111,3 +111,12 @@ GLOBAL_LIST_EMPTY(living_heart_cache) //A list of all living hearts in existance
#define BLOB_SPREAD_COST 4
#define BLOB_ATTACK_REFUND 2 //blob refunds this much if it attacks and doesn't spread
#define BLOB_REFLECTOR_COST 15
/// How many telecrystals a normal traitor starts with
#define TELECRYSTALS_DEFAULT 20
/// How many telecrystals mapper/admin only "precharged" uplink implant
#define TELECRYSTALS_PRELOADED_IMPLANT 10
/// The normal cost of an uplink implant; used for calcuating how many
/// TC to charge someone if they get a free implant through choice or
/// because they have nothing else that supports an implant.
#define UPLINK_IMPLANT_TELECRYSTAL_COST 4

View File

@@ -1,65 +1,119 @@
// This is eventually for wjohn to add more color standardization stuff like I keep asking him >:(
#define COLOR_INPUT_DISABLED "#F0F0F0"
#define COLOR_INPUT_ENABLED "#D3B5B5"
#define COLOR_FLOORTILE_GRAY "#8D8B8B"
#define COLOR_ALMOST_BLACK "#333333"
#define COLOR_BLACK "#000000"
#define COLOR_RED "#FF0000"
#define COLOR_RED_LIGHT "#FF3333"
#define COLOR_MAROON "#800000"
#define COLOR_YELLOW "#FFFF00"
#define COLOR_OLIVE "#808000"
#define COLOR_LIME "#32CD32"
#define COLOR_GREEN "#008000"
#define COLOR_CYAN "#00FFFF"
#define COLOR_TEAL "#008080"
#define COLOR_BLUE "#0000FF"
#define COLOR_BLUE_LIGHT "#33CCFF"
#define COLOR_NAVY "#000080"
#define COLOR_PINK "#FFC0CB"
#define COLOR_MAGENTA "#FF00FF"
#define COLOR_PURPLE "#800080"
#define COLOR_ORANGE "#FF9900"
#define COLOR_BEIGE "#CEB689"
#define COLOR_BLUE_GRAY "#75A2BB"
#define COLOR_BROWN "#BA9F6D"
#define COLOR_SOFT_RED "#FA8282"
#define COLOR_DARK_BROWN "#997C4F"
#define COLOR_DARK_ORANGE "#C3630C"
#define COLOR_GREEN_GRAY "#99BB76"
#define COLOR_RED_GRAY "#B4696A"
#define COLOR_PALE_BLUE_GRAY "#98C5DF"
#define COLOR_PALE_GREEN_GRAY "#B7D993"
#define COLOR_PALE_ORANGE "#FFC066"
#define COLOR_PALE_RED_GRAY "#D59998"
#define COLOR_PALE_PURPLE_GRAY "#CBB1CA"
#define COLOR_PURPLE_GRAY "#AE8CA8"
#define COLOR_INPUT_DISABLED "#F0F0F0"
#define COLOR_INPUT_ENABLED "#D3B5B5"
// Color defines used by the assembly detailer.
#define COLOR_ASSEMBLY_BLACK "#545454"
#define COLOR_ASSEMBLY_BGRAY "#9497AB"
#define COLOR_ASSEMBLY_WHITE "#E2E2E2"
#define COLOR_ASSEMBLY_RED "#CC4242"
#define COLOR_ASSEMBLY_ORANGE "#E39751"
#define COLOR_ASSEMBLY_BEIGE "#AF9366"
#define COLOR_ASSEMBLY_BROWN "#97670E"
#define COLOR_ASSEMBLY_GOLD "#AA9100"
#define COLOR_ASSEMBLY_YELLOW "#CECA2B"
#define COLOR_ASSEMBLY_GURKHA "#999875"
#define COLOR_ASSEMBLY_LGREEN "#789876"
#define COLOR_ASSEMBLY_GREEN "#44843C"
#define COLOR_ASSEMBLY_LBLUE "#5D99BE"
#define COLOR_ASSEMBLY_BLUE "#38559E"
#define COLOR_ASSEMBLY_PURPLE "#6F6192"
#define COLOR_ASSEMBLY_PINK "#ff4adc"
#define COLOR_DARKMODE_BACKGROUND "#202020"
#define COLOR_DARKMODE_DARKBACKGROUND "#171717"
#define COLOR_DARKMODE_TEXT "#a4bad6"
#define COLOR_WHITE "#FFFFFF"
#define COLOR_VERY_LIGHT_GRAY "#EEEEEE"
#define COLOR_SILVER "#C0C0C0"
#define COLOR_GRAY "#808080"
#define COLOR_WHITE "#FFFFFF"
#define COLOR_VERY_LIGHT_GRAY "#EEEEEE"
#define COLOR_SILVER "#C0C0C0"
#define COLOR_GRAY "#808080"
#define COLOR_FLOORTILE_GRAY "#8D8B8B"
#define COLOR_DARK "#454545"
#define COLOR_ALMOST_BLACK "#333333"
#define COLOR_BLACK "#000000"
#define COLOR_HALF_TRANSPARENT_BLACK "#0000007A"
#define COLOR_RED "#FF0000"
#define COLOR_MOSTLY_PURE_RED "#FF3300"
#define COLOR_DARK_RED "#A50824"
#define COLOR_RED_LIGHT "#FF3333"
#define COLOR_MAROON "#800000"
#define COLOR_VIVID_RED "#FF3232"
#define COLOR_LIGHT_GRAYISH_RED "#E4C7C5"
#define COLOR_SOFT_RED "#FA8282"
#define COLOR_BUBBLEGUM_RED "#950A0A"
#define COLOR_YELLOW "#FFFF00"
#define COLOR_VIVID_YELLOW "#FBFF23"
#define COLOR_VERY_SOFT_YELLOW "#FAE48E"
#define COLOR_OLIVE "#808000"
#define COLOR_VIBRANT_LIME "#00FF00"
#define COLOR_LIME "#32CD32"
#define COLOR_DARK_LIME "#00aa00"
#define COLOR_VERY_PALE_LIME_GREEN "#DDFFD3"
#define COLOR_VERY_DARK_LIME_GREEN "#003300"
#define COLOR_GREEN "#008000"
#define COLOR_DARK_MODERATE_LIME_GREEN "#44964A"
#define COLOR_CYAN "#00FFFF"
#define COLOR_DARK_CYAN "#00A2FF"
#define COLOR_TEAL "#008080"
#define COLOR_BLUE "#0000FF"
#define COLOR_STRONG_BLUE "#1919c8"
#define COLOR_BRIGHT_BLUE "#2CB2E8"
#define COLOR_MODERATE_BLUE "#555CC2"
#define COLOR_AMETHYST "#822BFF"
#define COLOR_BLUE_LIGHT "#33CCFF"
#define COLOR_NAVY "#000080"
#define COLOR_BLUE_GRAY "#75A2BB"
#define COLOR_PINK "#FFC0CB"
#define COLOR_LIGHT_PINK "#ff3cc8"
#define COLOR_MOSTLY_PURE_PINK "#E4005B"
#define COLOR_MAGENTA "#FF00FF"
#define COLOR_STRONG_MAGENTA "#B800B8"
#define COLOR_PURPLE "#800080"
#define COLOR_VIOLET "#B900F7"
#define COLOR_STRONG_VIOLET "#6927c5"
#define COLOR_ORANGE "#FF9900"
#define COLOR_MOSTLY_PURE_ORANGE "#ff8000"
#define COLOR_TAN_ORANGE "#FF7B00"
#define COLOR_BRIGHT_ORANGE "#E2853D"
#define COLOR_LIGHT_ORANGE "#ffc44d"
#define COLOR_PALE_ORANGE "#FFBE9D"
#define COLOR_BEIGE "#CEB689"
#define COLOR_DARK_ORANGE "#C3630C"
#define COLOR_DARK_MODERATE_ORANGE "#8B633B"
#define COLOR_BROWN "#BA9F6D"
#define COLOR_DARK_BROWN "#997C4F"
#define COLOR_ORANGE_BROWN "#a9734f"
//Color defines used by the soapstone (based on readability against grey tiles)
#define COLOR_SOAPSTONE_PLASTIC "#a19d94"
#define COLOR_SOAPSTONE_IRON "#b2b2b2"
#define COLOR_SOAPSTONE_BRONZE "#FE8001"
#define COLOR_SOAPSTONE_SILVER "#FFFFFF"
#define COLOR_SOAPSTONE_GOLD "#FFD900"
#define COLOR_SOAPSTONE_DIAMOND "#00ffee"
#define COLOR_GREEN_GRAY "#99BB76"
#define COLOR_RED_GRAY "#B4696A"
#define COLOR_PALE_BLUE_GRAY "#98C5DF"
#define COLOR_PALE_GREEN_GRAY "#B7D993"
#define COLOR_PALE_RED_GRAY "#D59998"
#define COLOR_PALE_PURPLE_GRAY "#CBB1CA"
#define COLOR_PURPLE_GRAY "#AE8CA8"
//Color defines used by the assembly detailer.
#define COLOR_ASSEMBLY_BLACK "#545454"
#define COLOR_ASSEMBLY_BGRAY "#9497AB"
#define COLOR_ASSEMBLY_WHITE "#E2E2E2"
#define COLOR_ASSEMBLY_RED "#CC4242"
#define COLOR_ASSEMBLY_ORANGE "#E39751"
#define COLOR_ASSEMBLY_BEIGE "#AF9366"
#define COLOR_ASSEMBLY_BROWN "#97670E"
#define COLOR_ASSEMBLY_GOLD "#AA9100"
#define COLOR_ASSEMBLY_YELLOW "#CECA2B"
#define COLOR_ASSEMBLY_GURKHA "#999875"
#define COLOR_ASSEMBLY_LGREEN "#789876"
#define COLOR_ASSEMBLY_GREEN "#44843C"
#define COLOR_ASSEMBLY_LBLUE "#5D99BE"
#define COLOR_ASSEMBLY_BLUE "#38559E"
#define COLOR_ASSEMBLY_PURPLE "#6F6192"
///Colors for xenobiology vatgrowing
#define COLOR_SAMPLE_YELLOW "#c0b823"
#define COLOR_SAMPLE_PURPLE "#342941"
#define COLOR_SAMPLE_GREEN "#98b944"
#define COLOR_SAMPLE_BROWN "#91542d"
#define COLOR_SAMPLE_GRAY "#5e5856"
///Main colors for UI themes
#define COLOR_THEME_MIDNIGHT "#6086A0"
@@ -69,3 +123,75 @@
#define COLOR_THEME_OPERATIVE "#B8221F"
#define COLOR_THEME_GLASS "#75A4C4"
#define COLOR_THEME_CLOCKWORK "#CFBA47"
///Colors for eigenstates
#define COLOR_PERIWINKLEE "#9999FF"
/**
* Some defines to generalise colours used in lighting.
*
* Important note: colors can end up significantly different from the basic html picture, especially when saturated
*/
/// Bright but quickly dissipating neon green. rgb(100, 200, 100)
#define LIGHT_COLOR_GREEN "#64C864"
/// Electric green. rgb(0, 255, 0)
#define LIGHT_COLOR_ELECTRIC_GREEN "#00FF00"
/// Cold, diluted blue. rgb(100, 150, 250)
#define LIGHT_COLOR_BLUE "#6496FA"
/// Light blueish green. rgb(125, 225, 175)
#define LIGHT_COLOR_BLUEGREEN "#7DE1AF"
/// Diluted cyan. rgb(125, 225, 225)
#define LIGHT_COLOR_CYAN "#7DE1E1"
/// Electric cyan rgb(0, 255, 255)
#define LIGHT_COLOR_ELECTRIC_CYAN "#00FFFF"
/// More-saturated cyan. rgb(64, 206, 255)
#define LIGHT_COLOR_LIGHT_CYAN "#40CEFF"
/// Saturated blue. rgb(51, 117, 248)
#define LIGHT_COLOR_DARK_BLUE "#6496FA"
/// Diluted, mid-warmth pink. rgb(225, 125, 225)
#define LIGHT_COLOR_PINK "#E17DE1"
/// Dimmed yellow, leaning kaki. rgb(225, 225, 125)
#define LIGHT_COLOR_YELLOW "#E1E17D"
/// Clear brown, mostly dim. rgb(150, 100, 50)
#define LIGHT_COLOR_BROWN "#966432"
/// Mostly pure orange. rgb(250, 150, 50)
#define LIGHT_COLOR_ORANGE "#FA9632"
/// Light Purple. rgb(149, 44, 244)
#define LIGHT_COLOR_PURPLE "#952CF4"
/// Less-saturated light purple. rgb(155, 81, 255)
#define LIGHT_COLOR_LAVENDER "#9B51FF"
///slightly desaturated bright yellow.
#define LIGHT_COLOR_HOLY_MAGIC "#FFF743"
/// deep crimson
#define LIGHT_COLOR_BLOOD_MAGIC "#D00000"
/* These ones aren't a direct colour like the ones above, because nothing would fit */
/// Warm orange color, leaning strongly towards yellow. rgb(250, 160, 25)
#define LIGHT_COLOR_FIRE "#FAA019"
/// Very warm yellow, leaning slightly towards orange. rgb(196, 138, 24)
#define LIGHT_COLOR_LAVA "#C48A18"
/// Bright, non-saturated red. Leaning slightly towards pink for visibility. rgb(250, 100, 75)
#define LIGHT_COLOR_FLARE "#FA644B"
/// Weird color, between yellow and green, very slimy. rgb(175, 200, 75)
#define LIGHT_COLOR_SLIME_LAMP "#AFC84B"
/// Extremely diluted yellow, close to skin color (for some reason). rgb(250, 225, 175)
#define LIGHT_COLOR_TUNGSTEN "#FAE1AF"
/// Barely visible cyan-ish hue, as the doctor prescribed. rgb(240, 250, 250)
#define LIGHT_COLOR_HALOGEN "#F0FAFA"
//The GAGS greyscale_colors for each department's computer/machine circuits
#define CIRCUIT_COLOR_GENERIC "#1A7A13"
#define CIRCUIT_COLOR_COMMAND "#1B4594"
#define CIRCUIT_COLOR_SECURITY "#9A151E"
#define CIRCUIT_COLOR_SCIENCE "#BC4A9B"
#define CIRCUIT_COLOR_SERVICE "#92DCBA"
#define CIRCUIT_COLOR_MEDICAL "#00CCFF"
#define CIRCUIT_COLOR_ENGINEERING "#F8D700"
#define CIRCUIT_COLOR_SUPPLY "#C47749"
/// Colors for pride week
#define COLOR_PRIDE_RED "#FF6666"
#define COLOR_PRIDE_ORANGE "#FC9F3C"
#define COLOR_PRIDE_YELLOW "#EAFF51"
#define COLOR_PRIDE_GREEN "#41FC66"
#define COLOR_PRIDE_BLUE "#42FFF2"
#define COLOR_PRIDE_PURPLE "#5D5DFC"

View File

@@ -38,6 +38,9 @@
#define CHAT_PLANE -1 //We don't want heard messages to be hidden by FoV.
/// Plane for balloon text (text that fades up)
#define BALLOON_CHAT_PLANE -1.2
#define CHAT_LAYER 12.0001 // Do not insert layers between these two values
#define CHAT_LAYER_MAX 12.9999

View File

@@ -30,31 +30,6 @@
//Important note on colors. Colors can end up significantly different from the basic html picture, especially when saturated
#define LIGHT_COLOR_WHITE "#FFFFFF"
#define LIGHT_COLOR_RED "#FA8282" //Warm but extremely diluted red. rgb(250, 130, 130)
#define LIGHT_COLOR_GREEN "#64C864" //Bright but quickly dissipating neon green. rgb(100, 200, 100)
#define LIGHT_COLOR_BLUE "#6496FA" //Cold, diluted blue. rgb(100, 150, 250)
#define LIGHT_COLOR_BLUEGREEN "#7DE1AF" //Light blueish green. rgb(125, 225, 175)
#define LIGHT_COLOR_PALEBLUE "#7DAFE1" //A pale blue-ish color. rgb(125, 175, 225)
#define LIGHT_COLOR_CYAN "#7DE1E1" //Diluted cyan. rgb(125, 225, 225)
#define LIGHT_COLOR_LIGHT_CYAN "#40CEFF" //More-saturated cyan. rgb(64, 206, 255)
#define LIGHT_COLOR_DARK_BLUE "#6496FA" //Saturated blue. rgb(51, 117, 248)
#define LIGHT_COLOR_PINK "#E17DE1" //Diluted, mid-warmth pink. rgb(225, 125, 225)
#define LIGHT_COLOR_YELLOW "#E1E17D" //Dimmed yellow, leaning kaki. rgb(225, 225, 125)
#define LIGHT_COLOR_BROWN "#966432" //Clear brown, mostly dim. rgb(150, 100, 50)
#define LIGHT_COLOR_ORANGE "#FA9632" //Mostly pure orange. rgb(250, 150, 50)
#define LIGHT_COLOR_PURPLE "#952CF4" //Light Purple. rgb(149, 44, 244)
#define LIGHT_COLOR_LAVENDER "#9B51FF" //Less-saturated light purple. rgb(155, 81, 255)
#define LIGHT_COLOR_HOLY_MAGIC "#FFF743" //slightly desaturated bright yellow.
#define LIGHT_COLOR_BLOOD_MAGIC "#D00000" //deep crimson
//These ones aren't a direct colour like the ones above, because nothing would fit
#define LIGHT_COLOR_FIRE "#FAA019" //Warm orange color, leaning strongly towards yellow. rgb(250, 160, 25)
#define LIGHT_COLOR_LAVA "#C48A18" //Very warm yellow, leaning slightly towards orange. rgb(196, 138, 24)
#define LIGHT_COLOR_FLARE "#FA644B" //Bright, non-saturated red. Leaning slightly towards pink for visibility. rgb(250, 100, 75)
#define LIGHT_COLOR_SLIME_LAMP "#AFC84B" //Weird color, between yellow and green, very slimy. rgb(175, 200, 75)
#define LIGHT_COLOR_TUNGSTEN "#FAE1AF" //Extremely diluted yellow, close to skin color (for some reason). rgb(250, 225, 175)
#define LIGHT_COLOR_HALOGEN "#F0FAFA" //Barely visible cyan-ish hue, as the doctor prescribed. rgb(240, 250, 250)
#define LIGHT_RANGE_FIRE 3 //How many tiles standard fires glow.

View File

@@ -29,10 +29,10 @@
* if the arguments to addtimer are the same as an existing timer, it doesn't create a new timer,
* and returns the id of the existing timer
*/
#define TIMER_UNIQUE (1<<0)
#define TIMER_UNIQUE (1<<0)
///For unique timers: Replace the old timer rather then not start this one
#define TIMER_OVERRIDE (1<<1)
#define TIMER_OVERRIDE (1<<1)
/**
* Timing should be based on how timing progresses on clients, not the server.
@@ -41,20 +41,23 @@
* should only be used in conjuction with things that have to progress client side, such as
* animate() or sound()
*/
#define TIMER_CLIENT_TIME (1<<2)
#define TIMER_CLIENT_TIME (1<<2)
///Timer can be stopped using deltimer()
#define TIMER_STOPPABLE (1<<3)
#define TIMER_STOPPABLE (1<<3)
///prevents distinguishing identical timers with the wait variable
///
///To be used with TIMER_UNIQUE
#define TIMER_NO_HASH_WAIT (1<<4)
#define TIMER_NO_HASH_WAIT (1<<4)
///Loops the timer repeatedly until qdeleted
///
///In most cases you want a subsystem instead, so don't use this unless you have a good reason
#define TIMER_LOOP (1<<5)
#define TIMER_LOOP (1<<5)
///Delete the timer on parent datum Destroy() and when deltimer'd
#define TIMER_DELETE_ME (1<<6)
///Empty ID define
#define TIMER_ID_NULL -1
@@ -188,6 +191,7 @@
#define FIRE_PRIORITY_CALLBACKS 600
// #define FIRE_PRIORITY_EXPLOSIONS 666
#define FIRE_PRIORITY_TIMER 700
#define FIRE_PRIORITY_SOUND_LOOPS 800
#define FIRE_PRIORITY_INPUT 1000 // This must always always be the max highest priority. Player input must never be lost.
// SS runlevels

5
code/__DEFINES/text.dm Normal file
View File

@@ -0,0 +1,5 @@
/// Prepares a text to be used for maptext. Use this so it doesn't look hideous.
#define MAPTEXT(text) {"<span class='maptext'>[##text]</span>"}
/// Macro from Lummox used to get height from a MeasureText proc
#define WXH_TO_HEIGHT(x) text2num(copytext(x, findtextEx(x, "x") + 1))

10
code/__DEFINES/uplink.dm Normal file
View File

@@ -0,0 +1,10 @@
// These are used in uplink_devices.dm to determine whether or not an item is purchasable.
/// This item is purchasable to traitors
#define UPLINK_TRAITORS (1 << 0)
/// This item is purchasable to nuke ops
#define UPLINK_NUKE_OPS (1 << 1)
/// This item is purchasable to clown ops
#define UPLINK_CLOWN_OPS (1 << 2)

View File

@@ -1,32 +1,45 @@
/*
* Holds procs to help with list operations
* Contains groups:
* Misc
* Sorting
* Misc
* Sorting
*/
/*
* Misc
*/
#define LAZYINITLIST(L) if (!L) L = list()
#define LAZYINITLIST(L) if (!L) { L = list(); }
#define UNSETEMPTY(L) if (L && !length(L)) L = null
#define LAZYCOPY(L) (L ? L.Copy() : list() )
///Like LAZYCOPY - copies an input list if the list has entries, If it doesn't the assigned list is nulled
#define LAZYLISTDUPLICATE(L) (L ? L.Copy() : null )
#define LAZYREMOVE(L, I) if(L) { L -= I; if(!length(L)) { L = null; } }
#define LAZYADD(L, I) if(!L) { L = list(); } L += I;
#define LAZYOR(L, I) if(!L) { L = list(); } L |= I;
#define LAZYFIND(L, V) (L ? L.Find(V) : 0)
///returns L[I] if L exists and I is a valid index of L, runtimes if L is not a list
#define LAZYACCESS(L, I) (L ? (isnum(I) ? (I > 0 && I <= length(L) ? L[I] : null) : L[I]) : null)
#define LAZYSET(L, K, V) if(!L) { L = list(); } L[K] = V;
#define LAZYLEN(L) length(L)
//Sets a list to null
///Sets a list to null
#define LAZYNULL(L) L = null
#define LAZYCLEARLIST(L) if(L) L.Cut()
#define SANITIZE_LIST(L) ( islist(L) ? L : list() )
#define reverseList(L) reverseRange(L.Copy())
#define LAZYADDASSOC_TG(L, K, V) if(!L) { L = list(); } L[K] += V;
///This is used to add onto lazy assoc list when the value you're adding is a /list/. This one has extra safety over lazyaddassoc because the value could be null (and thus cant be used to += objects)
#define LAZYADDASSOC(L, K, V) if(!L) { L = list(); } L[K] += list(V);
#define LAZYREMOVEASSOC(L, K, V) if(L) { if(L[K]) { L[K] -= V; if(!length(L[K])) L -= K; } if(!length(L)) L = null; }
#define LAZYACCESSASSOC(L, I, K) L ? L[I] ? L[I][K] ? L[I][K] : null : null : null
#define QDEL_LAZYLIST(L) for(var/I in L) qdel(I); L = null;
//These methods don't null the list
#define LAZYCOPY(L) (L ? L.Copy() : list() ) //Use LAZYLISTDUPLICATE instead if you want it to null with no entries
#define LAZYCLEARLIST(L) if(L) L.Cut() // Consider LAZYNULL instead
#define SANITIZE_LIST(L) ( islist(L) ? L : list() )
#define reverseList(L) reverseRange(L.Copy())
/// Performs an insertion on the given lazy list with the given key and value. If the value already exists, a new one will not be made.
#define LAZYORASSOCLIST(lazy_list, key, value) \
LAZYINITLIST(lazy_list); \
LAZYINITLIST(lazy_list[key]); \
lazy_list[key] |= value;
/// Passed into BINARY_INSERT to compare keys
#define COMPARE_KEY __BIN_LIST[__BIN_MID]
@@ -69,7 +82,7 @@
} while(FALSE)
//Returns a list in plain english as a string
/proc/english_list(list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "")
/proc/english_list(list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "" )
var/total = length(input)
switch(total)
if (0)
@@ -92,6 +105,7 @@
/**
* English_list but associative supporting. Higher overhead.
* @depricated
*/
/proc/english_list_assoc(list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "")
var/total = length(input)
@@ -119,6 +133,7 @@
return "[output][and_text][input[index]]"
//Returns list element or null. Should prevent "index out of bounds" error.
/// @depricated
/proc/listgetindex(list/L, index)
if(LAZYLEN(L))
if(isnum(index) && ISINTEGER(index))
@@ -129,17 +144,19 @@
return
//Return either pick(list) or null if list is not of type /list or is empty
/// @depricated
/proc/safepick(list/L)
if(LAZYLEN(L))
return pick(L)
//Checks if the list is empty
/// @depricated
/proc/isemptylist(list/L)
if(!L.len)
return TRUE
return FALSE
//Checks for specific types in a list
//Checks for specific types in a listc
/proc/is_type_in_list(atom/A, list/L)
if(!LAZYLEN(L) || !A)
return FALSE
@@ -181,45 +198,45 @@
/proc/typecache_filter_list_reverse(list/atoms, list/typecache)
RETURN_TYPE(/list)
. = list()
for(var/thing in atoms)
var/atom/A = thing
if(!typecache[A.type])
. += A
for(var/atom/atom as anything in atoms)
if(!typecache[atom.type])
. += atom
/proc/typecache_filter_multi_list_exclusion(list/atoms, list/typecache_include, list/typecache_exclude)
. = list()
for(var/thing in atoms)
var/atom/A = thing
if(typecache_include[A.type] && !typecache_exclude[A.type])
. += A
for(var/atom/atom as anything in atoms)
if(typecache_include[atom.type] && !typecache_exclude[atom.type])
. += atom
//Like typesof() or subtypesof(), but returns a typecache instead of a list
///Like typesof() or subtypesof(), but returns a typecache instead of a list
/proc/typecacheof(path, ignore_root_path, only_root_path = FALSE)
if(ispath(path))
var/list/types = list()
var/list/types
var/list/output = list()
if(only_root_path)
types = list(path)
output[path] = TRUE
else
types = ignore_root_path ? subtypesof(path) : typesof(path)
var/list/L = list()
for(var/T in types)
L[T] = TRUE
return L
for(var/T in types)
output[T] = TRUE
return output
else if(islist(path))
var/list/pathlist = path
var/list/L = list()
var/list/output = list()
if(ignore_root_path)
for(var/P in pathlist)
for(var/T in subtypesof(P))
L[T] = TRUE
for(var/current_path in pathlist)
for(var/subtype in subtypesof(current_path))
output[subtype] = TRUE
return output
if(only_root_path)
for(var/current_path in pathlist)
output[current_path] = TRUE
else
for(var/P in pathlist)
if(only_root_path)
L[P] = TRUE
else
for(var/T in typesof(P))
L[T] = TRUE
return L
for(var/current_path in pathlist)
for(var/subpath in typesof(current_path))
output[subpath] = TRUE
return output
/proc/typecacheof_assoc_list(list/pathlist, ignore_root_path = FALSE)
. = list()
@@ -278,9 +295,10 @@
//Picks a random element from a list based on a weighting system:
//1. Adds up the total of weights for each element
//2. Gets the total from 0% to 100% of previous total value.
//2. Gets a number between 1 and that total
//3. For each element in the list, subtracts its weighting from that number
//4. If that makes the number 0 or less, return that element.
//Will output null sometimes if you use decimals (e.g. 0.1 instead of 10) as rand() uses integers, not floats
/proc/pickweight(list/L, base_weight = 1)
var/total = 0
var/item
@@ -289,12 +307,14 @@
L[item] = base_weight
total += L[item]
total = rand() * total
total = rand(base_weight, total)
for (item in L)
total -= L[item]
total -=L [item]
if (total <= 0)
return item
return null
/proc/pickweightAllowZero(list/L) //The original pickweight proc will sometimes pick entries with zero weight. I'm not sure if changing the original will break anything, so I left it be.
var/total = 0
var/item
@@ -366,13 +386,13 @@
//Results will have a length of quality
return results
//Pick a random element from the list and remove it from the list.
/// Pick a random element from the list and remove it from the list.
/proc/pick_n_take(list/L)
RETURN_TYPE(L[_].type)
if(L.len)
var/picked = rand(1,L.len)
. = L[picked]
L.Cut(picked,picked+1) //Cut is far more efficient that Remove()
L.Cut(picked,picked+1) //Cut is far more efficient that Remove()
//Pick a random element from the list by weight and remove it from the list.
//Result is returned as a list in the format list(key, value)
@@ -468,7 +488,7 @@
//uses sortList() but uses the var's name specifically. This should probably be using mergeAtom() instead
/proc/sortNames(list/L, order=1)
return sortTim(L, order >= 0 ? /proc/cmp_name_asc : /proc/cmp_name_dsc)
return sortTim(L.Copy(), order >= 0 ? /proc/cmp_name_asc : /proc/cmp_name_dsc)
//Converts a bitfield to a list of numbers (or words if a wordlist is provided)
@@ -504,10 +524,12 @@
if (L[i] == val)
.++
/// Returns datum/data/record
/proc/find_record(field, value, list/L)
for(var/datum/data/record/R in L)
if(R.fields[field] == value)
return R
return null
//Move a single element from position fromIndex within a list, to position toIndex
@@ -517,10 +539,10 @@
//fromIndex and toIndex must be in the range [1,L.len+1]
//This will preserve associations ~Carnie
/proc/moveElement(list/L, fromIndex, toIndex)
if(fromIndex == toIndex || fromIndex+1 == toIndex) //no need to move
if(fromIndex == toIndex || fromIndex+1 == toIndex) //no need to move
return
if(fromIndex > toIndex)
++fromIndex //since a null will be inserted before fromIndex, the index needs to be nudged right by one
++fromIndex //since a null will be inserted before fromIndex, the index needs to be nudged right by one
L.Insert(toIndex, null)
L.Swap(fromIndex, toIndex)
@@ -532,10 +554,10 @@
//This will preserve associations ~Carnie
/proc/moveRange(list/L, fromIndex, toIndex, len=1)
var/distance = abs(toIndex - fromIndex)
if(len >= distance) //there are more elements to be moved than the distance to be moved. Therefore the same result can be achieved (with fewer operations) by moving elements between where we are and where we are going. The result being, our range we are moving is shifted left or right by dist elements
if(len >= distance) //there are more elements to be moved than the distance to be moved. Therefore the same result can be achieved (with fewer operations) by moving elements between where we are and where we are going. The result being, our range we are moving is shifted left or right by dist elements
if(fromIndex <= toIndex)
return //no need to move
fromIndex += len //we want to shift left instead of right
return //no need to move
fromIndex += len //we want to shift left instead of right
for(var/i=0, i<distance, ++i)
L.Insert(fromIndex, null)
@@ -555,7 +577,7 @@
//Note: if the two ranges overlap, only the destination order will be preserved fully, since some elements will be within both ranges ~Carnie
/proc/swapRange(list/L, fromIndex, toIndex, len=1)
var/distance = abs(toIndex - fromIndex)
if(len > distance) //there is an overlap, therefore swapping each element will require more swaps than inserting new elements
if(len > distance) //there is an overlap, therefore swapping each element will require more swaps than inserting new elements
if(fromIndex < toIndex)
toIndex += len
else
@@ -601,6 +623,12 @@
if(D.vars[varname] == value)
return D
//remove all nulls from a list
/proc/removeNullsFromList(list/L)
while(L.Remove(null))
continue
return L
//Copies a list, and all lists inside it recusively
//Does not copy any other reference type
/proc/deepCopyList(list/l)
@@ -633,11 +661,6 @@
used_key_list[input_key] = 1
return input_key
#if DM_VERSION > 514
#error Remie said that lummox was adding a way to get a lists
#error contents via list.values, if that is true remove this
#error otherwise, update the version and bug lummox
#endif
//Flattens a keyed list into a list of it's contents
/proc/flatten_list(list/key_list)
if(!islist(key_list))
@@ -714,6 +737,29 @@
ret += key
return ret
/proc/compare_list(list/l,list/d)
if(!islist(l) || !islist(d))
return FALSE
if(l.len != d.len)
return FALSE
for(var/i in 1 to l.len)
if(l[i] != d[i])
return FALSE
return TRUE
#define LAZY_LISTS_OR(left_list, right_list)\
( length(left_list)\
? length(right_list)\
? (left_list | right_list)\
: left_list.Copy()\
: length(right_list)\
? right_list.Copy()\
: null\
)
/proc/is_type_in_ref_list(path, list/L)
if(!ispath(path))//not a path
return

View File

@@ -396,12 +396,16 @@
/proc/ScreenText(obj/O, maptext="", screen_loc="CENTER-7,CENTER-7", maptext_height=480, maptext_width=480)
if(!isobj(O))
O = new /atom/movable/screen/text()
O.maptext = maptext
O.maptext = MAPTEXT(maptext)
O.maptext_height = maptext_height
O.maptext_width = maptext_width
O.screen_loc = screen_loc
return O
/// Removes an image from a client's `.images`. Useful as a callback.
/proc/remove_image_from_client(image/image, client/remove_from)
remove_from?.images -= image
/proc/remove_images_from_clients(image/I, list/show_to)
for(var/client/C in show_to)
C.images -= I

View File

@@ -86,16 +86,6 @@
// Keybindings
init_keybindings()
//Uplink Items
for(var/path in subtypesof(/datum/uplink_item))
var/datum/uplink_item/I = path
if(!initial(I.item)) //We add categories to a separate list.
GLOB.uplink_categories |= initial(I.category)
continue
GLOB.uplink_items += path
//(sub)typesof entries are listed by the order they are loaded in the code, so we'll have to rearrange them here.
GLOB.uplink_items = sortList(GLOB.uplink_items, /proc/cmp_uplink_items_dsc)
init_subtypes(/datum/crafting_recipe, GLOB.crafting_recipes)
INVOKE_ASYNC(GLOBAL_PROC, /proc/init_ref_coin_values) //so the current procedure doesn't sleep because of UNTIL()

View File

@@ -992,7 +992,7 @@ world
letter = lowertext(letter)
var/image/text_image = new(loc = A)
text_image.maptext = "<font size = 4>[letter]</font>"
text_image.maptext = MAPTEXT("<font size = 4>[letter]</font>")
text_image.pixel_x = 7
text_image.pixel_y = 5
qdel(atom_icon)

View File

@@ -1,4 +1,4 @@
// Ensure the frequency is within bounds of what it should be sending/receiving at
/// Ensure the frequency is within bounds of what it should be sending/receiving at
/proc/sanitize_frequency(frequency, free = FALSE)
frequency = round(frequency)
if(free)
@@ -8,12 +8,26 @@
if(!(. % 2)) // Ensure the last digit is an odd number
. += 1
// Format frequency by moving the decimal.
/// Format frequency by moving the decimal.
/proc/format_frequency(frequency)
frequency = text2num(frequency)
return "[round(frequency / 10)].[frequency % 10]"
//Opposite of format, returns as a number
///Opposite of format, returns as a number
/proc/unformat_frequency(frequency)
frequency = text2num(frequency)
return frequency * 10
///returns a random unused frequency between MIN_FREE_FREQ & MAX_FREE_FREQ if free = TRUE, and MIN_FREQ & MAX_FREQ if FALSE
/proc/return_unused_frequency(free = FALSE)
var/start = free ? MIN_FREE_FREQ : MIN_FREQ
var/end = free ? MAX_FREE_FREQ : MAX_FREQ
var/freq_to_check = 0
do
freq_to_check = rand(start, end)
if(!(freq_to_check % 2)) // Ensure the last digit is an odd number
freq_to_check++
while((freq_to_check == 0) || ("[freq_to_check]" in GLOB.reverseradiochannels))
return freq_to_check

View File

@@ -216,7 +216,13 @@ GLOBAL_LIST_INIT(jumpsuitlist, list(PREF_SUIT, PREF_SKIRT))
#define UPLINK_PDA "PDA"
#define UPLINK_RADIO "Radio"
#define UPLINK_PEN "Pen" //like a real spy!
GLOBAL_LIST_INIT(uplink_spawn_loc_list, list(UPLINK_PDA, UPLINK_RADIO, UPLINK_PEN))
#define UPLINK_IMPLANT "Implant"
#define UPLINK_IMPLANT_WITH_PRICE "[UPLINK_IMPLANT] (-[UPLINK_IMPLANT_TELECRYSTAL_COST] TC)"
// What we show to the user
GLOBAL_LIST_INIT(uplink_spawn_loc_list, list(UPLINK_PDA, UPLINK_RADIO, UPLINK_PEN, UPLINK_IMPLANT_WITH_PRICE))
// What is actually saved; if the uplink implant price changes, it won't affect save files then
GLOBAL_LIST_INIT(uplink_spawn_loc_list_save, list(UPLINK_PDA, UPLINK_RADIO, UPLINK_PEN, UPLINK_IMPLANT))
//List of cached alpha masked icons.
GLOBAL_LIST_EMPTY(alpha_masked_worn_icons)

View File

@@ -19,7 +19,6 @@ GLOBAL_LIST(chemical_reactions_list) //list of all /datum/chemical_reaction d
GLOBAL_LIST(chemical_reagents_list) //list of all /datum/reagent datums indexed by reagent id. Used by chemistry stuff
GLOBAL_LIST_EMPTY(tech_list) //list of all /datum/tech datums indexed by id.
GLOBAL_LIST_EMPTY(surgeries_list) //list of all surgeries by name, associated with their path.
GLOBAL_LIST_EMPTY(uplink_items) //list of all uplink item typepaths, ascendingly sorted by their initial name.
GLOBAL_LIST_EMPTY(uplink_categories) //list of all uplink categories, listed by the order they are loaded in code. Be careful.
GLOBAL_LIST_EMPTY(crafting_recipes) //list of all table craft recipes
GLOBAL_LIST_EMPTY(rcd_list) //list of Rapid Construction Devices.

View File

@@ -44,7 +44,7 @@
icon = I
parent = P
icon_state = credited
maptext = credited
maptext = MAPTEXT(credited)
maptext_x = world.icon_size + 8
maptext_y = (world.icon_size / 2) - 4
maptext_width = world.icon_size * 3

View File

@@ -17,7 +17,6 @@ SUBSYSTEM_DEF(processing)
/datum/controller/subsystem/processing/fire(resumed = FALSE)
if (!resumed)
currentrun = processing.Copy()
var/delta_time = (flags & SS_TICKER)? (wait * world.tick_lag * 0.1) : (wait * 0.1)
//cache for sanic speed (lists are references anyways)
var/list/current_run = currentrun
@@ -26,7 +25,7 @@ SUBSYSTEM_DEF(processing)
current_run.len--
if(QDELETED(thing))
processing -= thing
else if(thing.process(delta_time) == PROCESS_KILL)
else if(thing.process(wait * 0.1) == PROCESS_KILL)
// fully stop so that a future START_PROCESSING will work
STOP_PROCESSING(src, thing)
if (MC_TICK_CHECK)
@@ -47,5 +46,5 @@ SUBSYSTEM_DEF(processing)
* If you override this do not call parent, as it will return PROCESS_KILL. This is done to prevent objects that dont override process() from staying in the processing list
*/
/datum/proc/process(delta_time)
SHOULD_NOT_SLEEP(TRUE)
set waitfor = FALSE
return PROCESS_KILL

View File

@@ -4,7 +4,7 @@ SUBSYSTEM_DEF(sounds)
name = "Sounds"
flags = SS_NO_FIRE
init_order = INIT_ORDER_SOUNDS
var/static/using_channels_max = CHANNEL_HIGHEST_AVAILABLE //BYOND max channels
var/static/using_channels_max = CHANNEL_HIGHEST_AVAILABLE //BYOND max channels
/// Amount of channels to reserve for random usage rather than reservations being allowed to reserve all channels. Also a nice safeguard for when someone screws up.
var/static/random_channels_min = 50
@@ -42,7 +42,7 @@ SUBSYSTEM_DEF(sounds)
var/text_channel = num2text(channel)
var/using = using_channels[text_channel]
using_channels -= text_channel
if(using != TRUE) // datum channel
if(using != TRUE) // datum channel
using_channels_by_datum[using] -= channel
if(!length(using_channels_by_datum[using]))
using_channels_by_datum -= using
@@ -65,7 +65,7 @@ SUBSYSTEM_DEF(sounds)
/// NO AUTOMATIC CLEANUP - If you use this, you better manually free it later! Returns an integer for channel.
/datum/controller/subsystem/sounds/proc/reserve_sound_channel_datumless()
. = reserve_channel()
if(!.) //oh no..
if(!.) //oh no..
return FALSE
var/text_channel = num2text(.)
using_channels[text_channel] = DATUMLESS
@@ -74,7 +74,7 @@ SUBSYSTEM_DEF(sounds)
/// Reserves a channel for a datum. Automatic cleanup only when the datum is deleted. Returns an integer for channel.
/datum/controller/subsystem/sounds/proc/reserve_sound_channel(datum/D)
if(!D) //i don't like typechecks but someone will fuck it up
if(!D) //i don't like typechecks but someone will fuck it up
CRASH("Attempted to reserve sound channel without datum using the managed proc.")
.= reserve_channel()
if(!.)
@@ -89,7 +89,7 @@ SUBSYSTEM_DEF(sounds)
*/
/datum/controller/subsystem/sounds/proc/reserve_channel()
PRIVATE_PROC(TRUE)
if(channel_reserve_high <= random_channels_min) // out of channels
if(channel_reserve_high <= random_channels_min) // out of channels
return
var/channel = channel_list[channel_reserve_high]
reserved_channels[num2text(channel)] = channel_reserve_high--
@@ -112,7 +112,7 @@ SUBSYSTEM_DEF(sounds)
// now, an existing reserved channel will likely (exception: unreserving last reserved channel) be at index
// get it, and update position.
var/text_reserved = num2text(channel_list[index])
if(!reserved_channels[text_reserved]) //if it isn't already reserved make sure we don't accidently mistakenly put it on reserved list!
if(!reserved_channels[text_reserved]) //if it isn't already reserved make sure we don't accidently mistakenly put it on reserved list!
return
reserved_channels[text_reserved] = index

View File

@@ -18,8 +18,6 @@
#define CHAT_LAYER_Z_STEP 0.0001
/// The number of z-layer 'slices' usable by the chat message layering
#define CHAT_LAYER_MAX_Z (CHAT_LAYER_MAX - CHAT_LAYER) / CHAT_LAYER_Z_STEP
/// Macro from Lummox used to get height from a MeasureText proc
#define WXH_TO_HEIGHT(x) text2num(copytext(x, findtextEx(x, "x") + 1))
/**
* # Chat Message Overlay
@@ -165,7 +163,7 @@
message.maptext_width = CHAT_MESSAGE_WIDTH
message.maptext_height = mheight
message.maptext_x = (CHAT_MESSAGE_WIDTH - owner.bound_width) * -0.5
message.maptext = complete_text
message.maptext = MAPTEXT(complete_text)
// View the message
LAZYADDASSOC(owned_by.seen_messages, message_loc, src)

View File

@@ -1,4 +1,5 @@
GLOBAL_LIST_EMPTY(uplinks)
#define PEN_ROTATIONS 2
/**
* Uplinks
@@ -17,7 +18,7 @@ GLOBAL_LIST_EMPTY(uplinks)
var/telecrystals
var/selected_cat
var/owner = null
var/datum/game_mode/gamemode
var/uplink_flag
var/datum/uplink_purchase_log/purchase_log
var/list/uplink_items
var/hidden_crystals = 0
@@ -26,11 +27,11 @@ GLOBAL_LIST_EMPTY(uplinks)
var/failsafe_code
var/compact_mode = FALSE
var/debug = FALSE
var/saved_player_population = 0
var/list/filters = list()
///Instructions on how to access the uplink based on location
var/unlock_text
var/list/previous_attempts
/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20, datum/traitor_class/traitor_class)
/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, uplink_flag = UPLINK_TRAITORS, starting_tc = TELECRYSTALS_DEFAULT)
if(!isitem(parent))
return COMPONENT_INCOMPATIBLE
@@ -44,16 +45,13 @@ GLOBAL_LIST_EMPTY(uplinks)
RegisterSignal(parent, COMSIG_IMPLANT_EXISTING_UPLINK, .proc/new_implant)
else if(istype(parent, /obj/item/pda))
RegisterSignal(parent, COMSIG_PDA_CHANGE_RINGTONE, .proc/new_ringtone)
// RegisterSignal(parent, COMSIG_PDA_CHECK_DETONATE, .proc/check_detonate)
else if(istype(parent, /obj/item/radio))
RegisterSignal(parent, COMSIG_RADIO_NEW_FREQUENCY, .proc/new_frequency)
else if(istype(parent, /obj/item/pen))
RegisterSignal(parent, COMSIG_PEN_ROTATED, .proc/pen_rotation)
GLOB.uplinks += src
if(istype(traitor_class))
filters = traitor_class.uplink_filters
starting_tc = traitor_class.TC
uplink_items = get_uplink_items(gamemode, TRUE, allow_restricted, filters)
GLOB.uplinks |= src
if(_owner)
owner = _owner
@@ -64,44 +62,58 @@ GLOBAL_LIST_EMPTY(uplinks)
purchase_log = new(owner, src)
lockable = _lockable
active = _enabled
gamemode = _gamemode
src.uplink_flag = uplink_flag
update_items()
telecrystals = starting_tc
if(!lockable)
active = TRUE
locked = FALSE
saved_player_population = GLOB.joined_player_list.len
previous_attempts = list()
/datum/component/uplink/InheritComponent(datum/component/uplink/U)
lockable |= U.lockable
active |= U.active
if(!gamemode)
gamemode = U.gamemode
uplink_flag |= U.uplink_flag
telecrystals += U.telecrystals
if(purchase_log && U.purchase_log)
purchase_log.MergeWithAndDel(U.purchase_log)
/datum/component/uplink/Destroy()
GLOB.uplinks -= src
gamemode = null
purchase_log = null
return ..()
/datum/component/uplink/proc/update_items()
var/updated_items
updated_items = get_uplink_items(uplink_flag, TRUE, allow_restricted)
update_sales(updated_items)
uplink_items = updated_items
/datum/component/uplink/proc/update_sales(updated_items)
var/discount_categories = list("Discounted Gear", "Discounted Team Gear", "Limited Stock Team Gear")
if (uplink_items == null)
return
for (var/category in discount_categories) // Makes sure discounted items aren't renewed or replaced
if (uplink_items[category] != null && updated_items[category] != null)
updated_items[category] = uplink_items[category]
/datum/component/uplink/proc/LoadTC(mob/user, obj/item/stack/telecrystal/TC, silent = FALSE)
if(!silent)
to_chat(user, "<span class='notice'>You slot [TC] into [parent] and charge its internal uplink.</span>")
to_chat(user, span_notice("You slot [TC] into [parent] and charge its internal uplink."))
var/amt = TC.amount
telecrystals += amt
TC.use(amt)
/datum/component/uplink/proc/set_gamemode(_gamemode)
gamemode = _gamemode
uplink_items = get_uplink_items(gamemode, TRUE, allow_restricted)
// log_uplink("[key_name(user)] loaded [amt] telecrystals into [parent]'s uplink")
/datum/component/uplink/proc/OnAttackBy(datum/source, obj/item/I, mob/user)
SIGNAL_HANDLER
if(!active)
return //no hitting everyone/everything just to try to slot tcs in!
return //no hitting everyone/everything just to try to slot tcs in!
if(istype(I, /obj/item/stack/telecrystal))
LoadTC(user, I)
// CIT SPECIFIC: STEALING from unlocked uplink.
if(active)
if(I.GetComponent(/datum/component/uplink))
var/datum/component/uplink/hidden_uplink = I.GetComponent(/datum/component/uplink)
@@ -118,31 +130,26 @@ GLOBAL_LIST_EMPTY(uplinks)
var/cost = UI.refund_amount || UI.cost
if(I.type == path && UI.refundable && I.check_uplink_validity())
telecrystals += cost
purchase_log.total_spent -= cost
to_chat(user, "<span class='notice'>[I] refunded.</span>")
// log_uplink("[key_name(user)] refunded [UI] for [cost] telecrystals using [parent]'s uplink")
if(purchase_log)
purchase_log.total_spent -= cost
to_chat(user, span_notice("[I] refunded."))
qdel(I)
return
/datum/component/uplink/proc/interact(datum/source, mob/user)
SIGNAL_HANDLER
if(locked)
return
active = TRUE
update_items()
if(user)
//update the saved population
var/previous_player_population = saved_player_population
saved_player_population = GLOB.joined_player_list.len
//if population has changed, update uplink items
if(saved_player_population != previous_player_population)
//make sure discounts are not rerolled
var/old_discounts = uplink_items["Discounted Gear"]
uplink_items = get_uplink_items(gamemode, FALSE, allow_restricted, filters)
if(old_discounts)
uplink_items["Discounted Gear"] = old_discounts
ui_interact(user)
INVOKE_ASYNC(src, .proc/ui_interact, user)
// an unlocked uplink blocks also opening the PDA or headset menu
return COMPONENT_NO_INTERACT
/datum/component/uplink/ui_state(mob/user)
if(istype(parent, /obj/item/implant/uplink))
return GLOB.not_incapacitated_state
@@ -178,15 +185,10 @@ GLOBAL_LIST_EMPTY(uplinks)
var/datum/uplink_item/I = uplink_items[category][item]
if(I.limited_stock == 0)
continue
if(I.restricted_roles.len)
var/is_inaccessible = TRUE
for(var/R in I.restricted_roles)
if(R == user.mind.assigned_role || debug)
is_inaccessible = FALSE
if(is_inaccessible)
if(length(I.restricted_roles))
if(!debug && !(user.mind.assigned_role in I.restricted_roles))
continue
/*
if(I.restricted_species) //catpeople specfic gloves.
if(I.restricted_species)
if(ishuman(user))
var/is_inaccessible = TRUE
var/mob/living/carbon/human/H = user
@@ -196,7 +198,6 @@ GLOBAL_LIST_EMPTY(uplinks)
break
if(is_inaccessible)
continue
*/
cat["items"] += list(list(
"name" = I.name,
"cost" = I.cost,
@@ -255,25 +256,41 @@ GLOBAL_LIST_EMPTY(uplinks)
// Implant signal responses
/datum/component/uplink/proc/implant_activation()
SIGNAL_HANDLER
var/obj/item/implant/implant = parent
locked = FALSE
interact(null, implant.imp_in)
/datum/component/uplink/proc/implanting(datum/source, list/arguments)
SIGNAL_HANDLER
var/mob/user = arguments[2]
owner = "[user.key]"
owner = user?.key
if(owner && !purchase_log)
LAZYINITLIST(GLOB.uplink_purchase_logs_by_key)
if(GLOB.uplink_purchase_logs_by_key[owner])
purchase_log = GLOB.uplink_purchase_logs_by_key[owner]
else
purchase_log = new(owner, src)
/datum/component/uplink/proc/old_implant(datum/source, list/arguments, obj/item/implant/new_implant)
SIGNAL_HANDLER
// It kinda has to be weird like this until implants are components
return SEND_SIGNAL(new_implant, COMSIG_IMPLANT_EXISTING_UPLINK, src)
/datum/component/uplink/proc/new_implant(datum/source, datum/component/uplink/uplink)
SIGNAL_HANDLER
uplink.telecrystals += telecrystals
return COMPONENT_DELETE_NEW_IMPLANT
// PDA signal responses
/datum/component/uplink/proc/new_ringtone(datum/source, mob/living/user, new_ring_text)
SIGNAL_HANDLER
var/obj/item/pda/master = parent
if(trim(lowertext(new_ring_text)) != trim(lowertext(unlock_code)))
if(trim(lowertext(new_ring_text)) == trim(lowertext(failsafe_code)))
@@ -282,14 +299,21 @@ GLOBAL_LIST_EMPTY(uplinks)
return
locked = FALSE
interact(null, user)
to_chat(user, "<span class='hear'>The PDA softly beeps.</span>")
to_chat(user, span_hear("The PDA softly beeps."))
user << browse(null, "window=pda")
master.mode = 0
return COMPONENT_STOP_RINGTONE_CHANGE
/datum/component/uplink/proc/check_detonate()
SIGNAL_HANDLER
// return COMPONENT_PDA_NO_DETONATE
// Radio signal responses
/datum/component/uplink/proc/new_frequency(datum/source, list/arguments)
SIGNAL_HANDLER
var/obj/item/radio/master = parent
var/frequency = arguments[1]
if(frequency != unlock_code)
@@ -303,15 +327,22 @@ GLOBAL_LIST_EMPTY(uplinks)
// Pen signal responses
/datum/component/uplink/proc/pen_rotation(datum/source, degrees, mob/living/carbon/user)
SIGNAL_HANDLER
var/obj/item/pen/master = parent
if(degrees != unlock_code)
if(degrees == failsafe_code) //Getting failsafes on pens is risky business
failsafe()
return
locked = FALSE
master.degrees = 0
interact(null, user)
to_chat(user, "<span class='warning'>Your pen makes a clicking noise, before quickly rotating back to 0 degrees!</span>")
previous_attempts += degrees
if(length(previous_attempts) > PEN_ROTATIONS)
popleft(previous_attempts)
if(compare_list(previous_attempts, unlock_code))
locked = FALSE
previous_attempts.Cut()
master.degrees = 0
interact(null, user)
to_chat(user, span_warning("Your pen makes a clicking noise, before quickly rotating back to 0 degrees!"))
else if(compare_list(previous_attempts, failsafe_code))
failsafe(user)
/datum/component/uplink/proc/setup_unlock_code()
unlock_code = generate_code()
@@ -321,15 +352,18 @@ GLOBAL_LIST_EMPTY(uplinks)
else if(istype(parent,/obj/item/radio))
unlock_note = "<B>Radio Frequency:</B> [format_frequency(unlock_code)] ([P.name])."
else if(istype(parent,/obj/item/pen))
unlock_note = "<B>Uplink Degrees:</B> [unlock_code] ([P.name])."
unlock_note = "<B>Uplink Degrees:</B> [english_list(unlock_code)] ([P.name])."
/datum/component/uplink/proc/generate_code()
if(istype(parent,/obj/item/pda))
return "[rand(100,999)] [pick(GLOB.phonetic_alphabet)]"
else if(istype(parent,/obj/item/radio))
return sanitize_frequency(rand(MIN_FREQ, MAX_FREQ))
return return_unused_frequency()
else if(istype(parent,/obj/item/pen))
return rand(1, 360)
var/list/L = list()
for(var/i in 1 to PEN_ROTATIONS)
L += rand(1, 360)
return L
/datum/component/uplink/proc/failsafe(mob/living/carbon/user)
if(!parent)
@@ -339,5 +373,5 @@ GLOBAL_LIST_EMPTY(uplinks)
return
message_admins("[ADMIN_LOOKUPFLW(user)] has triggered an uplink failsafe explosion at [AREACOORD(T)] The owner of the uplink was [ADMIN_LOOKUPFLW(owner)].")
log_game("[key_name(user)] triggered an uplink failsafe explosion. The owner of the uplink was [key_name(owner)].")
explosion(T,1,2,3)
explosion(parent, devastation_range = 1, heavy_impact_range = 2, light_impact_range = 3)
qdel(parent) //Alternatively could brick the uplink.

View File

@@ -106,7 +106,7 @@
active_timers = null
for(var/thing in timers)
var/datum/timedevent/timer = thing
if (timer.spent)
if (timer.spent && !(timer.flags & TIMER_DELETE_ME))
continue
qdel(timer)

View File

@@ -267,11 +267,18 @@
remove_rev()
SSticker.mode.update_cult_icons_removed(src)
/datum/mind/proc/equip_traitor(datum/traitor_class/traitor_class, silent = FALSE, datum/antagonist/uplink_owner)
/**
* ## give_uplink
*
* A mind proc for giving anyone an uplink.
* arguments:
* * traitor_class: (cit specific) the type of antag the user is.
* * silent: if this should send a message to the mind getting the uplink. traitors do not use this silence, but the silence var on their antag datum.
* * antag_datum: the antag datum of the uplink owner, for storing it in antag memory. optional!
*/
/datum/mind/proc/equip_traitor(silent = FALSE, datum/antagonist/antag_datum)
if(!current)
return
if(!traitor_class)
traitor_class = GLOB.traitor_classes[TRAITOR_HUMAN]
var/mob/living/carbon/human/traitor_mob = current
if (!istype(traitor_mob))
return
@@ -285,16 +292,9 @@
P = locate() in PDA
if (!P) // If we couldn't find a pen in the PDA, or we didn't even have a PDA, do it the old way
P = locate() in all_contents
if(!P) // I do not have a pen.
var/obj/item/pen/inowhaveapen
if(istype(traitor_mob.back,/obj/item/storage)) //ok buddy you better have a backpack!
inowhaveapen = new /obj/item/pen(traitor_mob.back)
else
inowhaveapen = new /obj/item/pen(traitor_mob.loc)
traitor_mob.put_in_hands(inowhaveapen) // I hope you don't have arms and your traitor pen gets stolen for all this trouble you've caused.
P = inowhaveapen
var/obj/item/uplink_loc
var/implant = FALSE
if(traitor_mob.client && traitor_mob.client.prefs)
switch(traitor_mob.client.prefs.uplink_spawn_loc)
@@ -312,33 +312,38 @@
uplink_loc = P
if(UPLINK_PEN)
uplink_loc = P
if(!uplink_loc)
uplink_loc = PDA
if(!uplink_loc)
uplink_loc = R
if(UPLINK_IMPLANT)
implant = TRUE
if (!uplink_loc)
if(!silent)
to_chat(traitor_mob, "Unfortunately, [traitor_class.employer] wasn't able to get you an Uplink.")
. = 0
else
. = uplink_loc
var/datum/component/uplink/U = uplink_loc.AddComponent(/datum/component/uplink, traitor_mob.key,traitor_class)
if(!U)
CRASH("Uplink creation failed.")
U.setup_unlock_code()
if(!silent)
if(uplink_loc == R)
to_chat(traitor_mob, "[traitor_class.employer] has cunningly disguised a Syndicate Uplink as your [R.name]. Simply dial the frequency [format_frequency(U.unlock_code)] to unlock its hidden features.")
else if(uplink_loc == PDA)
to_chat(traitor_mob, "[traitor_class.employer] has cunningly disguised a Syndicate Uplink as your [PDA.name]. Simply enter the code \"[U.unlock_code]\" into the ringtone select to unlock its hidden features.")
else if(uplink_loc == P)
to_chat(traitor_mob, "[traitor_class.employer] has cunningly disguised a Syndicate Uplink as your [P.name]. Simply twist the top of the pen [U.unlock_code] from its starting position to unlock its hidden features.")
if(!uplink_loc) // We've looked everywhere, let's just implant you
implant = TRUE
if(uplink_owner)
uplink_owner.antag_memory += U.unlock_note + "<br>"
else
traitor_mob.mind.store_memory(U.unlock_note)
if(implant)
var/obj/item/implant/uplink/starting/new_implant = new(traitor_mob)
new_implant.implant(traitor_mob, null, silent = TRUE)
if(!silent)
to_chat(traitor_mob, span_boldnotice("Your Syndicate Uplink has been cunningly implanted in you, for a small TC fee. Simply trigger the uplink to access it."))
return new_implant
. = uplink_loc
var/unlock_text
var/datum/component/uplink/new_uplink = uplink_loc.AddComponent(/datum/component/uplink, traitor_mob.key)
if(!new_uplink)
CRASH("Uplink creation failed.")
new_uplink.setup_unlock_code()
if(uplink_loc == R)
unlock_text = "Your Uplink is cunningly disguised as your [R.name]. Simply dial the frequency [format_frequency(new_uplink.unlock_code)] to unlock its hidden features."
else if(uplink_loc == PDA)
unlock_text = "Your Uplink is cunningly disguised as your [PDA.name]. Simply enter the code \"[new_uplink.unlock_code]\" into the ringtone select to unlock its hidden features."
else if(uplink_loc == P)
unlock_text = "Your Uplink is cunningly disguised as your [P.name]. Simply twist the top of the pen [english_list(new_uplink.unlock_code)] from its starting position to unlock its hidden features."
new_uplink.unlock_text = unlock_text
if(!silent)
to_chat(traitor_mob, span_boldnotice(unlock_text))
if(!antag_datum)
traitor_mob.mind.store_memory(new_uplink.unlock_note)
return
antag_datum.antag_memory += new_uplink.unlock_note + "<br>"
//Link a new mobs mind to the creator of said mob. They will join any team they are currently on, and will only switch teams when their creator does.

View File

@@ -1,3 +1,5 @@
//A reference to this list is passed into area sound managers, and it's modified in a manner that preserves that reference in ash_storm.dm
GLOBAL_LIST_EMPTY(ash_storm_sounds)
//Ash storms happen frequently on lavaland. They heavily obscure vision, and cause high fire damage to anyone caught outside.
/datum/weather/ash_storm
name = "ash storm"
@@ -25,55 +27,41 @@
probability = 90
barometer_predictable = TRUE
var/datum/looping_sound/active_outside_ashstorm/sound_ao = new(list(), FALSE, TRUE)
var/datum/looping_sound/active_inside_ashstorm/sound_ai = new(list(), FALSE, TRUE)
var/datum/looping_sound/weak_outside_ashstorm/sound_wo = new(list(), FALSE, TRUE)
var/datum/looping_sound/weak_inside_ashstorm/sound_wi = new(list(), FALSE, TRUE)
var/list/weak_sounds = list()
var/list/strong_sounds = list()
/datum/weather/ash_storm/telegraph()
. = ..()
var/list/inside_areas = list()
var/list/outside_areas = list()
var/list/eligible_areas = list()
for (var/z in impacted_z_levels)
eligible_areas += SSmapping.areas_in_z["[z]"]
for(var/i in 1 to eligible_areas.len)
var/area/place = eligible_areas[i]
if(place.outdoors)
outside_areas += place
weak_sounds[place] = /datum/looping_sound/weak_outside_ashstorm
strong_sounds[place] = /datum/looping_sound/active_outside_ashstorm
else
inside_areas += place
weak_sounds[place] = /datum/looping_sound/weak_inside_ashstorm
strong_sounds[place] = /datum/looping_sound/active_inside_ashstorm
CHECK_TICK
sound_ao.output_atoms = outside_areas
sound_ai.output_atoms = inside_areas
sound_wo.output_atoms = outside_areas
sound_wi.output_atoms = inside_areas
sound_wo.start()
sound_wi.start()
//We modify this list instead of setting it to weak/stron sounds in order to preserve things that hold a reference to it
//It's essentially a playlist for a bunch of components that chose what sound to loop based on the area a player is in
GLOB.ash_storm_sounds += weak_sounds
return ..()
/datum/weather/ash_storm/start()
. = ..()
sound_wo.stop()
sound_wi.stop()
sound_ao.start()
sound_ai.start()
GLOB.ash_storm_sounds -= weak_sounds
GLOB.ash_storm_sounds += strong_sounds
return ..()
/datum/weather/ash_storm/wind_down()
. = ..()
sound_ao.stop()
sound_ai.stop()
sound_wo.start()
sound_wi.start()
GLOB.ash_storm_sounds -= strong_sounds
GLOB.ash_storm_sounds += weak_sounds
return ..()
/datum/weather/ash_storm/end()
. = ..()
sound_wo.stop()
sound_wi.stop()
GLOB.ash_storm_sounds -= weak_sounds
return ..()
/datum/weather/ash_storm/proc/is_ash_immune(atom/L)
while (L && !isturf(L))
@@ -88,6 +76,11 @@
var/mob/living/the_mob = L
if("ash" in the_mob.weather_immunities)
return TRUE
// if(istype(L, /obj/structure/closet))
// var/obj/structure/closet/the_locker = L
// if(the_locker.weather_protection)
// if("ash" in the_locker.weather_protection)
// return TRUE
L = L.loc //Check parent items immunities (recurses up to the turf)
return FALSE //RIP you

View File

@@ -1287,9 +1287,7 @@
/obj/item/update_filters()
. = ..()
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
update_action_buttons()
/atom/proc/get_filter(name)
if(filter_data && filter_data[name])

View File

@@ -3,6 +3,7 @@
desc = "A machine to give your apparel a fresh new color! Recommended to use with white items for best results."
icon = 'icons/obj/vending.dmi'
icon_state = "colormate"
// light_mask = "colormate-light-mask"
density = TRUE
anchored = TRUE
circuit = /obj/item/circuitboard/machine/colormate

View File

@@ -14,7 +14,7 @@ GLOBAL_LIST_EMPTY(cryopod_computers)
/obj/machinery/computer/cryopod
name = "cryogenic oversight console"
desc = "An interface between crew and the cryogenic storage oversight systems."
icon = 'icons/obj/machines/cryopod.dmi'
icon = 'icons/obj/Cryogenic2.dmi'
icon_state = "cellconsole_1"
icon_keyboard = null
// circuit = /obj/item/circuitboard/cryopodcontrol

View File

@@ -1220,3 +1220,14 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
pain_stam_pct = (!isnull(embedding["pain_stam_pct"]) ? embedding["pain_stam_pct"] : EMBEDDED_PAIN_STAM_PCT),\
embed_chance_turf_mod = (!isnull(embedding["embed_chance_turf_mod"]) ? embedding["embed_chance_turf_mod"] : EMBED_CHANCE_TURF_MOD))
return TRUE
/**
* Updates all action buttons associated with this item
*
* Arguments:
* * status_only - Update only current availability status of the buttons to show if they are ready or not to use
* * force - Force buttons update even if the given button icon state has not changed
*/
/obj/item/proc/update_action_buttons(status_only = FALSE, force = FALSE)
for(var/datum/action/current_action as anything in actions)
current_action.UpdateButtonIcon(status_only, force)

View File

@@ -20,4 +20,7 @@
imp_type = /obj/item/implant/uplink/precharged
/obj/item/implant/uplink/precharged
starting_tc = 10
starting_tc = TELECRYSTALS_PRELOADED_IMPLANT
/obj/item/implant/uplink/starting
starting_tc = TELECRYSTALS_DEFAULT - UPLINK_IMPLANT_TELECRYSTAL_COST

View File

@@ -121,7 +121,7 @@
/obj/structure/noticeboard/deconstruct(disassembled = TRUE)
if(!(flags_1 & NODECONSTRUCT_1))
new /obj/item/stack/sheet/iron (loc, 1)
new /obj/item/stack/sheet/metal (loc, 1)
for(var/obj/item/content in contents)
remove_item(content)
qdel(src)

View File

@@ -79,7 +79,7 @@
. = TRUE
if("mass_apply")
if(!check_rights_for(usr.client, R_FUN))
to_chat(usr, "<span class='userdanger>Stay in your lane, jannie.</span>'")
to_chat(usr, span_userdanger("Stay in your lane, jannie."))
return
var/target_path = text2path(params["path"])
if(!target_path)

View File

@@ -1,33 +1,70 @@
GLOBAL_LIST_EMPTY(antagonists)
/datum/antagonist
///Public name for this antagonist. Appears for player prompts and round-end reports.
var/name = "Antagonist"
var/roundend_category = "other antagonists" //Section of roundend report, datums with same category will be displayed together, also default header for the section
var/show_in_roundend = TRUE //Set to false to hide the antagonists from roundend report
var/datum/mind/owner //Mind that owns this datum
var/silent = FALSE //Silent will prevent the gain/lose texts to show
var/can_coexist_with_others = TRUE //Whether or not the person will be able to have more than one datum
var/list/typecache_datum_blacklist = list() //List of datums this type can't coexist with
var/delete_on_mind_deletion = TRUE
///Section of roundend report, datums with same category will be displayed together, also default header for the section
var/roundend_category = "other antagonists"
///Set to false to hide the antagonists from roundend report
var/show_in_roundend = TRUE
///If false, the roundtype will still convert with this antag active
var/prevent_roundtype_conversion = TRUE
///Mind that owns this datum
var/datum/mind/owner
///Silent will prevent the gain/lose texts to show
var/silent = FALSE
///Whether or not the person will be able to have more than one datum
var/can_coexist_with_others = TRUE
///List of datums this type can't coexist with
var/list/typecache_datum_blacklist = list()
///The define string we use to identify the role for bans/player polls to spawn a random new one in.
var/job_rank
var/replace_banned = TRUE //Should replace jobbaned player with ghosts if granted.
///Should replace jobbanned player with ghosts if granted.
var/replace_banned = TRUE
///List of the objective datums that this role currently has, completing all objectives at round-end will cause this antagonist to greentext.
var/list/objectives = list()
var/antag_memory = ""//These will be removed with antag datum
var/antag_moodlet //typepath of moodlet that the mob will gain with their status
///String dialogue that is added to the player's in-round notes and memories regarding specifics of that antagonist, eg. the nuke code for nuke ops, or your unlock code for traitors.
var/antag_memory = ""
///typepath of moodlet that the mob will gain when granted this antagonist type.
var/antag_moodlet
///What is the configuration of this antagonist's hud icon, such as it's screen position and style, so thatit doesn't break other in-game hud icons.
var/antag_hud_type
///Name of the antag hud we provide to this mob.
var/antag_hud_name
/// If above 0, this is the multiplier for the speed at which we hijack the shuttle. Do not directly read, use hijack_speed().
var/hijack_speed = 0
/// If set to true, the antag will not be added to the living antag list.
var/soft_antag = FALSE
/// The battlecry this antagonist shouts when suiciding with C4/X4.
var/suicide_cry = ""
//Antag panel properties
var/show_in_antagpanel = TRUE //This will hide adding this antag type in antag panel, use only for internal subtypes that shouldn't be added directly but still show if possessed by mind
var/antagpanel_category = "Uncategorized" //Antagpanel will display these together, REQUIRED
var/show_name_in_check_antagonists = FALSE //Will append antagonist name in admin listings - use for categories that share more than one antag type
var/list/blacklisted_quirks = list(/datum/quirk/nonviolent,/datum/quirk/mute) // Quirks that will be removed upon gaining this antag. Pacifist and mute are default.
var/threat = 0 // Amount of threat this antag poses, for dynamic mode
var/show_to_ghosts = FALSE // Should this antagonist be shown as antag to ghosts? Shouldn't be used for stealthy antagonists like traitors
///This will hide adding this antag type in antag panel, use only for internal subtypes that shouldn't be added directly but still show if possessed by mind
var/show_in_antagpanel = TRUE
///Antagpanel will display these together, REQUIRED
var/antagpanel_category = "Uncategorized"
///Will append antagonist name in admin listings - use for categories that share more than one antag type
var/show_name_in_check_antagonists = FALSE
/// Should this antagonist be shown as antag to ghosts? Shouldn't be used for stealthy antagonists like traitors
var/show_to_ghosts = FALSE
/* CIT SPECIFIC */
/// Quirks that will be removed upon gaining this antag. Pacifist and mute are default.
var/list/blacklisted_quirks = list(/datum/quirk/nonviolent,/datum/quirk/mute)
/// Amount of threat this antag poses, for dynamic mode
var/threat = 0
var/delete_on_mind_deletion = TRUE
var/list/skill_modifiers
/* CIT SPECIFIC end */
//ANTAG UI
///name of the UI that will try to open, right now having nothing means this won't exist but in the future all should.
var/ui_name
///button to access antag interface
var/datum/action/antag_info/info_button
/datum/antagonist/New()
GLOB.antagonists += src
@@ -35,7 +72,9 @@ GLOBAL_LIST_EMPTY(antagonists)
/datum/antagonist/Destroy()
GLOB.antagonists -= src
if(owner)
if(!owner)
stack_trace("Destroy()ing antagonist datum when it has no owner.")
else
LAZYREMOVE(owner.antag_datums, src)
owner = null
return ..()
@@ -55,14 +94,14 @@ GLOBAL_LIST_EMPTY(antagonists)
/datum/antagonist/proc/specialization(datum/mind/new_owner)
return src
///Called by the transfer_to() mind proc after the mind (mind.current and new_character.mind) has moved but before the player (key and client) is transfered.
///Called by the transfer_to() mind proc after the mind (mind.current and new_character.mind) has moved but before the player (key and client) is transfered.
/datum/antagonist/proc/on_body_transfer(mob/living/old_body, mob/living/new_body)
SHOULD_CALL_PARENT(TRUE)
remove_innate_effects(old_body)
if(old_body.stat != DEAD && !LAZYLEN(old_body.mind?.antag_datums))
if(!soft_antag && old_body.stat != DEAD && !LAZYLEN(old_body.mind?.antag_datums))
old_body.remove_from_current_living_antags()
apply_innate_effects(new_body)
if(new_body.stat != DEAD)
if(!soft_antag && new_body.stat != DEAD)
new_body.add_to_current_living_antags()
//This handles the application of antag huds/special abilities
@@ -73,46 +112,76 @@ GLOBAL_LIST_EMPTY(antagonists)
/datum/antagonist/proc/remove_innate_effects(mob/living/mob_override)
return
/// This is called when the antagonist is being mindshielded.
/datum/antagonist/proc/pre_mindshield(mob/implanter, mob/living/mob_override)
SIGNAL_HANDLER
// return COMPONENT_MINDSHIELD_PASSED
/// This is called when the antagonist is successfully mindshielded.
/datum/antagonist/proc/on_mindshield(mob/implanter, mob/living/mob_override)
SIGNAL_HANDLER
return
// Adds the specified antag hud to the player. Usually called in an antag datum file
/datum/antagonist/proc/add_antag_hud(antag_hud_type, antag_hud_name, mob/living/mob_override)
var/datum/atom_hud/antag/hud = GLOB.huds[antag_hud_type]
hud.join_hud(mob_override)
set_antag_hud(mob_override, antag_hud_name)
// Removes the specified antag hud from the player. Usually called in an antag datum file
/datum/antagonist/proc/remove_antag_hud(antag_hud_type, mob/living/mob_override)
var/datum/atom_hud/antag/hud = GLOB.huds[antag_hud_type]
hud.leave_hud(mob_override)
set_antag_hud(mob_override, null)
// Handles adding and removing the clumsy mutation from clown antags. Gets called in apply/remove_innate_effects
/// Handles adding and removing the clumsy mutation from clown antags. Gets called in apply/remove_innate_effects
/datum/antagonist/proc/handle_clown_mutation(mob/living/mob_override, message, removing = TRUE)
var/mob/living/carbon/human/H = mob_override
if(H && istype(H) && owner.assigned_role == "Clown")
if(removing) // They're a clown becoming an antag, remove clumsy
H.dna.remove_mutation(CLOWNMUT)
if(!silent && message)
to_chat(H, "<span class='boldnotice'>[message]</span>")
else
H.dna.add_mutation(CLOWNMUT) // We're removing their antag status, add back clumsy
if(!ishuman(mob_override) || owner.assigned_role != "Clown")
return
var/mob/living/carbon/human/human_override = mob_override
if(removing) // They're a clown becoming an antag, remove clumsy
human_override.dna.remove_mutation(CLOWNMUT)
if(!silent && message)
to_chat(human_override, span_boldnotice("[message]"))
else
human_override.dna.add_mutation(CLOWNMUT) // We're removing their antag status, add back clumsy
//Assign default team and creates one for one of a kind team antagonists
/datum/antagonist/proc/create_team(datum/team/team)
return
///Called by the add_antag_datum() mind proc after the instanced datum is added to the mind's antag_datums list.
///Called by the add_antag_datum() mind proc after the instanced datum is added to the mind's antag_datums list.
/datum/antagonist/proc/on_gain()
SHOULD_CALL_PARENT(TRUE)
set waitfor = FALSE
if(!(owner?.current))
return
if(!owner)
CRASH("[src] ran on_gain() without a mind")
if(!owner.current)
CRASH("[src] ran on_gain() on a mind without a mob")
if(ui_name)//in the future, this should entirely replace greet.
info_button = new(owner.current, src)
info_button.Grant(owner.current)
if(!silent)
greet()
if(ui_name)
to_chat(owner.current, span_big("You are \a [src]."))
to_chat(owner.current, span_boldnotice("For more info, read the panel. you can always come back to it using the button in the top left."))
info_button.Trigger()
apply_innate_effects()
give_antag_moodies()
remove_blacklisted_quirks()
// RegisterSignal(owner, COMSIG_PRE_MINDSHIELD_IMPLANT, .proc/pre_mindshield)
// RegisterSignal(owner, COMSIG_MINDSHIELD_IMPLANTED, .proc/on_mindshield)
if(is_banned(owner.current) && replace_banned)
replace_banned_player()
// else if(owner.current.client?.holder && (CONFIG_GET(flag/auto_deadmin_antagonists) || owner.current.client.prefs?.toggles & DEADMIN_ANTAGONIST))
// owner.current.client.holder.auto_deadmin()
if(!soft_antag && owner.current.stat != DEAD)
owner.current.add_to_current_living_antags()
// cit skill
if(skill_modifiers)
for(var/A in skill_modifiers)
ADD_SINGLETON_SKILL_MODIFIER(owner, A, type)
@@ -120,61 +189,95 @@ GLOBAL_LIST_EMPTY(antagonists)
if(istype(M))
M.name = "[name] Training"
owner.current.AddComponent(/datum/component/activity)
if(owner.current.stat != DEAD)
owner.current.add_to_current_living_antags()
SEND_SIGNAL(owner.current, COMSIG_MOB_ANTAG_ON_GAIN, src)
/**
* Proc that checks the sent mob aganst the banlistfor this antagonist.
* Returns FALSE if no mob is sent, or the mob is not found to be banned.
*
* * mob/M: The mob that you are looking for on the banlist.
*/
/datum/antagonist/proc/is_banned(mob/M)
if(!M)
return FALSE
. = (jobban_isbanned(M, ROLE_SYNDICATE) || QDELETED(M) || (job_rank && (jobban_isbanned(M,job_rank) || QDELETED(M))))
/**
* Proc that replaces a player who cannot play a specific antagonist due to being banned via a poll, and alerts the player of their being on the banlist.
*/
/datum/antagonist/proc/replace_banned_player()
set waitfor = FALSE
var/list/mob/candidates = pollCandidatesForMob("Do you want to play as a [name]?", "[name]", null, job_rank, 50, owner.current)
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [name]?", "[name]", job_rank, 50, owner.current)
if(LAZYLEN(candidates))
var/mob/C = pick(candidates)
var/mob/dead/observer/C = pick(candidates)
to_chat(owner, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!")
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(owner.current)]) to replace a jobbaned player.")
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(owner)]) to replace a jobbanned player.")
owner.current.ghostize(0)
C.transfer_ckey(owner.current, FALSE)
///Called by the remove_antag_datum() and remove_all_antag_datums() mind procs for the antag datum to handle its own removal and deletion.
/**
* Called by the remove_antag_datum() and remove_all_antag_datums() mind procs for the antag datum to handle its own removal and deletion.
*/
/datum/antagonist/proc/on_removal()
SHOULD_CALL_PARENT(TRUE)
if(!owner)
CRASH("Antag datum with no owner.")
remove_innate_effects()
clear_antag_moodies()
if(owner)
LAZYREMOVE(owner.antag_datums, src)
for(var/A in skill_modifiers)
owner.remove_skill_modifier(GET_SKILL_MOD_ID(A, type))
if(!LAZYLEN(owner.antag_datums))
owner.current.remove_from_current_living_antags()
if(!silent && owner.current)
farewell()
LAZYREMOVE(owner.antag_datums, src)
// cit skill
for(var/A in skill_modifiers)
owner.remove_skill_modifier(GET_SKILL_MOD_ID(A, type))
// end
if(!LAZYLEN(owner.antag_datums) && !soft_antag)
owner.current.remove_from_current_living_antags()
if(info_button)
QDEL_NULL(info_button)
if(!silent && owner.current)
farewell()
// UnregisterSignal(owner, COMSIG_PRE_MINDSHIELD_IMPLANT)
// UnregisterSignal(owner, COMSIG_MINDSHIELD_IMPLANTED)
var/datum/team/team = get_team()
if(team)
team.remove_member(owner)
// we don't remove the activity component on purpose--no real point to it
qdel(src)
/**
* Proc that sends fluff or instructional messages to the player when they are given this antag datum.
* Use this proc for playing sounds, sending alerts, or helping to setup non-gameplay influencing aspects of the antagonist type.
*/
/datum/antagonist/proc/greet()
return
/**
* Proc that sends fluff or instructional messages to the player when they lose this antag datum.
* Use this proc for playing sounds, sending alerts, or otherwise informing the player that they're no longer a specific antagonist type.
*/
/datum/antagonist/proc/farewell()
return
/**
* Proc that assigns this antagonist's ascribed moodlet to the player.
*/
/datum/antagonist/proc/give_antag_moodies()
if(!antag_moodlet)
return
SEND_SIGNAL(owner.current, COMSIG_ADD_MOOD_EVENT, "antag_moodlet", antag_moodlet)
/**
* Proc that removes this antagonist's ascribed moodlet from the player.
*/
/datum/antagonist/proc/clear_antag_moodies()
if(!antag_moodlet)
return
SEND_SIGNAL(owner.current, COMSIG_CLEAR_MOOD_EVENT, "antag_moodlet")
/**
* Removes invalid quirks.
*/
/datum/antagonist/proc/remove_blacklisted_quirks()
var/mob/living/L = owner.current
if(istype(L))
@@ -185,16 +288,22 @@ GLOBAL_LIST_EMPTY(antagonists)
to_chat(L, "<span class='boldannounce'>[initial(Q.antag_removal_text)]</span>")
qdel(Q)
//Returns the team antagonist belongs to if any.
/**
* Proc that will return the team this antagonist belongs to, when called. Helpful with antagonists that may belong to multiple potential teams in a single round, like families.
*/
/datum/antagonist/proc/get_team()
return
//Individual roundend report
/**
* Proc that sends string information for the end-round report window to the server.
* This runs on every instance of every antagonist that exists at the end of the round.
* This is the body of the message, sandwiched between roundend_report_header and roundend_report_footer.
*/
/datum/antagonist/proc/roundend_report()
var/list/report = list()
if(!owner)
CRASH("antagonist datum without owner")
CRASH("Antagonist datum without owner")
report += printplayer(owner)
@@ -213,11 +322,19 @@ GLOBAL_LIST_EMPTY(antagonists)
return report.Join("<br>")
//Displayed at the start of roundend_category section, default to roundend_category header
/**
* Proc that sends string data for the round-end report.
* Displayed before roundend_report and roundend_report_footer.
* Appears at start of roundend_catagory section.
*/
/datum/antagonist/proc/roundend_report_header()
return "<span class='header'>The [roundend_category] were:</span><br>"
return "<span class='header'>The [roundend_category] were:</span><br>"
//Displayed at the end of roundend_category section
/**
* Proc that sends string data for the round-end report.
* Displayed after roundend_report and roundend_report_footer.
* Appears at the end of the roundend_catagory section.
*/
/datum/antagonist/proc/roundend_report_footer()
return
@@ -226,22 +343,24 @@ GLOBAL_LIST_EMPTY(antagonists)
//Called when using admin tools to give antag status
/datum/antagonist/proc/admin_add(datum/mind/new_owner,mob/admin)
message_admins("[key_name_admin(admin)] made [new_owner.current] into [name].")
log_admin("[key_name(admin)] made [new_owner.current] into [name].")
message_admins("[key_name_admin(admin)] made [key_name_admin(new_owner)] into [name].")
log_admin("[key_name(admin)] made [key_name(new_owner)] into [name].")
new_owner.add_antag_datum(src)
//Called when removing antagonist using admin tools
/datum/antagonist/proc/admin_remove(mob/user)
if(!user)
return
message_admins("[key_name_admin(user)] has removed [name] antagonist status from [owner.current].")
log_admin("[key_name(user)] has removed [name] antagonist status from [owner.current].")
message_admins("[key_name_admin(user)] has removed [name] antagonist status from [key_name_admin(owner)].")
log_admin("[key_name(user)] has removed [name] antagonist status from [key_name(owner)].")
on_removal()
//gamemode/proc/is_mode_antag(antagonist/A) => TRUE/FALSE
//Additional data to display in antagonist panel section
//nuke disk code, genome count, etc
/**
* Additional data to display in the antagonist panel section.
* For example, nuke disk code, genome count, etc
*/
/datum/antagonist/proc/antag_panel_data()
return ""
@@ -253,7 +372,7 @@ GLOBAL_LIST_EMPTY(antagonists)
return FALSE
return TRUE
// List if ["Command"] = CALLBACK(), user will be appeneded to callback arguments on execution
/// List of ["Command"] = CALLBACK(), user will be appeneded to callback arguments on execution
/datum/antagonist/proc/get_admin_commands()
. = list()
@@ -283,14 +402,19 @@ GLOBAL_LIST_EMPTY(antagonists)
return
antag_memory = new_memo
/// Gets how fast we can hijack the shuttle, return 0 for can not hijack. Defaults to hijack_speed var, override for custom stuff like buffing hijack speed for hijack objectives or something.
/**
* Gets how fast we can hijack the shuttle, return 0 for can not hijack.
* Defaults to hijack_speed var, override for custom stuff like buffing hijack speed for hijack objectives or something.
*/
/datum/antagonist/proc/hijack_speed()
var/datum/objective/hijack/H = locate() in objectives
if(!isnull(H?.hijack_speed_override))
return H.hijack_speed_override
return hijack_speed
/// Gets our threat level. Defaults to threat var, override for custom stuff like different traitor goals having different threats.
/**
* Gets our threat level. Override this proc for custom functionality/dynamic threat level.
*/
/datum/antagonist/proc/threat()
. = CONFIG_GET(keyed_list/antag_threat)[lowertext(name)]
if(. == null)
@@ -300,6 +424,13 @@ GLOBAL_LIST_EMPTY(antagonists)
/datum/antagonist/custom
antagpanel_category = "Custom"
show_name_in_check_antagonists = TRUE //They're all different
var/datum/team/custom_team
/datum/antagonist/custom/create_team(datum/team/team)
custom_team = team
/datum/antagonist/custom/get_team()
return custom_team
/datum/antagonist/custom/admin_add(datum/mind/new_owner,mob/admin)
var/custom_name = stripped_input(admin, "Custom antagonist name:", "Custom antag", "Antagonist")
@@ -308,3 +439,48 @@ GLOBAL_LIST_EMPTY(antagonists)
else
return
..()
///ANTAGONIST UI STUFF
/datum/antagonist/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_name, name)
ui.open()
/datum/antagonist/ui_state(mob/user)
return GLOB.always_state
///generic helper to send objectives as data through tgui. supports smart objectives too!
/datum/antagonist/proc/get_objectives()
var/objective_count = 1
var/list/objective_data = list()
//all obj
for(var/datum/objective/objective in objectives)
objective_data += list(list(
"count" = objective_count,
"name" = objective.name,
"explanation" = objective.explanation_text,
"complete" = objective.completed,
))
objective_count++
return objective_data
//button for antags to review their descriptions/info
/datum/action/antag_info
name = "Open Antag Information:"
button_icon_state = "round_end"
var/datum/antagonist/antag_datum
/datum/action/antag_info/New(Target, datum/antagonist/antag_datum)
. = ..()
src.antag_datum = antag_datum
name += " [antag_datum.name]"
/datum/action/antag_info/Trigger()
if(antag_datum)
antag_datum.ui_interact(owner)
/datum/action/antag_info/IsAvailable()
return TRUE

View File

@@ -17,11 +17,13 @@
B.objectives += objective
M.add_antag_datum(B)
var/begin_message = "<span class='deadsay'><b>[L]</b> has been brainwashed with the following objectives: "
var/begin_message = " has been brainwashed with the following objectives: "
var/obj_message = english_list(directives)
var/end_message = "</b>.</span>"
var/end_message = "."
var/rendered = begin_message + obj_message + end_message
deadchat_broadcast(rendered, follow_target = L, turf_target = get_turf(L), message_type=DEADCHAT_REGULAR)
deadchat_broadcast(rendered, "<b>[L]</b>", follow_target = L, turf_target = get_turf(L), message_type=DEADCHAT_ANNOUNCEMENT)
if(prob(1) || SSevents.holidays && SSevents.holidays[APRIL_FOOLS])
L.say("You son of a bitch! I'm in.", forced = "That son of a bitch! They're in.")
/datum/antagonist/brainwashed
name = "Brainwashed Victim"
@@ -30,19 +32,21 @@
show_in_antagpanel = TRUE
antagpanel_category = "Other"
show_name_in_check_antagonists = TRUE
ui_name = "AntagInfoBrainwashed"
suicide_cry = "FOR... SOMEONE!!"
/datum/antagonist/brainwashed/greet()
to_chat(owner, "<span class='warning'>Your mind reels as it begins focusing on a single purpose...</span>")
to_chat(owner, "<big><span class='warning'><b>Follow the Directives, at any cost!</b></span></big>")
var/i = 1
for(var/X in objectives)
var/datum/objective/O = X
to_chat(owner, "<b>[i].</b> [O.explanation_text]")
i++
/datum/antagonist/brainwashed/ui_static_data(mob/user)
. = ..()
var/list/data = list()
data["objectives"] = get_objectives()
return data
/datum/antagonist/brainwashed/farewell()
to_chat(owner, "<span class='warning'>Your mind suddenly clears...</span>")
to_chat(owner, "<big><span class='warning'><b>You feel the weight of the Directives disappear! You no longer have to obey them.</b></span></big>")
to_chat(owner, span_warning("Your mind suddenly clears..."))
to_chat(owner, "<big>[span_warning("<b>You feel the weight of the Directives disappear! You no longer have to obey them.</b>")]</big>")
if(owner.current)
var/mob/living/owner_mob = owner.current
owner_mob.log_message("is no longer brainwashed with the objectives: [english_list(objectives)].", LOG_ATTACK)
owner.announce_objectives()
/datum/antagonist/brainwashed/admin_add(datum/mind/new_owner,mob/admin)
@@ -54,9 +58,9 @@
var/objective = stripped_input(admin, "Add an objective, or leave empty to finish.", "Brainwashing", null, MAX_MESSAGE_LEN)
if(objective)
objectives += objective
while(tgui_alert(admin, "Add another objective?","More Brainwashing",list("Yes","No")) == "Yes")
while(tgui_alert(admin,"Add another objective?","More Brainwashing",list("Yes","No")) == "Yes")
if(tgui_alert(admin, "Confirm Brainwashing?","Are you sure?",list("Yes","No")) == "No")
if(tgui_alert(admin,"Confirm Brainwashing?","Are you sure?",list("Yes","No")) == "No")
return
if(!LAZYLEN(objectives))
@@ -69,6 +73,7 @@
brainwash(C, objectives)
var/obj_list = english_list(objectives)
message_admins("[key_name_admin(admin)] has brainwashed [key_name_admin(C)] with the following objectives: [obj_list].")
C.log_message("has been force-brainwashed with the objective '[obj_list]' by admin [key_name(admin)]", LOG_ATTACK, log_globally = FALSE)
log_admin("[key_name(admin)] has brainwashed [key_name(C)] with the following objectives: [obj_list].")
/datum/objective/brainwashing

View File

@@ -6,6 +6,7 @@
job_rank = ROLE_SERVANT_OF_RATVAR
antag_moodlet = /datum/mood_event/cult
skill_modifiers = list(/datum/skill_modifier/job/level/wiring, /datum/skill_modifier/job/level/dwarfy/blacksmithing)
ui_name = "AntagInfoClockwork"
var/datum/action/innate/hierophant/hierophant_network = new
threat = 3
var/datum/team/clockcult/clock_team
@@ -14,6 +15,12 @@
var/ignore_eligibility_check = FALSE
var/ignore_holy_water = FALSE
/datum/antagonist/brainwashed/ui_static_data(mob/user)
. = ..()
var/list/data = list()
data["objectives"] = get_objectives()
return data
/datum/antagonist/clockcult/silent
name = "Silent Clock Cultist"
silent = TRUE
@@ -22,6 +29,8 @@
/datum/antagonist/clockcult/neutered
name = "Neutered Clock Cultist"
neutered = TRUE
soft_antag = TRUE
ui_name = null // no.
/datum/antagonist/clockcult/neutered/traitor
name = "Traitor Clock Cultist"

View File

@@ -3,5 +3,6 @@
show_name_in_check_antagonists = TRUE
show_in_antagpanel = FALSE
threat = 2
ui_name = "AntagInfoMorph"
//It does nothing! (Besides tracking)

View File

@@ -4,3 +4,5 @@
show_name_in_check_antagonists = TRUE
threat = 5
show_to_ghosts = TRUE
ui_name = "AntagInfoNightmare"
suicide_cry = "FOR THE DARKNESS!!"

View File

@@ -236,6 +236,8 @@
var/obj/machinery/nuclearbomb/tracked_nuke
var/core_objective = /datum/objective/nuclear
var/memorized_code
var/list/team_discounts
var/datum/weakref/war_button_ref
/datum/team/nuclear/New()
..()

View File

@@ -121,7 +121,7 @@
return
var/mob/living/carbon/human/H = owner.current
// Give uplink
var/obj/item/uplink_holder = owner.equip_traitor(uplink_owner = src)
var/obj/item/uplink_holder = owner.equip_traitor()
var/datum/component/uplink/uplink = uplink_holder.GetComponent(/datum/component/uplink)
uplink.telecrystals = INITIAL_CRYSTALS
// Give AI hacking board

View File

@@ -7,37 +7,51 @@
/datum/antagonist/traitor/internal_affairs
name = "Internal Affairs Agent"
employer = "Nanotrasen"
special_role = "internal affairs agent"
suicide_cry = "FOR THE COMPANY!!"
antagpanel_category = "IAA"
var/special_role = "internal affairs agent"
var/syndicate = FALSE
var/last_man_standing = FALSE
var/list/datum/mind/targets_stolen
/datum/antagonist/traitor/internal_affairs/New()
. = ..()
LAZYADD(targets_stolen, src)
/datum/antagonist/traitor/internal_affairs/proc/give_pinpointer()
if(owner && owner.current)
if(!owner)
CRASH("Antag datum with no owner.")
if(owner.current)
owner.current.apply_status_effect(/datum/status_effect/agent_pinpointer)
/datum/antagonist/traitor/internal_affairs/apply_innate_effects()
.=..() //in case the base is used in future
if(owner && owner.current)
. = ..()
if(!owner)
CRASH("Antag datum with no owner.")
if(owner.current)
give_pinpointer(owner.current)
/datum/antagonist/traitor/internal_affairs/remove_innate_effects()
.=..()
if(owner && owner.current)
. = ..()
if(!owner)
CRASH("Antag datum with no owner.")
if(owner.current)
owner.current.remove_status_effect(/datum/status_effect/agent_pinpointer)
/datum/antagonist/traitor/internal_affairs/on_gain()
START_PROCESSING(SSprocessing, src)
.=..()
. = ..()
/datum/antagonist/traitor/internal_affairs/on_removal()
STOP_PROCESSING(SSprocessing,src)
.=..()
. = ..()
/datum/antagonist/traitor/internal_affairs/process()
iaa_process()
/datum/status_effect/agent_pinpointer
id = "agent_pinpointer"
duration = -1
@@ -46,6 +60,8 @@
var/minimum_range = PINPOINTER_MINIMUM_RANGE
var/range_fuzz_factor = PINPOINTER_EXTRA_RANDOM_RANGE
var/mob/scan_target = null
var/range_mid = 8
var/range_far = 16
/atom/movable/screen/alert/status_effect/agent_pinpointer
name = "Internal Affairs Integrated Pinpointer"
@@ -66,13 +82,13 @@
linked_alert.icon_state = "pinondirect"
else
linked_alert.setDir(get_dir(here, there))
switch(get_dist(here, there))
if(1 to 8)
linked_alert.icon_state = "pinonclose"
if(9 to 16)
linked_alert.icon_state = "pinonmedium"
if(16 to INFINITY)
linked_alert.icon_state = "pinonfar"
var/dist = (get_dist(here, there))
if(dist >= 1 && dist <= range_mid)
linked_alert.icon_state = "pinonclose"
else if(dist > range_mid && dist <= range_far)
linked_alert.icon_state = "pinonmedium"
else if(dist > range_far)
linked_alert.icon_state = "pinonfar"
/datum/status_effect/agent_pinpointer/proc/scan_for_target()
scan_target = null
@@ -99,37 +115,42 @@
return (istype(O, /datum/objective/assassinate/internal)||istype(O, /datum/objective/destroy/internal))
/datum/antagonist/traitor/proc/replace_escape_objective()
if(!owner || !objectives.len)
if(!owner)
CRASH("Antag datum with no owner.")
if(!objectives.len)
return
for (var/objective_ in objectives)
if(!(istype(objective_, /datum/objective/escape)||istype(objective_, /datum/objective/survive)))
for (var/objective in objectives)
if(!(istype(objective, /datum/objective/escape) || istype(objective, /datum/objective/survive)))
continue
remove_objective(objective_)
objectives -= objective
var/datum/objective/martyr/martyr_objective = new
martyr_objective.owner = owner
add_objective(martyr_objective)
/datum/antagonist/traitor/proc/reinstate_escape_objective()
if(!owner||!objectives.len)
if(!owner)
CRASH("Antag datum with no owner.")
if(!objectives.len)
return
for (var/objective_ in objectives)
if(!istype(objective_, /datum/objective/martyr))
for (var/objective in objectives)
if(!istype(objective, /datum/objective/martyr))
continue
remove_objective(objective_)
remove_objective(objective)
/datum/antagonist/traitor/internal_affairs/reinstate_escape_objective()
..()
var/objtype = !istype(traitor_kind,TRAITOR_AI) ? /datum/objective/escape : /datum/objective/survive
var/datum/objective/escape_objective = new objtype
for (var/datum/objective/martyr/martyr_objective in objectives)
objectives -= martyr_objective
var/datum/objective/escape_objective = new /datum/objective/escape()
escape_objective.owner = owner
add_objective(escape_objective)
objectives += escape_objective
/datum/antagonist/traitor/internal_affairs/proc/steal_targets(datum/mind/victim)
if(!owner.current||owner.current.stat==DEAD)
return
to_chat(owner.current, "<span class='userdanger'> Target eliminated: [victim.name]</span>")
LAZYINITLIST(targets_stolen)
to_chat(owner.current, span_userdanger("Target eliminated: [victim.name]"))
for(var/objective_ in victim.get_all_objectives())
if(istype(objective_, /datum/objective/assassinate/internal))
var/datum/objective/assassinate/internal/objective = objective_
@@ -143,7 +164,7 @@
add_objective(new_objective)
targets_stolen += objective.target
var/status_text = objective.check_completion() ? "neutralised" : "active"
to_chat(owner.current, "<span class='userdanger'> New target added to database: [objective.target.name] ([status_text]) </span>")
to_chat(owner.current, span_userdanger("New target added to database: [objective.target.name] ([status_text])"))
else if(istype(objective_, /datum/objective/destroy/internal))
var/datum/objective/destroy/internal/objective = objective_
var/datum/objective/destroy/internal/new_objective = new
@@ -156,7 +177,7 @@
add_objective(new_objective)
targets_stolen += objective.target
var/status_text = objective.check_completion() ? "neutralised" : "active"
to_chat(owner.current, "<span class='userdanger'> New target added to database: [objective.target.name] ([status_text]) </span>")
to_chat(owner.current, span_userdanger("New target added to database: [objective.target.name] ([status_text])"))
last_man_standing = TRUE
for(var/objective_ in objectives)
if(!is_internal_objective(objective_))
@@ -167,13 +188,15 @@
return
if(last_man_standing)
if(syndicate)
to_chat(owner.current,"<span class='userdanger'>All the suspected agents are dead, and no more is required of you. Die a glorious death, agent.</span>")
replace_escape_objective(owner)
to_chat(owner.current,span_userdanger("All the suspected agents are dead, and no more is required of you. Die a glorious death, agent."))
else
to_chat(owner.current,"<span class='userdanger'>All the other agents are dead. You have done us all a great service and shall be honorably exiled upon returning to base.</span>")
to_chat(owner.current,span_userdanger("All the other agents are dead. You have done us all a great service and shall be honorably exiled upon returning to base."))
replace_escape_objective(owner)
/datum/antagonist/traitor/internal_affairs/proc/iaa_process()
if(owner&&owner.current&&owner.current.stat!=DEAD)
if(!owner)
CRASH("Antag datum with no owner.")
if(owner.current && owner.current.stat != DEAD)
for(var/objective_ in objectives)
if(!is_internal_objective(objective_))
continue
@@ -188,12 +211,12 @@
objective.stolen = TRUE
else
if(objective.stolen)
var/fail_msg = "<span class='userdanger'>Your sensors tell you that [objective.target.current.real_name], one of the targets you were meant to have killed, pulled one over on you, and is still alive - do the job properly this time! </span>"
var/fail_msg = span_userdanger("Your sensors tell you that [objective.target.current.real_name], one of the targets you were meant to have killed, pulled one over on you, and is still alive - do the job properly this time! ")
if(last_man_standing)
if(syndicate)
fail_msg += "<span class='userdanger'> You no longer have permission to die. </span>"
fail_msg += span_userdanger(" You no longer have permission to die. ")
else
fail_msg += "<span class='userdanger'> The truth could still slip out!</font><B><font size=5 color=red> Cease any terrorist actions as soon as possible, unneeded property damage or loss of employee life will lead to great shame.</span>"
fail_msg += span_userdanger(" The truth could still slip out!</font><B><font size=5 color=red> Cease any terrorist actions as soon as possible, unneeded property damage or loss of employee life will lead to your contract being terminated.")
reinstate_escape_objective(owner)
last_man_standing = FALSE
to_chat(owner.current, fail_msg)
@@ -220,29 +243,24 @@
/datum/antagonist/traitor/internal_affairs/forge_traitor_objectives()
forge_iaa_objectives()
var/objtype = !istype(traitor_kind,TRAITOR_AI) ? /datum/objective/escape : /datum/objective/survive
var/datum/objective/escape_objective = new objtype
var/datum/objective/escape_objective = new /datum/objective/escape()
escape_objective.owner = owner
add_objective(escape_objective)
/datum/antagonist/traitor/internal_affairs/proc/greet_iaa()
var/crime = pick("distribution of contraband" , "embezzlement", "piloting under the influence", "dereliction of duty", "syndicate collaboration", "mutiny", "multiple homicides", "corporate espionage", "receiving bribes", "malpractice", "worship of prohibited life forms", "possession of profane texts", "murder", "arson", "insulting their manager", "grand theft", "conspiracy", "attempting to unionize", "vandalism", "gross incompetence")
var/crime = pick("distribution of contraband", "embezzlement", "piloting under the influence", "dereliction of duty", "syndicate collaboration", "mutiny", "multiple homicides", "corporate espionage", "receiving bribes", "malpractice", "worship of prohibited life forms", "possession of profane texts", "murder", "arson", "insulting their manager", "grand theft", "conspiracy", "attempting to unionize", "vandalism", "gross incompetence")
to_chat(owner.current, "<span class='userdanger'>You are the [special_role].</span>")
to_chat(owner.current, span_userdanger("You are the [special_role]."))
if(syndicate)
to_chat(owner.current, "<span class='userdanger'>GREAT LEADER IS DEAD. NANOTRASEN MUST FALL.</span>")
to_chat(owner.current, "<span class='userdanger'>Your have infiltrated this vessel to cause chaos and assassinate targets known to have conspired against the Syndicate.</span>")
to_chat(owner.current, "<span class='userdanger'>Any damage you cause will be a further embarrassment to Nanotrasen, so you have no limits on collateral damage.</span>")
to_chat(owner.current, "<span class='userdanger'>You have been provided with a standard uplink to accomplish your task. </span>")
to_chat(owner.current, "<span class='userdanger'>By no means reveal that you are a Syndicate agent. By no means reveal that your targets are being hunted.</span>")
to_chat(owner.current, span_userdanger("Your target has been framed for [crime], and you have been tasked with eliminating them to prevent them defending themselves in court."))
to_chat(owner.current, "<span class='warningplain'><B><font size=5 color=red>Any damage you cause will be a further embarrassment to Nanotrasen, so you have no limits on collateral damage.</font></B></span>")
to_chat(owner.current, span_userdanger("You have been provided with a standard uplink to accomplish your task."))
else
to_chat(owner.current, "<span class='userdanger'>CAUTION: Your legal status as a citizen of NanoTrasen will be permanently revoked upon completion of your first contract.</span>")
to_chat(owner.current, "<span class='userdanger'>Your target has been suspected of [crime], and must be removed from this plane.</span>")
to_chat(owner.current, "<span class='userdanger'>While you have a license to kill, you are to eliminate your targets with no collateral or unrelated deaths.</span>")
to_chat(owner.current, "<span class='userdanger'>For the sake of plausable deniability, you have been equipped with captured Syndicate equipment via uplink.</span>")
to_chat(owner.current, "<span class='userdanger'>By no means reveal that you, or any other NT employees, are undercover agents.</span>")
to_chat(owner.current, span_userdanger("Your target is suspected of [crime], and you have been tasked with eliminating them by any means necessary to avoid a costly and embarrassing public trial."))
to_chat(owner.current, "<span class='warningplain'><B><font size=5 color=red>While you have a license to kill, unneeded property damage or loss of employee life will lead to your contract being terminated.</font></B></span>")
to_chat(owner.current, span_userdanger("For the sake of plausible deniability, you have been equipped with an array of captured Syndicate weaponry available via uplink."))
to_chat(owner.current, "<span class='userdanger'>Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.</span>")
to_chat(owner.current, span_userdanger("Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them."))
owner.announce_objectives()
/datum/antagonist/traitor/internal_affairs/greet()

View File

@@ -5,7 +5,7 @@
chaos = 5
threat = 5
min_players = 20
uplink_filters = list(/datum/uplink_item/stealthy_weapons/romerol_kit,/datum/uplink_item/bundles_TC/contract_kit)
uplink_filters = list(/datum/uplink_item/stealthy_weapons/romerol_kit,/datum/uplink_item/bundles_tc/contract_kit)
/datum/traitor_class/human/martyr/forge_objectives(datum/antagonist/traitor/T)
var/datum/objective/martyr/O = new

View File

@@ -11,6 +11,8 @@ GLOBAL_LIST_EMPTY(traitor_classes)
/// Minimum players for this to randomly roll via get_random_traitor_kind().
var/min_players = 0
var/list/uplink_filters
/// Specific tgui theme for the player's antag info panel.
var/tgui_theme = "syndicate"
/datum/traitor_class/New()
..()

View File

@@ -5,14 +5,22 @@
job_rank = ROLE_TRAITOR
antag_moodlet = /datum/mood_event/focused
skill_modifiers = list(/datum/skill_modifier/job/level/wiring/basic)
var/special_role = ROLE_TRAITOR
hijack_speed = 0.5 //10 seconds per hijack stage by default
ui_name = "AntagInfoTraitor"
suicide_cry = "FOR THE SYNDICATE!!"
var/employer = "The Syndicate"
var/give_objectives = TRUE
var/should_give_codewords = TRUE
var/should_equip = TRUE
///special datum about what kind of employer the trator has
var/datum/traitor_class/traitor_kind
///reference to the uplink this traitor was given, if they were.
var/datum/component/uplink/uplink
var/datum/contractor_hub/contractor_hub
hijack_speed = 0.5 //10 seconds per hijack stage by default
threat = 5
/datum/antagonist/traitor/New()
@@ -45,7 +53,7 @@
/datum/antagonist/traitor/process()
traitor_kind.on_process(src)
/proc/get_random_traitor_kind(var/list/blacklist = list())
/proc/get_random_traitor_kind(list/blacklist = list())
var/list/weights = list()
for(var/C in GLOB.traitor_classes)
if(!(C in blacklist))
@@ -62,23 +70,24 @@
return choice
/datum/antagonist/traitor/on_gain()
owner.special_role = job_rank
if(owner.current && isAI(owner.current))
set_traitor_kind(TRAITOR_AI)
else
set_traitor_kind(get_random_traitor_kind())
SSticker.mode.traitors += owner
owner.special_role = special_role
finalize_traitor()
..()
uplink = owner.find_syndicate_uplink()
return ..()
/datum/antagonist/traitor/on_removal()
if(!silent && owner.current)
to_chat(owner.current,span_userdanger("You are no longer the [job_rank]!"))
//Remove malf powers.
traitor_kind.on_removal(src)
SSticker.mode.traitors -= owner
if(!silent && owner.current)
to_chat(owner.current,"<span class='userdanger'> You are no longer the [special_role]! </span>")
owner.special_role = null
. = ..()
return ..()
/datum/antagonist/traitor/proc/handle_hearing(datum/source, list/hearing_args)
var/message = hearing_args[HEARING_RAW_MESSAGE]
@@ -93,6 +102,7 @@
/datum/antagonist/traitor/proc/remove_objective(datum/objective/O)
objectives -= O
/// Generates a complete set of traitor objectives up to the traitor objective limit, including non-generic objectives such as martyr and hijack.
/datum/antagonist/traitor/proc/forge_traitor_objectives()
traitor_kind.forge_objectives(src)
@@ -151,21 +161,42 @@
H.dna.add_mutation(CLOWNMUT)
UnregisterSignal(M, COMSIG_MOVABLE_HEAR)
/datum/antagonist/traitor/ui_static_data(mob/user)
var/list/data = list()
data["phrases"] = jointext(GLOB.syndicate_code_phrase, ", ")
data["responses"] = jointext(GLOB.syndicate_code_response, ", ")
data["theme"] = traitor_kind.tgui_theme //traitor_flavor["ui_theme"]
data["code"] = uplink.unlock_code
data["intro"] = "You are from [traitor_kind.employer]." //traitor_flavor["introduction"]
data["allies"] = "Most other syndicate operatives are not to be trusted (but try not to rat them out), as they might have been assigned opposing objectives." //traitor_flavor["allies"]
data["goal"] = "We do not approve of mindless killing of innocent workers; \"get in, get done, get out\" is our motto." //traitor_flavor["goal"]
data["has_uplink"] = uplink ? TRUE : FALSE
if(uplink)
data["uplink_intro"] = "You have been provided with a standard uplink to accomplish your task." //traitor_flavor["uplink"]
data["uplink_unlock_info"] = uplink.unlock_text
data["objectives"] = get_objectives()
return data
/// Outputs this shift's codewords and responses to the antag's chat and copies them to their memory.
/datum/antagonist/traitor/proc/give_codewords()
if(!owner.current)
return
var/mob/traitor_mob=owner.current
var/mob/traitor_mob = owner.current
var/phrases = jointext(GLOB.syndicate_code_phrase, ", ")
var/responses = jointext(GLOB.syndicate_code_response, ", ")
var/dat = "<U><B>The Syndicate have provided you with the following codewords to identify fellow agents:</B></U>\n"
dat += "<B>Code Phrase</B>: <span class='blue'>[phrases]</span>\n"
dat += "<B>Code Response</B>: <span class='red'>[responses]</span>"
to_chat(traitor_mob, dat)
to_chat(traitor_mob, "<U><B>The Syndicate have provided you with the following codewords to identify fellow agents:</B></U>")
to_chat(traitor_mob, "<B>Code Phrase</B>: [span_blue("[phrases]")]")
to_chat(traitor_mob, "<B>Code Response</B>: [span_red("[responses]")]")
antag_memory += "<b>Code Phrase</b>: <span class='blue'>[phrases]</span><br>"
antag_memory += "<b>Code Response</b>: <span class='red'>[responses]</span><br>"
antag_memory += "<b>Code Phrase</b>: [span_blue("[phrases]")]<br>"
antag_memory += "<b>Code Response</b>: [span_red("[responses]")]<br>"
to_chat(traitor_mob, "Use the codewords during regular conversation to identify other agents. Proceed with caution, however, as everyone is a potential foe.")
to_chat(traitor_mob, span_alertwarning("You memorize the codewords, allowing you to recognise them when heard."))
/datum/antagonist/traitor/proc/add_law_zero()
var/mob/living/silicon/ai/killer = owner.current
@@ -220,44 +251,43 @@
where = "In your [equipped_slot]"
to_chat(mob, "<BR><BR><span class='info'>[where] is a folder containing <b>secret documents</b> that another Syndicate group wants. We have set up a meeting with one of their agents on station to make an exchange. Exercise extreme caution as they cannot be trusted and may be hostile.</span><BR>")
//TODO Collate
/datum/antagonist/traitor/roundend_report()
var/list/result = list()
var/traitorwin = TRUE
var/traitor_won = TRUE
result += printplayer(owner)
var/TC_uses = 0
var/uplink_true = FALSE
var/used_telecrystals = 0
var/uplink_owned = FALSE
var/purchases = ""
LAZYINITLIST(GLOB.uplink_purchase_logs_by_key)
var/datum/uplink_purchase_log/H = GLOB.uplink_purchase_logs_by_key[owner.key]
if(H)
TC_uses = H.total_spent
uplink_true = TRUE
purchases += H.generate_render(FALSE)
// Uplinks add an entry to uplink_purchase_logs_by_key on init.
var/datum/uplink_purchase_log/purchase_log = GLOB.uplink_purchase_logs_by_key[owner.key]
if(purchase_log)
used_telecrystals = purchase_log.total_spent
uplink_owned = TRUE
purchases += purchase_log.generate_render(FALSE)
var/objectives_text = ""
if(objectives.len)//If the traitor had no objectives, don't need to process this.
if(objectives.len) //If the traitor had no objectives, don't need to process this.
var/count = 1
for(var/datum/objective/objective in objectives)
if(objective.completable)
var/completion = objective.check_completion()
if(completion >= 1)
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</B></span>"
else if(completion <= 0)
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
traitorwin = FALSE
else
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='yellowtext'>[completion*100]%</span>"
var/completion = objective.check_completion()
if(completion >= 1)
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] [span_greentext("Success!")]"
else if(completion <= 0)
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] [span_redtext("Fail.")]"
traitor_won = FALSE
else
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text]"
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='yellowtext'>[completion*100]%</span>"
count++
if(uplink_true)
var/uplink_text = "(used [TC_uses] TC) [purchases]"
if(TC_uses==0 && traitorwin)
if(uplink_owned)
var/uplink_text = "(used [used_telecrystals] TC) [purchases]"
if((used_telecrystals == 0) && traitor_won)
var/static/icon/badass = icon('icons/badass.dmi', "badass")
uplink_text += "<BIG>[icon2html(badass, world)]</BIG>"
result += uplink_text
@@ -266,55 +296,59 @@
var/special_role_text = lowertext(name)
if(contractor_hub)
if (contractor_hub)
result += contractor_round_end()
if(traitorwin)
result += "<span class='greentext'>The [special_role_text] was successful!</span>"
if(traitor_won)
result += span_greentext("The [special_role_text] was successful!")
else
result += "<span class='redtext'>The [special_role_text] has failed!</span>"
result += span_redtext("The [special_role_text] has failed!")
SEND_SOUND(owner.current, 'sound/ambience/ambifailure.ogg')
return result.Join("<br>")
/// Proc detailing contract kit buys/completed contracts/additional info
/datum/antagonist/traitor/proc/contractor_round_end()
var result = ""
var total_spent_rep = 0
var/result = ""
var/total_spent_rep = 0
var/completed_contracts = 0
var/completed_contracts = contractor_hub.contracts_completed
var/tc_total = contractor_hub.contract_TC_payed_out + contractor_hub.contract_TC_to_redeem
for(var/datum/syndicate_contract/contract in contractor_hub.assigned_contracts)
if(contract.status == CONTRACT_STATUS_COMPLETE)
completed_contracts++
var/contractor_item_icons = "" // Icons of purchases
var/contractor_support_unit = "" // Set if they had a support unit - and shows appended to their contracts completed
for(var/datum/contractor_item/contractor_purchase in contractor_hub.purchased_items) // Get all the icons/total cost for all our items bought
/// Get all the icons/total cost for all our items bought
for (var/datum/contractor_item/contractor_purchase in contractor_hub.purchased_items)
contractor_item_icons += "<span class='tooltip_container'>\[ <i class=\"fas [contractor_purchase.item_icon]\"></i><span class='tooltip_hover'><b>[contractor_purchase.name] - [contractor_purchase.cost] Rep</b><br><br>[contractor_purchase.desc]</span> \]</span>"
total_spent_rep += contractor_purchase.cost
if(istype(contractor_purchase, /datum/contractor_item/contractor_partner)) // Special case for reinforcements, we want to show their ckey and name on round end.
/// Special case for reinforcements, we want to show their ckey and name on round end.
if (istype(contractor_purchase, /datum/contractor_item/contractor_partner))
var/datum/contractor_item/contractor_partner/partner = contractor_purchase
contractor_support_unit += "<br><b>[partner.partner_mind.key]</b> played <b>[partner.partner_mind.current.name]</b>, their contractor support unit."
if (contractor_hub.purchased_items.len)
result += "<br>(used [total_spent_rep] Rep)"
result += "<br>(used [total_spent_rep] Rep) "
result += contractor_item_icons
result += "<br>"
if(completed_contracts > 0)
if (completed_contracts > 0)
var/pluralCheck = "contract"
if(completed_contracts > 1)
if (completed_contracts > 1)
pluralCheck = "contracts"
result += "Completed <span class='greentext'>[completed_contracts]</span> [pluralCheck] for a total of \
<span class='greentext'>[tc_total] TC</span>!<br>"
result += "Completed [span_greentext("[completed_contracts]")] [pluralCheck] for a total of \
[span_greentext("[tc_total] TC")]![contractor_support_unit]<br>"
return result
/datum/antagonist/traitor/roundend_report_footer()
var/phrases = jointext(GLOB.syndicate_code_phrase, ", ")
var/responses = jointext(GLOB.syndicate_code_response, ", ")
var message = "<br><b>The code phrases were:</b> <span class='bluetext'>[phrases]</span><br>\
<b>The code responses were:</b> <span class='redtext'>[responses]</span><br>"
var/message = "<br><b>The code phrases were:</b> <span class='bluetext'>[phrases]</span><br>\
<b>The code responses were:</b> [span_redtext("[responses]")]<br>"
return message

View File

@@ -3,12 +3,15 @@
roundend_category = "wizards/witches"
antagpanel_category = "Wizard"
job_rank = ROLE_WIZARD
antag_hud_type = ANTAG_HUD_WIZ
antag_hud_name = "wizard"
antag_moodlet = /datum/mood_event/focused
threat = 30
hijack_speed = 0.5
ui_name = "AntagInfoWizard"
suicide_cry = "FOR THE FEDERATION!!"
var/give_objectives = TRUE
var/strip = TRUE //strip before equipping
var/allow_rename = TRUE
var/hud_version = "wizard"
var/datum/team/wizard/wiz_team //Only created if wizard summons apprentices
var/move_to_lair = TRUE
var/outfit_type = /datum/outfit/wizard
@@ -50,16 +53,17 @@
wiz_team = new(owner)
wiz_team.name = "[owner.current.real_name] team"
wiz_team.master_wizard = src
update_wiz_icons_added(owner.current)
add_antag_hud(antag_hud_type, antag_hud_name, owner.current)
/datum/antagonist/wizard/proc/send_to_lair()
if(!owner || !owner.current)
if(!owner)
CRASH("Antag datum with no owner.")
if(!owner.current)
return
if(!GLOB.wizardstart.len)
SSjob.SendToLateJoin(owner.current)
to_chat(owner, "HOT INSERTION, GO GO GO")
else
owner.current.forceMove(pick(GLOB.wizardstart))
owner.current.forceMove(pick(GLOB.wizardstart))
/datum/antagonist/wizard/proc/create_objectives()
var/datum/objective/flavor/wizard/new_objective = new
@@ -79,7 +83,7 @@
/datum/antagonist/wizard/proc/equip_wizard()
if(!owner)
return
CRASH("Antag datum with no owner.")
var/mob/living/carbon/human/H = owner.current
if(!istype(H))
return
@@ -91,18 +95,14 @@
H.age = wiz_age
H.equipOutfit(outfit_type)
/datum/antagonist/wizard/greet()
to_chat(owner, "<span class='boldannounce'>You are the Space Wizard!</span>")
to_chat(owner, "<B>The Space Wizards Federation has given you the following tasks:</B>")
owner.announce_objectives()
to_chat(owner, "<B>These are merely guidelines! The federation are your masters, but you forge your own path!</B>")
to_chat(owner, "You will find a list of available spells in your spell book. Choose your magic arsenal carefully.")
to_chat(owner, "The spellbook is bound to you, and others cannot use it.")
to_chat(owner, "In your pockets you will find a teleport scroll. Use it as needed.")
to_chat(owner,"<B>Remember:</B> do not forget to prepare your spells.")
/datum/antagonist/wizard/ui_static_data(mob/user)
. = ..()
var/list/data = list()
data["objectives"] = get_objectives()
return data
/datum/antagonist/wizard/farewell()
to_chat(owner, "<span class='userdanger'>You have been brainwashed! You are no longer a wizard!</span>")
to_chat(owner, span_userdanger("You have been brainwashed! You are no longer a wizard!"))
/datum/antagonist/wizard/proc/rename_wizard()
set waitfor = FALSE
@@ -111,7 +111,7 @@
var/wizard_name_second = pick(GLOB.wizard_second)
var/randomname = "[wizard_name_first] [wizard_name_second]"
var/mob/living/wiz_mob = owner.current
var/newname = reject_bad_name(stripped_input(wiz_mob, "You are the [name]. Would you like to change your name to something else?", "Name change", randomname, MAX_NAME_LEN))
var/newname = sanitize_name(reject_bad_text(stripped_input(wiz_mob, "You are the [name]. Would you like to change your name to something else?", "Name change", randomname, MAX_NAME_LEN)))
if (!newname)
newname = randomname
@@ -120,12 +120,12 @@
/datum/antagonist/wizard/apply_innate_effects(mob/living/mob_override)
var/mob/living/M = mob_override || owner.current
update_wiz_icons_added(M, wiz_team ? TRUE : FALSE) //Don't bother showing the icon if you're solo wizard
add_antag_hud(antag_hud_type, antag_hud_name, M)
M.faction |= ROLE_WIZARD
/datum/antagonist/wizard/remove_innate_effects(mob/living/mob_override)
var/mob/living/M = mob_override || owner.current
update_wiz_icons_removed(M)
remove_antag_hud(antag_hud_type, M)
M.faction -= ROLE_WIZARD
@@ -138,7 +138,7 @@
/datum/antagonist/wizard/apprentice
name = "Wizard Apprentice"
hud_version = "apprentice"
antag_hud_name = "apprentice"
var/datum/mind/master
var/school = APPRENTICE_DESTRUCTION
outfit_type = /datum/outfit/wizard/apprentice
@@ -157,7 +157,7 @@
/datum/antagonist/wizard/apprentice/equip_wizard()
. = ..()
if(!owner)
return
CRASH("Antag datum with no owner.")
var/mob/living/carbon/human/H = owner.current
if(!istype(H))
return
@@ -169,12 +169,12 @@
if(APPRENTICE_BLUESPACE)
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/turf_teleport/blink(null))
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(null))
to_chat(owner, "<B>Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned reality bending mobility spells. You are able to cast teleport and ethereal jaunt.")
to_chat(owner, "<B>Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned reality-bending mobility spells. You are able to cast teleport and ethereal jaunt.")
if(APPRENTICE_HEALING)
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/charge(null))
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/forcewall(null))
H.put_in_hands(new /obj/item/gun/magic/staff/healing(H))
to_chat(owner, "<B>Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned livesaving survival spells. You are able to cast charge and forcewall.")
to_chat(owner, "<B>Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned life-saving survival spells. You are able to cast charge and forcewall.")
if(APPRENTICE_ROBELESS)
owner.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/knock(null))
owner.AddSpell(new /obj/effect/proc_holder/spell/pointed/mind_transfer(null))
@@ -194,6 +194,7 @@
//Random event wizard
/datum/antagonist/wizard/apprentice/imposter
name = "Wizard Imposter"
show_in_antagpanel = FALSE
allow_rename = FALSE
move_to_lair = FALSE
@@ -224,20 +225,11 @@
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/turf_teleport/blink(null))
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(null))
/datum/antagonist/wizard/proc/update_wiz_icons_added(mob/living/wiz,join = TRUE)
var/datum/atom_hud/antag/wizhud = GLOB.huds[ANTAG_HUD_WIZ]
wizhud.join_hud(wiz)
set_antag_hud(wiz, hud_version)
/datum/antagonist/wizard/proc/update_wiz_icons_removed(mob/living/wiz)
var/datum/atom_hud/antag/wizhud = GLOB.huds[ANTAG_HUD_WIZ]
wizhud.leave_hud(wiz)
set_antag_hud(wiz, null)
/datum/antagonist/wizard/academy
name = "Academy Teacher"
show_in_antagpanel = FALSE
outfit_type = /datum/outfit/wizard/academy
move_to_lair = FALSE
/datum/antagonist/wizard/academy/equip_wizard()
. = ..()
@@ -250,7 +242,7 @@
if(!istype(M))
return
var/obj/item/implant/exile/Implant = new
var/obj/item/implant/exile/Implant = new/obj/item/implant/exile(M)
Implant.implant(M)
/datum/antagonist/wizard/academy/create_objectives()
@@ -265,25 +257,25 @@
parts += printplayer(owner)
var/count = 1
var/wizardwin = 1
var/wizardwin = TRUE
for(var/datum/objective/objective in objectives)
if(objective.completable)
var/completion = objective.check_completion()
if(completion >= 1)
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</B></span>"
parts += "<br><B>Objective #[count]</B>: [objective.explanation_text] [span_greentext("Success!")]"
else if(completion <= 0)
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
parts += "<br><B>Objective #[count]</B>: [objective.explanation_text] [span_redtext("Fail.")]"
wizardwin = FALSE
else
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='yellowtext'>[completion*100]%</span>"
parts += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='yellowtext'>[completion*100]%</span>"
else
parts += "<B>Objective #[count]</B>: [objective.explanation_text]"
count++
if(wizardwin)
parts += "<span class='greentext'>The wizard was successful!</span>"
parts += span_greentext("The wizard was successful!")
else
parts += "<span class='redtext'>The wizard has failed!</span>"
parts += span_redtext("The wizard has failed!")
if(owner.spell_list.len>0)
parts += "<B>[owner.name] used the following spells: </B>"

View File

@@ -13,9 +13,6 @@ GLOBAL_LIST_EMPTY(asset_datums)
var/_abstract = /datum/asset
var/cached_url_mappings
/// Whether or not this asset should be loaded in the "early assets" SS
var/early = FALSE
/datum/asset/New()
GLOB.asset_datums[type] = src
register()
@@ -368,28 +365,3 @@ GLOBAL_LIST_EMPTY(asset_datums)
/datum/asset/simple/namespaced/proc/get_htmlloader(filename)
return url2htmlloader(SSassets.transport.get_asset_url(filename, assets[filename]))
/// A subtype to generate a JSON file from a list
/datum/asset/json
_abstract = /datum/asset/json
/// The filename, will be suffixed with ".json"
var/name
/datum/asset/json/send(client)
return SSassets.transport.send_assets(client, "data/[name].json")
/datum/asset/json/get_url_mappings()
return list(
"[name].json" = SSassets.transport.get_asset_url("data/[name].json"),
)
/datum/asset/json/register()
var/filename = "data/[name].json"
fdel(filename)
text2file(json_encode(generate()), filename)
SSassets.transport.register_asset(filename, fcopy_rsc(filename))
fdel(filename)
/// Returns the data that will be JSON encoded
/datum/asset/json/proc/generate()
SHOULD_CALL_PARENT(FALSE)
CRASH("generate() not implemented for [type]!")

View File

@@ -1,11 +1,5 @@
//DEFINITIONS FOR ASSET DATUMS START HERE.
/datum/asset/simple/tgui_common
keep_local_name = TRUE
assets = list(
"tgui-common.bundle.js" = file("tgui/public/tgui-common.bundle.js"),
)
/datum/asset/simple/tgui
keep_local_name = TRUE
assets = list(
@@ -54,9 +48,14 @@
/datum/asset/simple/radar_assets
assets = list(
"ntosradarbackground.png" = 'icons/UI_Icons/tgui/ntosradar_background.png',
"ntosradarpointer.png" = 'icons/UI_Icons/tgui/ntosradar_pointer.png',
"ntosradarpointerS.png" = 'icons/UI_Icons/tgui/ntosradar_pointer_S.png'
"ntosradarbackground.png" = 'icons/ui_icons/tgui/ntosradar_background.png',
"ntosradarpointer.png" = 'icons/ui_icons/tgui/ntosradar_pointer.png',
"ntosradarpointerS.png" = 'icons/ui_icons/tgui/ntosradar_pointer_S.png'
)
/datum/asset/simple/circuit_assets
assets = list(
"grid_background.png" = 'icons/ui_icons/tgui/grid_background.png'
)
/datum/asset/spritesheet/simple/pda
@@ -91,6 +90,7 @@
"status" = 'icons/pda_icons/pda_status.png',
"dronephone" = 'icons/pda_icons/pda_dronephone.png',
"emoji" = 'icons/pda_icons/pda_emoji.png'
// "droneblacklist" = 'icons/pda_icons/pda_droneblacklist.png',
)
/datum/asset/spritesheet/simple/paper
@@ -116,7 +116,7 @@
/datum/asset/simple/irv
assets = list(
"jquery-ui.custom-core-widgit-mouse-sortable-min.js" = 'html/IRV/jquery-ui.custom-core-widgit-mouse-sortable-min.js',
"jquery-ui.custom-core-widgit-mouse-sortable-min.js" = 'html/jquery/jquery-ui.custom-core-widgit-mouse-sortable.min.js',
)
/datum/asset/group/irv
@@ -149,11 +149,10 @@
)
parents = list("changelog.html" = 'html/changelog.html')
/datum/asset/simple/jquery
legacy = TRUE
assets = list(
"jquery.min.js" = 'html/jquery.min.js',
"jquery.min.js" = 'html/jquery/jquery.min.js',
)
/datum/asset/simple/namespaced/fontawesome
@@ -223,102 +222,102 @@
/datum/asset/simple/arcade
assets = list(
"boss1.gif" = 'icons/UI_Icons/Arcade/boss1.gif',
"boss2.gif" = 'icons/UI_Icons/Arcade/boss2.gif',
"boss3.gif" = 'icons/UI_Icons/Arcade/boss3.gif',
"boss4.gif" = 'icons/UI_Icons/Arcade/boss4.gif',
"boss5.gif" = 'icons/UI_Icons/Arcade/boss5.gif',
"boss6.gif" = 'icons/UI_Icons/Arcade/boss6.gif',
"boss1.gif" = 'icons/ui_icons/arcade/boss1.gif',
"boss2.gif" = 'icons/ui_icons/arcade/boss2.gif',
"boss3.gif" = 'icons/ui_icons/arcade/boss3.gif',
"boss4.gif" = 'icons/ui_icons/arcade/boss4.gif',
"boss5.gif" = 'icons/ui_icons/arcade/boss5.gif',
"boss6.gif" = 'icons/ui_icons/arcade/boss6.gif',
)
/datum/asset/spritesheet/simple/achievements
name ="achievements"
assets = list(
"default" = 'icons/UI_Icons/Achievements/default.png',
"basemisc" = 'icons/UI_Icons/Achievements/basemisc.png',
"baseboss" = 'icons/UI_Icons/Achievements/baseboss.png',
"baseskill" = 'icons/UI_Icons/Achievements/baseskill.png',
"bbgum" = 'icons/UI_Icons/Achievements/Boss/bbgum.png',
"colossus" = 'icons/UI_Icons/Achievements/Boss/colossus.png',
"hierophant" = 'icons/UI_Icons/Achievements/Boss/hierophant.png',
"drake" = 'icons/UI_Icons/Achievements/Boss/drake.png',
"legion" = 'icons/UI_Icons/Achievements/Boss/legion.png',
"miner" = 'icons/UI_Icons/Achievements/Boss/miner.png',
"swarmer" = 'icons/UI_Icons/Achievements/Boss/swarmer.png',
"tendril" = 'icons/UI_Icons/Achievements/Boss/tendril.png',
"featofstrength" = 'icons/UI_Icons/Achievements/Misc/featofstrength.png',
"helbital" = 'icons/UI_Icons/Achievements/Misc/helbital.png',
"jackpot" = 'icons/UI_Icons/Achievements/Misc/jackpot.png',
"meteors" = 'icons/UI_Icons/Achievements/Misc/meteors.png',
"timewaste" = 'icons/UI_Icons/Achievements/Misc/timewaste.png',
"upgrade" = 'icons/UI_Icons/Achievements/Misc/upgrade.png',
"clownking" = 'icons/UI_Icons/Achievements/Misc/clownking.png',
"clownthanks" = 'icons/UI_Icons/Achievements/Misc/clownthanks.png',
"rule8" = 'icons/UI_Icons/Achievements/Misc/rule8.png',
"longshift" = 'icons/UI_Icons/Achievements/Misc/longshift.png',
"snail" = 'icons/UI_Icons/Achievements/Misc/snail.png',
"ascension" = 'icons/UI_Icons/Achievements/Misc/ascension.png',
"ashascend" = 'icons/UI_Icons/Achievements/Misc/ashascend.png',
"fleshascend" = 'icons/UI_Icons/Achievements/Misc/fleshascend.png',
"rustascend" = 'icons/UI_Icons/Achievements/Misc/rustascend.png',
"voidascend" = 'icons/UI_Icons/Achievements/Misc/voidascend.png',
"toolbox_soul" = 'icons/UI_Icons/Achievements/Misc/toolbox_soul.png',
"chem_tut" = 'icons/UI_Icons/Achievements/Misc/chem_tut.png',
"mining" = 'icons/UI_Icons/Achievements/Skills/mining.png',
"mafia" = 'icons/UI_Icons/Achievements/Mafia/mafia.png',
"town" = 'icons/UI_Icons/Achievements/Mafia/town.png',
"neutral" = 'icons/UI_Icons/Achievements/Mafia/neutral.png',
"hated" = 'icons/UI_Icons/Achievements/Mafia/hated.png',
"basemafia" ='icons/UI_Icons/Achievements/basemafia.png',
"frenching" = 'icons/UI_Icons/Achievements/Misc/frenchingthebubble.png'
"default" = 'icons/ui_icons/achievements/default.png',
"basemisc" = 'icons/ui_icons/achievements/basemisc.png',
"baseboss" = 'icons/ui_icons/achievements/baseboss.png',
"baseskill" = 'icons/ui_icons/achievements/baseskill.png',
"bbgum" = 'icons/ui_icons/achievements/Boss/bbgum.png',
"colossus" = 'icons/ui_icons/achievements/Boss/colossus.png',
"hierophant" = 'icons/ui_icons/achievements/Boss/hierophant.png',
"drake" = 'icons/ui_icons/achievements/Boss/drake.png',
"legion" = 'icons/ui_icons/achievements/Boss/legion.png',
"miner" = 'icons/ui_icons/achievements/Boss/miner.png',
"swarmer" = 'icons/ui_icons/achievements/Boss/swarmer.png',
"tendril" = 'icons/ui_icons/achievements/Boss/tendril.png',
"featofstrength" = 'icons/ui_icons/achievements/Misc/featofstrength.png',
"helbital" = 'icons/ui_icons/achievements/Misc/helbital.png',
"jackpot" = 'icons/ui_icons/achievements/Misc/jackpot.png',
"meteors" = 'icons/ui_icons/achievements/Misc/meteors.png',
"timewaste" = 'icons/ui_icons/achievements/Misc/timewaste.png',
"upgrade" = 'icons/ui_icons/achievements/Misc/upgrade.png',
"clownking" = 'icons/ui_icons/achievements/Misc/clownking.png',
"clownthanks" = 'icons/ui_icons/achievements/Misc/clownthanks.png',
"rule8" = 'icons/ui_icons/achievements/Misc/rule8.png',
"longshift" = 'icons/ui_icons/achievements/Misc/longshift.png',
"snail" = 'icons/ui_icons/achievements/Misc/snail.png',
"ascension" = 'icons/ui_icons/achievements/Misc/ascension.png',
"ashascend" = 'icons/ui_icons/achievements/Misc/ashascend.png',
"fleshascend" = 'icons/ui_icons/achievements/Misc/fleshascend.png',
"rustascend" = 'icons/ui_icons/achievements/Misc/rustascend.png',
"voidascend" = 'icons/ui_icons/achievements/Misc/voidascend.png',
"toolbox_soul" = 'icons/ui_icons/achievements/Misc/toolbox_soul.png',
"chem_tut" = 'icons/ui_icons/achievements/Misc/chem_tut.png',
"mining" = 'icons/ui_icons/achievements/Skills/mining.png',
"mafia" = 'icons/ui_icons/achievements/Mafia/mafia.png',
"town" = 'icons/ui_icons/achievements/Mafia/town.png',
"neutral" = 'icons/ui_icons/achievements/Mafia/neutral.png',
"hated" = 'icons/ui_icons/achievements/Mafia/hated.png',
"basemafia" ='icons/ui_icons/achievements/basemafia.png',
"frenching" = 'icons/ui_icons/achievements/Misc/frenchingthebubble.png'
)
/datum/asset/spritesheet/simple/pills
name = "pills"
assets = list(
"pill1" = 'icons/UI_Icons/Pills/pill1.png',
"pill2" = 'icons/UI_Icons/Pills/pill2.png',
"pill3" = 'icons/UI_Icons/Pills/pill3.png',
"pill4" = 'icons/UI_Icons/Pills/pill4.png',
"pill5" = 'icons/UI_Icons/Pills/pill5.png',
"pill6" = 'icons/UI_Icons/Pills/pill6.png',
"pill7" = 'icons/UI_Icons/Pills/pill7.png',
"pill8" = 'icons/UI_Icons/Pills/pill8.png',
"pill9" = 'icons/UI_Icons/Pills/pill9.png',
"pill10" = 'icons/UI_Icons/Pills/pill10.png',
"pill11" = 'icons/UI_Icons/Pills/pill11.png',
"pill12" = 'icons/UI_Icons/Pills/pill12.png',
"pill13" = 'icons/UI_Icons/Pills/pill13.png',
"pill14" = 'icons/UI_Icons/Pills/pill14.png',
"pill15" = 'icons/UI_Icons/Pills/pill15.png',
"pill16" = 'icons/UI_Icons/Pills/pill16.png',
"pill17" = 'icons/UI_Icons/Pills/pill17.png',
"pill18" = 'icons/UI_Icons/Pills/pill18.png',
"pill19" = 'icons/UI_Icons/Pills/pill19.png',
"pill20" = 'icons/UI_Icons/Pills/pill20.png',
"pill21" = 'icons/UI_Icons/Pills/pill21.png',
"pill22" = 'icons/UI_Icons/Pills/pill22.png',
"pill1" = 'icons/ui_icons/pills/pill1.png',
"pill2" = 'icons/ui_icons/pills/pill2.png',
"pill3" = 'icons/ui_icons/pills/pill3.png',
"pill4" = 'icons/ui_icons/pills/pill4.png',
"pill5" = 'icons/ui_icons/pills/pill5.png',
"pill6" = 'icons/ui_icons/pills/pill6.png',
"pill7" = 'icons/ui_icons/pills/pill7.png',
"pill8" = 'icons/ui_icons/pills/pill8.png',
"pill9" = 'icons/ui_icons/pills/pill9.png',
"pill10" = 'icons/ui_icons/pills/pill10.png',
"pill11" = 'icons/ui_icons/pills/pill11.png',
"pill12" = 'icons/ui_icons/pills/pill12.png',
"pill13" = 'icons/ui_icons/pills/pill13.png',
"pill14" = 'icons/ui_icons/pills/pill14.png',
"pill15" = 'icons/ui_icons/pills/pill15.png',
"pill16" = 'icons/ui_icons/pills/pill16.png',
"pill17" = 'icons/ui_icons/pills/pill17.png',
"pill18" = 'icons/ui_icons/pills/pill18.png',
"pill19" = 'icons/ui_icons/pills/pill19.png',
"pill20" = 'icons/ui_icons/pills/pill20.png',
"pill21" = 'icons/ui_icons/pills/pill21.png',
"pill22" = 'icons/ui_icons/pills/pill22.png',
)
// /datum/asset/spritesheet/simple/condiments
// name = "condiments"
// assets = list(
// CONDIMASTER_STYLE_FALLBACK = 'icons/UI_Icons/Condiments/emptycondiment.png',
// "enzyme" = 'icons/UI_Icons/Condiments/enzyme.png',
// "flour" = 'icons/UI_Icons/Condiments/flour.png',
// "mayonnaise" = 'icons/UI_Icons/Condiments/mayonnaise.png',
// "milk" = 'icons/UI_Icons/Condiments/milk.png',
// "blackpepper" = 'icons/UI_Icons/Condiments/peppermillsmall.png',
// "rice" = 'icons/UI_Icons/Condiments/rice.png',
// "sodiumchloride" = 'icons/UI_Icons/Condiments/saltshakersmall.png',
// "soymilk" = 'icons/UI_Icons/Condiments/soymilk.png',
// "soysauce" = 'icons/UI_Icons/Condiments/soysauce.png',
// "sugar" = 'icons/UI_Icons/Condiments/sugar.png',
// "ketchup" = 'icons/UI_Icons/Condiments/ketchup.png',
// "capsaicin" = 'icons/UI_Icons/Condiments/hotsauce.png',
// "frostoil" = 'icons/UI_Icons/Condiments/coldsauce.png',
// "bbqsauce" = 'icons/UI_Icons/Condiments/bbqsauce.png',
// "cornoil" = 'icons/UI_Icons/Condiments/oliveoil.png',
// CONDIMASTER_STYLE_FALLBACK = 'icons/ui_icons/condiments/emptycondiment.png',
// "enzyme" = 'icons/ui_icons/condiments/enzyme.png',
// "flour" = 'icons/ui_icons/condiments/flour.png',
// "mayonnaise" = 'icons/ui_icons/condiments/mayonnaise.png',
// "milk" = 'icons/ui_icons/condiments/milk.png',
// "blackpepper" = 'icons/ui_icons/condiments/peppermillsmall.png',
// "rice" = 'icons/ui_icons/condiments/rice.png',
// "sodiumchloride" = 'icons/ui_icons/condiments/saltshakersmall.png',
// "soymilk" = 'icons/ui_icons/condiments/soymilk.png',
// "soysauce" = 'icons/ui_icons/condiments/soysauce.png',
// "sugar" = 'icons/ui_icons/condiments/sugar.png',
// "ketchup" = 'icons/ui_icons/condiments/ketchup.png',
// "capsaicin" = 'icons/ui_icons/condiments/hotsauce.png',
// "frostoil" = 'icons/ui_icons/condiments/coldsauce.png',
// "bbqsauce" = 'icons/ui_icons/condiments/bbqsauce.png',
// "cornoil" = 'icons/ui_icons/condiments/oliveoil.png',
// )
//this exists purely to avoid meta by pre-loading all language icons.
@@ -410,9 +409,15 @@
if (machine)
item = machine
// Check for GAGS support where necessary
// var/greyscale_config = initial(item.greyscale_config)
// var/greyscale_colors = initial(item.greyscale_colors)
// if (greyscale_config && greyscale_colors)
// icon_file = SSgreyscale.GetColoredIconByType(greyscale_config, greyscale_colors)
// else
icon_file = initial(item.icon)
icon_state = initial(item.icon_state)
icon_state = initial(item.icon_state)
if(!(icon_state in icon_states(icon_file)))
warning("design [D] with icon '[icon_file]' missing state '[icon_state]'")
continue
@@ -441,7 +446,11 @@
if (!ispath(item, /atom))
continue
var/icon_file = initial(item.icon)
var/icon_file
// if (initial(item.greyscale_colors) && initial(item.greyscale_config))
// icon_file = SSgreyscale.GetColoredIconByType(initial(item.greyscale_config), initial(item.greyscale_colors))
// else
icon_file = initial(item.icon)
var/icon_state = initial(item.icon_state)
var/icon/I
@@ -543,6 +552,35 @@
// Insert(id, fish_icon, fish_icon_state)
// ..()
/datum/asset/simple/adventure
assets = list(
"default" = 'icons/ui_icons/adventure/default.png',
"grue" = 'icons/ui_icons/adventure/grue.png',
"signal_lost" ='icons/ui_icons/adventure/signal_lost.png',
"trade" = 'icons/ui_icons/adventure/trade.png',
)
/datum/asset/simple/inventory
assets = list(
"inventory-glasses.png" = 'icons/ui_icons/inventory/glasses.png',
"inventory-head.png" = 'icons/ui_icons/inventory/head.png',
"inventory-neck.png" = 'icons/ui_icons/inventory/neck.png',
"inventory-mask.png" = 'icons/ui_icons/inventory/mask.png',
"inventory-ears.png" = 'icons/ui_icons/inventory/ears.png',
"inventory-uniform.png" = 'icons/ui_icons/inventory/uniform.png',
"inventory-suit.png" = 'icons/ui_icons/inventory/suit.png',
"inventory-gloves.png" = 'icons/ui_icons/inventory/gloves.png',
"inventory-hand_l.png" = 'icons/ui_icons/inventory/hand_l.png',
"inventory-hand_r.png" = 'icons/ui_icons/inventory/hand_r.png',
"inventory-shoes.png" = 'icons/ui_icons/inventory/shoes.png',
"inventory-suit_storage.png" = 'icons/ui_icons/inventory/suit_storage.png',
"inventory-id.png" = 'icons/ui_icons/inventory/id.png',
"inventory-belt.png" = 'icons/ui_icons/inventory/belt.png',
"inventory-back.png" = 'icons/ui_icons/inventory/back.png',
"inventory-pocket.png" = 'icons/ui_icons/inventory/pocket.png',
"inventory-collar.png" = 'icons/ui_icons/inventory/collar.png',
)
/// Removes all non-alphanumerics from the text, keep in mind this can lead to id conflicts
/proc/sanitize_css_class_name(name)
var/static/regex/regex = new(@"[^a-zA-Z0-9]","g")
@@ -550,5 +588,34 @@
/datum/asset/simple/tutorial_advisors
assets = list(
"chem_help_advisor.gif" = 'icons/UI_Icons/Advisors/chem_help_advisor.gif',
"chem_help_advisor.gif" = 'icons/ui_icons/advisors/chem_help_advisor.gif',
)
// /datum/asset/spritesheet/moods
// name = "moods"
// var/iconinserted = 1
// /datum/asset/spritesheet/moods/register()
// for(var/i in 1 to 9)
// var/target_to_insert = "mood"+"[iconinserted]"
// Insert(target_to_insert, 'icons/hud/screen_gen.dmi', target_to_insert)
// iconinserted++
// ..()
// /datum/asset/spritesheet/moods/ModifyInserted(icon/pre_asset)
// var/blended_color
// switch(iconinserted)
// if(1)
// blended_color = "#f15d36"
// if(2 to 3)
// blended_color = "#f38943"
// if(4)
// blended_color = "#dfa65b"
// if(5)
// blended_color = "#4b96c4"
// if(6)
// blended_color = "#86d656"
// else
// blended_color = "#2eeb9a"
// pre_asset.Blend(blended_color, ICON_MULTIPLY)
// return pre_asset

View File

@@ -115,7 +115,7 @@
if (unreceived.len)
if (unreceived.len >= ASSET_CACHE_TELL_CLIENT_AMOUNT)
to_chat(client, "Sending Resources...")
to_chat(client, "<span class='infoplain'>Sending Resources...</span>")
for (var/asset_name in unreceived)
var/new_asset_name = asset_name

View File

@@ -0,0 +1,89 @@
#define BALLOON_TEXT_WIDTH 200
#define BALLOON_TEXT_SPAWN_TIME (0.2 SECONDS)
#define BALLOON_TEXT_FADE_TIME (0.1 SECONDS)
#define BALLOON_TEXT_FULLY_VISIBLE_TIME (0.7 SECONDS)
#define BALLOON_TEXT_TOTAL_LIFETIME(mult) (BALLOON_TEXT_SPAWN_TIME + BALLOON_TEXT_FULLY_VISIBLE_TIME*mult + BALLOON_TEXT_FADE_TIME)
/// The increase in duration per character in seconds
#define BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MULT (0.05)
/// The amount of characters needed before this increase takes into effect
#define BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MIN 10
/// Creates text that will float from the atom upwards to the viewer.
/atom/proc/balloon_alert(mob/viewer, text)
SHOULD_NOT_SLEEP(TRUE)
INVOKE_ASYNC(src, .proc/balloon_alert_perform, viewer, text)
/// Create balloon alerts (text that floats up) to everything within range.
/// Will only display to people who can see.
/atom/proc/balloon_alert_to_viewers(message, self_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs)
SHOULD_NOT_SLEEP(TRUE)
var/list/hearers = get_hearers_in_view(vision_distance, src)
hearers -= ignored_mobs
for (var/mob/hearer in hearers)
if (hearer.is_blind())
continue
balloon_alert(hearer, (hearer == src && self_message) || message)
// Do not use.
// MeasureText blocks. I have no idea for how long.
// I would've made the maptext_height update on its own, but I don't know
// if this would look bad on laggy clients.
/atom/proc/balloon_alert_perform(mob/viewer, text)
var/client/viewer_client = viewer.client
if (isnull(viewer_client))
return
var/bound_width = world.icon_size
if (ismovable(src))
var/atom/movable/movable_source = src
bound_width = movable_source.bound_width
var/image/balloon_alert = image(loc = get_atom_on_turf(src), layer = ABOVE_MOB_LAYER)
balloon_alert.plane = BALLOON_CHAT_PLANE
balloon_alert.alpha = 0
balloon_alert.maptext = MAPTEXT("<span style='text-align: center; -dm-text-outline: 1px #0005'>[text]</span>")
balloon_alert.maptext_x = (BALLOON_TEXT_WIDTH - bound_width) * -0.5
balloon_alert.maptext_height = WXH_TO_HEIGHT(viewer_client?.MeasureText(text, null, BALLOON_TEXT_WIDTH))
balloon_alert.maptext_width = BALLOON_TEXT_WIDTH
viewer_client?.images += balloon_alert
var/duration_mult = 1
var/duration_length = length(text) - BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MIN
if(duration_length > 0)
duration_mult += duration_length*BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MULT
animate(
balloon_alert,
pixel_y = world.icon_size * 1.2,
time = BALLOON_TEXT_TOTAL_LIFETIME(1),
easing = SINE_EASING | EASE_OUT,
)
animate(
alpha = 255,
time = BALLOON_TEXT_SPAWN_TIME,
easing = CUBIC_EASING | EASE_OUT,
flags = ANIMATION_PARALLEL,
)
animate(
alpha = 0,
time = BALLOON_TEXT_FULLY_VISIBLE_TIME*duration_mult,
easing = CUBIC_EASING | EASE_IN,
)
addtimer(CALLBACK(GLOBAL_PROC, .proc/remove_image_from_client, balloon_alert, viewer_client), BALLOON_TEXT_TOTAL_LIFETIME(duration_mult))
#undef BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MIN
#undef BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MULT
#undef BALLOON_TEXT_FADE_TIME
#undef BALLOON_TEXT_FULLY_VISIBLE_TIME
#undef BALLOON_TEXT_SPAWN_TIME
#undef BALLOON_TEXT_TOTAL_LIFETIME
#undef BALLOON_TEXT_WIDTH

View File

@@ -52,7 +52,7 @@
desc = "Packs of tools waiting to be used for repairing. Contains a tool and engineering vending machine refill. Requires CE access."
cost = 5500 //Powerfull
access = ACCESS_CE
contains = list(/obj/item/vending_refill/tool,
contains = list(/obj/item/vending_refill/youtool,
/obj/item/vending_refill/engivend)
crate_name = "engineering supply crate"
crate_type = /obj/structure/closet/crate/secure/engineering

View File

@@ -141,7 +141,7 @@
pop_areas += A
var/list/targets = list()
for(var/H in GLOB.network_holopads)
for(var/H in GLOB.the_station_areas)
var/area/A = get_area(H)
if(!A || findtextEx(A.name, "AI") || !(A in pop_areas) || !is_station_level(H))
continue

View File

@@ -26,7 +26,7 @@
"light blue" = COLOR_ASSEMBLY_LBLUE,
"blue" = COLOR_ASSEMBLY_BLUE,
"purple" = COLOR_ASSEMBLY_PURPLE,
"pink" = COLOR_ASSEMBLY_PINK,
"pink" = LIGHT_COLOR_PINK,
"custom" = COLOR_ASSEMBLY_WHITE
)

View File

@@ -12,13 +12,13 @@
rad_flags = RAD_PROTECT_CONTENTS
armor = list("melee" = 0, "bullet" = 20, "laser" = 20, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 0, "acid" = 0)
var/enabled = 0 // Whether the computer is turned on.
var/screen_on = 1 // Whether the computer is active/opened/it's screen is on.
var/device_theme = "ntos" // Sets the theme for the main menu, hardware config, and file browser apps. Overridden by certain non-NT devices.
var/datum/computer_file/program/active_program = null // A currently active program running on the computer.
var/hardware_flag = 0 // A flag that describes this device type
var/enabled = 0 // Whether the computer is turned on.
var/screen_on = 1 // Whether the computer is active/opened/it's screen is on.
var/device_theme = "ntos" // Sets the theme for the main menu, hardware config, and file browser apps. Overridden by certain non-NT devices.
var/datum/computer_file/program/active_program = null // A currently active program running on the computer.
var/hardware_flag = 0 // A flag that describes this device type
var/last_power_usage = 0
var/last_battery_percent = 0 // Used for deciding if battery percentage has chandged
var/last_battery_percent = 0 // Used for deciding if battery percentage has chandged
var/last_world_time = "00:00"
var/list/last_header_icons
///Looping sound for when the computer is on
@@ -26,19 +26,19 @@
///Whether or not this modular computer uses the looping sound
var/looping_sound = TRUE
var/base_active_power_usage = 50 // Power usage when the computer is open (screen is active) and can be interacted with. Remember hardware can use power too.
var/base_idle_power_usage = 5 // Power usage when the computer is idle and screen is off (currently only applies to laptops)
var/base_active_power_usage = 50 // Power usage when the computer is open (screen is active) and can be interacted with. Remember hardware can use power too.
var/base_idle_power_usage = 5 // Power usage when the computer is idle and screen is off (currently only applies to laptops)
// Modular computers can run on various devices. Each DEVICE (Laptop, Console, Tablet,..)
// must have it's own DMI file. Icon states must be called exactly the same in all files, but may look differently
// If you create a program which is limited to Laptops and Consoles you don't have to add it's icon_state overlay for Tablets too, for example.
var/icon_state_unpowered = null // Icon state when the computer is turned off.
var/icon_state_powered = null // Icon state when the computer is turned on.
var/icon_state_menu = "menu" // Icon state overlay when the computer is turned on, but no program is loaded that would override the screen.
var/display_overlays = TRUE // If FALSE, don't draw overlays on this device at all
var/max_hardware_size = 0 // Maximal hardware w_class. Tablets/PDAs have 1, laptops 2, consoles 4.
var/steel_sheet_cost = 5 // Amount of steel sheets refunded when disassembling an empty frame of this computer.
var/icon_state_unpowered = null // Icon state when the computer is turned off.
var/icon_state_powered = null // Icon state when the computer is turned on.
var/icon_state_menu = "menu" // Icon state overlay when the computer is turned on, but no program is loaded that would override the screen.
var/display_overlays = TRUE // If FALSE, don't draw overlays on this device at all
var/max_hardware_size = 0 // Maximal hardware w_class. Tablets/PDAs have 1, laptops 2, consoles 4.
var/steel_sheet_cost = 5 // Amount of steel sheets refunded when disassembling an empty frame of this computer.
/// List of "connection ports" in this computer and the components with which they are plugged
var/list/all_components = list()
@@ -47,11 +47,11 @@
/// Number of total expansion bays this computer has available.
var/max_bays = 0
var/list/idle_threads // Idle programs on background. They still receive process calls but can't be interacted with.
var/obj/physical = null // Object that represents our computer. It's used for Adjacent() and UI visibility checks.
var/has_light = FALSE //If the computer has a flashlight/LED light/what-have-you installed
var/comp_light_luminosity = 3 //The brightness of that light
var/comp_light_color //The color of that light
var/list/idle_threads // Idle programs on background. They still receive process calls but can't be interacted with.
var/obj/physical = null // Object that represents our computer. It's used for Adjacent() and UI visibility checks.
var/has_light = FALSE //If the computer has a flashlight/LED light/what-have-you installed
var/comp_light_luminosity = 3 //The brightness of that light
var/comp_light_color //The color of that light
/obj/item/modular_computer/Initialize()
@@ -62,13 +62,12 @@
comp_light_color = "#FFFFFF"
idle_threads = list()
if(looping_sound)
soundloop = new(list(src), enabled)
update_icon()
soundloop = new(src, enabled)
update_appearance()
/obj/item/modular_computer/Destroy()
kill_program(forced = TRUE)
STOP_PROCESSING(SSobj, src)
QDEL_NULL(soundloop)
for(var/H in all_components)
var/obj/item/computer_hardware/CH = all_components[H]
if(CH.holder == src)
@@ -76,9 +75,19 @@
CH.holder = null
all_components.Remove(CH.device_type)
qdel(CH)
//Some components will actually try and interact with this, so let's do it later
QDEL_NULL(soundloop)
physical = null
return ..()
/**
* Plays a ping sound.
*
* Timers runtime if you try to make them call playsound. Yep.
*/
/obj/item/modular_computer/proc/play_ping()
playsound(loc, 'sound/machines/ping.ogg', get_clamped_volume(), FALSE, -1)
/obj/item/modular_computer/AltClick(mob/user)
..()
if(issilicon(user))
@@ -98,14 +107,34 @@
/obj/item/modular_computer/GetID()
var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
if(card_slot)
return card_slot.GetID()
var/obj/item/computer_hardware/card_slot/card_slot2 = all_components[MC_CARD2]
var/obj/item/card/id/first_id = card_slot?.GetID()
var/obj/item/card/id/second_id = card_slot2?.GetID()
// If we don't have both ID slots filled, pick the one that is filled.
if(first_id)
return first_id
if(second_id)
return second_id
// Otherwise, we have no ID at all.
return ..()
/obj/item/modular_computer/RemoveID()
var/obj/item/computer_hardware/card_slot/card_slot2 = all_components[MC_CARD2]
var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
return (card_slot2?.try_eject() || card_slot?.try_eject()) //Try the secondary one first.
var/removed_id = (card_slot2?.try_eject() || card_slot?.try_eject())
if(removed_id)
if(ishuman(loc))
var/mob/living/carbon/human/human_wearer = loc
if(human_wearer.wear_id == src)
human_wearer.sec_hud_set_ID()
update_slot_icon()
return removed_id
return ..()
/obj/item/modular_computer/InsertID(obj/item/inserting_item)
var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
@@ -118,7 +147,13 @@
return FALSE
if((card_slot?.try_insert(inserting_id)) || (card_slot2?.try_insert(inserting_id)))
if(ishuman(loc))
var/mob/living/carbon/human/human_wearer = loc
if(human_wearer.wear_id == src)
human_wearer.sec_hud_set_ID()
update_slot_icon()
return TRUE
return FALSE
/obj/item/modular_computer/MouseDrop(obj/over_object, src_location, over_location)
@@ -142,9 +177,8 @@
turn_on(user)
/obj/item/modular_computer/emag_act(mob/user)
. = ..()
if(!enabled)
to_chat(user, "<span class='warning'>You'd need to turn the [src] on first.</span>")
to_chat(user, span_warning("You'd need to turn the [src] on first."))
return FALSE
obj_flags |= EMAGGED //Mostly for consistancy purposes; the programs will do their own emag handling
var/newemag = FALSE
@@ -155,36 +189,31 @@
if(app.run_emag())
newemag = TRUE
if(newemag)
to_chat(user, "<span class='notice'>You swipe \the [src]. A console window momentarily fills the screen, with white text rapidly scrolling past.</span>")
to_chat(user, span_notice("You swipe \the [src]. A console window momentarily fills the screen, with white text rapidly scrolling past."))
return TRUE
to_chat(user, "<span class='notice'>You swipe \the [src]. A console window fills the screen, but it quickly closes itself after only a few lines are written to it.</span>")
to_chat(user, span_notice("You swipe \the [src]. A console window fills the screen, but it quickly closes itself after only a few lines are written to it."))
return FALSE
/obj/item/modular_computer/examine(mob/user)
. = ..()
if(obj_integrity <= integrity_failure * max_integrity)
. += "<span class='danger'>It is heavily damaged!</span>"
. += span_danger("It is heavily damaged!")
else if(obj_integrity < max_integrity)
. += "<span class='warning'>It is damaged.</span>"
. += span_warning("It is damaged.")
. += get_modular_computer_parts_examine(user)
/obj/item/modular_computer/update_icon_state()
if(!enabled)
icon_state = icon_state_unpowered
else
icon_state = icon_state_powered
icon_state = enabled ? icon_state_powered : icon_state_unpowered
return ..()
/obj/item/modular_computer/update_overlays()
. = ..()
if(!display_overlays)
return
if(enabled)
if(active_program)
. += active_program.program_icon_state ? active_program.program_icon_state : icon_state_menu
else
. += icon_state_menu
if(enabled)
. += active_program?.program_icon_state || icon_state_menu
if(obj_integrity <= integrity_failure * max_integrity)
. += "bsod"
. += "broken"
@@ -201,9 +230,9 @@
var/issynth = issilicon(user) // Robots and AIs get different activation messages.
if(obj_integrity <= integrity_failure * max_integrity)
if(issynth)
to_chat(user, "<span class='warning'>You send an activation signal to \the [src], but it responds with an error code. It must be damaged.</span>")
to_chat(user, span_warning("You send an activation signal to \the [src], but it responds with an error code. It must be damaged."))
else
to_chat(user, "<span class='warning'>You press the power button, but the computer fails to boot up, displaying variety of errors before shutting down again.</span>")
to_chat(user, span_warning("You press the power button, but the computer fails to boot up, displaying variety of errors before shutting down again."))
return FALSE
// If we have a recharger, enable it automatically. Lets computer without a battery work.
@@ -213,20 +242,20 @@
if(all_components[MC_CPU] && use_power()) // use_power() checks if the PC is powered
if(issynth)
to_chat(user, "<span class='notice'>You send an activation signal to \the [src], turning it on.</span>")
to_chat(user, span_notice("You send an activation signal to \the [src], turning it on."))
else
to_chat(user, "<span class='notice'>You press the power button and start up \the [src].</span>")
to_chat(user, span_notice("You press the power button and start up \the [src]."))
if(looping_sound)
soundloop.start()
enabled = 1
update_icon()
update_appearance()
ui_interact(user)
return TRUE
else // Unpowered
if(issynth)
to_chat(user, "<span class='warning'>You send an activation signal to \the [src] but it does not respond.</span>")
to_chat(user, span_warning("You send an activation signal to \the [src] but it does not respond."))
else
to_chat(user, "<span class='warning'>You press the power button but \the [src] does not respond.</span>")
to_chat(user, span_warning("You press the power button but \the [src] does not respond."))
return FALSE
// Process currently calls handle_power(), may be expanded in future if more things are added.
@@ -282,10 +311,10 @@
if(!caller || !caller.alert_able || caller.alert_silenced || !alerttext) //Yeah, we're checking alert_able. No, you don't get to make alerts that the user can't silence.
return
playsound(src, sound, 50, TRUE)
visible_message("<span class='notice'>The [src] displays a [caller.filedesc] notification: [alerttext]</span>")
visible_message(span_notice("The [src] displays a [caller.filedesc] notification: [alerttext]"))
var/mob/living/holder = loc
if(istype(holder))
to_chat(holder, "[icon2html(src)] <span class='notice'>The [src] displays a [caller.filedesc] notification: [alerttext]</span>")
to_chat(holder, "[icon2html(src)] [span_notice("The [src] displays a [caller.filedesc] notification: [alerttext]")]")
// Function used by NanoUI's to obtain data for header. All relevant entries begin with "PC_"
/obj/item/modular_computer/proc/get_header_data()
@@ -349,14 +378,13 @@
// Relays kill program request to currently active program. Use this to quit current program.
/obj/item/modular_computer/proc/kill_program(forced = FALSE)
set waitfor = FALSE
if(active_program)
active_program.kill_program(forced)
active_program = null
var/mob/user = usr
if(user && istype(user))
ui_interact(user) // Re-open the UI on this computer. It should show the main screen now.
update_icon()
update_appearance()
// Returns 0 for No Signal, 1 for Low Signal and 2 for Good Signal. 3 is for wired connection (always-on)
/obj/item/modular_computer/proc/get_ntnet_status(specific_action = 0)
@@ -370,6 +398,7 @@
if(!get_ntnet_status())
return FALSE
var/obj/item/computer_hardware/network_card/network_card = all_components[MC_NET]
return SSnetworks.station_network.add_log(text, network_card)
/obj/item/modular_computer/proc/shutdown_computer(loud = 1)
@@ -380,9 +409,9 @@
if(looping_sound)
soundloop.stop()
if(loud)
physical.visible_message("<span class='notice'>\The [src] shuts down.</span>")
physical.visible_message(span_notice("\The [src] shuts down."))
enabled = 0
update_icon()
update_appearance()
/**
* Toggles the computer's flashlight, if it has one.
@@ -412,20 +441,20 @@
if(!has_light || !color)
return FALSE
comp_light_color = color
// set_light_color(color)
set_light_color(color)
update_light()
return TRUE
/obj/item/modular_computer/screwdriver_act(mob/user, obj/item/tool)
if(!all_components.len)
to_chat(user, "<span class='warning'>This device doesn't have any components installed.</span>")
to_chat(user, span_warning("This device doesn't have any components installed."))
return
var/list/component_names = list()
for(var/h in all_components)
var/obj/item/computer_hardware/H = all_components[h]
component_names.Add(H.name)
var/choice = tgui_input_list(user, "Which component do you want to uninstall?", "Computer maintenance", sortList(component_names))
var/choice = input(user, "Which component do you want to uninstall?", "Computer maintenance", null) as null|anything in sortList(component_names)
if(!choice)
return
@@ -460,28 +489,34 @@
if(W.tool_behaviour == TOOL_WRENCH)
if(all_components.len)
to_chat(user, "<span class='warning'>Remove all components from \the [src] before disassembling it.</span>")
to_chat(user, span_warning("Remove all components from \the [src] before disassembling it."))
return
new /obj/item/stack/sheet/metal( get_turf(src.loc), steel_sheet_cost )
physical.visible_message("<span class='notice'>\The [src] is disassembled by [user].</span>")
physical.visible_message(span_notice("\The [src] is disassembled by [user]."))
relay_qdel()
qdel(src)
return
if(W.tool_behaviour == TOOL_WELDER)
if(obj_integrity == max_integrity)
to_chat(user, "<span class='warning'>\The [src] does not require repairs.</span>")
to_chat(user, span_warning("\The [src] does not require repairs."))
return
if(!W.tool_start_check(user, amount=1))
return
to_chat(user, "<span class='notice'>You begin repairing damage to \the [src]...</span>")
to_chat(user, span_notice("You begin repairing damage to \the [src]..."))
if(W.use_tool(src, user, 20, volume=50, amount=1))
obj_integrity = max_integrity
to_chat(user, "<span class='notice'>You repair \the [src].</span>")
to_chat(user, span_notice("You repair \the [src]."))
return
var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
// Check to see if we have an ID inside, and a valid input for money
if(card_slot?.GetID() && iscash(W))
var/obj/item/card/id/id = card_slot.GetID()
id.attackby(W, user) // If we do, try and put that attacking object in
return
..()
// Used by processor to relay qdel() to machinery type.

View File

@@ -118,12 +118,6 @@
update_appearance()
if(user && istype(user))
ui_interact(user) // Re-open the UI on this computer. It should show the main screen now.
if("eject_pen")
if(istype(src, /obj/item/modular_computer/tablet))
var/obj/item/modular_computer/tablet/self = src
if(self.can_have_pen)
self.remove_pen()
return
if("PC_killprogram")
var/prog = params["name"]

View File

@@ -12,7 +12,7 @@
/datum/computer_file/program/crew_manifest/ui_static_data(mob/user)
var/list/data = list()
data["manifest"] = GLOB.data_core.get_manifest()
data["manifest"] = GLOB.data_core.get_manifest_tg()
return data
/datum/computer_file/program/crew_manifest/ui_data(mob/user)

View File

@@ -18,6 +18,7 @@
var/list/blacklisted = list(
"AI",
"Assistant",
"Prisoner",
"Cyborg",
"Captain",
"Head of Personnel",
@@ -98,7 +99,7 @@
if("PRG_priority")
var/priority_target = params["target"]
var/datum/job/j = SSjob.GetJob(priority_target)
if(!j || (job?.title in blacklisted))
if(!j || (j?.title in blacklisted))
return
if(j.total_positions <= j.current_positions)
return

View File

@@ -25,7 +25,7 @@
var/list/data = list()
data["library"] = SSpersistence.paintings["library"] ? SSpersistence.paintings["library"] : 0
data["library_secure"] = SSpersistence.paintings["library_secure"] ? SSpersistence.paintings["library_secure"] : 0
data["library_private"] = SSpersistence.paintings["library_private"] ? SSpersistence.paintings["library_private"] : 0 //i'm gonna regret this, won't i?
data["library_private"] = SSpersistence.paintings["library_private"] ? SSpersistence.paintings["library_private"] : 0 //i'm gonna regret this, won't i? Yes you should.
return data
/datum/computer_file/program/portrait_printer/ui_assets(mob/user)

View File

@@ -5,7 +5,7 @@
* lipstick wiping is in code/game/objects/items/weapons/cosmetics.dm!
*/
#define MAX_PAPER_LENGTH 5000
#define MAX_PAPER_STAMPS 30 // Too low?
#define MAX_PAPER_STAMPS 30 // Too low?
#define MAX_PAPER_STAMPS_OVERLAYS 4
#define MODE_READING 0
#define MODE_WRITING 1
@@ -22,6 +22,8 @@
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "paper"
item_state = "paper"
// worn_icon_state = "paper"
// custom_fire_overlay = "paper_onfire_overlay"
throwforce = 0
w_class = WEIGHT_CLASS_TINY
throw_range = 1
@@ -41,8 +43,8 @@
var/show_written_words = TRUE
/// The (text for the) stamps on the paper.
var/list/stamps /// Positioning for the stamp in tgui
var/list/stamped /// Overlay info
var/list/stamps /// Positioning for the stamp in tgui
var/list/stamped /// Overlay info
var/contact_poison // Reagent ID to transfer on contact
var/contact_poison_volume = 0
@@ -61,20 +63,23 @@
/**
* This proc copies this sheet of paper to a new
* sheet, Makes it nice and easy for carbon and
* the copyer machine
* sheet. Used by carbon papers and the photocopier machine.
*/
/obj/item/paper/proc/copy()
var/obj/item/paper/N = new(arglist(args))
N.info = info
N.color = color
N.update_icon_state()
N.stamps = stamps
N.stamped = stamped.Copy()
N.form_fields = form_fields.Copy()
N.field_counter = field_counter
copy_overlays(N, TRUE)
return N
/obj/item/paper/proc/copy(paper_type = /obj/item/paper, atom/location = loc, colored = TRUE)
var/obj/item/paper/new_paper = new paper_type (location)
if(colored)
new_paper.color = color
new_paper.info = info
else //This basically just breaks the existing color tag, which we need to do because the innermost tag takes priority.
var/static/greyscale_info = regex("<font face=\"([PEN_FONT]|[CRAYON_FONT])\" color=", "i")
new_paper.info = replacetext(info, greyscale_info, "<font face=\"$1\" nocolor=")
new_paper.stamps = stamps?.Copy()
new_paper.stamped = stamped?.Copy()
new_paper.form_fields = form_fields.Copy()
new_paper.field_counter = field_counter
new_paper.update_icon_state()
copy_overlays(new_paper, TRUE)
return new_paper
/**
* This proc sets the text of the paper and updates the
@@ -100,11 +105,12 @@
. = ..()
pixel_x = initial(pixel_x) + rand(-9, 9)
pixel_y = initial(pixel_y) + rand(-8, 8)
update_icon()
update_appearance()
/obj/item/paper/update_icon_state()
if(info && show_written_words)
icon_state = "[initial(icon_state)]_words"
return ..()
/obj/item/paper/verb/rename()
set name = "Rename paper"
@@ -116,17 +122,17 @@
if(ishuman(usr))
var/mob/living/carbon/human/H = usr
if(HAS_TRAIT(H, TRAIT_CLUMSY) && prob(25))
to_chat(H, "<span class='warning'>You cut yourself on the paper! Ahhhh! Ahhhhh!</span>")
to_chat(H, span_warning("You cut yourself on the paper! Ahhhh! Ahhhhh!"))
H.damageoverlaytemp = 9001
H.update_damage_hud()
return
var/n_name = stripped_input(usr, "What would you like to label the paper?", "Paper Labelling", null, MAX_NAME_LEN)
if((loc == usr && usr.stat == CONSCIOUS))
if(((loc == usr || istype(loc, /obj/item/clipboard)) && usr.stat == CONSCIOUS))
name = "paper[(n_name ? text("- '[n_name]'") : null)]"
add_fingerprint(usr)
/obj/item/paper/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] scratches a grid on [user.p_their()] wrist with the paper! It looks like [user.p_theyre()] trying to commit sudoku...</span>")
user.visible_message(span_suicide("[user] scratches a grid on [user.p_their()] wrist with the paper! It looks like [user.p_theyre()] trying to commit sudoku..."))
return (BRUTELOSS)
/obj/item/paper/proc/clearpaper()
@@ -139,18 +145,18 @@
/obj/item/paper/examine(mob/user)
. = ..()
if(!in_range(user, src) && !isobserver(user))
. += "<span class='warning'>You're too far away to read it!</span>"
. += span_warning("You're too far away to read it!")
return
if(user.can_read(src))
ui_interact(user)
return
. += "<span class='warning'>You cannot read it!</span>"
. += span_warning("You cannot read it!")
/obj/item/paper/ui_status(mob/user,/datum/ui_state/state)
// Are we on fire? Hard ot read if so
if(resistance_flags & ON_FIRE)
return UI_CLOSE
if(!in_range(user,src))
if(!in_range(user, src) && !isobserver(user))
return UI_CLOSE
if(user.incapacitated(TRUE, TRUE) || (isobserver(user) && !IsAdminGhost(user)))
return UI_UPDATE
@@ -158,7 +164,7 @@
// .. or if you cannot read
if(!user.can_read(src))
return UI_CLOSE
if(in_contents_of(/obj/machinery/door/airlock))
if(in_contents_of(/obj/machinery/door/airlock) || in_contents_of(/obj/item/clipboard))
return UI_INTERACTIVE
return ..()
@@ -176,8 +182,8 @@
return
. = TRUE
if(!bypass_clumsy && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(10) && Adjacent(user))
user.visible_message("<span class='warning'>[user] accidentally ignites [user.p_them()]self!</span>", \
"<span class='userdanger'>You miss [src] and accidentally light yourself on fire!</span>")
user.visible_message(span_warning("[user] accidentally ignites [user.p_them()]self!"), \
span_userdanger("You miss [src] and accidentally light yourself on fire!"))
if(user.is_holding(I)) //checking if they're holding it in case TK is involved
user.dropItemToGround(I)
user.adjust_fire_stacks(1)
@@ -195,19 +201,23 @@
SStgui.close_uis(src)
return
if(istype(P, /obj/item/pen) || istype(P, /obj/item/toy/crayon))
// Enable picking paper up by clicking on it with the clipboard or folder
if(istype(P, /obj/item/clipboard) || istype(P, /obj/item/folder))
P.attackby(src, user)
return
else if(istype(P, /obj/item/pen) || istype(P, /obj/item/toy/crayon))
if(length(info) >= MAX_PAPER_LENGTH) // Sheet must have less than 1000 charaters
to_chat(user, "<span class='warning'>This sheet of paper is full!</span>")
to_chat(user, span_warning("This sheet of paper is full!"))
return
ui_interact(user)
return
else if(istype(P, /obj/item/stamp))
to_chat(user, "<span class='notice'>You ready your stamp over the paper! </span>")
to_chat(user, span_notice("You ready your stamp over the paper! "))
ui_interact(user)
return /// Normaly you just stamp, you don't need to read the thing
else
// cut paper? the sky is the limit!
ui_interact(user) // The other ui will be created with just read mode outside of this
ui_interact(user) // The other ui will be created with just read mode outside of this
return ..()
@@ -234,8 +244,8 @@
. = list()
.["text"] = info
.["max_length"] = MAX_PAPER_LENGTH
.["paper_color"] = !color || color == "white" ? "#FFFFFF" : color // color might not be set
.["paper_state"] = icon_state /// TODO: show the sheet will bloodied or crinkling?
.["paper_color"] = !color || color == "white" ? "#FFFFFF" : color // color might not be set
.["paper_state"] = icon_state /// TODO: show the sheet will bloodied or crinkling?
.["stamps"] = stamps
@@ -244,27 +254,34 @@
var/list/data = list()
data["edit_usr"] = "[user]"
var/obj/O = user.get_active_held_item()
if(istype(O, /obj/item/toy/crayon))
var/obj/item/toy/crayon/PEN = O
var/obj/holding = user.get_active_held_item()
// Use a clipboard's pen, if applicable
if(istype(loc, /obj/item/clipboard))
var/obj/item/clipboard/clipboard = loc
// This is just so you can still use a stamp if you're holding one. Otherwise, it'll
// use the clipboard's pen, if applicable.
if(!istype(holding, /obj/item/stamp) && clipboard.pen)
holding = clipboard.pen
if(istype(holding, /obj/item/toy/crayon))
var/obj/item/toy/crayon/PEN = holding
data["pen_font"] = CRAYON_FONT
data["pen_color"] = PEN.paint_color
data["edit_mode"] = MODE_WRITING
data["is_crayon"] = TRUE
data["stamp_class"] = "FAKE"
data["stamp_icon_state"] = "FAKE"
else if(istype(O, /obj/item/pen))
var/obj/item/pen/PEN = O
else if(istype(holding, /obj/item/pen))
var/obj/item/pen/PEN = holding
data["pen_font"] = PEN.font
data["pen_color"] = PEN.colour
data["edit_mode"] = MODE_WRITING
data["is_crayon"] = FALSE
data["stamp_class"] = "FAKE"
data["stamp_icon_state"] = "FAKE"
else if(istype(O, /obj/item/stamp))
else if(istype(holding, /obj/item/stamp))
var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/simple/paper)
data["stamp_icon_state"] = O.icon_state
data["stamp_class"] = sheet.icon_class_name(O.icon_state)
data["stamp_icon_state"] = holding.icon_state
data["stamp_class"] = sheet.icon_class_name(holding.icon_state)
data["edit_mode"] = MODE_STAMPING
data["pen_font"] = "FAKE"
data["pen_color"] = "FAKE"
@@ -276,6 +293,10 @@
data["is_crayon"] = FALSE
data["stamp_icon_state"] = "FAKE"
data["stamp_class"] = "FAKE"
if(istype(loc, /obj/structure/noticeboard))
var/obj/structure/noticeboard/noticeboard = loc
if(!noticeboard.allowed(user))
data["edit_mode"] = MODE_READING
data["field_counter"] = field_counter
data["form_fields"] = form_fields
@@ -289,14 +310,14 @@
if("stamp")
var/stamp_x = text2num(params["x"])
var/stamp_y = text2num(params["y"])
var/stamp_r = text2num(params["r"]) // rotation in degrees
var/stamp_r = text2num(params["r"]) // rotation in degrees
var/stamp_icon_state = params["stamp_icon_state"]
var/stamp_class = params["stamp_class"]
if (isnull(stamps))
stamps = list()
if(stamps.len < MAX_PAPER_STAMPS)
// I hate byond when dealing with freaking lists
stamps[++stamps.len] = list(stamp_class, stamp_x, stamp_y, stamp_r) /// WHHHHY
stamps[++stamps.len] = list(stamp_class, stamp_x, stamp_y, stamp_r) /// WHHHHY
/// This does the overlay stuff
if (isnull(stamped))
@@ -307,10 +328,11 @@
stampoverlay.pixel_y = rand(-3, 2)
add_overlay(stampoverlay)
LAZYADD(stamped, stamp_icon_state)
update_icon()
update_static_data(usr,ui)
var/obj/O = ui.user.get_active_held_item()
ui.user.visible_message("<span class='notice'>[ui.user] stamps [src] with \the [O.name]!</span>", "<span class='notice'>You stamp [src] with \the [O.name]!</span>")
ui.user.visible_message(span_notice("[ui.user] stamps [src] with \the [O.name]!"), span_notice("You stamp [src] with \the [O.name]!"))
else
to_chat(usr, pick("You try to stamp but you miss!", "There is no where else you can stamp!"))
. = TRUE
@@ -336,9 +358,14 @@
update_static_data(usr,ui)
update_icon()
update_appearance()
. = TRUE
/obj/item/paper/ui_host(mob/user)
if(istype(loc, /obj/structure/noticeboard))
return loc
return ..()
/**
* Construction paper
*/
@@ -361,9 +388,6 @@
slot_flags = null
show_written_words = FALSE
/obj/item/paper/crumpled/update_icon_state()
return
/obj/item/paper/crumpled/bloody
icon_state = "scrap_bloodied"

View File

@@ -62,7 +62,7 @@
for(var/datum/mind/cult_mind in SSticker.mode.cult)
if(isliving(cult_mind.current))
var/mob/living/L = cult_mind.current
L.narsie_act()
INVOKE_ASYNC(L, /atom.proc/narsie_act)
for(var/mob/living/player in GLOB.player_list)
if(player.stat != DEAD && player.loc && is_station_level(player.loc.z) && !iscultist(player) && !isanimal(player))
souls_needed[player] = TRUE

View File

@@ -229,6 +229,57 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
if (!istype(C.glasses, /obj/item/clothing/glasses/meson) && (get_dist(user, src) < HALLUCINATION_RANGE(power)))
. += "<span class='danger'>You get headaches just from looking at it.</span>"
// SupermatterMonitor UI for ghosts only. Inherited attack_ghost will call this.
/obj/machinery/power/supermatter_crystal/ui_interact(mob/user, datum/tgui/ui)
if(!isobserver(user))
return FALSE
. = ..()
ui = SStgui.try_update_ui(user, src, ui)
if (!ui)
ui = new(user, src, "SupermatterMonitor")
ui.open()
/obj/machinery/power/supermatter_crystal/ui_data(mob/user)
var/list/data = list()
var/turf/local_turf = get_turf(src)
var/datum/gas_mixture/air = local_turf.return_air()
// singlecrystal set to true eliminates the back sign on the gases breakdown.
data["singlecrystal"] = TRUE
data["active"] = TRUE
data["SM_integrity"] = get_integrity()
data["SM_power"] = power
data["SM_ambienttemp"] = air.return_temperature()
data["SM_ambientpressure"] = air.return_pressure()
data["SM_bad_moles_amount"] = MOLE_PENALTY_THRESHOLD / gasefficency
data["SM_moles"] = 0
data["SM_uid"] = uid
var/area/active_supermatter_area = get_area(src)
data["SM_area_name"] = active_supermatter_area.name
var/list/gasdata = list()
if(air.total_moles())
data["SM_moles"] = air.total_moles()
for(var/id in air.get_gases())
var/gas_level = air.get_moles(id)/air.total_moles()
if(gas_level > 0)
gasdata.Add(list(list(
"name"= "[GLOB.gas_data.names[id]]",
"amount" = round(gas_level*100, 0.01))))
else
for(var/id in air.get_gases())
gasdata.Add(list(list(
"name"= "[GLOB.gas_data.names[id]]",
"amount" = 0)))
data["gases"] = gasdata
return data
/obj/machinery/power/supermatter_crystal/proc/get_status()
var/turf/T = get_turf(src)
if(!T)

View File

@@ -19,25 +19,46 @@
throw_range = 7
w_class = WEIGHT_CLASS_SMALL
/// The uplink flag for this type.
/// See [`code/__DEFINES/uplink.dm`]
var/uplink_flag = UPLINK_TRAITORS
/obj/item/uplink/Initialize(mapload, owner, tc_amount = 20)
. = ..()
AddComponent(/datum/component/uplink, owner, FALSE, TRUE, null, tc_amount)
AddComponent(/datum/component/uplink, owner, FALSE, TRUE, uplink_flag, tc_amount)
/obj/item/uplink/nuclear/Initialize()
/obj/item/uplink/debug
name = "debug uplink"
/obj/item/uplink/debug/Initialize(mapload, owner, tc_amount = 9000)
. = ..()
var/datum/component/uplink/hidden_uplink = GetComponent(/datum/component/uplink)
hidden_uplink.set_gamemode(/datum/game_mode/nuclear)
hidden_uplink.name = "debug uplink"
hidden_uplink.debug = TRUE
/obj/item/uplink/nuclear
uplink_flag = UPLINK_NUKE_OPS
/obj/item/uplink/nuclear/debug
name = "debug nuclear uplink"
uplink_flag = UPLINK_NUKE_OPS
/obj/item/uplink/nuclear/debug/Initialize(mapload, owner, tc_amount = 9000)
. = ..()
var/datum/component/uplink/hidden_uplink = GetComponent(/datum/component/uplink)
hidden_uplink.name = "debug nuclear uplink"
hidden_uplink.debug = TRUE
/obj/item/uplink/nuclear_restricted
uplink_flag = UPLINK_NUKE_OPS
/obj/item/uplink/nuclear_restricted/Initialize()
. = ..()
var/datum/component/uplink/hidden_uplink = GetComponent(/datum/component/uplink)
hidden_uplink.allow_restricted = FALSE
hidden_uplink.set_gamemode(/datum/game_mode/nuclear)
/obj/item/uplink/clownop/Initialize()
. = ..()
var/datum/component/uplink/hidden_uplink = GetComponent(/datum/component/uplink)
hidden_uplink.set_gamemode(/datum/game_mode/nuclear/clown_ops)
/obj/item/uplink/clownop
uplink_flag = UPLINK_CLOWN_OPS
/obj/item/uplink/old
name = "dusty radio"
@@ -51,28 +72,9 @@
// Multitool uplink
/obj/item/multitool/uplink/Initialize(mapload, owner, tc_amount = 20)
. = ..()
AddComponent(/datum/component/uplink, owner, FALSE, TRUE, null, tc_amount)
AddComponent(/datum/component/uplink, owner, FALSE, TRUE, UPLINK_TRAITORS, tc_amount)
// Pen uplink
/obj/item/pen/uplink/Initialize(mapload, owner, tc_amount = 20)
. = ..()
AddComponent(/datum/component/uplink, owner, TRUE, FALSE, null, tc_amount)
/obj/item/uplink/debug
name = "debug uplink"
/obj/item/uplink/debug/Initialize(mapload, owner, tc_amount = 9000)
. = ..()
var/datum/component/uplink/hidden_uplink = GetComponent(/datum/component/uplink)
hidden_uplink.name = "debug uplink"
hidden_uplink.debug = TRUE
/obj/item/uplink/nuclear/debug
name = "debug nuclear uplink"
/obj/item/uplink/nuclear/debug/Initialize(mapload, owner, tc_amount = 9000)
. = ..()
var/datum/component/uplink/hidden_uplink = GetComponent(/datum/component/uplink)
hidden_uplink.set_gamemode(/datum/game_mode/nuclear)
hidden_uplink.name = "debug nuclear uplink"
hidden_uplink.debug = TRUE
AddComponent(/datum/component/uplink, owner, TRUE, FALSE, UPLINK_TRAITORS, tc_amount)

View File

@@ -1,54 +1,76 @@
/proc/get_uplink_items(datum/game_mode/gamemode, allow_sales = TRUE, allow_restricted = TRUE, other_filter = list())
var/list/filtered_uplink_items = GLOB.uplink_categories.Copy() // list of uplink categories without associated values.
GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/proc/get_uplink_items(uplink_flag, allow_sales = TRUE, allow_restricted = TRUE)
var/list/filtered_uplink_items = list()
var/list/sale_items = list()
for(var/path in GLOB.uplink_items)
var/datum/uplink_item/I = new path
if(I.include_modes.len)
if(!gamemode && SSticker.mode && !(SSticker.mode.type in I.include_modes))
continue
if(gamemode && !(gamemode in I.include_modes))
continue
if(I.exclude_modes.len)
if(!gamemode && SSticker.mode && (SSticker.mode.type in I.exclude_modes))
continue
if(gamemode && (gamemode in I.exclude_modes))
continue
if(!I.item)
continue
if (!(I.purchasable_from & uplink_flag))
continue
if(I.player_minimum && I.player_minimum > GLOB.joined_player_list.len)
continue
if (I.restricted && !allow_restricted)
continue
if (I.type in other_filter)
continue
LAZYSET(filtered_uplink_items[I.category], I.name, I)
if(!filtered_uplink_items[I.category])
filtered_uplink_items[I.category] = list()
filtered_uplink_items[I.category][I.name] = I
if(I.limited_stock < 0 && !I.cant_discount && I.item && I.cost > 1)
sale_items += I
if(allow_sales)
for(var/i in 1 to 3)
var/datum/uplink_item/I = pick_n_take(sale_items)
var/datum/uplink_item/A = new I.type
var/discount = A.get_discount()
var/list/disclaimer = list("Void where prohibited.", "Not recommended for children.", "Contains small parts.", "Check local laws for legality in region.", "Do not taunt.", "Not responsible for direct, indirect, incidental or consequential damages resulting from any defect, error or failure to perform.", "Keep away from fire or flames.", "Product is provided \"as is\" without any implied or expressed warranties.", "As seen on TV.", "For recreational use only.", "Use only as directed.", "16% sales tax will be charged for orders originating within Space Nebraska.")
A.limited_stock = 1
I.refundable = FALSE //THIS MAN USES ONE WEIRD TRICK TO GAIN FREE TC, CODERS HATES HIM!
A.refundable = FALSE
if(A.cost >= 20) //Tough love for nuke ops
discount *= 0.5
A.cost = max(round(A.cost * discount),1)
A.category = "Discounted Gear"
A.name += " ([round(((initial(A.cost)-A.cost)/initial(A.cost))*100)]% off!)"
A.desc += " Normally costs [initial(A.cost)] TC. All sales final. [pick(disclaimer)]"
A.item = I.item
var/datum/team/nuclear/nuclear_team
// if (uplink_flag & UPLINK_NUKE_OPS) // uplink code kind of needs a redesign
// nuclear_team = locate() in GLOB.antagonist_teams // the team discounts could be in a GLOB with this design but it would make sense for them to be team specific...
if (!nuclear_team)
create_uplink_sales(3, "Discounted Gear", 1, sale_items, filtered_uplink_items)
else
if (!nuclear_team.team_discounts)
// create 5 unlimited stock discounts
create_uplink_sales(5, "Discounted Team Gear", -1, sale_items, filtered_uplink_items)
// Create 10 limited stock discounts
create_uplink_sales(10, "Limited Stock Team Gear", 1, sale_items, filtered_uplink_items)
nuclear_team.team_discounts = list("Discounted Team Gear" = filtered_uplink_items["Discounted Team Gear"], "Limited Stock Team Gear" = filtered_uplink_items["Limited Stock Team Gear"])
else
for(var/cat in nuclear_team.team_discounts)
for(var/item in nuclear_team.team_discounts[cat])
var/datum/uplink_item/D = nuclear_team.team_discounts[cat][item]
var/datum/uplink_item/O = filtered_uplink_items[initial(D.category)][initial(D.name)]
O.refundable = FALSE
LAZYSET(filtered_uplink_items[A.category], A.name, A)
filtered_uplink_items["Discounted Team Gear"] = nuclear_team.team_discounts["Discounted Team Gear"]
filtered_uplink_items["Limited Stock Team Gear"] = nuclear_team.team_discounts["Limited Stock Team Gear"]
for(var/category in filtered_uplink_items)
if(!filtered_uplink_items[category]) //empty categories with no associated uplink item. Remove.
filtered_uplink_items -= category
return filtered_uplink_items
/proc/create_uplink_sales(num, category_name, limited_stock, sale_items, uplink_items)
if (num <= 0)
return
if(!uplink_items[category_name])
uplink_items[category_name] = list()
for (var/i in 1 to num)
var/datum/uplink_item/I = pick_n_take(sale_items)
var/datum/uplink_item/A = new I.type
var/discount = A.get_discount()
var/list/disclaimer = list("Void where prohibited.", "Not recommended for children.", "Contains small parts.", "Check local laws for legality in region.", "Do not taunt.", "Not responsible for direct, indirect, incidental or consequential damages resulting from any defect, error or failure to perform.", "Keep away from fire or flames.", "Product is provided \"as is\" without any implied or expressed warranties.", "As seen on TV.", "For recreational use only.", "Use only as directed.", "16% sales tax will be charged for orders originating within Space Nebraska.")
A.limited_stock = limited_stock
I.refundable = FALSE //THIS MAN USES ONE WEIRD TRICK TO GAIN FREE TC, CODERS HATES HIM!
A.refundable = FALSE
if(A.cost >= 20) //Tough love for nuke ops
discount *= 0.5
A.category = category_name
A.cost = max(round(A.cost * discount),1)
A.name += " ([round(((initial(A.cost)-A.cost)/initial(A.cost))*100)]% off!)"
A.desc += " Normally costs [initial(A.cost)] TC. All sales final. [pick(disclaimer)]"
A.item = I.item
uplink_items[category_name][A.name] = A
/**
* Uplink Items
@@ -67,12 +89,14 @@
var/surplus = 100 // Chance of being included in the surplus crate.
var/cant_discount = FALSE
var/limited_stock = -1 //Setting this above zero limits how many times this item can be bought by the same traitor in a round, -1 is unlimited
var/list/include_modes = list() // Game modes to allow this item in.
var/list/exclude_modes = list() // Game modes to disallow this item from.
/// A bitfield to represent what uplinks can purchase this item.
/// See [`code/__DEFINES/uplink.dm`].
var/purchasable_from = ALL
var/list/restricted_roles = list() //If this uplink item is only available to certain roles. Roles are dependent on the frequency chip or stored ID.
var/player_minimum //The minimum crew size needed for this item to be added to uplinks.
var/purchase_log_vis = TRUE // Visible in the purchase log?
var/restricted = FALSE // Adds restrictions for VR/Events
var/list/restricted_species //Limits items to a specific species. Hopefully.
var/illegal_tech = TRUE // Can this item be deconstructed to unlock certain techweb research nodes?
/datum/uplink_item/proc/get_discount()
@@ -80,6 +104,7 @@
/datum/uplink_item/proc/purchase(mob/user, datum/component/uplink/U)
var/atom/A = spawn_item(item, user, U)
// log_uplink("[key_name(user)] purchased [src] for [cost] telecrystals from [U.parent]'s uplink")
if(purchase_log_vis && U.purchase_log)
U.purchase_log.LogPurchase(A, src, cost)
@@ -94,70 +119,66 @@
if(ishuman(user) && istype(A, /obj/item))
var/mob/living/carbon/human/H = user
if(H.put_in_hands(A))
to_chat(H, "[A] materializes into your hands!")
to_chat(H, span_boldnotice("[A] materializes into your hands!"))
return A
to_chat(user, "[A] materializes onto the floor.")
to_chat(user, span_boldnotice("[A] materializes onto the floor!"))
return A
/*
Uplink Categories:
Due to how the typesof() in-built byond proc works, it should be kept in mind
the order categories are displayed in the uplink UI is same to the order they are loaded in the code.
I trust no extra filter is needed as long as they are all contained within the following lines.
When adding new uplink categories, please keep them separate from their sub paths here and without set item.
Failure to comply may result in the new categories being listed at the bottom of the UI.
*/
//Discounts (dynamically filled above)
/datum/uplink_item/discounts
category = "Discounts"
// cit specific. idk
/datum/uplink_item/holiday
category = "Holiday"
/datum/uplink_item/bundles_TC
category = "Telecrystals and Bundles"
//All bundles and telecrystals
/datum/uplink_item/bundles_tc
category = "Bundles"
surplus = 0
cant_discount = TRUE
// Dangerous Items
/datum/uplink_item/dangerous
category = "Conspicuous Weapons"
/datum/uplink_item/stealthy_weapons
category = "Stealthy Weapons"
/datum/uplink_item/ammo
category = "Ammunition"
surplus = 40
/datum/uplink_item/explosives
category = "Explosives"
//Support and Mechs
/datum/uplink_item/support
category = "Support and Exosuits"
surplus = 0
include_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/suits
category = "Clothing"
surplus = 40
purchasable_from = UPLINK_NUKE_OPS
// Stealth Items
/datum/uplink_item/stealthy_tools
category = "Stealth Gadgets"
//Space Suits and Hardsuits
/datum/uplink_item/suits
category = "Space Suits"
surplus = 40
// Devices and Tools
/datum/uplink_item/device_tools
category = "Misc. Gadgets"
// Implants
/datum/uplink_item/implants
category = "Implants"
surplus = 50
//Race-specific items
/datum/uplink_item/race_restricted
category = "Species-Restricted"
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
surplus = 0
// Role-specific items
/datum/uplink_item/role_restricted
category = "Role-Restricted"
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
surplus = 0
cant_discount = TRUE
// Pointless
/datum/uplink_item/badass
category = "(Pointless) Badassery"
surplus = 0
//Discounts (dynamically filled above)
/datum/uplink_item/discounts
category = "Discounted Gear"

View File

@@ -12,7 +12,7 @@
desc = "Contains 10 additional .45-70 GOVT rounds. Caliber is exceedingly rare, and thus, comes at a premium."
item = /obj/item/ammo_box/g4570
cost = 5
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/ammo/pistol
name = "10mm Handgun Magazine"
@@ -20,7 +20,7 @@
are dirt cheap but are half as effective as .357 rounds."
item = /obj/item/ammo_box/magazine/m10mm
cost = 1
exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
purchasable_from = ~UPLINK_CLOWN_OPS
/datum/uplink_item/ammo/pistol/box
name = "Ammo Box - 10mm"
@@ -34,7 +34,7 @@
These rounds are less effective at injuring the target but penetrate protective gear."
item = /obj/item/ammo_box/magazine/m10mm/ap
cost = 2
exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
purchasable_from = ~UPLINK_CLOWN_OPS
/datum/uplink_item/ammo/pistolap/box
name = "Ammo Box - 10mm Armour Piercing"
@@ -48,7 +48,7 @@
These rounds are more damaging but ineffective against armour."
item = /obj/item/ammo_box/magazine/m10mm/hp
cost = 3
exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
purchasable_from = ~UPLINK_CLOWN_OPS
/datum/uplink_item/ammo/pistolhp/box
name = "Ammo Box - 10mm Hollow Point"
@@ -62,7 +62,7 @@
Loaded with incendiary rounds which inflict little damage, but ignite the target."
item = /obj/item/ammo_box/magazine/m10mm/fire
cost = 2
exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
purchasable_from = ~UPLINK_CLOWN_OPS
/datum/uplink_item/ammo/pistolfire/box
name = "Ammo Box - 10mm Incendiary"
@@ -85,7 +85,7 @@
/datum/uplink_item/ammo/shotgun
cost = 2
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/ammo/shotgun/bag
name = "12g Ammo Duffel Bag"
@@ -136,7 +136,7 @@
For when you really need a lot of things dead."
item = /obj/item/ammo_box/a357
cost = 3
exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
purchasable_from = ~UPLINK_CLOWN_OPS
/datum/uplink_item/ammo/revolver/ap
name = ".357 Armor Piercing Speed Loader"
@@ -150,25 +150,25 @@
Your teammates will ask you to not shoot these down small hallways."
item = /obj/item/ammo_casing/a40mm
cost = 2
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/ammo/smg/bag
name = ".45 Ammo Duffel Bag"
desc = "A duffel bag filled with enough .45 ammo to supply an entire team, at a discounted price."
item = /obj/item/storage/backpack/duffelbag/syndie/ammo/smg
cost = 20 //instead of 27 TC
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/ammo/smg
name = ".45 SMG Magazine"
desc = "An additional 24-round .45 magazine suitable for use with the C-20r submachine gun."
item = /obj/item/ammo_box/magazine/smgm45
cost = 3
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/ammo/sniper
cost = 4
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/ammo/sniper/basic
name = ".50 Magazine"
@@ -194,7 +194,7 @@
These bullets pack less punch than 7.12x82mm rounds, but they still offer more power than .45 ammo."
item = /obj/item/ammo_box/magazine/m556
cost = 4
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/ammo/machinegun/match
name = "7.12x82mm (Match) Box Magazine"
@@ -206,7 +206,7 @@
/datum/uplink_item/ammo/machinegun
cost = 6
surplus = 0
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/ammo/machinegun/basic
name = "1.95x129mm Box Magazine"
@@ -234,7 +234,7 @@
item = /obj/item/ammo_box/magazine/mm195x129/incen
/datum/uplink_item/ammo/rocket
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/ammo/rocket/basic
name = "84mm HE Rocket"
@@ -254,7 +254,7 @@
desc = "An additional 15-round 9mm magazine, compatible with the Stechkin APS pistol, found in the Spetsnaz Pyro bundle."
item = /obj/item/ammo_box/magazine/pistolm9mm
cost = 2
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/ammo/pistolaps
name = "Ammo Box - 9mm"
@@ -268,7 +268,7 @@
Loaded with armor piercing flechettes that very nearly ignore armor, but are not very effective against flesh."
item = /obj/item/ammo_box/magazine/flechette
cost = 2
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/ammo/flechettes
name = "Serrated Flechette Magazine"
@@ -277,7 +277,7 @@
These flechettes are highly likely to sever arteries, and even limbs."
item = /obj/item/ammo_box/magazine/flechette/s
cost = 2
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/ammo/toydarts
name = "Box of Riot Darts"
@@ -293,32 +293,32 @@
and broca systems, making it impossible for them to move or speak for some time."
item = /obj/item/storage/box/syndie_kit/bioterror
cost = 6
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
/datum/uplink_item/ammo/bolt_action
name = "Surplus Rifle Clip"
desc = "A stripper clip used to quickly load bolt action rifles. Contains 5 rounds."
item = /obj/item/ammo_box/a762
cost = 1
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/ammo/bolt_action_bulk
name = "Surplus Rifle Clip Box"
desc = "An ammo box we found in a warehouse, holding 7 clips of 5 rounds for bolt-action rifles. Yes, the cheap ones."
item = /obj/item/storage/toolbox/ammo
cost = 4
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/ammo/dark_gygax/bag
name = "Dark Gygax Ammo Bag"
desc = "A duffel bag containing ammo for three full reloads of the incendiary carbine and flash bang launcher that are equipped on a standard Dark Gygax exosuit."
item = /obj/item/storage/backpack/duffelbag/syndie/ammo/dark_gygax
cost = 4
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/ammo/mauler/bag
name = "Mauler Ammo Bag"
desc = "A duffel bag containing ammo for three full reloads of the LMG, scattershot carbine, and SRM-8 missile laucher that are equipped on a standard Mauler exosuit."
item = /obj/item/storage/backpack/duffelbag/syndie/ammo/mauler
cost = 6
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS

View File

@@ -14,9 +14,9 @@
item = /obj/item/storage/box/syndie_kit/chameleon/broken
/datum/uplink_item/badass/costumes
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
cost = 4
cant_discount = TRUE
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
/datum/uplink_item/badass/costumes/centcom_official
name = "CentCom Official Costume"
@@ -77,14 +77,14 @@
cost = 4
limited_stock = 1
cant_discount = TRUE
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
/datum/uplink_item/badass/gaming_cardpack
name = "TCG Card Operatives Bundle"
desc = "A bundle full of goodies required to work as a TCG Card Operative. A warm pajama, a mug of cocoa, a plushie and a two packs full of rare 2560 Core Set cards!"
item = /obj/item/storage/box/syndie_kit/sleepytime/cardpack
cost = 20
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
/datum/uplink_item/badass/cardpack
name = "TCG Nuclear Cardpack"

View File

@@ -7,30 +7,30 @@
When adding new entries to the file, please keep them sorted by category.
*/
/datum/uplink_item/bundles_TC/chemical
/datum/uplink_item/bundles_tc/chemical
name = "Bioterror bundle"
desc = "For the madman: Contains a handheld Bioterror chem sprayer, a Bioterror foam grenade, a box of lethal chemicals, a dart pistol, \
box of syringes, Donksoft assault rifle, and some riot darts. Remember: Seal suit and equip internals before use."
item = /obj/item/storage/backpack/duffelbag/syndie/med/bioterrorbundle
cost = 30 // normally 42
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/bundles_TC/bulldog
/datum/uplink_item/bundles_tc/bulldog
name = "Bulldog bundle"
desc = "Lean and mean: Optimized for people that want to get up close and personal. Contains the popular \
Bulldog shotgun, a 12g buckshot drum, a 12g taser slug drum and a pair of Thermal imaging goggles."
item = /obj/item/storage/backpack/duffelbag/syndie/bulldogbundle
cost = 13 // normally 16
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/bundles_TC/c20r
/datum/uplink_item/bundles_tc/c20r
name = "C-20r bundle"
desc = "Old Faithful: The classic C-20r, bundled with two magazines, and a (surplus) suppressor at discount price."
item = /obj/item/storage/backpack/duffelbag/syndie/c20rbundle
cost = 14 // normally 16
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/bundles_TC/contract_kit
/datum/uplink_item/bundles_tc/contract_kit
name = "Contract Kit"
desc = "The Syndicate have offered you the chance to become a contractor, take on kidnapping contracts for TC and cash payouts. Upon purchase, \
you'll be granted your own contract uplink embedded within the supplied tablet computer. Additionally, you'll be granted \
@@ -39,10 +39,10 @@
item = /obj/item/storage/box/syndie_kit/contract_kit
cost = 20
player_minimum = 25
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
restricted = TRUE
/datum/uplink_item/bundles_TC/northstar_bundle
/datum/uplink_item/bundles_tc/northstar_bundle
name = "Northstar Bundle"
desc = "An item usually reserved for the Gorlex Marauders and their operatives, now available for recreational use. \
These armbands let the user punch people very fast and with the lethality of a legendary martial artist. \
@@ -50,16 +50,16 @@
Combines with all martial arts, but the user will be unable to bring themselves to use guns, nor remove the armbands."
item = /obj/item/storage/box/syndie_kit/northstar
cost = 20
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs)
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
/datum/uplink_item/bundles_TC/scarp_bundle
/datum/uplink_item/bundles_tc/scarp_bundle
name = "Sleeping Carp Bundle"
desc = "Become one with your inner carp! Your ancient fish masters leave behind their legacy, and bestow to you their teachings, sacred uniform, and staff. \
Please be aware that you will not be able to use dishonerable ranged weapons."
item = /obj/item/storage/box/syndie_kit/scarp
cost = 20
player_minimum = 20
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs)
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
/datum/uplink_item/suits/infiltrator_bundle
name = "Insidious Infiltration Gear Case"
@@ -69,86 +69,85 @@
item = /obj/item/storage/toolbox/infiltrator
cost = 5
limited_stock = 1 //you only get one so you don't end up with too many gun cases
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
/datum/uplink_item/bundles_TC/cybernetics_bundle
/datum/uplink_item/bundles_tc/cybernetics_bundle
name = "Cybernetic Implants Bundle"
desc = "A random selection of cybernetic implants. Guaranteed 5 high quality implants. Comes with an autosurgeon."
item = /obj/item/storage/box/cyber_implants
cost = 40
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/bundles_TC/medical
/datum/uplink_item/bundles_tc/medical
name = "Medical bundle"
desc = "The support specialist: Aid your fellow operatives with this medical bundle. Contains a tactical medkit, \
a Donksoft LMG, a box of riot darts and a pair of magboots to rescue your friends in no-gravity environments."
item = /obj/item/storage/backpack/duffelbag/syndie/med/medicalbundle
cost = 15 // normally 20
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/bundles_TC/modular
/datum/uplink_item/bundles_tc/modular
name = "Modular Pistol Kit"
desc = "A heavy briefcase containing one modular pistol (chambered in 10mm), one supressor, and spare ammunition, including a box of soporific ammo. \
Includes a suit jacket that is padded with a robust liner."
item = /obj/item/storage/briefcase/modularbundle
cost = 12
/datum/uplink_item/bundles_TC/shredder
/datum/uplink_item/bundles_tc/shredder
name = "Shredder bundle"
desc = "A truly horrific weapon designed simply to maim its victim, the CX Shredder is banned by several intergalactic treaties. \
You'll get two of them with this. And spare ammo to boot. And we'll throw in an extra elite hardsuit and chest rig to hold them all!"
item = /obj/item/storage/backpack/duffelbag/syndie/shredderbundle
cost = 30 // normally 41
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/bundles_TC/sniper
/datum/uplink_item/bundles_tc/sniper
name = "Sniper bundle"
desc = "Elegant and refined: Contains a collapsed sniper rifle in an expensive carrying case, \
two soporific knockout magazines, a free surplus supressor, and a sharp-looking tactical turtleneck suit. \
We'll throw in a free red tie if you order NOW."
item = /obj/item/storage/briefcase/sniperbundle
cost = 20 // normally 26
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/bundles_TC/firestarter
/datum/uplink_item/bundles_tc/firestarter
name = "Spetsnaz Pyro bundle"
desc = "For systematic suppression of carbon lifeforms in close quarters: Contains a lethal New Russian backpack spray, Elite hardsuit, \
Stechkin APS pistol, two magazines, a minibomb and a stimulant syringe. \
Order NOW and comrade Boris will throw in an extra tracksuit."
item = /obj/item/storage/backpack/duffelbag/syndie/firestarter
cost = 30
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/bundles_TC/bundle
/datum/uplink_item/bundles_tc/bundle
name = "Syndicate Bundle"
desc = "Syndicate Bundles are specialized groups of items that arrive in a plain box. \
These items are collectively worth more than 20 telecrystals, but you do not know which specialization \
you will receive. May contain discontinued and/or exotic items."
item = /obj/item/storage/box/syndicate
cost = 20
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/traitor/internal_affairs)
purchasable_from = ~(UPLINK_NUKE_OPS)
cant_discount = TRUE
/datum/uplink_item/bundles_TC/surplus
/datum/uplink_item/bundles_tc/surplus
name = "Syndicate Surplus Crate"
desc = "A dusty crate from the back of the Syndicate warehouse. Rumored to contain a valuable assortment of items, \
but you never know. Contents are sorted to always be worth 50 TC."
item = /obj/structure/closet/crate
cost = 20
player_minimum = 20
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs)
cant_discount = TRUE
player_minimum = 25
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
var/starting_crate_value = 50
/datum/uplink_item/bundles_TC/surplus/super
/datum/uplink_item/bundles_tc/surplus/super
name = "Super Surplus Crate"
desc = "A dusty SUPER-SIZED from the back of the Syndicate warehouse. Rumored to contain a valuable assortment of items, \
but you never know. Contents are sorted to always be worth 125 TC."
cost = 40
player_minimum = 30
player_minimum = 40
starting_crate_value = 125
/datum/uplink_item/bundles_TC/surplus/purchase(mob/user, datum/component/uplink/U)
/datum/uplink_item/bundles_tc/surplus/purchase(mob/user, datum/component/uplink/U)
var/list/uplink_items = get_uplink_items(SSticker && SSticker.mode? SSticker.mode : null, FALSE)
var/crate_value = starting_crate_value
@@ -170,7 +169,7 @@
U.purchase_log.LogPurchase(goods, I, 0)
return C
/datum/uplink_item/bundles_TC/reroll
/datum/uplink_item/bundles_tc/reroll
name = "Renegotiate Contract"
desc = "Selecting this will inform your employers that you wish for new objectives. Can only be done twice."
item = /obj/effect/gibspawner/generic
@@ -179,22 +178,21 @@
restricted = TRUE
limited_stock = 2
/datum/uplink_item/bundles_TC/reroll/purchase(mob/user, datum/component/uplink/U)
/datum/uplink_item/bundles_tc/reroll/purchase(mob/user, datum/component/uplink/U)
var/datum/antagonist/traitor/T = user?.mind?.has_antag_datum(/datum/antagonist/traitor)
if(istype(T))
T.set_traitor_kind(get_random_traitor_kind(blacklist = list(/datum/traitor_class/human/freeform, /datum/traitor_class/human/hijack, /datum/traitor_class/human/martyr)))
else
to_chat(user,"Invalid user for contract renegotiation.")
/datum/uplink_item/bundles_TC/random
/datum/uplink_item/bundles_tc/random
name = "Random Item"
desc = "Picking this will purchase a random item. Useful if you have some TC to spare or if you haven't decided on a strategy yet."
item = /obj/effect/gibspawner/generic // non-tangible item because techwebs use this path to determine illegal tech
cost = 0
cant_discount = TRUE
exclude_modes = list(/datum/game_mode/traitor/internal_affairs)
/datum/uplink_item/bundles_TC/random/purchase(mob/user, datum/component/uplink/U)
/datum/uplink_item/bundles_tc/random/purchase(mob/user, datum/component/uplink/U)
var/list/uplink_items = U.uplink_items
var/list/possible_items = list()
for(var/category in uplink_items)
@@ -202,7 +200,7 @@
var/datum/uplink_item/I = uplink_items[category][item]
if(src == I || !I.item)
continue
if(istype(I, /datum/uplink_item/bundles_TC/reroll)) //oops!
if(istype(I, /datum/uplink_item/bundles_tc/reroll)) //oops!
continue
if(U.telecrystals < I.cost)
continue
@@ -215,7 +213,7 @@
SSblackbox.record_feedback("tally", "traitor_random_uplink_items_gotten", 1, initial(I.name))
U.MakePurchase(user, I)
/datum/uplink_item/bundles_TC/telecrystal
/datum/uplink_item/bundles_tc/telecrystal
name = "1 Raw Telecrystal"
desc = "A telecrystal in its rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
item = /obj/item/stack/telecrystal
@@ -226,13 +224,13 @@
// it's just used to buy more items (including itself!)
purchase_log_vis = FALSE
/datum/uplink_item/bundles_TC/telecrystal/five
/datum/uplink_item/bundles_tc/telecrystal/five
name = "5 Raw Telecrystals"
desc = "Five telecrystals in their rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
item = /obj/item/stack/telecrystal/five
cost = 5
/datum/uplink_item/bundles_TC/telecrystal/twenty
/datum/uplink_item/bundles_tc/telecrystal/twenty
name = "20 Raw Telecrystals"
desc = "Twenty telecrystals in their rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
item = /obj/item/stack/telecrystal/twenty

View File

@@ -12,35 +12,35 @@
desc = "A slightly armored conspicious jumpsuit that has no suit sensors attached to them, if someone sees you in this hope they think its a fake."
item = /obj/item/clothing/under/syndicate
cost = 1
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) //They already get these
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
/datum/uplink_item/suits/turtlenck_skirt
name = "Tactical Skirtleneck"
desc = "A slightly armored conspicious jumpsuit that has no suit sensors attached to them, if someone sees you in this hope they think its a fake."
item = /obj/item/clothing/under/syndicate/skirt
cost = 1
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) //They already get these
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
/datum/uplink_item/suits/padding
name = "Soft Padding"
desc = "An inconspicious soft padding meant to be worn underneath jumpsuits, will cushion the user from melee harm."
item = /obj/item/clothing/accessory/padding
cost = 2
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
/datum/uplink_item/suits/kevlar
name = "Kevlar Padding"
desc = "An inconspicious kevlar padding meant to be worn underneath jumpsuits, will cushion the wearer from ballistic harm."
item = /obj/item/clothing/accessory/kevlar
cost = 2
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
/datum/uplink_item/suits/plastic
name = "Ablative Padding"
desc = "An inconspicious ablative padding meant to be worn underneath jumpsuits, will cushion the wearer from energy lasers harm."
item = /obj/item/clothing/accessory/plastics
cost = 2
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
/datum/uplink_item/suits/space_suit
name = "Syndicate Space Suit"
@@ -59,7 +59,7 @@
Nanotrasen crew who spot these suits are known to panic."
item = /obj/item/clothing/suit/space/hardsuit/syndi
cost = 8
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) //you can't buy it in nuke, because the elite hardsuit costs the same while being better
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS) //you can't buy it in nuke, because the elite hardsuit costs the same while being better
/datum/uplink_item/suits/hardsuit/elite
name = "Elite Syndicate Hardsuit"
@@ -67,8 +67,7 @@
provides the user with superior armor and mobility compared to the standard Syndicate hardsuit."
item = /obj/item/clothing/suit/space/hardsuit/syndi/elite
cost = 8
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
exclude_modes = list()
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
/datum/uplink_item/suits/hardsuit/shielded
name = "Shielded Syndicate Hardsuit"
@@ -76,8 +75,7 @@
The shields can handle up to three impacts within a short duration and will rapidly recharge while not under fire."
item = /obj/item/clothing/suit/space/hardsuit/shielded/syndi
cost = 30
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
exclude_modes = list()
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
/datum/uplink_item/suits/thiefgloves
name = "Thieving Gloves"
@@ -90,13 +88,13 @@
desc = "Through bluespace magic stolen from an organisation that hoards technology, these boots simply allow you to slip through the atoms that make up anything, but only while walking, for safety reasons. As well as this, they unfortunately cause minor breath loss as the majority of atoms in your lungs are sucked out into any solid object you walk through."
item = /obj/item/clothing/shoes/wallwalkers
cost = 6
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
/datum/uplink_item/device_tools/guerrillagloves
name = "Guerrilla Gloves"
desc = "A pair of highly robust combat gripper gloves that excels at performing takedowns at close range, with an added lining of insulation. Careful not to hit a wall!"
item = /obj/item/clothing/gloves/tackler/combat/insulated
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
cost = 2
illegal_tech = FALSE
@@ -111,4 +109,4 @@
desc = "A pair of highly reinforced armwraps allowing the user to parry almost anything. Fully reflects projectiles, no downsides to failing, but is very hard to parry melee with."
cost = 6
item = /obj/item/clothing/gloves/fingerless/ablative
exclude_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS

View File

@@ -13,7 +13,7 @@
with suppressors."
item = /obj/item/storage/box/syndie_kit/pistol
cost = 7
exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
purchasable_from = ~UPLINK_CLOWN_OPS
/datum/uplink_item/dangerous/revolver
name = "Syndicate Revolver Kit"
@@ -22,7 +22,7 @@
cost = 13
player_minimum = 15
surplus = 50
exclude_modes = list(/datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs)
purchasable_from = ~UPLINK_CLOWN_OPS
/datum/uplink_item/dangerous/rawketlawnchair
name = "84mm Rocket Propelled Grenade Launcher"
@@ -31,7 +31,7 @@
item = /obj/item/gun/ballistic/rocketlauncher
cost = 8
surplus = 30
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/dangerous/antitank
name = "Anti Tank Pistol"
@@ -42,7 +42,7 @@
item = /obj/item/gun/ballistic/automatic/pistol/antitank/syndicate
cost = 14
surplus = 25
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/dangerous/pie_cannon
name = "Banana Cream Pie Cannon"
@@ -50,7 +50,7 @@
cost = 10
item = /obj/item/pneumatic_cannon/pie/selfcharge
surplus = 0
include_modes = list(/datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_CLOWN_OPS
/datum/uplink_item/dangerous/bananashield
name = "Bananium Energy Shield"
@@ -60,7 +60,7 @@
item = /obj/item/shield/energy/bananium
cost = 16
surplus = 0
include_modes = list(/datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_CLOWN_OPS
/datum/uplink_item/dangerous/clownsword
name = "Bananium Energy Sword"
@@ -69,7 +69,7 @@
item = /obj/item/melee/transforming/energy/sword/bananium
cost = 3
surplus = 0
include_modes = list(/datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_CLOWN_OPS
/datum/uplink_item/dangerous/bioterror
name = "Biohazardous Chemical Sprayer"
@@ -79,7 +79,7 @@
item = /obj/item/reagent_containers/spray/chemsprayer/bioterror
cost = 20
surplus = 0
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
/datum/uplink_item/dangerous/throwingweapons
name = "Box of Throwing Weapons"
@@ -95,7 +95,7 @@
item = /obj/item/gun/ballistic/automatic/shotgun/bulldog
cost = 8
surplus = 40
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/dangerous/smg
name = "C-20r Submachine Gun"
@@ -104,7 +104,7 @@
item = /obj/item/gun/ballistic/automatic/c20r
cost = 10
surplus = 40
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/dangerous/doublesword
name = "Double-Bladed Energy Sword"
@@ -113,7 +113,7 @@
item = /obj/item/dualsaber
player_minimum = 25
cost = 16
exclude_modes = list(/datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs)
purchasable_from = ~UPLINK_CLOWN_OPS
/datum/uplink_item/dangerous/doublesword/get_discount()
return pick(4;0.8,2;0.65,1;0.5)
@@ -125,7 +125,7 @@
item = /obj/item/dualsaber/hypereutactic
player_minimum = 25
cost = 16
exclude_modes = list(/datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs)
purchasable_from = ~UPLINK_CLOWN_OPS
/datum/uplink_item/dangerous/hyperblade/get_discount()
return pick(4;0.8,2;0.65,1;0.5)
@@ -136,7 +136,7 @@
pocketed when inactive. Activating it produces a loud, distinctive noise."
item = /obj/item/melee/transforming/energy/sword/saber
cost = 8
exclude_modes = list(/datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs)
purchasable_from = ~UPLINK_CLOWN_OPS
/datum/uplink_item/dangerous/shield
name = "Energy Shield"
@@ -145,7 +145,7 @@
item = /obj/item/shield/energy
cost = 16
surplus = 20
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/dangerous/rapier
name = "Rapier"
@@ -154,7 +154,7 @@
However, due to the size of the blade and obvious nature of the sheath, the weapon stands out as being obviously nefarious."
item = /obj/item/storage/belt/sabre/rapier
cost = 8
exclude_modes = list(/datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs)
purchasable_from = ~UPLINK_CLOWN_OPS
/datum/uplink_item/dangerous/flamethrower
name = "Flamethrower"
@@ -163,7 +163,7 @@
item = /obj/item/flamethrower/full/tank
cost = 4
surplus = 40
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/dangerous/flechettegun
name = "Flechette Launcher"
@@ -173,7 +173,7 @@
item = /obj/item/gun/ballistic/automatic/flechette
cost = 12
surplus = 30
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/dangerous/rapid
name = "Bands of the North Star"
@@ -182,7 +182,7 @@
Combines with all martial arts, but the user will be unable to bring themselves to use guns, nor remove the armbands."
item = /obj/item/clothing/gloves/fingerless/pugilist/rapid
cost = 30
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/dangerous/guardian
name = "Holoparasites"
@@ -194,7 +194,7 @@
refundable = TRUE
cant_discount = TRUE
surplus = 0
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs)
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
player_minimum = 25
restricted = TRUE
refund_path = /obj/item/guardiancreator/tech/choose/traitor
@@ -208,7 +208,7 @@
refundable = TRUE
surplus = 50
refund_path = /obj/item/guardiancreator/tech/choose/nukie
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/dangerous/machinegun
name = "L6 Squad Automatic Weapon"
@@ -217,7 +217,7 @@
item = /obj/item/gun/ballistic/automatic/l6_saw
cost = 18
surplus = 0
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/dangerous/carbine
name = "M-90gl Carbine"
@@ -226,7 +226,7 @@
item = /obj/item/gun/ballistic/automatic/m90
cost = 18
surplus = 50
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/dangerous/maulergauntlets
name = "Mauler Gauntlets"
@@ -245,7 +245,6 @@
deal extra damage and hit targets further. Use a screwdriver to take out any attached tanks."
item = /obj/item/melee/powerfist
cost = 8
exclude_modes = list(/datum/game_mode/traitor/internal_affairs)
/datum/uplink_item/dangerous/sniper
name = "Sniper Rifle"
@@ -253,14 +252,14 @@
item = /obj/item/gun/ballistic/automatic/sniper_rifle/syndicate
cost = 16
surplus = 25
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/dangerous/bolt_action
name = "Surplus Rifle"
desc = "A horribly outdated bolt action weapon. You've got to be desperate to use this."
item = /obj/item/gun/ballistic/shotgun/boltaction
cost = 2
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/dangerous/foamsmg
name = "Toy Submachine Gun"
@@ -268,7 +267,7 @@
item = /obj/item/gun/ballistic/automatic/c20r/toy
cost = 5
surplus = 0
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
/datum/uplink_item/dangerous/foammachinegun
name = "Toy Machine Gun"
@@ -277,7 +276,7 @@
item = /obj/item/gun/ballistic/automatic/l6_saw/toy
cost = 10
surplus = 0
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
/datum/uplink_item/dangerous/foampistol
name = "Toy Pistol with Riot Darts"
@@ -293,4 +292,4 @@
Allows you to cut from a far distance!"
item = /obj/item/gun/magic/staff/motivation
cost = 10
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS

View File

@@ -46,7 +46,7 @@
item = /obj/item/assault_pod
cost = 30
surplus = 0
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
restricted = TRUE
/datum/uplink_item/device_tools/binary
@@ -66,7 +66,7 @@
'Advanced Magboots' slow you down in simulated-gravity environments much like the standard issue variety."
item = /obj/item/clothing/shoes/magboots/syndie
cost = 2
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
/datum/uplink_item/device_tools/compressionkit
name = "Bluespace Compression Kit"
@@ -98,7 +98,7 @@
desc = "A robust seven-slot set of webbing that is capable of holding all manner of tactical equipment."
item = /obj/item/storage/belt/military
cost = 1
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
/datum/uplink_item/device_tools/ammo_pouch
name = "Ammo Pouch"
@@ -137,7 +137,7 @@
desc = "A cheap bottle of one use syndicate brand super glue. \
Use on any item to make it undroppable. \
Be careful not to glue an item you're already holding!"
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
item = /obj/item/syndie_glue
cost = 2
@@ -166,7 +166,7 @@
operatives in the fight, even while under fire. Don't cross the streams!"
item = /obj/item/gun/medbeam
cost = 15
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
/datum/uplink_item/device_tools/nutcracker
name = "Nutcracker"
@@ -224,7 +224,7 @@
and other supplies helpful for a field medic."
item = /obj/item/storage/firstaid/tactical/nukeop
cost = 4
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
/datum/uplink_item/device_tools/surgerybag
name = "Syndicate Surgery Duffel Bag"
@@ -272,7 +272,7 @@
desc = "A potion recovered at great risk by undercover Syndicate operatives and then subsequently modified with Syndicate technology. \
Using it will make any animal sentient, and bound to serve you, as well as implanting an internal radio for communication and an internal ID card for opening doors."
cost = 2
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
restricted = TRUE
/* for now

View File

@@ -15,7 +15,7 @@
item = /obj/item/grenade/chem_grenade/bioterrorfoam
cost = 5
surplus = 35
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
/datum/uplink_item/explosives/bombanana
name = "Bombanana"
@@ -24,7 +24,7 @@
item = /obj/item/reagent_containers/food/snacks/grown/banana/bombanana
cost = 4 //it is a bit cheaper than a minibomb because you have to take off your helmet to eat it, which is how you arm it
surplus = 0
include_modes = list(/datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_CLOWN_OPS
/datum/uplink_item/explosives/buzzkill
name = "Buzzkill Grenade Box"
@@ -33,7 +33,7 @@
item = /obj/item/storage/box/syndie_kit/bee_grenades
cost = 15
surplus = 35
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
/datum/uplink_item/explosives/c4
name = "Composition C-4"
@@ -58,7 +58,6 @@
item = /obj/item/storage/backpack/duffelbag/syndie/x4
cost = 4 //
cant_discount = TRUE
exclude_modes = list(/datum/game_mode/traitor/internal_affairs)
/datum/uplink_item/explosives/clown_bomb_clownops
name = "Clown Bomb"
@@ -70,7 +69,7 @@
item = /obj/item/sbeacondrop/clownbomb
cost = 15
surplus = 0
include_modes = list(/datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_CLOWN_OPS
/datum/uplink_item/explosives/detomatix
name = "Detomatix PDA Cartridge"
@@ -97,14 +96,14 @@
item = /obj/item/storage/box/syndie_kit/tuberculosisgrenade
cost = 8
surplus = 35
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
restricted = TRUE
/datum/uplink_item/explosives/grenadier
name = "Grenadier's belt"
desc = "A belt containing 26 lethally dangerous and destructive grenades. Comes with an extra multitool and screwdriver."
item = /obj/item/storage/belt/grenade/full
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
cost = 22
surplus = 0
@@ -125,7 +124,6 @@
be defused, and some crew may attempt to do so."
item = /obj/item/sbeacondrop/bomb
cost = 11
exclude_modes = list(/datum/game_mode/traitor/internal_affairs)
/datum/uplink_item/explosives/syndicate_detonator
name = "Syndicate Detonator"
@@ -135,7 +133,7 @@
the blast radius before using the detonator."
item = /obj/item/syndicatedetonator
cost = 3
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
/datum/uplink_item/explosives/syndicate_minibomb
name = "Syndicate Minibomb"
@@ -143,7 +141,7 @@
in addition to dealing high amounts of damage to nearby personnel."
item = /obj/item/grenade/syndieminibomb
cost = 6
exclude_modes = list(/datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs)
purchasable_from = ~UPLINK_CLOWN_OPS
/datum/uplink_item/explosives/tearstache
name = "Teachstache Grenade"
@@ -152,7 +150,7 @@
item = /obj/item/grenade/chem_grenade/teargas/moustache
cost = 3
surplus = 0
include_modes = list(/datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_CLOWN_OPS
/datum/uplink_item/explosives/viscerators
name = "Viscerator Delivery Grenade"
@@ -161,4 +159,4 @@
item = /obj/item/grenade/spawnergrenade/manhacks
cost = 5
surplus = 35
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS

View File

@@ -20,7 +20,7 @@
desc = "This implant will help you get back up on your feet faster after being stunned. Comes with an autosurgeon."
item = /obj/item/autosurgeon/anti_stun
cost = 12
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
/datum/uplink_item/implants/deathrattle
name = "Box of Deathrattle Implants"
@@ -31,7 +31,7 @@
item = /obj/item/storage/box/syndie_kit/imp_deathrattle
cost = 4
surplus = 0
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
/datum/uplink_item/implants/freedom
name = "Freedom Implant"
@@ -45,7 +45,7 @@
desc = "An implant injected into the body and later activated at the user's will. Allows the user to teleport to where they were 10 seconds ago. Has a 10 second cooldown."
item = /obj/item/storage/box/syndie_kit/imp_warp
cost = 6
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
/datum/uplink_item/implants/hijack
name = "Hijack Implant"
@@ -70,7 +70,7 @@
This will permanently destroy your body, however."
item = /obj/item/storage/box/syndie_kit/imp_microbomb
cost = 2
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
/datum/uplink_item/implants/macrobomb
name = "Macrobomb Implant"
@@ -78,7 +78,7 @@
Upon death, releases a massive explosion that will wipe out everything nearby."
item = /obj/item/storage/box/syndie_kit/imp_macrobomb
cost = 20
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
restricted = TRUE
/datum/uplink_item/implants/reviver
@@ -86,7 +86,7 @@
desc = "This implant will attempt to revive and heal you if you lose consciousness. Comes with an autosurgeon."
item = /obj/item/autosurgeon/reviver
cost = 8
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
/datum/uplink_item/implants/stealthimplant
name = "Stealth Implant"
@@ -107,7 +107,7 @@
desc = "These cybernetic eyes will give you thermal vision. Comes with a free autosurgeon."
item = /obj/item/autosurgeon/thermal_eyes
cost = 8
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
/datum/uplink_item/implants/uplink
name = "Uplink Implant"
@@ -125,4 +125,4 @@
item = /obj/item/autosurgeon/xray_eyes
cost = 10
surplus = 0
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS

View File

@@ -30,7 +30,6 @@
item = /obj/item/gun/blastcannon
cost = 14 //High cost because of the potential for extreme damage in the hands of a skilled gas masked scientist.
restricted_roles = list("Research Director", "Scientist")
exclude_modes = list(/datum/game_mode/traitor/internal_affairs)
/datum/uplink_item/role_restricted/alientech
name = "Alien Research Disk"
@@ -99,7 +98,6 @@
player_minimum = 20
refundable = TRUE
restricted_roles = list("Chaplain")
exclude_modes = list(/datum/game_mode/traitor/internal_affairs)
/datum/uplink_item/role_restricted/arcane_tome
name = "Arcane Tome"
@@ -109,7 +107,6 @@
player_minimum = 20
refundable = TRUE
restricted_roles = list("Chaplain")
exclude_modes = list(/datum/game_mode/traitor/internal_affairs)
/datum/uplink_item/role_restricted/explosive_hot_potato
name = "Exploding Hot Potato"

View File

@@ -19,14 +19,14 @@
to learn the abilities of krav maga to the wearer."
item = /obj/item/clothing/gloves/krav_maga/combatglovesplus
cost = 5
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
surplus = 0
/datum/uplink_item/stealthy_weapons/cqc
name = "CQC Manual"
desc = "A manual that teaches a single user tactical Close-Quarters Combat before self-destructing."
item = /obj/item/book/granter/martial/cqc
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS
cost = 13
surplus = 0
@@ -61,7 +61,7 @@
name = "Antique Derringer"
desc = "An easy to conceal, yet extremely deadly handgun, capable of firing .45-70 Govt rounds. Comes in a unique pack of cigarettes with additional munitions."
item = /obj/item/storage/fancy/cigarettes/derringer/midworld
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
cost = 10
surplus = 2
@@ -79,7 +79,7 @@
cost = 17
player_minimum = 20
surplus = 0
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
/datum/uplink_item/stealthy_weapons/martialartstwo
name = "Rising Bass Scroll"
@@ -89,7 +89,7 @@
cost = 18
player_minimum = 20
surplus = 0
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
/datum/uplink_item/stealthy_weapons/martialartsthree
name = "Krav Maga Scroll"
@@ -99,7 +99,6 @@
cost = 16
player_minimum = 25
surplus = 0
include_modes = list(/datum/game_mode/traitor/internal_affairs)
/datum/uplink_item/stealthy_weapons/crossbow
name = "Miniature Energy Crossbow"
@@ -112,7 +111,7 @@
item = /obj/item/gun/energy/kinetic_accelerator/crossbow
cost = 12
surplus = 50
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
/datum/uplink_item/stealthy_weapons/traitor_chem_bottle
name = "Poison Kit"
@@ -130,7 +129,7 @@
cost = 25
player_minimum = 25
cant_discount = TRUE
exclude_modes = list(/datum/game_mode/nuclear)
purchasable_from = ~UPLINK_NUKE_OPS
/datum/uplink_item/stealthy_weapons/sleepy_pen
name = "Sleepy Pen"
@@ -140,14 +139,14 @@
falls asleep, they will be able to move and act."
item = /obj/item/pen/sleepy
cost = 4
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
/datum/uplink_item/stealthy_weapons/taeclowndo_shoes
name = "Tae-clown-do Shoes"
desc = "A pair of shoes for the most elite agents of the honkmotherland. They grant the mastery of taeclowndo with some honk-fu moves as long as they're worn."
cost = 12
item = /obj/item/clothing/shoes/clown_shoes/taeclowndo
include_modes = list(/datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_CLOWN_OPS
/datum/uplink_item/stealthy_weapons/suppressor
name = "Suppressor"

View File

@@ -33,7 +33,7 @@
Due to budget cuts, the shoes don't provide protection against slipping."
item = /obj/item/storage/box/syndie_kit/chameleon
cost = 2
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
/datum/uplink_item/stealthy_tools/chameleon_proj
name = "Chameleon Projector"
@@ -57,7 +57,7 @@
item = /obj/item/clothing/shoes/clown_shoes/banana_shoes/combat
cost = 6
surplus = 0
include_modes = list(/datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_CLOWN_OPS
/datum/uplink_item/stealthy_tools/emplight
name = "EMP Flashlight"
@@ -75,7 +75,7 @@
cost = 1
surplus = 0
restricted = TRUE
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
/datum/uplink_item/stealthy_tools/failsafe/spawn_item(spawn_path, mob/user, datum/component/uplink/U)
if(!U)
@@ -93,7 +93,7 @@
item = /obj/item/reagent_containers/syringe/mulligan
cost = 3
surplus = 30
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
/datum/uplink_item/stealthy_tools/syndigaloshes
name = "No-Slip Chameleon Shoes"
@@ -101,13 +101,12 @@
They do not work on heavily lubricated surfaces."
item = /obj/item/clothing/shoes/chameleon/noslip
cost = 2
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
purchasable_from = ~(UPLINK_NUKE_OPS | UPLINK_CLOWN_OPS)
/datum/uplink_item/stealthy_tools/syndigaloshes/nuke
item = /obj/item/clothing/shoes/chameleon/noslip
cost = 4
exclude_modes = list()
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
/datum/uplink_item/stealthy_tools/jammer
name = "Radio Jammer"

View File

@@ -12,7 +12,7 @@
desc = "Call in an additional clown to share the fun, equipped with full starting gear, but no telecrystals."
item = /obj/item/antag_spawner/nuke_ops/clown
cost = 20
include_modes = list(/datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_CLOWN_OPS
restricted = TRUE
/datum/uplink_item/support/reinforcement
@@ -22,7 +22,7 @@
item = /obj/item/antag_spawner/nuke_ops
cost = 25
refundable = TRUE
include_modes = list(/datum/game_mode/nuclear)
purchasable_from = UPLINK_NUKE_OPS
restricted = TRUE
/datum/uplink_item/support/reinforcement/assault_borg
@@ -66,7 +66,7 @@
desc = "A clown combat mech equipped with bombanana peel and tearstache grenade launchers, as well as the ubiquitous HoNkER BlAsT 5000."
item = /obj/mecha/combat/honker/dark/loaded
cost = 80
include_modes = list(/datum/game_mode/nuclear/clown_ops)
purchasable_from = UPLINK_CLOWN_OPS
/datum/uplink_item/support/mauler
name = "Mauler Exosuit"

View File

@@ -1,8 +1,8 @@
GLOBAL_LIST(uplink_purchase_logs_by_key) //assoc key = /datum/uplink_purchase_log
GLOBAL_LIST(uplink_purchase_logs_by_key) //assoc key = /datum/uplink_purchase_log
/datum/uplink_purchase_log
var/owner
var/list/purchase_log //assoc path-of-item = /datum/uplink_purchase_entry
var/list/purchase_log //assoc path-of-item = /datum/uplink_purchase_entry
var/total_spent = 0
/datum/uplink_purchase_log/New(_owner, datum/component/uplink/_parent)

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,9 @@
/obj/machinery/vending/assist
name = "\improper Part-Mart"
desc = "All the finest of miscellaneous electronics one could ever need! Not responsible for any injuries caused by reckless misuse of parts."
// icon_state = "parts"
// icon_deny = "parts-deny"
products = list(/obj/item/assembly/prox_sensor = 7,
/obj/item/assembly/igniter = 6,
/obj/item/assembly/playback = 4,
@@ -15,13 +20,13 @@
premium = list(/obj/item/stock_parts/cell/upgraded/plus = 2,
/obj/item/flashlight/lantern = 2,
/obj/item/beacon = 2)
product_ads = "Only the finest!;Have some tools.;The most robust equipment.;The finest gear in space!"
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
refill_canister = /obj/item/vending_refill/assist
resistance_flags = FIRE_PROOF
product_ads = "Only the finest!;Have some tools.;The most robust equipment.;The finest gear in space!"
default_price = PRICE_REALLY_CHEAP
extra_price = PRICE_ALMOST_CHEAP
payment_department = NO_FREEBIES
// light_mask = "parts-light-mask"
/obj/item/vending_refill/assist
icon_state = "refill_engi"
machine_name = "Part-Mart"
icon_state = "refill_parts"

View File

@@ -3,32 +3,39 @@
desc = "A vending machine for costumes."
icon_state = "theater"
icon_deny = "theater-deny"
req_access = list(ACCESS_THEATRE)
product_slogans = "Dress for success!;Suited and booted!;It's show time!;Why leave style up to fate? Use AutoDrobe!"
vend_reply = "Thank you for using AutoDrobe!"
products = list(/obj/item/clothing/suit/chickensuit = 1,
/obj/item/clothing/head/chicken = 1,
/obj/item/clothing/under/costume/gladiator = 1,
/obj/item/clothing/head/helmet/gladiator = 1,
/obj/item/clothing/under/rank/captain/suit = 1,
/obj/item/clothing/head/flatcap = 1,
/obj/item/clothing/suit/toggle/labcoat/mad = 1,
/obj/item/clothing/shoes/jackboots = 1,
/obj/item/clothing/under/costume/schoolgirl = 1,
/obj/item/clothing/under/costume/schoolgirl/red = 1,
/obj/item/clothing/under/costume/schoolgirl/green = 1,
/obj/item/clothing/under/costume/schoolgirl/orange = 1,
/obj/item/clothing/head/kitty = 1,
/obj/item/clothing/under/dress/skirt = 1,
/obj/item/clothing/head/beret = 1,
/obj/item/clothing/accessory/waistcoat = 1,
/obj/item/clothing/under/suit/black = 1,
/obj/item/clothing/head/that = 1,
/obj/item/clothing/under/costume/kilt = 1,
/obj/item/clothing/head/beret = 1,
/obj/item/clothing/accessory/waistcoat = 1,
/obj/item/clothing/glasses/monocle =1,
/obj/item/clothing/head/bowler = 1,
/obj/item/cane = 1,
/obj/item/clothing/head/chicken = 1,
/obj/item/clothing/under/rank/civilian/clown/blue = 1,
/obj/item/clothing/under/rank/civilian/clown/green = 1,
/obj/item/clothing/under/rank/civilian/clown/yellow = 1,
/obj/item/clothing/under/rank/civilian/clown/orange = 1,
/obj/item/clothing/under/rank/civilian/clown/purple = 1,
/obj/item/clothing/under/costume/gladiator = 1,
/obj/item/clothing/head/helmet/gladiator = 1,
/obj/item/clothing/under/rank/captain/suit = 1,
/obj/item/clothing/under/rank/captain/suit/skirt = 1,
/obj/item/clothing/head/flatcap = 1,
/obj/item/clothing/suit/toggle/labcoat/mad = 1,
/obj/item/clothing/shoes/jackboots = 1,
/obj/item/clothing/under/costume/schoolgirl = 1,
/obj/item/clothing/under/costume/schoolgirl/red = 1,
/obj/item/clothing/under/costume/schoolgirl/green = 1,
/obj/item/clothing/under/costume/schoolgirl/orange = 1,
/obj/item/clothing/head/kitty = 1,
/obj/item/clothing/under/dress/skirt = 1,
/obj/item/clothing/head/beret = 1,
/obj/item/clothing/accessory/waistcoat = 1,
/obj/item/clothing/under/suit/black = 1,
/obj/item/clothing/head/that = 1,
/obj/item/clothing/under/costume/kilt = 1,
/obj/item/clothing/head/beret = 3,
/obj/item/clothing/accessory/waistcoat = 1,
/obj/item/clothing/glasses/monocle =1,
/obj/item/clothing/head/bowler = 1,
/obj/item/cane = 1,
/obj/item/clothing/under/rank/civilian/victorian_redsleeves = 1,
/obj/item/clothing/under/rank/civilian/victorian_redvest = 1,
/obj/item/clothing/under/rank/civilian/victorian_vest = 1,
@@ -39,110 +46,111 @@
/obj/item/clothing/under/rank/civilian/victorianblackdress = 1,
/obj/item/clothing/suit/vickyblack =1,
/obj/item/clothing/under/rank/civilian/dutch = 2,
/obj/item/clothing/under/suit/sl = 1,
/obj/item/clothing/mask/fakemoustache = 1,
/obj/item/clothing/suit/bio_suit/plaguedoctorsuit = 1,
/obj/item/clothing/head/plaguedoctorhat = 1,
/obj/item/clothing/mask/gas/plaguedoctor = 1,
/obj/item/clothing/suit/toggle/owlwings = 1,
/obj/item/clothing/under/costume/owl = 1,
/obj/item/clothing/mask/gas/owl_mask = 1,
/obj/item/clothing/suit/toggle/owlwings/griffinwings = 1,
/obj/item/clothing/under/costume/griffin = 1,
/obj/item/clothing/shoes/griffin = 1,
/obj/item/clothing/head/griffin = 1,
/obj/item/clothing/suit/apron = 1,
/obj/item/clothing/under/suit/waiter = 1,
/obj/item/clothing/suit/jacket/miljacket = 1,
/obj/item/clothing/under/costume/pirate = 1,
/obj/item/clothing/suit/pirate = 1,
/obj/item/clothing/head/pirate = 1,
/obj/item/clothing/head/bandana = 1,
/obj/item/clothing/head/bandana = 1,
/obj/item/clothing/under/costume/soviet = 1,
/obj/item/clothing/head/ushanka = 1,
/obj/item/clothing/suit/imperium_monk = 1,
/obj/item/clothing/mask/gas/cyborg = 1,
/obj/item/clothing/suit/chaplain/holidaypriest = 1,
/obj/item/clothing/head/wizard/marisa/fake = 1,
/obj/item/clothing/suit/wizrobe/marisa/fake = 1,
/obj/item/clothing/under/dress/sundress = 1,
/obj/item/clothing/head/witchwig = 1,
/obj/item/staff/broom = 1,
/obj/item/clothing/suit/wizrobe/fake = 1,
/obj/item/clothing/head/wizard/fake = 1,
/obj/item/staff = 3,
/obj/item/clothing/under/rank/civilian/mime/skirt = 1,
/obj/item/clothing/under/rank/captain/suit/skirt = 1,
/obj/item/clothing/under/suit/sl = 1,
/obj/item/clothing/mask/fakemoustache = 1,
/obj/item/clothing/suit/bio_suit/plaguedoctorsuit = 1,
/obj/item/clothing/head/plaguedoctorhat = 1,
/obj/item/clothing/mask/gas/plaguedoctor = 1,
/obj/item/clothing/suit/toggle/owlwings = 1,
/obj/item/clothing/under/costume/owl = 1,
/obj/item/clothing/mask/gas/owl_mask = 1,
/obj/item/clothing/suit/toggle/owlwings/griffinwings = 1,
/obj/item/clothing/under/costume/griffin = 1,
/obj/item/clothing/shoes/griffin = 1,
/obj/item/clothing/head/griffin = 1,
/obj/item/clothing/suit/apron = 1,
/obj/item/clothing/under/suit/waiter = 1,
/obj/item/clothing/suit/jacket/miljacket = 1,
/obj/item/clothing/under/costume/pirate = 1,
/obj/item/clothing/suit/pirate = 1,
/obj/item/clothing/head/pirate = 1,
/obj/item/clothing/head/bandana = 1,
/obj/item/clothing/head/bandana = 1,
/obj/item/clothing/under/costume/soviet = 1,
/obj/item/clothing/head/ushanka = 1,
/obj/item/clothing/suit/imperium_monk = 1,
/obj/item/clothing/mask/gas/cyborg = 1,
/obj/item/clothing/suit/chaplain/holidaypriest = 1,
/obj/item/clothing/head/wizard/marisa/fake = 1,
/obj/item/clothing/suit/wizrobe/marisa/fake = 1,
/obj/item/clothing/under/dress/sundress = 1,
/obj/item/clothing/head/witchwig = 1,
/obj/item/staff/broom = 1,
/obj/item/clothing/suit/wizrobe/fake = 1,
/obj/item/clothing/head/wizard/fake = 1,
/obj/item/staff = 3,
/obj/item/clothing/mask/gas/clown_hat/sexy = 1,
/obj/item/clothing/under/rank/civilian/clown/sexy = 1,
/obj/item/clothing/under/rank/civilian/clown/sexy = 1,
/obj/item/clothing/mask/gas/mime/sexy = 1,
/obj/item/clothing/under/rank/civilian/mime/sexy = 1,
/obj/item/clothing/mask/rat/bat = 1,
/obj/item/clothing/mask/rat/bee = 1,
/obj/item/clothing/mask/rat/bear = 1,
/obj/item/clothing/mask/rat/raven = 1,
/obj/item/clothing/mask/rat/jackal = 1,
/obj/item/clothing/mask/rat/fox = 1,
/obj/item/clothing/mask/frog = 1,
/obj/item/clothing/mask/rat/tribal = 1,
/obj/item/clothing/mask/rat = 1,
/obj/item/clothing/suit/apron/overalls = 1,
/obj/item/clothing/head/rabbitears =1,
/obj/item/clothing/head/sombrero = 1,
/obj/item/clothing/head/sombrero/green = 1,
/obj/item/clothing/suit/poncho = 1,
/obj/item/clothing/suit/poncho/green = 1,
/obj/item/clothing/suit/poncho/red = 1,
/obj/item/clothing/head/maid = 1,
/obj/item/clothing/under/costume/maid = 1,
/obj/item/clothing/under/rank/civilian/janitor/maid = 1,
/obj/item/clothing/under/rank/civilian/mime/sexy = 1,
/obj/item/clothing/under/rank/civilian/mime/skirt = 1,
/obj/item/clothing/mask/rat/bat = 1,
/obj/item/clothing/mask/rat/bee = 1,
/obj/item/clothing/mask/rat/bear = 1,
/obj/item/clothing/mask/rat/raven = 1,
/obj/item/clothing/mask/rat/jackal = 1,
/obj/item/clothing/mask/rat/fox = 1,
/obj/item/clothing/mask/frog = 1,
/obj/item/clothing/mask/rat/tribal = 1,
/obj/item/clothing/mask/rat = 1,
/obj/item/clothing/suit/apron/overalls = 1,
/obj/item/clothing/head/rabbitears =1,
/obj/item/clothing/head/sombrero = 1,
/obj/item/clothing/head/sombrero/green = 1,
/obj/item/clothing/suit/poncho = 1,
/obj/item/clothing/suit/poncho/green = 1,
/obj/item/clothing/suit/poncho/red = 1,
/obj/item/clothing/head/maid = 1,
/obj/item/clothing/under/costume/maid = 1,
/obj/item/clothing/under/rank/civilian/janitor/maid = 1,
/obj/item/clothing/gloves/evening = 1,
/obj/item/clothing/glasses/cold=1,
/obj/item/clothing/glasses/heat=1,
/obj/item/clothing/suit/whitedress = 1,
/obj/item/clothing/under/rank/civilian/clown/jester = 1,
/obj/item/clothing/head/jester = 1,
/obj/item/clothing/under/costume/villain = 1,
/obj/item/clothing/shoes/singery = 1,
/obj/item/clothing/under/costume/singer/yellow = 1,
/obj/item/clothing/shoes/singerb = 1,
/obj/item/clothing/under/costume/singer/blue = 1,
/obj/item/clothing/suit/hooded/carp_costume = 1,
/obj/item/clothing/suit/hooded/ian_costume = 1,
/obj/item/clothing/suit/hooded/bee_costume = 1,
/obj/item/clothing/suit/snowman = 1,
/obj/item/clothing/head/snowman = 1,
/obj/item/clothing/mask/joy = 1,
/obj/item/clothing/head/cueball = 1,
/obj/item/clothing/under/suit/white_on_white = 1,
/obj/item/clothing/under/costume/sailor = 1,
/obj/item/clothing/ears/headphones = 2,
/obj/item/clothing/head/wig/random = 3,
/obj/item/clothing/suit/ran = 2,
/obj/item/clothing/head/ran = 2,
/obj/item/clothing/mask/gas/timidcostume = 3,
/obj/item/clothing/suit/hooded/wintercoat/timidcostume = 3,
/obj/item/clothing/shoes/timidcostume = 3,
/obj/item/clothing/mask/gas/timidcostume/man = 3,
/obj/item/clothing/suit/hooded/wintercoat/timidcostume/man = 3,
/obj/item/clothing/shoes/timidcostume/man = 3,
)
/obj/item/clothing/glasses/cold=1,
/obj/item/clothing/glasses/heat=1,
/obj/item/clothing/suit/whitedress = 1,
/obj/item/clothing/under/rank/civilian/clown/jester = 1,
/obj/item/clothing/head/jester = 1,
/obj/item/clothing/under/costume/villain = 1,
/obj/item/clothing/shoes/singery = 1,
/obj/item/clothing/under/costume/singer/yellow = 1,
/obj/item/clothing/shoes/singerb = 1,
/obj/item/clothing/under/costume/singer/blue = 1,
/obj/item/clothing/suit/hooded/carp_costume = 1,
/obj/item/clothing/suit/hooded/ian_costume = 1,
/obj/item/clothing/suit/hooded/bee_costume = 1,
/obj/item/clothing/suit/snowman = 1,
/obj/item/clothing/head/snowman = 1,
/obj/item/clothing/mask/joy = 1,
/obj/item/clothing/head/cueball = 1,
/obj/item/clothing/under/suit/white_on_white = 1,
/obj/item/clothing/under/costume/sailor = 1,
/obj/item/clothing/ears/headphones = 2,
/obj/item/clothing/head/wig/random = 3,
/obj/item/clothing/suit/ran = 2,
/obj/item/clothing/head/ran = 2,
/obj/item/clothing/mask/gas/timidcostume = 3,
/obj/item/clothing/suit/hooded/wintercoat/timidcostume = 3,
/obj/item/clothing/shoes/timidcostume = 3,
/obj/item/clothing/mask/gas/timidcostume/man = 3,
/obj/item/clothing/suit/hooded/wintercoat/timidcostume/man = 3,
/obj/item/clothing/shoes/timidcostume/man = 3,
)
contraband = list(/obj/item/clothing/suit/judgerobe = 1,
/obj/item/clothing/head/powdered_wig = 1,
/obj/item/gun/magic/wand = 2,
/obj/item/clothing/glasses/sunglasses/garb = 2,
/obj/item/clothing/glasses/sunglasses/blindfold = 1,
/obj/item/clothing/mask/muzzle = 2,
/obj/item/clothing/under/syndicate/camo/cosmetic = 3)
/obj/item/clothing/head/powdered_wig = 1,
/obj/item/gun/magic/wand = 2,
/obj/item/clothing/glasses/sunglasses/garb = 2,
/obj/item/clothing/glasses/sunglasses/blindfold = 1,
/obj/item/clothing/mask/muzzle = 2,
/obj/item/clothing/under/syndicate/camo/cosmetic = 3
)
premium = list(/obj/item/clothing/suit/pirate/captain = 2,
/obj/item/clothing/head/pirate/captain = 2,
/obj/item/clothing/head/helmet/roman/fake = 1,
/obj/item/clothing/head/helmet/roman/legionnaire/fake = 1,
/obj/item/clothing/under/costume/roman = 1,
/obj/item/clothing/shoes/roman = 1,
/obj/item/shield/riot/roman/fake = 1,
/obj/item/skub = 1,
/obj/item/clothing/head/pirate/captain = 2,
/obj/item/clothing/under/rank/civilian/clown/rainbow = 1,
/obj/item/clothing/head/helmet/roman/fake = 1,
/obj/item/clothing/head/helmet/roman/legionnaire/fake = 1,
/obj/item/clothing/under/costume/roman = 1,
/obj/item/clothing/shoes/roman = 1,
/obj/item/shield/riot/roman/fake = 1,
/obj/item/skub = 1,
/obj/item/clothing/under/costume/lobster = 1,
/obj/item/clothing/head/lobsterhat = 1,
/obj/item/clothing/head/drfreezehat = 1,
@@ -157,11 +165,11 @@
/obj/item/clothing/head/christmashat = 3,
/obj/item/clothing/head/christmashatg = 3,
/obj/item/clothing/under/costume/drfreeze = 1)
refill_canister = /obj/item/vending_refill/autodrobe
default_price = PRICE_ALMOST_CHEAP
extra_price = PRICE_ALMOST_EXPENSIVE
payment_department = ACCOUNT_SRV
light_mask="theater-light-mask"
/obj/machinery/vending/autodrobe/Initialize()
. = ..()
@@ -170,6 +178,10 @@
/obj/machinery/vending/autodrobe/canLoadItem(obj/item/I,mob/user)
return (I.type in products)
/obj/machinery/vending/autodrobe/all_access
desc = "A vending machine for costumes. This model appears to have no access restrictions."
req_access = null
/obj/item/vending_refill/autodrobe
machine_name = "AutoDrobe"
icon_state = "refill_costume"

View File

@@ -41,13 +41,15 @@
premium = list(/obj/item/reagent_containers/glass/bottle/ethanol = 4,
/obj/item/reagent_containers/food/drinks/bottle/champagne = 5,
/obj/item/reagent_containers/food/drinks/bottle/trappist = 5)
product_slogans = "I hope nobody asks me for a bloody cup o' tea...;Alcohol is humanity's friend. Would you abandon a friend?;Quite delighted to serve you!;Is nobody thirsty on this station?"
product_ads = "Drink up!;Booze is good for you!;Alcohol is humanity's best friend.;Quite delighted to serve you!;Care for a nice, cold beer?;Nothing cures you like booze!;Have a sip!;Have a drink!;Have a beer!;Beer is good for you!;Only the finest alcohol!;Best quality booze since 2053!;Award-winning wine!;Maximum alcohol!;Man loves beer.;A toast for progress!"
refill_canister = /obj/item/vending_refill/boozeomat
default_price = PRICE_ALMOST_CHEAP
extra_price = PRICE_EXPENSIVE
payment_department = ACCOUNT_SRV
cost_multiplier_per_dept = list(ACCOUNT_SRV = 0)
light_mask = "boozeomat-light-mask"
/obj/machinery/vending/boozeomat/pubby_maint //abandoned bar on Pubbystation
products = list(/obj/item/reagent_containers/food/drinks/bottle/whiskey = 1,
@@ -67,12 +69,14 @@
/obj/item/reagent_containers/food/drinks/drinkingglass = 6,
/obj/item/reagent_containers/food/drinks/ice = 1,
/obj/item/reagent_containers/food/drinks/drinkingglass/shotglass = 4);
payment_department = ACCOUNT_SEC
/obj/machinery/vending/boozeomat/pubby_captain/Initialize()
. = ..()
cost_multiplier_per_dept = list("[ACCESS_CAPTAIN]" = 0)
/obj/machinery/vending/boozeomat/all_access
desc = "A technological marvel, supposedly able to mix just the mixture you'd like to drink the moment you ask for one. This model appears to have no access restrictions."
req_access = null
/obj/machinery/vending/boozeomat/syndicate_access
req_access = list(ACCESS_SYNDICATE)
age_restrictions = FALSE
payment_department = NO_FREEBIES
/obj/machinery/vending/boozeomat/syndicate_access/Initialize()

View File

@@ -11,19 +11,18 @@
/obj/item/cartridge/janitor = 10,
/obj/item/cartridge/signal/toxins = 10,
/obj/item/cartridge/roboticist = 10,
/obj/item/pda/heads = 10)
premium = list(/obj/item/cartridge/captain = 2,
/obj/item/cartridge/quartermaster = 2)
/obj/item/pda/heads = 10,
/obj/item/cartridge/captain = 3,
/obj/item/cartridge/quartermaster = 10)
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
refill_canister = /obj/item/vending_refill/cart
resistance_flags = FIRE_PROOF
default_price = PRICE_ALMOST_EXPENSIVE
extra_price = PRICE_ALMOST_ONE_GRAND
payment_department = ACCOUNT_SRV
/obj/machinery/vending/cart/Initialize()
. = ..()
cost_multiplier_per_dept = list("[ACCESS_CHANGE_IDS]" = 0)
light_mask="cart-light-mask"
/obj/item/vending_refill/cart
icon_state = "refill_pda"
machine_name = "PTech"
icon_state = "refill_smoke"

View File

@@ -17,13 +17,15 @@
/obj/item/storage/fancy/cigarettes/cigpack_shadyjims = 1,
/obj/item/clothing/mask/cigarette/dart = 3)
premium = list(/obj/item/storage/fancy/cigarettes/cigpack_robustgold = 3,
/obj/item/storage/fancy/cigarettes/cigars = 1,
/obj/item/storage/fancy/cigarettes/cigars/havana = 1,
/obj/item/storage/fancy/cigarettes/cigars/cohiba = 1)
/obj/item/lighter = 3,
/obj/item/storage/fancy/cigarettes/cigars = 1,
/obj/item/storage/fancy/cigarettes/cigars/havana = 1,
/obj/item/storage/fancy/cigarettes/cigars/cohiba = 1)
refill_canister = /obj/item/vending_refill/cigarette
default_price = PRICE_ALMOST_CHEAP
extra_price = PRICE_ABOVE_NORMAL
payment_department = ACCOUNT_SRV
light_mask = "cigs-light-mask"
/obj/machinery/vending/cigarette/syndicate
products = list(/obj/item/storage/fancy/cigarettes/cigpack_syndicate = 7,
@@ -34,7 +36,6 @@
/obj/item/storage/box/matches = 10,
/obj/item/lighter/greyscale = 4,
/obj/item/storage/fancy/rollingpapers = 5)
payment_department = NO_FREEBIES
/obj/machinery/vending/cigarette/syndicate/Initialize()
. = ..()

View File

@@ -1,10 +1,9 @@
//DON'T FORGET TO CHANGE THE REFILL SIZE IF YOU CHANGE THE MACHINE'S CONTENTS!
/obj/machinery/vending/clothing
name = "ClothesMate" //renamed to make the slogan rhyme
desc = "A vending machine for clothing."
icon_state = "clothes"
icon_deny = "clothes-deny"
product_slogans = "Dress for success!;Prepare to look swagalicious!;Look at all this free swag!;Why leave style up to fate? Use the ClothesMate!"
product_slogans = "Dress for success!;Prepare to look swagalicious!;Look at all this swag!;Why leave style up to fate? Use the ClothesMate!"
vend_reply = "Thank you for using the ClothesMate!"
products = list(/obj/item/clothing/head/that = 4,
/obj/item/clothing/head/fedora = 3,
@@ -231,9 +230,11 @@
/obj/item/clothing/suit/jacket/bluehoodie = 4,
/obj/item/clothing/suit/toggle/jacket/whitehoodie = 4)
refill_canister = /obj/item/vending_refill/clothing
default_price = PRICE_CHEAP
default_price = PRICE_CHEAP //Default of
extra_price = PRICE_BELOW_NORMAL
payment_department = NO_FREEBIES
light_mask = "wardrobe-light-mask"
light_color = LIGHT_COLOR_ELECTRIC_GREEN
/obj/machinery/vending/clothing/canLoadItem(obj/item/I,mob/user)
return (I.type in products)

View File

@@ -1,7 +1,7 @@
/obj/machinery/vending/coffee
name = "\improper Solar's Best Hot Drinks"
desc = "A vending machine which dispenses hot drinks."
product_ads = "Just what you need!;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"
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"
icon_vend = "coffee-vend"
products = list(/obj/item/reagent_containers/food/drinks/coffee = 25,
@@ -15,11 +15,12 @@
/obj/item/reagent_containers/food/drinks/bottle/cream = 2,
/obj/item/reagent_containers/food/condiment/sugar = 1,
/obj/item/reagent_containers/food/drinks/mug/tea/forest = 3,)
refill_canister = /obj/item/vending_refill/coffee
default_price = PRICE_REALLY_CHEAP
extra_price = PRICE_PRETTY_CHEAP
payment_department = ACCOUNT_SRV
light_mask = "coffee-light-mask"
light_color = COLOR_DARK_MODERATE_ORANGE
/obj/item/vending_refill/coffee
machine_name = "Solar's Best Hot Drinks"

View File

@@ -6,7 +6,7 @@
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/reagent_containers/food/drinks/soda_cans/cola = 10,
/obj/item/reagent_containers/food/drinks/soda_cans/space_mountain_wind = 10,
/obj/item/reagent_containers/food/drinks/soda_cans/space_mountain_wind = 10,
/obj/item/reagent_containers/food/drinks/soda_cans/dr_gibb = 10,
/obj/item/reagent_containers/food/drinks/soda_cans/starkist = 10,
/obj/item/reagent_containers/food/drinks/soda_cans/space_up = 10,
@@ -18,14 +18,15 @@
/obj/item/reagent_containers/food/drinks/soda_cans/shamblers = 6,
/obj/item/reagent_containers/glass/beaker/waterbottle/wataur = 2)
premium = list(/obj/item/reagent_containers/food/drinks/drinkingglass/filled/nuka_cola = 1,
/obj/item/reagent_containers/food/drinks/soda_cans/air = 1,
/obj/item/reagent_containers/food/drinks/soda_cans/grey_bull = 1,
/obj/item/reagent_containers/food/drinks/soda_cans/monkey_energy = 1)
/obj/item/reagent_containers/food/drinks/soda_cans/air = 1,
/obj/item/reagent_containers/food/drinks/soda_cans/monkey_energy = 1,
/obj/item/reagent_containers/food/drinks/soda_cans/grey_bull = 1)
refill_canister = /obj/item/vending_refill/cola
default_price = PRICE_CHEAP_AS_FREE
extra_price = PRICE_ABOVE_NORMAL
payment_department = ACCOUNT_SRV
/obj/item/vending_refill/cola
machine_name = "Robust Softdrinks"
icon_state = "refill_cola"
@@ -43,43 +44,56 @@
/obj/machinery/vending/cola/blue
icon_state = "Cola_Machine"
light_mask = "cola-light-mask"
light_color = COLOR_MODERATE_BLUE
/obj/machinery/vending/cola/black
icon_state = "cola_black"
light_mask = "cola-light-mask"
/obj/machinery/vending/cola/red
icon_state = "red_cola"
name = "\improper Space Cola Vendor"
desc = "It vends cola, in space."
product_slogans = "Cola in space!"
light_mask = "red_cola-light-mask"
light_color = COLOR_DARK_RED
/obj/machinery/vending/cola/space_up
icon_state = "space_up"
name = "\improper Space-up! Vendor"
desc = "Indulge in an explosion of flavor."
product_slogans = "Space-up! Like a hull breach in your mouth."
light_mask = "space_up-light-mask"
light_color = COLOR_DARK_MODERATE_LIME_GREEN
/obj/machinery/vending/cola/starkist
icon_state = "starkist"
name = "\improper Star-kist Vendor"
desc = "The taste of a star in liquid form."
product_slogans = "Drink the stars! Star-kist!"
light_mask = "starkist-light-mask"
light_color = COLOR_LIGHT_ORANGE
/obj/machinery/vending/cola/sodie
icon_state = "soda"
light_mask = "soda-light-mask"
light_color = COLOR_WHITE
/obj/machinery/vending/cola/pwr_game
icon_state = "pwr_game"
name = "\improper Pwr Game Vendor"
desc = "You want it, we got it. Brought to you in partnership with Vlad's Salads."
product_slogans = "The POWER that gamers crave! PWR GAME!"
light_mask = "pwr_game-light-mask"
light_color = COLOR_STRONG_VIOLET
/obj/machinery/vending/cola/shamblers
name = "\improper Shambler's Vendor"
desc = "~Shake me up some of that Shambler's Juice!~"
icon_state = "shamblers_juice"
products = list(/obj/item/reagent_containers/food/drinks/soda_cans/cola = 10,
/obj/item/reagent_containers/food/drinks/soda_cans/space_mountain_wind = 10,
/obj/item/reagent_containers/food/drinks/soda_cans/space_mountain_wind = 10,
/obj/item/reagent_containers/food/drinks/soda_cans/dr_gibb = 10,
/obj/item/reagent_containers/food/drinks/soda_cans/starkist = 10,
/obj/item/reagent_containers/food/drinks/soda_cans/space_up = 10,
@@ -89,7 +103,8 @@
/obj/item/reagent_containers/food/drinks/soda_cans/shamblers = 10)
product_slogans = "~Shake me up some of that Shambler's Juice!~"
product_ads = "Refreshing!;Jyrbv dv lg jfdv fw kyrk Jyrdscvi'j Alztv!;Over 1 trillion souls drank!;Thirsty? Nyp efk uizeb kyv uribevjj?;Kyv Jyrdscvi uizebj kyv ezxyk!;Drink up!;Krjkp."
light_mask = "shamblers-light-mask"
light_color = COLOR_MOSTLY_PURE_PINK
/obj/machinery/vending/cola/buzz_fuzz
name = "\improper Buzz Fuzz Vendor"
desc = "~A hive of Flavour!~"

View File

@@ -5,9 +5,9 @@
icon_state = "engi"
icon_deny = "engi-deny"
products = list(/obj/item/clothing/under/rank/engineering/chief_engineer = 4,
/obj/item/clothing/under/rank/engineering/engineer = 4,
/obj/item/clothing/shoes/sneakers/orange = 4,
/obj/item/clothing/head/hardhat = 4,
/obj/item/clothing/under/rank/engineering/engineer = 4,
/obj/item/clothing/shoes/sneakers/orange = 4,
/obj/item/clothing/head/hardhat = 4,
/obj/item/storage/belt/utility = 4,
/obj/item/clothing/glasses/meson/engine = 4,
/obj/item/clothing/gloves/color/yellow = 4,
@@ -26,9 +26,13 @@
/obj/item/stock_parts/micro_laser = 5,
/obj/item/stock_parts/matter_bin = 5,
/obj/item/stock_parts/manipulator = 5)
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
refill_canister = /obj/item/vending_refill/engineering
resistance_flags = FIRE_PROOF
default_price = PRICE_NORMAL
extra_price = PRICE_NORMAL
payment_department = ACCOUNT_ENG
cost_multiplier_per_dept = list(ACCOUNT_ENG = 0)
light_mask = "engi-light-mask"
/obj/item/vending_refill/engineering
machine_name = "Robco Tool Maker"
icon_state = "refill_engi"

View File

@@ -27,13 +27,13 @@
/obj/item/rcd_ammo/large = 5,
/obj/item/storage/bag/material = 3
)
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
refill_canister = /obj/item/vending_refill/engivend
resistance_flags = FIRE_PROOF
default_price = PRICE_ALMOST_EXPENSIVE
extra_price = PRICE_ABOVE_EXPENSIVE
payment_department = ACCOUNT_ENG
cost_multiplier_per_dept = list(ACCOUNT_ENG = 0)
light_mask = "engivend-light-mask"
/obj/item/vending_refill/engivend
machine_name = "Engi-Vend"
icon_state = "refill_engi"

View File

@@ -4,15 +4,17 @@
product_ads = "Escape to a fantasy world!;Fuel your gambling addiction!;Ruin your friendships!;Roll for initiative!;Elves and dwarves!;Paranoid computers!;Totally not satanic!;Fun times forever!"
icon_state = "games"
products = list(/obj/item/toy/cards/deck = 5,
/obj/item/storage/dice = 10,
/obj/item/toy/cards/deck/cas = 3,
/obj/item/toy/cards/deck/cas/black = 3,
/obj/item/storage/dice = 10,
/obj/item/toy/cards/deck/cas = 3,
/obj/item/toy/cards/deck/cas/black = 3,
/obj/item/toy/cards/deck/unum = 3,
/obj/item/camera = 3,
/obj/item/cardpack/series_one = 10,
/obj/item/dyespray=3,
/obj/item/tcgcard_binder = 5,
/obj/item/canvas = 3,
/obj/item/toy/crayon/spraycan = 3)
/obj/item/toy/crayon/spraycan = 3,
/obj/item/dyespray=3,
)
contraband = list(/obj/item/dice/fudge = 9)
premium = list(/obj/item/melee/skateboard/pro = 3,
/obj/item/melee/skateboard/hoverboard = 1)
@@ -20,7 +22,7 @@
default_price = PRICE_CHEAP
extra_price = PRICE_ALMOST_EXPENSIVE
payment_department = ACCOUNT_SRV
cost_multiplier_per_dept = list(ACCOUNT_SRV = 0)
light_mask = "games-light-mask"
/obj/item/vending_refill/games
machine_name = "\improper Good Clean Fun"

View File

@@ -2,15 +2,15 @@
name = "\improper Liberation Station"
desc = "An overwhelming amount of <b>ancient patriotism</b> washes over you just by looking at the machine."
icon_state = "liberationstation"
product_slogans = "Liberation Station: Your one-stop shop for all things second ammendment!;Be a patriot today, pick up a gun!;Quality weapons for cheap prices!;Better dead than red!"
product_ads = "Float like an astronaut, sting like a bullet!;Express your second ammendment today!;Guns don't kill people, but you can!;Who needs responsibilities when you have guns?"
product_slogans = "Liberation Station: Your one-stop shop for all things second amendment!;Be a patriot today, pick up a gun!;Quality weapons for cheap prices!;Better dead than red!"
product_ads = "Float like an astronaut, sting like a bullet!;Express your second amendment today!;Guns don't kill people, but you can!;Who needs responsibilities when you have guns?"
vend_reply = "Remember the name: Liberation Station!"
products = list(/obj/item/reagent_containers/food/snacks/burger/plain = 5, //O say can you see, by the dawn's early light
/obj/item/reagent_containers/food/snacks/burger/baseball = 3, //What so proudly we hailed at the twilight's last gleaming
/obj/item/reagent_containers/food/snacks/fries = 5, //Whose broad stripes and bright stars through the perilous fight
/obj/item/reagent_containers/food/drinks/beer/light = 10, //O'er the ramparts we watched, were so gallantly streaming?
/obj/item/gun/ballistic/automatic/pistol/deagle/gold = 2,
/obj/item/gun/ballistic/automatic/pistol/deagle/camo = 2,
/obj/item/gun/ballistic/automatic/pistol/deagle/camo = 2,
/obj/item/gun/ballistic/automatic/pistol/m1911 = 2,
/obj/item/gun/ballistic/automatic/proto/unrestricted = 2,
/obj/item/gun/ballistic/shotgun/automatic/combat = 2,
@@ -18,16 +18,16 @@
/obj/item/gun/ballistic/shotgun = 2,
/obj/item/gun/ballistic/automatic/ar = 2)
premium = list(/obj/item/ammo_box/magazine/smgm9mm = 2,
/obj/item/ammo_box/magazine/m50 = 4,
/obj/item/ammo_box/magazine/m45 = 2,
/obj/item/ammo_box/magazine/m75 = 2,
/obj/item/ammo_box/magazine/m50 = 4,
/obj/item/ammo_box/magazine/m45 = 2,
/obj/item/ammo_box/magazine/m75 = 2,
/obj/item/reagent_containers/food/snacks/cheesyfries = 5,
/obj/item/reagent_containers/food/snacks/burger/baconburger = 5) //Premium burgers for the premium section
contraband = list(/obj/item/clothing/under/misc/patriotsuit = 3,
/obj/item/bedsheet/patriot = 5,
/obj/item/bedsheet/patriot = 5,
/obj/item/reagent_containers/food/snacks/burger/superbite = 3) //U S A
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
resistance_flags = FIRE_PROOF
default_price = PRICE_ABOVE_NORMAL
extra_price = PRICE_ABOVE_EXPENSIVE
payment_department = ACCOUNT_SEC
light_mask = "liberation-light-mask"

View File

@@ -16,19 +16,16 @@
/obj/item/clothing/suit/syndicatefake = 5,
/obj/item/clothing/head/syndicatefake = 5) //OPS IN DORMS oh wait it's just an assistant
contraband = list(/obj/item/gun/ballistic/shotgun/toy/crossbow = 10, //Congrats, you unlocked the +18 setting!
/obj/item/gun/ballistic/automatic/c20r/toy/unrestricted/riot = 10,
/obj/item/gun/ballistic/automatic/l6_saw/toy/unrestricted/riot = 10,
/obj/item/ammo_box/foambox/riot = 20,
/obj/item/toy/katana = 10,
/obj/item/dualsaber/toy = 5,
/obj/item/toy/cards/deck/syndicate = 10) //Gambling and it hurts, making it a +18 item
/obj/item/gun/ballistic/automatic/c20r/toy/unrestricted/riot = 10,
/obj/item/gun/ballistic/automatic/l6_saw/toy/unrestricted/riot = 10,
/obj/item/ammo_box/foambox/riot = 20,
/obj/item/toy/katana = 10,
/obj/item/dualsaber/toy = 5,
/obj/item/toy/cards/deck/syndicate = 10) //Gambling and it hurts, making it a +18 item
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
resistance_flags = FIRE_PROOF
refill_canister = /obj/item/vending_refill/donksoft
default_price = PRICE_ABOVE_NORMAL
extra_price = PRICE_EXPENSIVE
payment_department = NO_FREEBIES
/obj/machinery/vending/toyliberationstation/Initialize()
. = ..()
cost_multiplier_per_dept = list("[ACCESS_SYNDICATE]" = 0)
payment_department = ACCOUNT_SRV
light_mask = "donksoft-light-mask"

View File

@@ -4,18 +4,19 @@
icon_state = "MagiVend"
product_slogans = "Sling spells the proper way with MagiVend!;Be your own Houdini! Use MagiVend!"
vend_reply = "Have an enchanted evening!"
product_ads = "EI NATH;Destroy the station!;Admin conspiracies since forever!;Space-time bending hardware!;Now-magic proofing venders!"
product_ads = "FJKLFJSD;AJKFLBJAKL;1234 LOONIES LOL!;>MFW;Kill them fuckers!;GET DAT FUKKEN DISK;HONK!;EI NATH;Destroy the station!;Admin conspiracies since forever!;Space-time bending hardware!"
products = list(/obj/item/clothing/head/wizard = 1,
/obj/item/clothing/suit/wizrobe = 1,
/obj/item/clothing/head/wizard/red = 1,
/obj/item/clothing/suit/wizrobe/red = 1,
/obj/item/clothing/head/wizard/yellow = 1,
/obj/item/clothing/suit/wizrobe/yellow = 1,
/obj/item/clothing/shoes/sandal/magic = 1,
/obj/item/staff = 2)
contraband = list(/obj/item/reagent_containers/glass/bottle/wizarditis = 1) //No one can get to the machine to hack it anyways; for the lulz - Microwave
/obj/item/clothing/suit/wizrobe = 1,
/obj/item/clothing/head/wizard/red = 1,
/obj/item/clothing/suit/wizrobe/red = 1,
/obj/item/clothing/head/wizard/yellow = 1,
/obj/item/clothing/suit/wizrobe/yellow = 1,
/obj/item/clothing/shoes/sandal/magic = 1,
/obj/item/staff = 2)
contraband = list(/obj/item/reagent_containers/glass/bottle/wizarditis = 1) //No one can get to the machine to hack it anyways; for the lulz - Microwave
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50, "magic" = 100)
resistance_flags = FIRE_PROOF
default_price = PRICE_EXPENSIVE
default_price = 0 //Just in case, since it's primary use is storage.
extra_price = PRICE_ABOVE_EXPENSIVE
payment_department = ACCOUNT_SRV
light_mask = "magivend-light-mask"

View File

@@ -4,6 +4,7 @@
icon_state = "med"
icon_deny = "med-deny"
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/reagent_containers/syringe = 12,
/obj/item/reagent_containers/dropper = 3,
/obj/item/healthanalyzer = 4,
@@ -50,13 +51,11 @@
/obj/item/storage/briefcase/medical = 2,
/obj/item/plunger/reinforced = 2)
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
resistance_flags = FIRE_PROOF
refill_canister = /obj/item/vending_refill/medical
default_price = PRICE_ALMOST_CHEAP
extra_price = PRICE_ABOVE_NORMAL
payment_department = ACCOUNT_MED
cost_multiplier_per_dept = list(ACCOUNT_MED = 0)
light_mask = "med-light-mask"
/obj/item/vending_refill/medical
machine_name = "NanoMed Plus"
@@ -64,8 +63,9 @@
/obj/machinery/vending/medical/syndicate_access
name = "\improper SyndiMed Plus"
payment_department = NO_FREEBIES
req_access = list(ACCESS_SYNDICATE)
/obj/machinery/vending/medical/syndicate_access/Initialize()
/obj/machinery/vending/medical/syndicate_access/Initialize(mapload)
. = ..()
cost_multiplier_per_dept = list("[ACCESS_SYNDICATE]" = 0)

View File

@@ -18,14 +18,28 @@
contraband = list(/obj/item/reagent_containers/pill/tox = 2,
/obj/item/reagent_containers/pill/morphine = 2)
premium = list(/obj/item/reagent_containers/medspray/synthflesh = 2)
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
resistance_flags = FIRE_PROOF
refill_canister = /obj/item/vending_refill/wallmed
default_price = PRICE_FREE
extra_price = PRICE_NORMAL
payment_department = ACCOUNT_MED
cost_multiplier_per_dept = list(ACCOUNT_MED = 0)
tiltable = FALSE
light_mask = "wallmed-light-mask"
/obj/machinery/vending/wallmed/directional/north
dir = SOUTH
pixel_y = 32
/obj/machinery/vending/wallmed/directional/south
dir = NORTH
pixel_y = -32
/obj/machinery/vending/wallmed/directional/east
dir = WEST
pixel_x = 32
/obj/machinery/vending/wallmed/directional/west
dir = EAST
pixel_x = -32
/obj/item/vending_refill/wallmed
machine_name = "NanoMed"

View File

@@ -4,6 +4,7 @@
product_slogans = "THIS'S WHERE TH' SEEDS LIVE! GIT YOU SOME!;Hands down the best seed selection on the station!;Also certain mushroom varieties available, more for experts! Get certified today!"
product_ads = "We like plants!;Grow some crops!;Grow, baby, growww!;Aw h'yeah son!"
icon_state = "seeds"
light_mask = "seeds-light-mask"
products = list(/obj/item/seeds/aloe = 3,
/obj/item/seeds/ambrosia = 3,
/obj/item/seeds/apple = 3,
@@ -20,6 +21,7 @@
/obj/item/seeds/cotton = 3,
/obj/item/seeds/corn = 3,
/obj/item/seeds/eggplant = 3,
/obj/item/seeds/garlic = 3,
/obj/item/seeds/grape = 3,
/obj/item/seeds/grass = 3,
/obj/item/seeds/lemon = 3,
@@ -56,13 +58,11 @@
/obj/item/seeds/starthistle = 2,
/obj/item/seeds/random = 2)
premium = list(/obj/item/reagent_containers/spray/waterflower = 1)
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
refill_canister = /obj/item/vending_refill/hydroseeds
resistance_flags = FIRE_PROOF
default_price = PRICE_ALMOST_CHEAP
extra_price = PRICE_NORMAL
payment_department = ACCOUNT_SRV
cost_multiplier_per_dept = list(ACCOUNT_SRV = 0)
/obj/item/vending_refill/hydroseeds
icon_state = "refill_hydro"
machine_name = "MegaSeed Servitor"
icon_state = "refill_plant"

View File

@@ -5,6 +5,7 @@
product_ads = "We like plants!;Don't you want some?;The greenest thumbs ever.;We like big plants.;Soft soil..."
icon_state = "nutri"
icon_deny = "nutri-deny"
light_mask = "nutri-light-mask"
products = list(/obj/item/reagent_containers/glass/bottle/nutrient/ez = 30,
/obj/item/reagent_containers/glass/bottle/nutrient/l4z = 20,
/obj/item/reagent_containers/glass/bottle/nutrient/rh = 10,
@@ -15,14 +16,12 @@
/obj/item/shovel/spade = 3,
/obj/item/plant_analyzer = 4)
contraband = list(/obj/item/reagent_containers/glass/bottle/ammonia = 10,
/obj/item/reagent_containers/glass/bottle/diethylamine = 5)
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
/obj/item/reagent_containers/glass/bottle/diethylamine = 5)
refill_canister = /obj/item/vending_refill/hydronutrients
resistance_flags = FIRE_PROOF
default_price = PRICE_REALLY_CHEAP
extra_price = PRICE_CHEAP
payment_department = ACCOUNT_SRV
cost_multiplier_per_dept = list(ACCOUNT_SRV = 0)
/obj/item/vending_refill/hydronutrients
icon_state = "refill_hydro"
machine_name = "NutriMax"
icon_state = "refill_plant"

View File

@@ -1,10 +1,10 @@
//This one's from bay12
/obj/machinery/vending/plasmaresearch
name = "\improper Toximate 3000"
name = "\improper Bombuddy 3000"
desc = "All the fine parts you need in one vending machine!"
products = list(/obj/item/clothing/under/rank/rnd/scientist = 6,
/obj/item/clothing/suit/bio_suit = 6,
/obj/item/clothing/head/bio_hood = 6,
/obj/item/clothing/suit/bio_suit = 6,
/obj/item/clothing/head/bio_hood = 6,
/obj/item/transfer_valve = 6,
/obj/item/assembly/timer = 6,
/obj/item/assembly/signaler = 6,
@@ -14,4 +14,3 @@
default_price = PRICE_EXPENSIVE
extra_price = PRICE_REALLY_EXPENSIVE
payment_department = ACCOUNT_SCI
cost_multiplier_per_dept = list(ACCOUNT_SCI = 0)

View File

@@ -4,6 +4,8 @@
desc = "All the tools you need to create your own robot army."
icon_state = "robotics"
icon_deny = "robotics-deny"
light_mask = "robotics-light-mask"
req_access = list(ACCESS_ROBOTICS)
products = list(/obj/item/clothing/suit/toggle/labcoat = 4,
/obj/item/clothing/under/rank/rnd/roboticist = 4,
/obj/item/stack/cable_coil = 4,
@@ -14,13 +16,16 @@
/obj/item/healthanalyzer = 3,
/obj/item/scalpel = 2,
/obj/item/circular_saw = 2,
/obj/item/bonesetter = 2,
/obj/item/tank/internals/anesthetic = 2,
/obj/item/clothing/mask/breath/medical = 5,
/obj/item/screwdriver = 5,
/obj/item/crowbar = 6,
/obj/item/crowbar = 5,
/obj/item/stack/medical/nanogel = 5)
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
resistance_flags = FIRE_PROOF
refill_canister = /obj/item/vending_refill/robotics
default_price = PRICE_EXPENSIVE
payment_department = ACCOUNT_SCI
cost_multiplier_per_dept = list(ACCOUNT_SCI = 0)
/obj/item/vending_refill/robotics
machine_name = "Robotech Deluxe"
icon_state = "refill_engi"

View File

@@ -1,9 +1,11 @@
/obj/machinery/vending/security
name = "\improper SecTech"
desc = "A security equipment vendor."
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?"
product_ads = "Crack communist 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"
icon_deny = "sec-deny"
light_mask = "sec-light-mask"
req_access = list(ACCESS_SECURITY)
products = list(/obj/item/restraints/handcuffs = 8,
/obj/item/restraints/handcuffs/cable/zipties = 10,
/obj/item/grenade/flashbang = 4,
@@ -17,20 +19,17 @@
/obj/item/storage/fancy/donut_box = 2,
/obj/item/storage/belt/sabre/secbelt = 1)
premium = list(/obj/item/coin/antagtoken = 1,
/obj/item/clothing/head/helmet/blueshirt = 1,
/obj/item/clothing/suit/armor/vest/blueshirt = 1,
/obj/item/clothing/head/helmet/blueshirt = 1,
/obj/item/clothing/suit/armor/vest/blueshirt = 1,
/obj/item/clothing/under/rank/security/officer/blueshirt = 1,
/obj/item/clothing/gloves/tackler = 5,
/obj/item/grenade/stingbang = 1,
/obj/item/clothing/gloves/tackler = 5,
/obj/item/grenade/stingbang = 1,
/obj/item/ssword_kit = 1,
/obj/item/storage/bag/ammo = 3)
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
resistance_flags = FIRE_PROOF
refill_canister = /obj/item/vending_refill/security
default_price = PRICE_ALMOST_EXPENSIVE
extra_price = PRICE_REALLY_EXPENSIVE
payment_department = ACCOUNT_SEC
cost_multiplier_per_dept = list(ACCOUNT_SEC = 0)
/obj/machinery/vending/security/pre_throw(obj/item/I)
if(istype(I, /obj/item/grenade))
@@ -42,4 +41,4 @@
F.update_brightness()
/obj/item/vending_refill/security
icon_state = "refill_games"
icon_state = "refill_sec"

View File

@@ -4,6 +4,7 @@
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!"
icon_state = "snack"
light_mask = "snack-light-mask"
products = list(/obj/item/reagent_containers/food/snacks/candy = 5,
/obj/item/reagent_containers/food/snacks/chocolatebar = 5,
/obj/item/reagent_containers/food/drinks/dry_ramen = 5,
@@ -25,13 +26,11 @@
/obj/item/reagent_containers/food/snacks/chococoin = 1,
/obj/item/storage/box/marshmallow = 1,
/obj/item/storage/box/donkpockets = 2)
refill_canister = /obj/item/vending_refill/snack
canload_access_list = list(ACCESS_KITCHEN)
default_price = PRICE_REALLY_CHEAP
extra_price = PRICE_ALMOST_CHEAP
payment_department = ACCOUNT_SRV
cost_multiplier_per_dept = list(ACCOUNT_SRV = 0)
input_display_header = "Chef's Food Selection"
/obj/item/vending_refill/snack

View File

@@ -2,11 +2,17 @@
name = "\improper BODA"
desc = "Old sweet water vending machine."
icon_state = "sovietsoda"
light_mask = "soviet-light-mask"
product_ads = "For Tsar and Country.;Have you fulfilled your nutrition quota today?;Very nice!;We are simple people, for this is all we eat.;If there is a person, there is a problem. If there is no person, then there is no problem."
products = list(/obj/item/reagent_containers/food/drinks/drinkingglass/filled/soda = 30)
contraband = list(/obj/item/reagent_containers/food/drinks/drinkingglass/filled/cola = 20)
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
resistance_flags = FIRE_PROOF
default_price = PRICE_FREE
extra_price = PRICE_FREE
refill_canister = /obj/item/vending_refill/sovietsoda
default_price = 1
extra_price = 2 //One credit for every state of FREEDOM
payment_department = NO_FREEBIES
light_color = COLOR_PALE_ORANGE
/obj/item/vending_refill/sovietsoda
machine_name = "BODA"
icon_state = "refill_cola"

View File

@@ -2,21 +2,24 @@
name = "\improper Sustenance Vendor"
desc = "A vending machine which vends food, as required by section 47-C of the NT's Prisoner Ethical Treatment Agreement."
product_slogans = "Enjoy your meal.;Enough calories to support strenuous labor."
product_ads = "Sufficiently healthy.;Efficiently produced tofu!;Mmm! So good!;Have a meal.;You need food to live!;Have some more candy corn!;Try our new ice cups!"
product_ads = "Sufficiently healthy.;Efficiently produced tofu!;Mmm! So good!;Have a meal.;You need food to live!;Even prisoners deserve their daily bread!;Have some more candy corn!;Try our new ice cups!"
light_mask = "snack-light-mask"
icon_state = "sustenance"
products = list(/obj/item/reagent_containers/food/snacks/tofu = 24,
/obj/item/reagent_containers/food/drinks/ice/sustanance = 12,
/obj/item/reagent_containers/food/snacks/candy_corn = 6)
/obj/item/reagent_containers/food/snacks/candy_corn = 6
)
contraband = list(/obj/item/kitchen/knife = 6,
/obj/item/reagent_containers/food/drinks/coffee = 12,
/obj/item/tank/internals/emergency_oxygen = 6,
/obj/item/clothing/mask/breath = 6)
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
/obj/item/clothing/mask/breath = 6
)
refill_canister = /obj/item/vending_refill/sustenance
resistance_flags = FIRE_PROOF
default_price = PRICE_FREE
extra_price = PRICE_FREE
payment_department = NO_FREEBIES
/obj/item/vending_refill/sustenance
icon_state = "refill_cook"
machine_name = "Sustenance Vendor"
icon_state = "refill_snack"

View File

@@ -5,6 +5,7 @@
product_slogans = "Get your cool toys today!;Trigger a valid hunter today!;Quality toy weapons for cheap prices!;Give them to HoPs for all access!;Give them to HoS to get permabrigged!"
product_ads = "Feel robust with your toys!;Express your inner child today!;Toy weapons don't kill people, but valid hunters do!;Who needs responsibilities when you have toy weapons?;Make your next murder FUN!"
vend_reply = "Come back for more!"
light_mask = "donksoft-light-mask"
circuit = /obj/item/circuitboard/machine/vending/donksofttoyvendor
products = list(
/obj/item/gun/ballistic/automatic/toy/unrestricted = 10,
@@ -22,8 +23,6 @@
/obj/item/gun/ballistic/automatic/l6_saw/toy/unrestricted = 10,
/obj/item/toy/katana = 10,
/obj/item/dualsaber/toy = 5)
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
resistance_flags = FIRE_PROOF
refill_canister = /obj/item/vending_refill/donksoft
default_price = PRICE_ABOVE_NORMAL
extra_price = PRICE_EXPENSIVE

View File

@@ -6,6 +6,7 @@
extra_price = PRICE_EXPENSIVE
payment_department = NO_FREEBIES
input_display_header = "Returned Clothing"
light_mask = "wardrobe-light-mask"
/obj/machinery/vending/wardrobe/canLoadItem(obj/item/I,mob/user)
return (I.type in products)
@@ -35,51 +36,11 @@
/obj/item/clothing/head/beret/sec/navyofficer = 5)
refill_canister = /obj/item/vending_refill/wardrobe/sec_wardrobe
payment_department = ACCOUNT_SEC
cost_multiplier_per_dept = list(ACCOUNT_SEC = 0)
default_price = PRICE_ABOVE_NORMAL
extra_price = PRICE_EXPENSIVE
light_color = COLOR_MOSTLY_PURE_RED
/obj/item/vending_refill/wardrobe/sec_wardrobe
machine_name = "SecDrobe"
/obj/machinery/vending/wardrobe/det_wardrobe
name = "\improper DetDrobe"
desc = "A machine for all your detective needs, as long as you need clothes."
icon_state = "detdrobe"
product_ads = "Apply your brilliant deductive methods in style!"
vend_reply = "Thank you for using the DetDrobe!"
products = list(/obj/item/clothing/under/rank/security/detective = 2,
/obj/item/clothing/under/rank/security/detective/skirt = 2,
/obj/item/clothing/under/rank/security/detective/brown = 2,
/obj/item/clothing/under/rank/security/detective/brown/brown2 = 2,
/obj/item/clothing/under/rank/security/officer/blueshirt/seccorp/detcorp = 2,
/obj/item/clothing/under/rank/security/officer/util = 2,
/obj/item/clothing/shoes/sneakers/brown = 2,
/obj/item/clothing/suit/det_suit = 2,
/obj/item/clothing/head/fedora/det_hat = 2,
/obj/item/clothing/under/rank/security/detective/grey = 2,
/obj/item/clothing/under/rank/security/detective/grey/skirt = 2,
/obj/item/clothing/accessory/waistcoat = 2,
/obj/item/clothing/shoes/laceup = 2,
/obj/item/clothing/suit/det_suit/grey = 1,
/obj/item/clothing/suit/det_suit/forensicsred = 1,
/obj/item/clothing/suit/det_suit/forensicsred/long = 1,
/obj/item/clothing/suit/det_suit/forensicsblue = 1,
/obj/item/clothing/suit/det_suit/forensicsblue/long = 1,
/obj/item/clothing/head/fedora = 2,
/obj/item/clothing/gloves/color/black = 2,
/obj/item/clothing/gloves/color/latex = 2,
/obj/item/reagent_containers/food/drinks/flask/det = 2,
/obj/item/storage/fancy/cigarettes = 5)
premium = list(/obj/item/clothing/head/flatcap = 1)
refill_canister = /obj/item/vending_refill/wardrobe/det_wardrobe
extra_price = 350
payment_department = ACCOUNT_SEC
/obj/item/vending_refill/wardrobe/det_wardrobe
machine_name = "DetDrobe"
/obj/machinery/vending/wardrobe/medi_wardrobe
name = "\improper MediDrobe"
desc = "A vending machine rumoured to be capable of dispensing clothing for medical personnel."
@@ -118,7 +79,6 @@
/obj/item/clothing/suit/toggle/labcoat/emt/highvis = 5)
refill_canister = /obj/item/vending_refill/wardrobe/medi_wardrobe
payment_department = ACCOUNT_MED
cost_multiplier_per_dept = list(ACCOUNT_MED = 0)
/obj/item/vending_refill/wardrobe/medi_wardrobe
machine_name = "MediDrobe"
@@ -149,7 +109,7 @@
/obj/item/clothing/head/hardhat/weldhat = 3)
refill_canister = /obj/item/vending_refill/wardrobe/engi_wardrobe
payment_department = ACCOUNT_ENG
cost_multiplier_per_dept = list(ACCOUNT_ENG = 0)
light_color = COLOR_VIVID_YELLOW
/obj/item/vending_refill/wardrobe/engi_wardrobe
machine_name = "EngiDrobe"
@@ -172,7 +132,7 @@
/obj/item/clothing/shoes/sneakers/black = 5)
refill_canister = /obj/item/vending_refill/wardrobe/atmos_wardrobe
payment_department = ACCOUNT_ENG
cost_multiplier_per_dept = list(ACCOUNT_ENG = 0)
light_color = COLOR_VIVID_YELLOW
/obj/item/vending_refill/wardrobe/atmos_wardrobe
machine_name = "AtmosDrobe"
@@ -195,7 +155,6 @@
/obj/item/radio/headset/headset_cargo = 3)
refill_canister = /obj/item/vending_refill/wardrobe/cargo_wardrobe
payment_department = ACCOUNT_CAR
cost_multiplier_per_dept = list(ACCOUNT_CAR = 0)
/obj/item/vending_refill/wardrobe/cargo_wardrobe
machine_name = "CargoDrobe"
@@ -223,17 +182,16 @@
/obj/item/clothing/under/misc/mechsuitblue = 1)
contraband = list(/obj/item/clothing/suit/hooded/techpriest = 2)
refill_canister = /obj/item/vending_refill/wardrobe/robo_wardrobe
extra_price = PRICE_EXPENSIVE * 1.2
payment_department = ACCOUNT_SCI
cost_multiplier_per_dept = list(ACCOUNT_SCI = 0)
/obj/item/vending_refill/wardrobe/robo_wardrobe
machine_name = "RoboDrobe"
/obj/machinery/vending/wardrobe/science_wardrobe
name = "SciDrobe"
desc = "A simple vending machine suitable to dispense well tailored science clothing. Endorsed by Cubans."
desc = "A simple vending machine suitable to dispense well tailored science clothing. Endorsed by Space Cubans."
icon_state = "scidrobe"
product_ads = "Longing for the smell of flesh plasma? Buy your science clothing now!;Made with 10% Auxetics, so you don't have to worry losing your arm!"
product_ads = "Longing for the smell of plasma burnt flesh? Buy your science clothing now!;Made with 10% Auxetics, so you don't have to worry about losing your arm!"
vend_reply = "Thank you for using the SciDrobe!"
products = list(/obj/item/clothing/accessory/pocketprotector = 5,
/obj/item/clothing/head/beret/sci = 3,
@@ -251,8 +209,6 @@
/obj/item/clothing/mask/gas = 5)
refill_canister = /obj/item/vending_refill/wardrobe/science_wardrobe
payment_department = ACCOUNT_SCI
cost_multiplier_per_dept = list(ACCOUNT_SCI = 0)
/obj/item/vending_refill/wardrobe/science_wardrobe
machine_name = "SciDrobe"
@@ -274,7 +230,7 @@
/obj/item/clothing/mask/bandana = 4)
refill_canister = /obj/item/vending_refill/wardrobe/hydro_wardrobe
payment_department = ACCOUNT_SRV
cost_multiplier_per_dept = list(ACCOUNT_SRV = 0)
light_color = LIGHT_COLOR_ELECTRIC_GREEN
/obj/item/vending_refill/wardrobe/hydro_wardrobe
machine_name = "HyDrobe"
@@ -299,9 +255,7 @@
/obj/item/clothing/glasses/regular/jamjar = 1,
/obj/item/storage/bag/books = 1)
refill_canister = /obj/item/vending_refill/wardrobe/curator_wardrobe
payment_department = ACCOUNT_CIV
cost_multiplier_per_dept = list(ACCOUNT_CIV = 0)
payment_department = ACCOUNT_SRV
/obj/item/vending_refill/wardrobe/curator_wardrobe
machine_name = "CuraDrobe"
@@ -331,8 +285,6 @@
/obj/item/storage/belt/bandolier = 1)
refill_canister = /obj/item/vending_refill/wardrobe/bar_wardrobe
payment_department = ACCOUNT_SRV
cost_multiplier_per_dept = list(ACCOUNT_SRV = 0)
/obj/item/vending_refill/wardrobe/bar_wardrobe
machine_name = "BarDrobe"
@@ -340,8 +292,8 @@
name = "ChefDrobe"
desc = "This vending machine might not dispense meat, but it certainly dispenses chef related clothing."
icon_state = "chefdrobe"
product_ads = "Our clothes are guaranteed to protect you from food splatters!;Now stocking recipe books!"
vend_reply = "Thank you for using the ChefDrobe!;Just like your grandmother's old recipes!"
product_ads = "Our clothes are guaranteed to protect you from food splatters!"
vend_reply = "Thank you for using the ChefDrobe!"
products = list(/obj/item/clothing/under/suit/waiter = 3,
/obj/item/radio/headset/headset_srv = 4,
/obj/item/clothing/accessory/waistcoat = 3,
@@ -358,8 +310,6 @@
/obj/item/book/granter/crafting_recipe/coldcooking = 2)
refill_canister = /obj/item/vending_refill/wardrobe/chef_wardrobe
payment_department = ACCOUNT_SRV
cost_multiplier_per_dept = list(ACCOUNT_SRV = 0)
/obj/item/vending_refill/wardrobe/chef_wardrobe
machine_name = "ChefDrobe"
@@ -390,8 +340,10 @@
/obj/item/screwdriver = 2,
/obj/item/stack/cable_coil/random = 4)
refill_canister = /obj/item/vending_refill/wardrobe/jani_wardrobe
default_price = PRICE_CHEAP
extra_price = PRICE_EXPENSIVE * 0.8
payment_department = ACCOUNT_SRV
cost_multiplier_per_dept = list(ACCOUNT_SRV = 0)
light_color = COLOR_STRONG_MAGENTA
/obj/item/vending_refill/wardrobe/jani_wardrobe
machine_name = "JaniDrobe"
@@ -423,18 +375,16 @@
/obj/item/clothing/shoes/laceup = 3,
/obj/item/clothing/accessory/lawyers_badge = 3)
refill_canister = /obj/item/vending_refill/wardrobe/law_wardrobe
payment_department = ACCOUNT_CIV
cost_multiplier_per_dept = list(ACCOUNT_CIV = 0)
payment_department = ACCOUNT_SRV
/obj/item/vending_refill/wardrobe/law_wardrobe
machine_name = "LawDrobe"
/obj/machinery/vending/wardrobe/chap_wardrobe
name = "ChapDrobe"
desc = "This most blessed and holy machine vends clothing only suitable for chaplains to gaze upon."
name = "DeusVend"
desc = "God wills your purchase."
icon_state = "chapdrobe"
product_ads = "Are you being bothered by cultists or pesky revenants? Then come and dress like the holy man!;Clothes for men of the cloth!"
vend_reply = "Thank you for using the ChapDrobe!"
vend_reply = "Thank you for using the DeusVend!"
products = list(/obj/item/choice_beacon/holy = 1,
/obj/item/storage/backpack/cultpack = 2,
/obj/item/clothing/accessory/pocketprotector/cosmetology = 2,
@@ -451,11 +401,9 @@
premium = list(/obj/item/toy/plush/plushvar = 1,
/obj/item/toy/plush/narplush = 1)
refill_canister = /obj/item/vending_refill/wardrobe/chap_wardrobe
payment_department = ACCOUNT_CIV
cost_multiplier_per_dept = list(ACCOUNT_CIV = 0)
payment_department = ACCOUNT_SRV
/obj/item/vending_refill/wardrobe/chap_wardrobe
machine_name = "ChapDrobe"
machine_name = "DeusVend"
/obj/machinery/vending/wardrobe/chem_wardrobe
name = "ChemDrobe"
@@ -475,8 +423,6 @@
/obj/item/fermichem/pHbooklet = 3)
refill_canister = /obj/item/vending_refill/wardrobe/chem_wardrobe
payment_department = ACCOUNT_MED
cost_multiplier_per_dept = list(ACCOUNT_MED = 0)
/obj/item/vending_refill/wardrobe/chem_wardrobe
machine_name = "ChemDrobe"
@@ -494,9 +440,7 @@
/obj/item/storage/backpack/genetics = 3,
/obj/item/storage/backpack/satchel/gen = 3)
refill_canister = /obj/item/vending_refill/wardrobe/gene_wardrobe
payment_department = ACCOUNT_MED
cost_multiplier_per_dept = list(ACCOUNT_MED = 0)
payment_department = ACCOUNT_SCI
/obj/item/vending_refill/wardrobe/gene_wardrobe
machine_name = "GeneDrobe"
@@ -517,11 +461,46 @@
/obj/item/storage/backpack/satchel/vir = 3)
refill_canister = /obj/item/vending_refill/wardrobe/viro_wardrobe
payment_department = ACCOUNT_MED
cost_multiplier_per_dept = list(ACCOUNT_MED = 0)
/obj/item/vending_refill/wardrobe/viro_wardrobe
machine_name = "ViroDrobe"
/obj/machinery/vending/wardrobe/det_wardrobe
name = "\improper DetDrobe"
desc = "A machine for all your detective needs, as long as you need clothes."
icon_state = "detdrobe"
product_ads = "Apply your brilliant deductive methods in style!"
vend_reply = "Thank you for using the DetDrobe!"
products = list(/obj/item/clothing/under/rank/security/detective = 2,
/obj/item/clothing/under/rank/security/detective/skirt = 2,
/obj/item/clothing/under/rank/security/detective/brown = 2,
/obj/item/clothing/under/rank/security/detective/brown/brown2 = 2,
/obj/item/clothing/under/rank/security/officer/blueshirt/seccorp/detcorp = 2,
/obj/item/clothing/under/rank/security/officer/util = 2,
/obj/item/clothing/shoes/sneakers/brown = 2,
/obj/item/clothing/suit/det_suit = 2,
/obj/item/clothing/head/fedora/det_hat = 2,
/obj/item/clothing/under/rank/security/detective/grey = 2,
/obj/item/clothing/under/rank/security/detective/grey/skirt = 2,
/obj/item/clothing/accessory/waistcoat = 2,
/obj/item/clothing/shoes/laceup = 2,
/obj/item/clothing/suit/det_suit/grey = 1,
/obj/item/clothing/suit/det_suit/forensicsred = 1,
/obj/item/clothing/suit/det_suit/forensicsred/long = 1,
/obj/item/clothing/suit/det_suit/forensicsblue = 1,
/obj/item/clothing/suit/det_suit/forensicsblue/long = 1,
/obj/item/clothing/head/fedora = 2,
/obj/item/clothing/gloves/color/black = 2,
/obj/item/clothing/gloves/color/latex = 2,
/obj/item/reagent_containers/food/drinks/flask/det = 2,
/obj/item/storage/fancy/cigarettes = 5)
premium = list(/obj/item/clothing/head/flatcap = 1)
refill_canister = /obj/item/vending_refill/wardrobe/det_wardrobe
extra_price = PRICE_EXPENSIVE * 1.75
payment_department = ACCOUNT_SEC
/obj/item/vending_refill/wardrobe/det_wardrobe
machine_name = "DetDrobe"
/obj/machinery/vending/wardrobe/cap_wardrobe
name = "Captain's Wardrobe"
desc = "The latest and greatest in Nanotrasen fashion for your great leader."
@@ -552,10 +531,6 @@
default_price = PRICE_ALMOST_EXPENSIVE
extra_price = PRICE_ABOVE_EXPENSIVE
/obj/machinery/vending/wardrobe/cap_wardrobe/Initialize()
. = ..()
cost_multiplier_per_dept = list("[ACCESS_CAPTAIN]" = 0)
/obj/item/vending_refill/wardrobe/cap_wardrobe
machine_name = "Captain's Wardrobe"
icon_state = "refill_caps"

View File

@@ -3,6 +3,7 @@
desc = "Tools for tools."
icon_state = "tool"
icon_deny = "tool-deny"
light_mask = "tool-light-mask"
products = list(/obj/item/stack/cable_coil/random = 15,
/obj/item/crowbar = 10,
/obj/item/weldingtool = 6,
@@ -19,13 +20,11 @@
/obj/item/multitool = 2)
premium = list(/obj/item/clothing/gloves/color/yellow = 2,
/obj/item/weldingtool/hugetank = 2)
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 70)
refill_canister = /obj/item/vending_refill/tool
resistance_flags = FIRE_PROOF
refill_canister = /obj/item/vending_refill/youtool
default_price = PRICE_REALLY_CHEAP
extra_price = PRICE_EXPENSIVE
payment_department = ACCOUNT_ENG
cost_multiplier_per_dept = list(ACCOUNT_ENG = 0)
/obj/item/vending_refill/tool
/obj/item/vending_refill/youtool
machine_name = "YouTool"
icon_state = "refill_engi"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

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