Merge pull request #1 from Citadel-Station-13/master

update
This commit is contained in:
bunny232
2020-03-08 07:19:42 -04:00
committed by GitHub
122 changed files with 2595 additions and 1863 deletions
@@ -1545,21 +1545,6 @@
},
/turf/open/floor/plasteel,
/area/engine/engineering)
"RK" = (
/obj/machinery/portable_atmospherics/canister/toxins,
/obj/effect/turf_decal/delivery,
/obj/structure/cable/yellow{
icon_state = "4-8"
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
/obj/structure/window/reinforced{
dir = 8
},
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plasteel,
/area/engine/engineering)
"RQ" = (
/obj/machinery/atmospherics/components/binary/pump{
dir = 1
@@ -2237,7 +2222,7 @@ yf
"}
(12,1,1) = {"
cS
RK
QS
uy
PK
iZ
+39 -11
View File
@@ -655,7 +655,7 @@
/turf/open/floor/plating,
/area/mine/laborcamp)
"ia" = (
/obj/item/reagent_containers/glass/bucket,
/obj/item/reagent_containers/glass/bucket/wood,
/obj/structure/stone_tile/block/cracked{
dir = 4
},
@@ -750,8 +750,23 @@
/obj/item/stack/sheet/mineral/wood,
/obj/item/stack/sheet/mineral/wood,
/obj/item/stack/sheet/mineral/wood,
/obj/item/seeds/tower,
/obj/item/seeds/tower,
/obj/item/seeds/ambrosia/deus{
yield = 5
potency = 50
},
/obj/item/seeds/ambrosia/deus{
yield = 5
potency = 50
},
/obj/item/seeds/tower{
yield = 5
potency = 50
},
/obj/item/seeds/tower{
yield = 5
potency = 50
},
/mob/living/simple_animal/hostile/asteroid/gutlunch/guthen,
/turf/open/indestructible/boss,
/area/ruin/unpowered/ash_walkers)
"iJ" = (
@@ -2179,8 +2194,15 @@
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/ruin/unpowered/ash_walkers)
"wm" = (
/obj/item/seeds/glowshroom,
/obj/item/seeds/glowshroom,
/obj/item/seeds/glowshroom{
yield = 5
potency = 50
},
/obj/item/seeds/glowshroom{
yield = 5
potency = 50
},
/mob/living/simple_animal/hostile/asteroid/gutlunch/gubbuck,
/obj/structure/stone_tile/block{
dir = 4
},
@@ -3327,8 +3349,15 @@
dir = 4
},
/obj/item/storage/bag/plants/portaseeder,
/obj/item/seeds/cotton,
/obj/item/seeds/cotton,
/obj/item/storage/bag/plants,
/obj/item/seeds/cotton{
yield = 5
potency = 50
},
/obj/item/seeds/cotton{
yield = 5
potency = 50
},
/turf/open/indestructible/boss,
/area/ruin/unpowered/ash_walkers)
"Vj" = (
@@ -3355,10 +3384,9 @@
/turf/open/floor/plasteel,
/area/mine/laborcamp)
"VI" = (
/obj/structure/stone_tile{
dir = 8
},
/obj/structure/reagent_dispensers/watertank,
/obj/structure/well_foundation,
/obj/item/reagent_containers/glass/bucket/wood,
/obj/item/reagent_containers/glass/bucket/wood,
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/ruin/unpowered/ash_walkers)
"VP" = (
File diff suppressed because it is too large Load Diff
+15
View File
@@ -34,6 +34,21 @@
#define HIJACK_HIJACKER 1 //Needs to be present for shuttle to be hijacked
#define HIJACK_PREVENT 2 //Prevents hijacking same way as non-antags
//Syndicate Contracts
#define CONTRACT_STATUS_INACTIVE 1
#define CONTRACT_STATUS_ACTIVE 2
#define CONTRACT_STATUS_BOUNTY_CONSOLE_ACTIVE 3
#define CONTRACT_STATUS_EXTRACTING 4
#define CONTRACT_STATUS_COMPLETE 5
#define CONTRACT_STATUS_ABORTED 6
#define CONTRACT_PAYOUT_LARGE 1
#define CONTRACT_PAYOUT_MEDIUM 2
#define CONTRACT_PAYOUT_SMALL 3
#define CONTRACT_UPLINK_PAGE_CONTRACTS "CONTRACTS"
#define CONTRACT_UPLINK_PAGE_HUB "HUB"
//Overthrow time to update heads obj
#define OBJECTIVE_UPDATING_TIME 300
+13 -5
View File
@@ -17,6 +17,9 @@
//ids
#define MOVESPEED_ID_MOB_WALK_RUN_CONFIG_SPEED "MOB_WALK_RUN"
#define MOVESPEED_ID_MOB_GRAB_STATE "MOB_GRAB_STATE"
#define MOVESPEED_ID_MOB_EQUIPMENT "MOB_EQUIPMENT"
#define MOVESPEED_ID_MOB_GRAVITY "MOB_GRAVITY"
#define MOVESPEED_ID_CONFIG_SPEEDMOD "MOB_CONFIG_MODIFIER"
#define MOVESPEED_ID_SLIME_REAGENTMOD "SLIME_REAGENT_MODIFIER"
@@ -28,6 +31,7 @@
#define MOVESPEED_ID_TARANTULA_WEB "TARANTULA_WEB"
#define MOVESPEED_ID_LIVING_TURF_SPEEDMOD "LIVING_TURF_SPEEDMOD"
#define MOVESPEED_ID_LIVING_LIMBLESS "LIVING_LIMBLESS"
#define MOVESPEED_ID_CARBON_SOFTCRIT "CARBON_SOFTCRIT"
#define MOVESPEED_ID_CARBON_OLDSPEED "CARBON_DEPRECATED_SPEED"
@@ -59,15 +63,19 @@
#define MOVESPEED_ID_HUMAN_CARRYING "HUMAN_CARRY"
#define MOVESPEED_ID_SHRINK_RAY "SHRUNKEN_SPEED_MODIFIER"
#define MOVESPEED_ID_TASED_STATUS "TASED"
#define MOVESPEED_ID_SLAUGHTER "SLAUGHTER"
#define MOVESPEED_ID_CYBER_THRUSTER "CYBER_IMPLANT_THRUSTER"
#define MOVESPEED_ID_JETPACK "JETPACK"
#define MOVESPEED_ID_SHOVE "SHOVE"
#define MOVESPEED_ID_MKULTRA "MKULTRA"
#define MOVESPEED_ID_ELECTROSTAFF "ELECTROSTAFF"
#define MOVESPEED_ID_TASED_STATUS "TASED"
#define MOVESPEED_ID_ELECTROSTAFF "ELECTROSTAFF"
#define MOVESPEED_ID_SHOVE "SHOVE"
#define MOVESPEED_ID_FAT "FAT"
#define MOVESPEED_ID_COLD "COLD"
#define MOVESPEED_ID_HUNGRY "HUNGRY"
#define MOVESPEED_ID_DAMAGE_SLOWDOWN "DAMAGE"
#define MOVESPEED_ID_DAMAGE_SLOWDOWN_FLYING "FLYING"
+5
View File
@@ -1,5 +1,10 @@
#define BP_MAX_ROOM_SIZE 300
GLOBAL_LIST_INIT(typecache_powerfailure_safe_areas, typecacheof(/area/engine/engineering, \
/area/engine/supermatter, \
/area/engine/atmospherics_engine, \
/area/ai_monitored/turret_protected/ai))
//Repopulates sortedAreas list
/proc/repopulate_sorted_areas()
GLOB.sortedAreas = list()
+33
View File
@@ -549,3 +549,36 @@
var/pressure = environment.return_pressure()
if(pressure <= LAVALAND_EQUIPMENT_EFFECT_PRESSURE)
. = TRUE
/proc/ispipewire(item)
var/static/list/pipe_wire = list(
/obj/machinery/atmospherics,
/obj/structure/disposalpipe,
/obj/structure/cable
)
return (is_type_in_list(item, pipe_wire))
// Find a obstruction free turf that's within the range of the center. Can also condition on if it is of a certain area type.
/proc/find_obstruction_free_location(var/range, var/atom/center, var/area/specific_area)
var/list/turfs = RANGE_TURFS(range, center)
var/list/possible_loc = list()
for(var/turf/found_turf in turfs)
var/area/turf_area = get_area(found_turf)
if (specific_area) // We check if both the turf is a floor, and that it's actually in the area. // We also want a location that's clear of any obstructions.
if(!istype(turf_area, specific_area))
continue
if(!isspaceturf(found_turf))
if(!is_blocked_turf(found_turf))
possible_loc.Add(found_turf)
if (possible_loc.len < 1) // Need at least one free location.
return FALSE
return pick(possible_loc)
/proc/power_fail(duration_min, duration_max)
for(var/P in GLOB.apcs_list)
var/obj/machinery/power/apc/C = P
if(C.cell && SSmapping.level_trait(C.z, ZTRAIT_STATION))
var/area/A = C.area
if(GLOB.typecache_powerfailure_safe_areas[A.type])
continue
C.energy_fail(rand(duration_min,duration_max))
+1
View File
@@ -354,6 +354,7 @@
roundend_report.set_content(content)
roundend_report.stylesheets = list()
roundend_report.add_stylesheet("roundend", 'html/browser/roundend.css')
roundend_report.add_stylesheet("font-awesome", 'html/font-awesome/css/all.min.css')
roundend_report.open(0)
/datum/controller/subsystem/ticker/proc/personal_report(client/C, popcount)
+15 -1
View File
@@ -49,7 +49,7 @@
alert("Invalid name.")
return ""
return sanitize(t)
/proc/sanitize_filename(t)
return sanitize_simple(t, list("\n"="", "\t"="", "/"="", "\\"="", "?"="", "%"="", "*"="", ":"="", "|"="", "\""="", "<"="", ">"=""))
@@ -798,3 +798,17 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
out += prob(replaceprob)? pick(replacementchars) : char
return out.Join("")
/proc/readable_corrupted_text(text)
var/list/corruption_options = list("..", "£%", "~~\"", "!!", "*", "^", "$!", "-", "}", "?")
var/corrupted_text = ""
for(var/letter_index = 1; letter_index <= length(text); letter_index++) // Have every letter have a chance of creating corruption on either side
var/letter = text[letter_index] // Small chance of letters being removed in place of corruption - still overall readable
if(prob(15))
corrupted_text += pick(corruption_options)
if(prob(95))
corrupted_text += letter
else
corrupted_text += pick(corruption_options)
if(prob(15))
corrupted_text += pick(corruption_options)
return corrupted_text
-111
View File
@@ -1,111 +0,0 @@
/*
// Contains VOREStation based vore description type2type functions
// list2text - takes delimiter and returns text
// text2list - takes delimiter, and creates list
//
*/
// Concatenates a list of strings into a single string. A seperator may optionally be provided.
/proc/list2text(list/ls, sep)
if (ls.len <= 1) // Early-out code for empty or singleton lists.
return ls.len ? ls[1] : ""
var/l = ls.len // Made local for sanic speed.
var/i = 0 // Incremented every time a list index is accessed.
if (sep <> null)
// Macros expand to long argument lists like so: sep, ls[++i], sep, ls[++i], sep, ls[++i], etc...
#define S1 sep, ls[++i]
#define S4 S1, S1, S1, S1
#define S16 S4, S4, S4, S4
#define S64 S16, S16, S16, S16
. = "[ls[++i]]" // Make sure the initial element is converted to text.
// Having the small concatenations come before the large ones boosted speed by an average of at least 5%.
if (l-1 & 0x01) // 'i' will always be 1 here.
. = text("[][][]", ., S1) // Append 1 element if the remaining elements are not a multiple of 2.
if (l-i & 0x02)
. = text("[][][][][]", ., S1, S1) // Append 2 elements if the remaining elements are not a multiple of 4.
if (l-i & 0x04)
. = text("[][][][][][][][][]", ., S4) // And so on....
if (l-i & 0x08)
. = text("[][][][][][][][][][][][][][][][][]", ., S4, S4)
if (l-i & 0x10)
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S16)
if (l-i & 0x20)
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S16, S16)
if (l-i & 0x40)
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64)
while (l > i) // Chomp through the rest of the list, 128 elements at a time.
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, S64)
#undef S64
#undef S16
#undef S4
#undef S1
else
// Macros expand to long argument lists like so: ls[++i], ls[++i], ls[++i], etc...
#define S1 ls[++i]
#define S4 S1, S1, S1, S1
#define S16 S4, S4, S4, S4
#define S64 S16, S16, S16, S16
. = "[ls[++i]]" // Make sure the initial element is converted to text.
if (l-1 & 0x01) // 'i' will always be 1 here.
. += S1 // Append 1 element if the remaining elements are not a multiple of 2.
if (l-i & 0x02)
. = text("[][][]", ., S1, S1) // Append 2 elements if the remaining elements are not a multiple of 4.
if (l-i & 0x04)
. = text("[][][][][]", ., S4) // And so on...
if (l-i & 0x08)
. = text("[][][][][][][][][]", ., S4, S4)
if (l-i & 0x10)
. = text("[][][][][][][][][][][][][][][][][]", ., S16)
if (l-i & 0x20)
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S16, S16)
if (l-i & 0x40)
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64)
while (l > i) // Chomp through the rest of the list, 128 elements at a time.
. = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, S64)
#undef S64
#undef S16
#undef S4
#undef S1
// Converts a string into a list by splitting the string at each delimiter found. (discarding the seperator)
/proc/text2list(text, delimiter="\n")
var/delim_len = length(delimiter)
if (delim_len < 1)
return list(text)
. = list()
var/last_found = 1
var/found
do
found = findtext(text, delimiter, last_found, 0)
. += copytext(text, last_found, found)
last_found = found + delim_len
while (found)
// Returns true if val is from min to max, inclusive.
/proc/IsInRange(val, min, max)
return (val >= min) && (val <= max)
-39
View File
@@ -1,39 +0,0 @@
/datum/projectile_data
var/src_x
var/src_y
var/time
var/distance
var/power_x
var/power_y
var/dest_x
var/dest_y
/datum/projectile_data/New(var/src_x, var/src_y, var/time, var/distance, \
var/power_x, var/power_y, var/dest_x, var/dest_y)
src.src_x = src_x
src.src_y = src_y
src.time = time
src.distance = distance
src.power_x = power_x
src.power_y = power_y
src.dest_x = dest_x
src.dest_y = dest_y
/proc/projectile_trajectory(src_x, src_y, rotation, angle, power)
// returns the destination (Vx,y) that a projectile shot at [src_x], [src_y], with an angle of [angle],
// rotated at [rotation] and with the power of [power]
// Thanks to VistaPOWA for this function
var/power_x = power * cos(angle)
var/power_y = power * sin(angle)
var/time = 2* power_y / 10 //10 = g
var/distance = time * power_x
var/dest_x = src_x + distance*sin(rotation);
var/dest_y = src_y + distance*cos(rotation);
return new /datum/projectile_data(src_x, src_y, time, distance, power_x, power_y, dest_x, dest_y)
+3 -1
View File
@@ -18,6 +18,7 @@
#define POLL_IGNORE_DEMON "demon"
#define POLL_IGNORE_WIZARD "wizard"
#define POLL_IGNORE_CLONE "clone"
#define POLL_IGNORE_CONTRACTOR_SUPPORT "contractor_support"
GLOBAL_LIST_INIT(poll_ignore_desc, list(
POLL_IGNORE_SENTIENCE_POTION = "Sentience potion",
@@ -37,7 +38,8 @@ GLOBAL_LIST_INIT(poll_ignore_desc, list(
POLL_IGNORE_SPLITPERSONALITY = "Split Personality",
POLL_IGNORE_DEMON = "Demons",
POLL_IGNORE_WIZARD = "Wizards",
POLL_IGNORE_CLONE = "Defective/SDGF clones"
POLL_IGNORE_CLONE = "Defective/SDGF clones",
POLL_IGNORE_CONTRACTOR_SUPPORT = "Contractor Support Unit"
))
GLOBAL_LIST_INIT(poll_ignore, init_poll_ignore())
+3 -2
View File
@@ -499,10 +499,11 @@ SUBSYSTEM_DEF(vote)
modes_to_add -= "traitor" // makes it so that traitor is always available
choices.Add(modes_to_add)
if("dynamic")
var/list/probabilities = CONFIG_GET(keyed_list/storyteller_weight)
for(var/T in config.storyteller_cache)
var/datum/dynamic_storyteller/S = T
var/list/probabilities = CONFIG_GET(keyed_list/storyteller_weight)
if(probabilities[initial(S.config_tag)] > 0)
var/probability = ((initial(S.config_tag) in probabilities) ? probabilities[initial(S.config_tag)] : initial(S.weight))
if(probability > 0)
choices.Add(initial(S.name))
choice_descs.Add(initial(S.desc))
if("custom")
+9 -3
View File
@@ -39,12 +39,18 @@
//title_image = ntitle_image
/datum/browser/proc/add_stylesheet(name, file)
if(istype(name, /datum/asset/spritesheet))
if (istype(name, /datum/asset/spritesheet))
var/datum/asset/spritesheet/sheet = name
stylesheets["spritesheet_[sheet.name].css"] = "data/spritesheets/[sheet.name]"
else
stylesheets["[ckey(name)].css"] = file
register_asset("[ckey(name)].css", file)
var/asset_name = "[name].css"
stylesheets[asset_name] = file
if(!SSassets.cache[asset_name])
register_asset(asset_name, file)
/datum/browser/proc/add_script(name, file)
scripts["[ckey(name)].js"] = file
register_asset("[ckey(name)].js", file)
/datum/browser/proc/set_content(ncontent)
content = ncontent
@@ -298,19 +298,15 @@
subcategory = CAT_AMMO
/datum/crafting_recipe/ashen_arrow
name = "Bonfire-Hardened Arrow"
name = "Fire Hardened Arrow"
result = /obj/item/ammo_casing/caseless/arrow/ashen
tools = list(/obj/structure/bonfire)
tools = list(TOOL_WELDER)
time = 30
always_availible = FALSE
reqs = list(/obj/item/ammo_casing/caseless/arrow = 1)
category = CAT_WEAPONRY
subcategory = CAT_AMMO
/datum/crafting_recipe/ashen_arrow/welder
name = "Welder-Hardened Arrow"
tools = list(TOOL_WELDER)
/datum/crafting_recipe/smartdart
name = "Medical smartdart"
result = /obj/item/reagent_containers/syringe/dart
+14 -16
View File
@@ -26,10 +26,10 @@
/datum/proc/vv_get_dropdown()
. = list()
. += "---"
.["Call Proc"] = "?_src_=vars;[HrefToken()];proc_call=[REF(src)]"
.["Mark Object"] = "?_src_=vars;[HrefToken()];mark_object=[REF(src)]"
.["Delete"] = "?_src_=vars;[HrefToken()];delete=[REF(src)]"
.["Show VV To Player"] = "?_src_=vars;[HrefToken(TRUE)];expose=[REF(src)]"
.["Call Proc"] = "?_src_=vars;[HrefToken()];proc_call=\ref[src]"
.["Mark Object"] = "?_src_=vars;[HrefToken()];mark_object=\ref[src]"
.["Delete"] = "?_src_=vars;[HrefToken()];delete=\ref[src]"
.["Show VV To Player"] = "?_src_=vars;[HrefToken(TRUE)];expose=\ref[src]"
/datum/proc/on_reagent_change(changetype)
@@ -54,7 +54,7 @@
return
var/title = ""
var/refid = REF(D)
var/refid = "\ref[D]"
var/icon/sprite
var/hash
@@ -62,8 +62,6 @@
if (!islist)
type = D.type
if(istype(D, /atom))
var/atom/AT = D
if(AT.icon && AT.icon_state)
@@ -410,7 +408,7 @@
/client/proc/vv_update_display(datum/D, span, content)
src << output("[span]:[content]", "variables[REF(D)].browser:replace_span")
src << output("[span]:[content]", "variables\ref[D].browser:replace_span")
#define VV_HTML_ENCODE(thing) ( sanitize ? html_encode(thing) : thing )
@@ -423,9 +421,9 @@
name = DA[name] //name is really the index until this line
else
value = DA[name]
header = "<li style='backgroundColor:white'>(<a href='?_src_=vars;[HrefToken()];listedit=[REF(DA)];index=[index]'>E</a>) (<a href='?_src_=vars;[HrefToken()];listchange=[REF(DA)];index=[index]'>C</a>) (<a href='?_src_=vars;[HrefToken()];listremove=[REF(DA)];index=[index]'>-</a>) "
header = "<li style='backgroundColor:white'>(<a href='?_src_=vars;[HrefToken()];listedit=\ref[DA];index=[index]'>E</a>) (<a href='?_src_=vars;[HrefToken()];listchange=\ref[DA];index=[index]'>C</a>) (<a href='?_src_=vars;[HrefToken()];listremove=\ref[DA];index=[index]'>-</a>) "
else
header = "<li style='backgroundColor:white'>(<a href='?_src_=vars;[HrefToken()];datumedit=[REF(DA)];varnameedit=[name]'>E</a>) (<a href='?_src_=vars;[HrefToken()];datumchange=[REF(DA)];varnamechange=[name]'>C</a>) (<a href='?_src_=vars;[HrefToken()];datummass=[REF(DA)];varnamemass=[name]'>M</a>) "
header = "<li style='backgroundColor:white'>(<a href='?_src_=vars;[HrefToken()];datumedit=\ref[DA];varnameedit=[name]'>E</a>) (<a href='?_src_=vars;[HrefToken()];datumchange=\ref[DA];varnamechange=[name]'>C</a>) (<a href='?_src_=vars;[HrefToken()];datummass=\ref[DA];varnamemass=[name]'>M</a>) "
else
header = "<li>"
@@ -440,7 +438,7 @@
#ifdef VARSICON
var/icon/I = new/icon(value)
var/rnd = rand(1,10000)
var/rname = "tmp[REF(I)][rnd].png"
var/rname = "tmp\ref[I][rnd].png"
usr << browse_rsc(I, rname)
item = "[VV_HTML_ENCODE(name)] = (<span class='value'>[value]</span>) <img class=icon src=\"[rname]\">"
#else
@@ -453,9 +451,9 @@
else if (istype(value, /datum))
var/datum/D = value
if ("[D]" != "[D.type]") //if the thing as a name var, lets use it.
item = "<a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>[VV_HTML_ENCODE(name)] [REF(value)]</a> = [D] [D.type]"
item = "<a href='?_src_=vars;[HrefToken()];Vars=\ref[value]'>[VV_HTML_ENCODE(name)] [REF(value)]</a> = [D] [D.type]"
else
item = "<a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>[VV_HTML_ENCODE(name)] [REF(value)]</a> = [D.type]"
item = "<a href='?_src_=vars;[HrefToken()];Vars=\ref[value]'>[VV_HTML_ENCODE(name)] [REF(value)]</a> = [D.type]"
else if (islist(value))
var/list/L = value
@@ -473,9 +471,9 @@
items += debug_variable(key, val, level + 1, sanitize = sanitize)
item = "<a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>[VV_HTML_ENCODE(name)] = /list ([L.len])</a><ul>[items.Join()]</ul>"
item = "<a href='?_src_=vars;[HrefToken()];Vars=\ref[value]'>[VV_HTML_ENCODE(name)] = /list ([L.len])</a><ul>[items.Join()]</ul>"
else
item = "<a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>[VV_HTML_ENCODE(name)] = /list ([L.len])</a>"
item = "<a href='?_src_=vars;[HrefToken()];Vars=\ref[value]'>[VV_HTML_ENCODE(name)] = /list ([L.len])</a>"
else if (name in GLOB.bitfields)
var/list/flags = list()
@@ -587,7 +585,7 @@
var/prompt = alert("Do you want to grant [C] access to view this VV window? (they will not be able to edit or change anything nor open nested vv windows unless they themselves are an admin)", "Confirm", "Yes", "No")
if (prompt != "Yes" || !usr.client)
return
message_admins("[key_name_admin(usr)] Showed [key_name_admin(C)] a <a href='?_src_=vars;[HrefToken(TRUE)];datumrefresh=[REF(thing)]'>VV window</a>")
message_admins("[key_name_admin(usr)] Showed [key_name_admin(C)] a <a href='?_src_=vars;[HrefToken(TRUE)];datumrefresh=\ref[thing]'>VV window</a>")
log_admin("Admin [key_name(usr)] Showed [key_name(C)] a VV window of a [thing]")
to_chat(C, "[usr.client.holder.fakekey ? "an Administrator" : "[usr.client.key]"] has granted you access to view a View Variables window")
C.debug_variables(thing)
+2 -2
View File
@@ -119,7 +119,7 @@
D.grabbedby(A, 1)
if(old_grab_state == GRAB_PASSIVE)
D.drop_all_held_items()
A.grab_state = GRAB_AGGRESSIVE //Instant agressive grab if on grab intent
A.setGrabState(GRAB_AGGRESSIVE) //Instant agressive grab if on grab intent
log_combat(A, D, "grabbed", addition="aggressively")
D.visible_message("<span class='warning'>[A] violently grabs [D]!</span>", \
"<span class='userdanger'>[A] violently grabs you!</span>")
@@ -185,7 +185,7 @@
D.SetSleeping(400)
restraining = FALSE
if(A.grab_state < GRAB_NECK)
A.grab_state = GRAB_NECK
A.setGrabState(GRAB_NECK)
else
restraining = FALSE
return FALSE
+2 -2
View File
@@ -34,10 +34,10 @@
log_combat(A, D, "grabbed", addition="aggressively")
D.visible_message("<span class='warning'>[A] violently grabs [D]!</span>", \
"<span class='userdanger'>[A] violently grabs you!</span>")
A.grab_state = GRAB_AGGRESSIVE //Instant aggressive grab
A.setGrabState(GRAB_AGGRESSIVE) //Instant aggressive grab
else
log_combat(A, D, "grabbed", addition="passively")
A.grab_state = GRAB_PASSIVE
A.setGrabState(GRAB_PASSIVE)
if(4)
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
atk_verb = "headbutts"
+1 -1
View File
@@ -115,7 +115,7 @@
D.grabbedby(A, 1)
if(old_grab_state == GRAB_PASSIVE)
D.drop_all_held_items()
A.grab_state = GRAB_AGGRESSIVE //Instant agressive grab if on grab intent
A.setGrabState(GRAB_AGGRESSIVE) //Instant agressive grab if on grab intent
log_combat(A, D, "grabbed", addition="aggressively")
D.visible_message("<span class='warning'>[A] violently grabs [D]!</span>", \
"<span class='userdanger'>[A] violently grabs you!</span>")
+4
View File
@@ -617,6 +617,10 @@
if(!(has_antag_datum(/datum/antagonist/traitor)))
add_antag_datum(/datum/antagonist/traitor)
/datum/mind/proc/make_Contractor_Support()
if(!(has_antag_datum(/datum/antagonist/traitor/contractor_support)))
add_antag_datum(/datum/antagonist/traitor/contractor_support)
/datum/mind/proc/make_Changeling()
var/datum/antagonist/changeling/C = has_antag_datum(/datum/antagonist/changeling)
if(!C)
-33
View File
@@ -514,39 +514,6 @@ GLOBAL_LIST_EMPTY(teleportlocs)
/client/proc/ResetAmbiencePlayed()
played = FALSE
/atom/proc/has_gravity(turf/T)
if(!T || !isturf(T))
T = get_turf(src)
if(!T)
return 0
var/list/forced_gravity = list()
SEND_SIGNAL(src, COMSIG_ATOM_HAS_GRAVITY, T, forced_gravity)
if(!forced_gravity.len)
SEND_SIGNAL(T, COMSIG_TURF_HAS_GRAVITY, src, forced_gravity)
if(forced_gravity.len)
var/max_grav
for(var/i in forced_gravity)
max_grav = max(max_grav, i)
if(max_grav)
return max_grav
if(isspaceturf(T)) // Turf never has gravity
return 0
var/area/A = get_area(T)
if(A.has_gravity) // Areas which always has gravity
return A.has_gravity
else
// There's a gravity generator on our z level
if(GLOB.gravity_generators["[T.z]"])
var/max_grav = 0
for(var/obj/machinery/gravity_generator/main/G in GLOB.gravity_generators["[T.z]"])
max_grav = max(G.setting,max_grav)
return max_grav
return SSmapping.level_trait(T.z, ZTRAIT_GRAVITY)
/area/proc/setup(a_name)
name = a_name
power_equip = FALSE
+2
View File
@@ -3,6 +3,8 @@
/area/ruin/space
has_gravity = FALSE
blob_allowed = FALSE //Nope, no winning in space as a blob. Gotta eat the station.
outdoors = TRUE
ambientsounds = SPACE
/area/ruin/space/has_grav
has_gravity = STANDARD_GRAVITY
+46
View File
@@ -918,3 +918,49 @@ Proc for attack log creation, because really why not
if(!(material_flags & MATERIAL_NO_EFFECTS))
custom_material.on_applied(src, materials[custom_material] * multiplier * material_modifier, material_flags)
custom_materials[custom_material] += materials[x] * multiplier
/**
* Returns true if this atom has gravity for the passed in turf
*
* Sends signals COMSIG_ATOM_HAS_GRAVITY and COMSIG_TURF_HAS_GRAVITY, both can force gravity with
* the forced gravity var
*
* Gravity situations:
* * No gravity if you're not in a turf
* * No gravity if this atom is in is a space turf
* * Gravity if the area it's in always has gravity
* * Gravity if there's a gravity generator on the z level
* * Gravity if the Z level has an SSMappingTrait for ZTRAIT_GRAVITY
* * otherwise no gravity
*/
/atom/proc/has_gravity(turf/T)
if(!T || !isturf(T))
T = get_turf(src)
if(!T)
return 0
var/list/forced_gravity = list()
SEND_SIGNAL(src, COMSIG_ATOM_HAS_GRAVITY, T, forced_gravity)
if(!forced_gravity.len)
SEND_SIGNAL(T, COMSIG_TURF_HAS_GRAVITY, src, forced_gravity)
if(forced_gravity.len)
var/max_grav
for(var/i in forced_gravity)
max_grav = max(max_grav, i)
return max_grav
if(isspaceturf(T)) // Turf never has gravity
return 0
var/area/A = get_area(T)
if(A.has_gravity) // Areas which always has gravity
return A.has_gravity
else
// There's a gravity generator on our z level
if(GLOB.gravity_generators["[T.z]"])
var/max_grav = 0
for(var/obj/machinery/gravity_generator/main/G in GLOB.gravity_generators["[T.z]"])
max_grav = max(G.setting,max_grav)
return max_grav
return SSmapping.level_trait(T.z, ZTRAIT_GRAVITY)
+8 -3
View File
@@ -131,7 +131,7 @@
return FALSE
// Are we trying to pull something we are already pulling? Then enter grab cycle and end.
if(AM == pulling)
grab_state = state
setGrabState(state)
if(istype(AM,/mob/living))
var/mob/living/AMob = AM
AMob.grabbedby(src)
@@ -142,7 +142,7 @@
AM.pulledby.stop_pulling() //an object can't be pulled by two mobs at once.
pulling = AM
AM.pulledby = src
grab_state = state
setGrabState(state)
if(ismob(AM))
var/mob/M = AM
log_combat(src, M, "grabbed", addition="passive grab")
@@ -155,7 +155,7 @@
pulling.pulledby = null
var/mob/living/ex_pulled = pulling
pulling = null
grab_state = 0
setGrabState(0)
if(isliving(ex_pulled))
var/mob/living/L = ex_pulled
L.update_mobility()// mob gets up if it was lyng down in a chokehold
@@ -563,6 +563,11 @@
return FALSE
return TRUE
/// Updates the grab state of the movable
/// This exists to act as a hook for behaviour
/atom/movable/proc/setGrabState(newstate)
grab_state = newstate
/obj/item/proc/do_pickup_animation(atom/target)
set waitfor = FALSE
if(!istype(loc, /turf))
+25 -4
View File
@@ -86,8 +86,10 @@ GLOBAL_LIST_EMPTY(objectives)
if(M)
. += M
/datum/objective/proc/find_target()
/datum/objective/proc/find_target(dupe_search_range, blacklist)
var/list/datum/mind/owners = get_owners()
if(!dupe_search_range)
dupe_search_range = get_owners()
var/list/possible_targets = list()
var/try_target_late_joiners = FALSE
for(var/I in owners)
@@ -96,7 +98,8 @@ GLOBAL_LIST_EMPTY(objectives)
try_target_late_joiners = TRUE
for(var/datum/mind/possible_target in get_crewmember_minds())
if(!(possible_target in owners) && ishuman(possible_target.current) && (possible_target.current.stat != DEAD) && is_unique_objective(possible_target))
possible_targets += possible_target
if(!(possible_target in blacklist))
possible_targets += possible_target
if(try_target_late_joiners)
var/list/all_possible_targets = possible_targets.Copy()
for(var/I in all_possible_targets)
@@ -1075,7 +1078,7 @@ GLOBAL_LIST_EMPTY(cult_contraband)
var/mob/living/carbon/human/H = owner
H.equip_in_one_of_slots(I, list("backpack" = SLOT_IN_BACKPACK))
hoarded_item = I
GLOBAL_LIST_EMPTY(possible_sabotages)
@@ -1092,7 +1095,7 @@ GLOBAL_LIST_EMPTY(possible_sabotages)
if(!GLOB.possible_sabotages.len)//Only need to fill the list when it's needed.
for(var/I in subtypesof(/datum/sabotage_objective))
new I
/datum/objective/sabotage/find_target()
var/list/datum/mind/owners = get_owners()
var/approved_targets = list()
@@ -1155,3 +1158,21 @@ GLOBAL_LIST_EMPTY(possible_sabotages)
/datum/objective/flavor/wizard
flavor_file = "strings/flavor_objectives/wizard.txt"
/datum/objective/contract
var/payout = 0
var/payout_bonus = 0
var/area/dropoff = null
/datum/objective/contract/proc/generate_dropoff() // Generate a random valid area on the station that the dropoff will happen.
var/found = FALSE
while(!found)
var/area/dropoff_area = pick(GLOB.sortedAreas)
if(dropoff_area && is_station_level(dropoff_area.z) && !dropoff_area.outdoors)
dropoff = dropoff_area
found = TRUE
/datum/objective/contract/proc/dropoff_check(mob/user, mob/target) // Check if both the contractor and contract target are at the dropoff point.
var/area/user_area = get_area(user)
var/area/target_area = get_area(target)
return (istype(user_area, dropoff) && istype(target_area, dropoff))
+4 -4
View File
@@ -23,18 +23,18 @@
START_PROCESSING(SSprocessing, src)
/datum/sabotage_objective/processing/proc/check_condition_processing()
return 100
return 1
/datum/sabotage_objective/processing/process()
check_condition_processing()
if(won >= 100)
if(won >= 1)
STOP_PROCESSING(SSprocessing,src)
/datum/sabotage_objective/processing/check_conditions()
return won
/datum/sabotage_objective/processing/power_sink
name = "Drain at least 1 gigajoule of power using a power sink."
name = "Drain at least 100 megajoules of power using a power sink."
sabotage_type = "powersink"
special_equipment = list(/obj/item/sbeacondrop/powersink)
var/sink_found = FALSE
@@ -47,7 +47,7 @@
for(var/datum/powernet/PN in GLOB.powernets)
for(var/obj/item/powersink/sink in PN.nodes)
sink_found_this_time = TRUE
won = max(won,sink.power_drained/1e9)
won = max(won,sink.power_drained/1e8)
sink_found = sink_found_this_time
count = 0
return FALSE
+2
View File
@@ -377,6 +377,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
qdel(src)
item_flags &= ~IN_INVENTORY
SEND_SIGNAL(src, COMSIG_ITEM_DROPPED,user)
user.update_equipment_speed_mods()
// called just as an item is picked up (loc is not yet changed)
/obj/item/proc/pickup(mob/user)
@@ -422,6 +423,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
if(item_action_slot_check(slot, user, A)) //some items only give their actions buttons when in a specific slot.
A.Grant(user)
item_flags |= IN_INVENTORY
user.update_equipment_speed_mods()
//sometimes we only want to grant the item's action if it's equipped in a specific slot.
/obj/item/proc/item_action_slot_check(slot, mob/user, datum/action/A)
+130 -24
View File
@@ -181,13 +181,60 @@
slot_flags = ITEM_SLOT_BELT
force = 12 //9 hit crit
w_class = WEIGHT_CLASS_NORMAL
var/cooldown = 13
var/on = TRUE
var/last_hit = 0
var/stun_stam_cost_coeff = 1.25
var/hardstun_ds = 1
var/hardstun_ds = TRUE
var/softstun_ds = 0
var/stam_dmg = 30
var/cooldown_check = 0 // Used internally, you don't want to modify
var/cooldown = 13 // Default wait time until can stun again.
var/stun_time_silicon = 60 // How long it stuns silicons for - 6 seconds.
var/affect_silicon = FALSE // Does it stun silicons.
var/on_sound // "On" sound, played when switching between able to stun or not.
var/on_stun_sound = "sound/effects/woodhit.ogg" // Default path to sound for when we stun.
var/stun_animation = TRUE // Do we animate the "hit" when stunning.
var/on = TRUE // Are we on or off
var/on_icon_state // What is our sprite when turned on
var/off_icon_state // What is our sprite when turned off
var/on_item_state // What is our in-hand sprite when turned on
var/force_on // Damage when on - not stunning
var/force_off // Damage when off - not stunning
var/weight_class_on // What is the new size class when turned on
/obj/item/melee/classic_baton/Initialize()
. = ..()
// Description for trying to stun when still on cooldown.
/obj/item/melee/classic_baton/proc/get_wait_description()
return
// Description for when turning their baton "on"
/obj/item/melee/classic_baton/proc/get_on_description()
. = list()
.["local_on"] = "<span class ='warning'>You extend the baton.</span>"
.["local_off"] = "<span class ='notice'>You collapse the baton.</span>"
return .
// Default message for stunning mob.
/obj/item/melee/classic_baton/proc/get_stun_description(mob/living/target, mob/living/user)
. = list()
.["visible"] = "<span class ='danger'>[user] has knocked down [target] with [src]!</span>"
.["local"] = "<span class ='danger'>[user] has knocked down [target] with [src]!</span>"
return .
// Default message for stunning a silicon.
/obj/item/melee/classic_baton/proc/get_silicon_stun_description(mob/living/target, mob/living/user)
. = list()
.["visible"] = "<span class='danger'>[user] pulses [target]'s sensors with the baton!</span>"
.["local"] = "<span class='danger'>You pulse [target]'s sensors with the baton!</span>"
return .
// Are we applying any special effects when we stun to carbon
/obj/item/melee/classic_baton/proc/additional_effects_carbon(mob/living/target, mob/living/user)
return
// Are we applying any special effects when we stun to silicon
/obj/item/melee/classic_baton/proc/additional_effects_silicon(mob/living/target, mob/living/user)
return
/obj/item/melee/classic_baton/attack(mob/living/target, mob/living/user)
if(!on)
@@ -208,15 +255,28 @@
user.take_bodypart_damage(2*force)
return
if(iscyborg(target))
..()
if(user.a_intent != INTENT_HARM) // We don't stun if we're on harm.
if(affect_silicon)
var/list/desc = get_silicon_stun_description(target, user)
target.flash_act(affect_silicon = TRUE)
target.Stun(stun_time_silicon)
additional_effects_silicon(target, user)
user.visible_message(desc["visible"], desc["local"])
playsound(get_turf(src), on_stun_sound, 100, TRUE, -1)
if(stun_animation)
user.do_attack_animation(target)
else
..()
else
..()
return
if(!isliving(target))
return
if (user.a_intent == INTENT_HARM)
if(user.a_intent == INTENT_HARM)
if(!..() || !iscyborg(target))
return
else
if(last_hit < world.time)
if(cooldown_check < world.time)
if(target.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK))
playsound(target, 'sound/weapons/genhit.ogg', 50, 1)
return
@@ -224,18 +284,25 @@
var/mob/living/carbon/human/H = target
if(check_martial_counter(H, user))
return
playsound(get_turf(src), 'sound/effects/woodhit.ogg', 75, 1, -1)
var/list/desc = get_stun_description(target, user)
if(stun_animation)
user.do_attack_animation(target)
playsound(get_turf(src), on_stun_sound, 75, 1, -1)
target.DefaultCombatKnockdown(softstun_ds, TRUE, FALSE, hardstun_ds, stam_dmg)
additional_effects_carbon(target, user)
log_combat(user, target, "stunned", src)
src.add_fingerprint(user)
target.visible_message("<span class ='danger'>[user] has knocked down [target] with [src]!</span>", \
"<span class ='userdanger'>[user] has knocked down [target] with [src]!</span>")
add_fingerprint(user)
target.visible_message(desc["visible"], desc["local"])
if(!iscarbon(user))
target.LAssailant = null
else
target.LAssailant = user
last_hit = world.time + cooldown
target.LAssailant = WEAKREF(user)
cooldown_check = world.time + cooldown
user.adjustStaminaLossBuffered(getweight())//CIT CHANGE - makes swinging batons cost stamina
else
var/wait_desc = get_wait_description()
if(wait_desc)
to_chat(user, wait_desc)
/obj/item/melee/classic_baton/telescopic
name = "telescopic baton"
@@ -250,6 +317,13 @@
item_flags = NONE
force = 0
on = FALSE
on_sound = 'sound/weapons/batonextend.ogg'
on_icon_state = "telebaton_1"
off_icon_state = "telebaton_0"
on_item_state = "nullrod"
force_on = 10
force_off = 0
weight_class_on = WEIGHT_CLASS_BULKY
total_mass = TOTAL_MASS_NORMAL_ITEM
/obj/item/melee/classic_baton/telescopic/suicide_act(mob/user)
@@ -260,7 +334,7 @@
if(!on)
src.attack_self(user)
else
playsound(loc, 'sound/weapons/batonextend.ogg', 50, 1)
playsound(loc, on_sound, 50, 1)
add_fingerprint(user)
sleep(3)
if (H && !QDELETED(H))
@@ -272,25 +346,57 @@
/obj/item/melee/classic_baton/telescopic/attack_self(mob/user)
on = !on
var/list/desc = get_on_description()
if(on)
to_chat(user, "<span class ='warning'>You extend the baton.</span>")
icon_state = "telebaton_1"
item_state = "nullrod"
w_class = WEIGHT_CLASS_BULKY //doesnt fit in backpack when its on for balance
force = 10 //stunbaton damage
to_chat(user, desc["local_on"])
icon_state = on_icon_state
item_state = on_item_state
w_class = weight_class_on
force = force_on
attack_verb = list("smacked", "struck", "cracked", "beaten")
else
to_chat(user, "<span class ='notice'>You collapse the baton.</span>")
icon_state = "telebaton_0"
to_chat(user, desc["local_off"])
icon_state = off_icon_state
item_state = null //no sprite for concealment even when in hand
slot_flags = ITEM_SLOT_BELT
w_class = WEIGHT_CLASS_SMALL
force = 0 //not so robust now
force = force_off
attack_verb = list("hit", "poked")
playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, 1)
playsound(src.loc, on_sound, 50, 1)
add_fingerprint(user)
/obj/item/melee/classic_baton/telescopic/contractor_baton
name = "contractor baton"
desc = "A compact, specialised baton assigned to Syndicate contractors. Applies light electrical shocks to targets."
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "contractor_baton_0"
lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
item_state = null
slot_flags = ITEM_SLOT_BELT
w_class = WEIGHT_CLASS_SMALL
item_flags = NONE
force = 5
cooldown = 20
stam_dmg = 45 //3 hit stamcrit
affect_silicon = TRUE
on_sound = 'sound/weapons/contractorbatonextend.ogg'
on_stun_sound = 'sound/effects/contractorbatonhit.ogg'
on_icon_state = "contractor_baton_1"
off_icon_state = "contractor_baton_0"
on_item_state = "contractor_baton"
force_on = 16
force_off = 5
weight_class_on = WEIGHT_CLASS_NORMAL
/obj/item/melee/classic_baton/telescopic/contractor_baton/get_wait_description()
return "<span class='danger'>The baton is still charging!</span>"
/obj/item/melee/classic_baton/telescopic/contractor_baton/additional_effects_carbon(mob/living/target, mob/living/user)
target.Jitter(20)
target.apply_effect(EFFECT_STUTTER, 20)
target.apply_status_effect(/datum/status_effect/electrostaff, 30) //knockdown, disarm, and slowdown, the unholy triumvirate of stam combat
/obj/item/melee/supermatter_sword
name = "supermatter sword"
desc = "In a station full of bad ideas, this might just be the worst."
+9 -2
View File
@@ -17,6 +17,7 @@
var/active = FALSE
var/atom/movable/target //The thing we're searching for
var/minimum_range = 0 //at what range the pinpointer declares you to be at your destination
var/ignore_suit_sensor_level = FALSE // Do we find people even if their suit sensors are turned off
var/alert = FALSE // TRUE to display things more seriously
/obj/item/pinpointer/Initialize()
@@ -77,6 +78,8 @@
name = "crew pinpointer"
desc = "A handheld tracking device that points to crew suit sensors."
icon_state = "pinpointer_crew"
var/has_owner = FALSE
var/pinpointer_owner = null
/obj/item/pinpointer/crew/proc/trackable(mob/living/carbon/human/H)
var/turf/here = get_turf(src)
@@ -84,7 +87,7 @@
var/obj/item/clothing/under/U = H.w_uniform
// Suit sensors must be on maximum.
if(!U.has_sensor || U.sensor_mode < SENSOR_COORDS)
if(!U.has_sensor || U.sensor_mode < SENSOR_COORDS && !ignore_suit_sensor_level)
return FALSE
var/turf/there = get_turf(H)
@@ -101,7 +104,11 @@
STOP_PROCESSING(SSfastprocess, src)
update_icon()
return
if (has_owner && !pinpointer_owner)
pinpointer_owner = user
if (pinpointer_owner && pinpointer_owner != user)
to_chat(user, "<span class='notice'>The pinpointer doesn't respond. It seems to only recognise its owner.</span>")
return
var/list/name_counts = list()
var/list/names = list()
@@ -229,6 +229,7 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \
null, \
new/datum/stack_recipe("rifle stock", /obj/item/weaponcrafting/stock, 10, time = 40), \
new/datum/stack_recipe("rolling pin", /obj/item/kitchen/rollingpin, 2, time = 30), \
new/datum/stack_recipe("wooden bucket", /obj/item/reagent_containers/glass/bucket/wood, 2, time = 30), \
new/datum/stack_recipe("wooden buckler", /obj/item/shield/riot/buckler, 20, time = 40), \
new/datum/stack_recipe("baseball bat", /obj/item/melee/baseball_bat, 5, time = 15),\
null, \
@@ -397,3 +397,97 @@
/obj/item/storage/box/syndie_kit/revolver/PopulateContents()
new /obj/item/gun/ballistic/revolver(src)
new /obj/item/ammo_box/a357(src)
/obj/item/storage/box/syndie_kit/contract_kit
name = "contractor kit"
desc = "Supplied to Syndicate contractors in active mission areas."
/obj/item/storage/box/syndicate/contractor_loadout
name = "standard loadout"
desc = "Supplied to Syndicate contractors, providing their specialised space suit and chameleon uniform."
icon_state = "syndiebox"
illustration = "writing_syndie"
/obj/item/paper/contractor_guide
name = "Contractor Guide"
/obj/item/paper/contractor_guide/Initialize()
info = {"<p>Welcome agent, congratulations on your new position as contractor. On top of your already assigned objectives,
this kit will provide you contracts to take on for TC payments.</p>
<p>Provided within, we give your specialist contractor space suit. It's even more compact, being able to fit into a pocket, and faster than the
Syndicate space suit available to you on the uplink. We also provide your chameleon jumpsuit and mask, both of which can be changed
to any form you need for the moment. The cigarettes are a special blend - it'll heal your injuries slowly overtime.</p>
<p>The three additional items, apart from the tablet and loadout box, have been randomly selected from what we had available. We hope
they're useful to you for you mission.</p>
<p>The contractor hub, available at the top right of the uplink, will provide you unique items and abilities. These are bought using Contractor Rep,
with two Rep being provided each time you complete a contract.</p>
<h3>Using the tablet</h3>
<ol>
<li>Open the Syndicate Contract Uplink program.</li>
<li>Assign yourself.</li>
<li>Here, you can accept a contract, and redeem your TC payments from completed contracts.</li>
<li>The payment number shown in brackets is the bonus you'll recieve when bringing your target <b>alive</b>. You recieve the
other number regardless of if they were alive or dead.</li>
<li>Contracts are completed by bringing the target to designated dropoff, calling for extraction, and putting them
inside the pod.</li>
</ol>
<p>Be careful when accepting a contract. While you'll be able to see the location of the dropoff point, cancelling will make it
unavailable to take on again.</p>
<p>The tablet can also be recharged at any cell charger.</p>
<h3>Extracting</h3>
<ol>
<li>Make sure both yourself and your target are at the dropoff.</li>
<li>Call the extraction, and stand back from the drop point</li>
<li>If it fails, make sure your target is inside, and there's a free space for the pod to land.</li>
<li>Grab your target, and drag them into the pod.</li>
</ol>
<h3>Ransoms</h3>
<p>We need your target for our own reasons, but we ransom them back to your mission area once their use is served. They will return back
from where you sent them off from in several minutes time. You will be paid in TC for your services.</p>
<p>Good luck agent. You can burn this document with the supplied lighter.</p>"}
return ..()
/obj/item/storage/box/syndicate/contractor_loadout/PopulateContents()
new /obj/item/clothing/head/helmet/space/syndicate/contract(src)
new /obj/item/clothing/suit/space/syndicate/contract(src)
new /obj/item/clothing/under/chameleon(src)
new /obj/item/clothing/mask/chameleon(src)
new /obj/item/card/id/syndicate(src)
new /obj/item/storage/fancy/cigarettes/cigpack_syndicate(src)
new /obj/item/lighter(src)
/obj/item/storage/box/syndie_kit/contract_kit/PopulateContents()
new /obj/item/modular_computer/tablet/syndicate_contract_uplink/preset/uplink(src)
new /obj/item/storage/box/syndicate/contractor_loadout(src)
new /obj/item/melee/classic_baton/telescopic/contractor_baton(src)
var/list/item_list = list( // All 4 TC or less - some nukeops only items, but fit nicely to the theme.
/obj/item/storage/backpack/duffelbag/syndie/x4,
/obj/item/storage/box/syndie_kit/throwing_weapons,
/obj/item/gun/syringe/syndicate,
/obj/item/pen/edagger,
/obj/item/pen/sleepy,
/obj/item/flashlight/emp,
/obj/item/reagent_containers/syringe/mulligan,
/obj/item/clothing/shoes/chameleon/noslip,
/obj/item/storage/firstaid/tactical,
/obj/item/storage/backpack/duffelbag/syndie/surgery,
/obj/item/encryptionkey/syndicate,
/obj/item/clothing/glasses/thermal/syndi,
/obj/item/slimepotion/slime/sentience/nuclear,
/obj/item/storage/box/syndie_kit/imp_radio,
/obj/item/storage/box/syndie_kit/imp_uplink,
/obj/item/clothing/gloves/krav_maga/combatglovesplus,
/obj/item/gun/ballistic/automatic/c20r/toy/unrestricted/riot,
/obj/item/reagent_containers/syringe/stimulants,
/obj/item/storage/box/syndie_kit/imp_freedom,
/obj/item/toy/eightball/haunted
)
var/obj/item1 = pick_n_take(item_list)
var/obj/item2 = pick_n_take(item_list)
var/obj/item3 = pick_n_take(item_list)
new item1(src) // Create three, non repeat items from the list.
new item2(src)
new item3(src)
new /obj/item/paper/contractor_guide(src) //Paper guide
+3 -1
View File
@@ -25,7 +25,7 @@
/obj/item/melee/baton/examine(mob/user)
. = ..()
. += "<span class='notice'>Right click attack while in combat mode to disarm instead of stun.</span>"
. += "<span class='notice'>Right click attack while in combat mode or attack while in disarm intent to disarm instead of stun.</span>"
/obj/item/melee/baton/get_cell()
. = cell
@@ -149,6 +149,8 @@
//return TRUE to interrupt attack chain.
/obj/item/melee/baton/proc/common_baton_melee(mob/M, mob/living/user, disarming = FALSE)
if(user.a_intent == INTENT_DISARM)
disarming = TRUE //override if they're in disarm intent.
if(iscyborg(M) || !isliving(M)) //can't baton cyborgs
return FALSE
if(status && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
+72 -8
View File
@@ -444,9 +444,6 @@
C.adjustFireLoss(5)
to_chat(C, "<span class='danger'>The water is searing!</span>")
/obj/item/bikehorn/rubberducky
name = "rubber ducky"
desc = "Rubber ducky you're so fine, you make bathtime lots of fuuun. Rubber ducky I'm awfully fooooond of yooooouuuu~" //thanks doohl
@@ -454,8 +451,6 @@
icon_state = "rubberducky"
item_state = "rubberducky"
/obj/structure/sink
name = "sink"
icon = 'icons/obj/watercloset.dmi'
@@ -465,7 +460,6 @@
var/busy = FALSE //Something's being washed at the moment
var/dispensedreagent = /datum/reagent/water // for whenever plumbing happens
/obj/structure/sink/attack_hand(mob/living/user)
. = ..()
if(.)
@@ -578,12 +572,82 @@
new /obj/item/stack/sheet/metal (loc, 3)
qdel(src)
/obj/structure/sink/kitchen
name = "kitchen sink"
icon_state = "sink_alt"
/obj/structure/sink/well
name = "well"
desc = "A well, used to get water from an underground reservoir."
icon_state = "well"
//The making of the well
/obj/structure/well_foundation
name = "well foundation"
desc = "A small patch of dirt, ready for a well to be made over it. Just use a shovel!"
icon = 'icons/obj/watercloset.dmi'
icon_state = "well_1"
density = FALSE
anchored = TRUE
max_integrity = 1000
var/steps = 0
/obj/structure/well_foundation/attackby(obj/item/S, mob/user, params)
if(steps == 0 && S.tool_behaviour == TOOL_SHOVEL)
S.use_tool(src, user, 80, volume=100)
steps = 1
desc = "A deep patch of dirt, ready for a well to be made over it. Just add some sandstone!"
icon_state = "well_1"
return TRUE
if(steps == 1 && istype(S, /obj/item/stack/sheet/mineral/sandstone))
if(S.use(15))
steps = 2
desc = "A patch of dirt and bricks. Just add some more sandstone!"
icon_state = "well_2"
return TRUE
else
to_chat(user, "<span class='warning'>You need at least fifteen pieces of sandstone!</span>")
return
if(steps == 2 && istype(S, /obj/item/stack/sheet/mineral/sandstone))
if(S.use(25))
steps = 3
desc = "A large well foundation ready to be dug out. Just use a shovel!"
icon_state = "well_3"
return TRUE
else
to_chat(user, "<span class='warning'>You need at least tweenty-five pieces of sandstone!</span>")
return
if(steps == 3 && S.tool_behaviour == TOOL_SHOVEL)
S.use_tool(src, user, 80, volume=100)
steps = 4
desc = "A deep patch of dirt, needs something to hold a bucket and rope. Just add some wood planks!"
icon_state = "well_3"
return TRUE
if(steps == 4 && istype(S, /obj/item/stack/sheet/mineral/wood))
if(S.use(3))
steps = 5
desc = "A dug out well, A dug out well with out rope. Just add some cloth!"
icon_state = "well_4"
return TRUE
else
to_chat(user, "<span class='warning'>You need at least three planks!</span>")
return
if(steps == 5 && istype(S, /obj/item/stack/sheet/cloth))
if(S.use(2))
steps = 6
desc = "A dug out well with a rope. Just add a wooden bucket!"
icon_state = "well_5"
return TRUE
else
to_chat(user, "<span class='warning'>You need at least two pieces of cloth!</span>")
return
if(steps == 6 && istype(S, /obj/item/reagent_containers/glass/bucket/wood))
new /obj/structure/sink/well(loc)
qdel(S)
qdel(src)
return
else
return ..()
/obj/structure/sink/puddle //splishy splashy ^_^
name = "puddle"
@@ -4,6 +4,7 @@
var/name = "team"
var/member_name = "member"
var/list/objectives = list() //common objectives, these won't be added or removed automatically, subtypes handle this, this is here for bookkeeping purposes.
var/show_roundend_report = TRUE
/datum/team/New(starting_members)
. = ..()
@@ -25,6 +26,8 @@
//Display members/victory/failure/objectives for the team
/datum/team/proc/roundend_report()
if(!show_roundend_report)
return
var/list/report = list()
report += "<span class='header'>[name]:</span>"
@@ -13,6 +13,7 @@
var/should_give_codewords = TRUE
var/should_equip = TRUE
var/traitor_kind = TRAITOR_HUMAN //Set on initial assignment
var/datum/contractor_hub/contractor_hub
hijack_speed = 0.5 //10 seconds per hijack stage by default
/datum/antagonist/traitor/on_gain()
@@ -413,6 +414,9 @@
var/special_role_text = lowertext(name)
if(contractor_hub)
result += contractor_round_end()
if(traitorwin)
result += "<span class='greentext'>The [special_role_text] was successful!</span>"
else
@@ -421,12 +425,44 @@
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/completed_contracts = 0
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
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.
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 += contractor_item_icons
result += "<br>"
if(completed_contracts > 0)
var/pluralCheck = "contract"
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>"
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>"
<b>The code responses were:</b> <span class='redtext'>[responses]</span><br>"
return message
@@ -0,0 +1,227 @@
// Support unit gets it's own very basic antag datum for admin logging.
/datum/antagonist/traitor/contractor_support
name = "Contractor Support Unit"
antag_moodlet = /datum/mood_event/focused
show_in_roundend = FALSE /// We're already adding them in to the contractor's roundend.
give_objectives = TRUE /// We give them their own custom objective.
show_in_antagpanel = FALSE /// Not a proper/full antag.
should_equip = FALSE /// Don't give them an uplink.
var/datum/team/contractor_team/contractor_team
/datum/team/contractor_team // Team for storing both the contractor and their support unit - only really for the HUD and admin logging.
show_roundend_report = FALSE
/datum/antagonist/traitor/contractor_support/forge_traitor_objectives()
var/datum/objective/generic_objective = new
generic_objective.name = "Follow Contractor's Orders"
generic_objective.explanation_text = "Follow your orders. Assist agents in this mission area."
generic_objective.completed = TRUE
add_objective(generic_objective)
/datum/contractor_hub
var/contract_rep = 0
var/list/hub_items = list()
var/list/purchased_items = list()
var/static/list/contractor_items = typecacheof(/datum/contractor_item/, TRUE)
var/datum/syndicate_contract/current_contract
var/list/datum/syndicate_contract/assigned_contracts = list()
var/list/assigned_targets = list() // used as a blacklist to make sure we're not assigning targets already assigned
var/contract_TC_payed_out = 0 // Keeping track for roundend reporting
var/contract_TC_to_redeem = 0 // Used internally and roundend reporting - what TC we have available to cashout.
/datum/contractor_hub/proc/create_hub_items()
for(var/path in contractor_items)
var/datum/contractor_item/contractor_item = new path
hub_items.Add(contractor_item)
/datum/contractor_hub/proc/create_contracts(datum/mind/owner) // 6 initial contracts
var/list/to_generate = list(
CONTRACT_PAYOUT_LARGE,
CONTRACT_PAYOUT_MEDIUM,
CONTRACT_PAYOUT_SMALL,
CONTRACT_PAYOUT_SMALL,
CONTRACT_PAYOUT_SMALL,
CONTRACT_PAYOUT_SMALL
)
var/lowest_TC_threshold = 30 // We don't want the sum of all the payouts to be under this amount
var/total = 0
var/lowest_paying_sum = 0
var/datum/syndicate_contract/lowest_paying_contract
to_generate = shuffle(to_generate) // Randomise order, so we don't have contracts always in payout order.
var/start_index = 1 // Support contract generation happening multiple times
if(assigned_contracts.len != 0)
start_index = assigned_contracts.len + 1
for(var/i = 1; i <= to_generate.len; i++) // Generate contracts, and find the lowest paying.
var/datum/syndicate_contract/contract_to_add = new(owner, assigned_targets, to_generate[i])
var/contract_payout_total = contract_to_add.contract.payout + contract_to_add.contract.payout_bonus
assigned_targets.Add(contract_to_add.contract.target)
if(!lowest_paying_contract || (contract_payout_total < lowest_paying_sum))
lowest_paying_sum = contract_payout_total
lowest_paying_contract = contract_to_add
total += contract_payout_total
contract_to_add.id = start_index
assigned_contracts.Add(contract_to_add)
start_index++
if(total < lowest_TC_threshold) // If the threshold for TC payouts isn't reached, boost the lowest paying contract
lowest_paying_contract.contract.payout_bonus += (lowest_TC_threshold - total)
/datum/contractor_item
var/name // Name of item
var/desc // description of item
var/item // item path, no item path means the purchase needs it's own handle_purchase()
var/item_icon = "fa-broadcast-tower" // fontawesome icon to use inside the hub - https://fontawesome.com/icons/
var/limited = -1 // Any number above 0 for how many times it can be bought in a round for a single traitor. -1 is unlimited.
var/cost // Cost of the item in contract rep.
/datum/contractor_item/contract_reroll
name = "Contract Reroll"
desc = "Request a reroll of your current contract list. Will generate a new target, payment, and dropoff for the contracts you currently have available."
item_icon = "fa-dice"
limited = 2
cost = 0
/datum/contractor_item/contract_reroll/handle_purchase(var/datum/contractor_hub/hub)
. = ..()
if (.)
var/list/new_target_list = list() // We're not regenerating already completed/aborted/extracting contracts, but we don't want to repeat their targets.
for(var/datum/syndicate_contract/contract_check in hub.assigned_contracts)
if (contract_check.status != CONTRACT_STATUS_ACTIVE && contract_check.status != CONTRACT_STATUS_INACTIVE)
if (contract_check.contract.target)
new_target_list.Add(contract_check.contract.target)
continue
for(var/datum/syndicate_contract/rerolling_contract in hub.assigned_contracts) // Reroll contracts without duplicates
if (rerolling_contract.status != CONTRACT_STATUS_ACTIVE && rerolling_contract.status != CONTRACT_STATUS_INACTIVE)
continue
rerolling_contract.generate(new_target_list)
new_target_list.Add(rerolling_contract.contract.target)
hub.assigned_targets = new_target_list // Set our target list with the new set we've generated.
/datum/contractor_item/contractor_pinpointer
name = "Contractor Pinpointer"
desc = "A pinpointer that finds targets even without active suit sensors. Due to taking advantage of an exploit within the system, it can't pinpoint to the same accuracy as the traditional models. Becomes permanently locked to the user that first activates it."
item = /obj/item/pinpointer/crew/contractor
item_icon = "fa-search-location"
limited = 2
cost = 1
/datum/contractor_item/fulton_extraction_kit
name = "Fulton Extraction Kit"
desc = "For getting your target across the station to those difficult dropoffs. Place the beacon somewhere secure, and link the pack. Activating the pack on your target in space will send them over to the beacon - make sure they're not just going to run away though!"
item = /obj/item/storage/box/contractor/fulton_extraction
item_icon = "fa-parachute-box"
limited = 1
cost = 1
/datum/contractor_item/contractor_partner
name = "Reinforcements"
desc = "Upon purchase we'll contact available units in the area. Should there be an agent free, we'll send them down to assist you immediately. If no units are free, we give a full refund."
item_icon = "fa-user-friends"
limited = 1
cost = 2
var/datum/mind/partner_mind = null
/datum/contractor_item/contractor_partner/handle_purchase(var/datum/contractor_hub/hub, mob/living/user)
. = ..()
if (.)
to_chat(user, "<span class='notice'>The uplink vibrates quietly, connecting to nearby agents...</span>")
var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the Contractor Support Unit for [user.real_name]?", ROLE_PAI, null, FALSE, 100, POLL_IGNORE_CONTRACTOR_SUPPORT)
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
spawn_contractor_partner(user, C.key)
else
to_chat(user, "<span class='notice'>No available agents at this time, please try again later.</span>")
limited += 1 // refund and add the limit back.
hub.contract_rep += cost
hub.purchased_items -= src
/datum/outfit/contractor_partner
name = "Contractor Support Unit"
uniform = /obj/item/clothing/under/chameleon
suit = /obj/item/clothing/suit/chameleon
back = /obj/item/storage/backpack
belt = /obj/item/pda/chameleon
mask = /obj/item/clothing/mask/cigarette/syndicate
shoes = /obj/item/clothing/shoes/chameleon/noslip
ears = /obj/item/radio/headset/chameleon
id = /obj/item/card/id/syndicate
r_hand = /obj/item/storage/toolbox/syndicate
backpack_contents = list(/obj/item/storage/box/survival, /obj/item/implanter/uplink, /obj/item/clothing/mask/chameleon,
/obj/item/storage/fancy/cigarettes/cigpack_syndicate, /obj/item/lighter)
/datum/outfit/contractor_partner/post_equip(mob/living/carbon/human/H, visualsOnly)
. = ..()
var/obj/item/clothing/mask/cigarette/syndicate/cig = H.get_item_by_slot(SLOT_WEAR_MASK)
cig.light() // pre-light their cig for extra badass
/datum/contractor_item/contractor_partner/proc/spawn_contractor_partner(mob/living/user, key)
var/mob/living/carbon/human/partner = new()
var/datum/outfit/contractor_partner/partner_outfit = new()
partner_outfit.equip(partner)
var/obj/structure/closet/supplypod/arrival_pod = new()
arrival_pod.style = STYLE_SYNDICATE
arrival_pod.explosionSize = list(0,0,0,1)
arrival_pod.bluespace = TRUE
var/turf/free_location = find_obstruction_free_location(2, user)
if (!free_location) // We really want to send them - if we can't find a nice location just land it on top of them.
free_location = get_turf(user)
partner.forceMove(arrival_pod)
partner.ckey = key
partner_mind = partner.mind // We give a reference to the mind that'll be the support unit
partner_mind.make_Contractor_Support()
to_chat(partner_mind.current, "\n<span class='alertwarning'>[user.real_name] is your superior. Follow any, and all orders given by them. You're here to support their mission only.</span>")
to_chat(partner_mind.current, "<span class='alertwarning'>Should they perish, or be otherwise unavailable, you're to assist other active agents in this mission area to the best of your ability.</span>\n\n")
new /obj/effect/abstract/DPtarget(free_location, arrival_pod)
/datum/contractor_item/blackout
name = "Blackout"
desc = "Request Syndicate Command to distrupt the station's powernet. Disables power across the station for a short duration."
item_icon = "fa-bolt"
limited = 2
cost = 3
/datum/contractor_item/blackout/handle_purchase(var/datum/contractor_hub/hub)
. = ..()
if (.)
power_fail(35, 50)
priority_announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure", "poweroff")
// Subtract cost, and spawn if it's an item.
/datum/contractor_item/proc/handle_purchase(var/datum/contractor_hub/hub, mob/living/user)
if (hub.contract_rep >= cost)
hub.contract_rep -= cost
else
return FALSE
if (limited >= 1)
limited -= 1
else if (limited == 0)
return FALSE
hub.purchased_items.Add(src)
if (item && ispath(item))
var/atom/item_to_create = new item(get_turf(user))
if(user.put_in_hands(item_to_create))
to_chat(user, "<span class='notice'>Your purchase materializes into your hands!</span>")
else
to_chat(user, "<span class='notice'>Your purchase materializes onto the floor.</span>")
return item_to_create
return TRUE
/obj/item/pinpointer/crew/contractor
name = "contractor pinpointer"
desc = "A handheld tracking device that locks onto certain signals. Ignores suit sensors, but is much less accurate."
icon_state = "pinpointer_syndicate"
minimum_range = 25
has_owner = TRUE
ignore_suit_sensor_level = TRUE
/obj/item/storage/box/contractor/fulton_extraction
name = "Fulton Extraction Kit"
icon_state = "syndiebox"
illustration = "writing_syndie"
/obj/item/storage/box/contractor/fulton_extraction/PopulateContents()
new /obj/item/extraction_pack(src)
new /obj/item/fulton_core(src)
@@ -0,0 +1,144 @@
/datum/syndicate_contract
var/id = 0
var/status = CONTRACT_STATUS_INACTIVE
var/datum/objective/contract/contract = new()
var/ransom = 0
var/payout_type = null
var/list/victim_belongings = list()
/datum/syndicate_contract/New(contract_owner, blacklist, type=CONTRACT_PAYOUT_SMALL)
contract.owner = contract_owner
payout_type = type
generate(blacklist)
/datum/syndicate_contract/proc/generate(blacklist)
contract.find_target(null, blacklist)
if (payout_type == CONTRACT_PAYOUT_LARGE)
contract.payout_bonus = rand(9,13)
else if(payout_type == CONTRACT_PAYOUT_MEDIUM)
contract.payout_bonus = rand(6,8)
else
contract.payout_bonus = rand(2,4)
contract.payout = rand(0, 2)
contract.generate_dropoff()
ransom = 100 * rand(18, 45)
/datum/syndicate_contract/proc/handle_extraction(var/mob/living/user)
if (contract.target && contract.dropoff_check(user, contract.target.current))
var/turf/free_location = find_obstruction_free_location(3, user, contract.dropoff)
if(free_location) // We've got a valid location, launch.
launch_extraction_pod(free_location)
return TRUE
return FALSE
// Launch the pod to collect our victim.
/datum/syndicate_contract/proc/launch_extraction_pod(turf/empty_pod_turf)
var/obj/structure/closet/supplypod/extractionpod/empty_pod = new()
RegisterSignal(empty_pod, COMSIG_ATOM_ENTERED, .proc/enter_check)
empty_pod.stay_after_drop = TRUE
empty_pod.reversing = TRUE
empty_pod.explosionSize = list(0,0,0,1)
empty_pod.leavingSound = 'sound/effects/podwoosh.ogg'
new /obj/effect/abstract/DPtarget(empty_pod_turf, empty_pod)
/datum/syndicate_contract/proc/enter_check(datum/source, sent_mob)
if(istype(source, /obj/structure/closet/supplypod/extractionpod))
if(isliving(sent_mob))
var/mob/living/M = sent_mob
var/datum/antagonist/traitor/traitor_data = contract.owner.has_antag_datum(/datum/antagonist/traitor)
if(M == contract.target.current)
traitor_data.contractor_hub.contract_TC_to_redeem += contract.payout
if(M.stat != DEAD)
traitor_data.contractor_hub.contract_TC_to_redeem += contract.payout_bonus
status = CONTRACT_STATUS_COMPLETE
if(traitor_data.contractor_hub.current_contract == src)
traitor_data.contractor_hub.current_contract = null
traitor_data.contractor_hub.contract_rep += 2
else
status = CONTRACT_STATUS_ABORTED // Sending a target that wasn't even yours is as good as just aborting it
if(traitor_data.contractor_hub.current_contract == src)
traitor_data.contractor_hub.current_contract = null
if(iscarbon(M))
for(var/obj/item/W in M)
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(W == H.w_uniform || W == H.shoes)
continue //So all they're left with are shoes and uniform.
M.transferItemToLoc(W)
victim_belongings.Add(W)
var/obj/structure/closet/supplypod/extractionpod/pod = source
pod.send_up(pod) // Handle the pod returning
if(ishuman(M))
var/mob/living/carbon/human/target = M // After we remove items, at least give them what they need to live.
target.dna.species.give_important_for_life(target)
handleVictimExperience(M) // After pod is sent we start the victim narrative/heal.
var/points_to_check = SSshuttle.points // This is slightly delayed because of the sleep calls above to handle the narrative. We don't want to tell the station instantly.
if(points_to_check >= ransom)
SSshuttle.points -= ransom
else
SSshuttle.points -= points_to_check
priority_announce("One of your crew was captured by a rival organisation - we've needed to pay their ransom to bring them back. \
As is policy we've taken a portion of the station's funds to offset the overall cost.", null, "attention", null, "Nanotrasen Asset Protection")
/datum/syndicate_contract/proc/handleVictimExperience(var/mob/living/M) // They're off to holding - handle the return timer and give some text about what's going on.
addtimer(CALLBACK(src, .proc/returnVictim, M), (60 * 10) * 4) // Ship 'em back - dead or alive... 4 minutes wait.
if(M.stat != DEAD) //Even if they weren't the target, we're still treating them the same.
M.reagents.add_reagent(/datum/reagent/medicine/omnizine, 20) // Heal them up - gets them out of crit/soft crit.
M.flash_act()
M.confused += 10
M.blur_eyes(5)
to_chat(M, "<span class='warning'>You feel strange...</span>")
sleep(60)
to_chat(M, "<span class='warning'>That pod did something to you...</span>")
M.Dizzy(35)
sleep(65)
to_chat(M, "<span class='warning'>Your head pounds... It feels like it's going to burst out your skull!</span>")
M.flash_act()
M.confused += 20
M.blur_eyes(3)
sleep(30)
to_chat(M, "<span class='warning'>Your head pounds...</span>")
sleep(100)
M.flash_act()
M.Unconscious(200)
to_chat(M, "<span class='reallybig hypnophrase'>A million voices echo in your head... <i>\"Your mind held many valuable secrets - \
we thank you for providing them. Your value is expended, and you will be ransomed back to your station. We always get paid, \
so it's only a matter of time before we ship you back...\"</i></span>")
M.blur_eyes(10)
M.Dizzy(15)
M.confused += 20
/datum/syndicate_contract/proc/returnVictim(var/mob/living/M) // We're returning the victim
var/list/possible_drop_loc = list()
for(var/turf/possible_drop in contract.dropoff.contents)
if(!is_blocked_turf(possible_drop))
possible_drop_loc.Add(possible_drop)
if(possible_drop_loc.len > 0)
var/pod_rand_loc = rand(1, possible_drop_loc.len)
var/obj/structure/closet/supplypod/return_pod = new()
return_pod.bluespace = TRUE
return_pod.explosionSize = list(0,0,0,0)
return_pod.style = STYLE_SYNDICATE
do_sparks(8, FALSE, M)
M.visible_message("<span class='notice'>[M] vanishes...</span>")
for(var/obj/item/W in M)
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(W == H.w_uniform || W == H.shoes)
continue //So all they're left with are shoes and uniform.
M.dropItemToGround(W)
for(var/obj/item/W in victim_belongings)
W.forceMove(return_pod)
M.forceMove(return_pod)
M.flash_act()
M.blur_eyes(30)
M.Dizzy(35)
M.confused += 20
new /obj/effect/abstract/DPtarget(possible_drop_loc[pod_rand_loc], return_pod)
else
to_chat(M, "<span class='reallybig hypnophrase'>A million voices echo in your head... <i>\"Seems where you got sent here from won't \
be able to handle our pod... You will die here instead.\"</i></span>")
if(iscarbon(M))
var/mob/living/carbon/C = M
if(C.can_heartattack())
C.set_heartattack(TRUE)
+57 -16
View File
@@ -42,6 +42,8 @@
var/soundVolume = 80 //Volume to play sounds at. Ignores the cap
var/bay //Used specifically for the centcom_podlauncher datum. Holds the current bay the user is launching objects from. Bays are specific rooms on the centcom map.
var/list/explosionSize = list(0,0,2,3)
var/stay_after_drop = FALSE
var/specialised = TRUE // It's not a general use pod for cargo/admin use
/obj/structure/closet/supplypod/bluespacepod
style = STYLE_BLUESPACE
@@ -49,6 +51,15 @@
explosionSize = list(0,0,1,2)
landingDelay = 15 //Slightly quicker than the supplypod
/obj/structure/closet/supplypod/extractionpod
name = "Syndicate Extraction Pod"
desc = "A specalised, blood-red styled pod for extracting high-value targets out of active mission areas."
specialised = TRUE
style = STYLE_SYNDICATE
bluespace = TRUE
explosionSize = list(0,0,1,2)
landingDelay = 25 //Slightly longer than others
/obj/structure/closet/supplypod/centcompod
style = STYLE_CENTCOM
bluespace = TRUE
@@ -56,6 +67,13 @@
landingDelay = 20 //Very speedy!
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
/obj/structure/closet/supplypod/proc/specialisedPod()
return 1
/obj/structure/closet/supplypod/extractionpod/specialisedPod(atom/movable/holder)
holder.forceMove(pick(GLOB.holdingfacility)) // land in ninja jail
open(holder, forced = TRUE)
/obj/structure/closet/supplypod/Initialize()
. = ..()
setStyle(style, TRUE) //Upon initialization, give the supplypod an iconstate, name, and description based on the "style" variable. This system is important for the centcom_podlauncher to function correctly
@@ -76,7 +94,7 @@
return
style = chosenStyle
icon_state = POD_STYLES[chosenStyle][POD_ICON_STATE] //POD_STYLES is a 2D array we treat as a dictionary. The style represents the verticle index, with the icon state, name, and desc being stored in the horizontal indexes of the 2D array.
if (!adminNamed) //We dont want to name it ourselves if it has been specifically named by an admin using the centcom_podlauncher datum
if (!adminNamed && !specialised) //We dont want to name it ourselves if it has been specifically named by an admin using the centcom_podlauncher datum
name = POD_STYLES[chosenStyle][POD_NAME]
desc = POD_STYLES[chosenStyle][POD_DESC]
update_icon()
@@ -96,6 +114,30 @@
/obj/structure/closet/supplypod/toggle(mob/living/user) //Supplypods shouldn't be able to be manually opened under any circumstances, as the open() proc generates supply order datums
return
/obj/structure/closet/supplypod/proc/handleReturningClose(atom/movable/holder, returntobay)
opened = FALSE
INVOKE_ASYNC(holder, .proc/setClosed) //Use the INVOKE_ASYNC proc to call setClosed() on whatever the holder may be, without giving the atom/movable base class a setClosed() proc definition
for(var/atom/movable/O in get_turf(holder))
if ((ismob(O) && !isliving(O)) || (is_type_in_typecache(O, GLOB.blacklisted_cargo_types) && !isliving(O))) //We dont want to take ghosts with us, and we don't want blacklisted items going, but we allow mobs.
continue
O.forceMove(holder) //Put objects inside before we close
var/obj/effect/temp_visual/risingPod = new /obj/effect/abstract/DPfall(get_turf(holder), src) //Make a nice animation of flying back up
risingPod.pixel_z = 0 //The initial value of risingPod's pixel_z is 200 because it normally comes down from a high spot
animate(risingPod, pixel_z = 200, time = 10, easing = LINEAR_EASING) //Animate our rising pod
if(returntobay)
holder.forceMove(bay) //Move the pod back to centcom, where it belongs
QDEL_IN(risingPod, 10)
reversing = FALSE //Now that we're done reversing, we set this to false (otherwise we would get stuck in an infinite loop of calling the close proc at the bottom of open() )
bluespace = TRUE //Make it so that the pod doesn't stay in centcom forever
open(holder, forced = TRUE)
else
reversing = FALSE //Now that we're done reversing, we set this to false (otherwise we would get stuck in an infinite loop of calling the close proc at the bottom of open() )
bluespace = TRUE //Make it so that the pod doesn't stay in centcom forever
QDEL_IN(risingPod, 10)
audible_message("<span class='notice'>The pod hisses, closing quickly and launching itself away from the station.</span>", "<span class='notice'>The ground vibrates, the nearby pod launching away from the station.</span>")
stay_after_drop = FALSE
specialisedPod(holder) // Do special actions for specialised pods - this is likely if we were already doing manual launches
/obj/structure/closet/supplypod/proc/preOpen() //Called before the open() proc. Handles anything that occurs right as the pod lands.
var/turf/T = get_turf(src)
var/list/B = explosionSize //Mostly because B is more readable than explosionSize :p
@@ -172,7 +214,8 @@
if (style == STYLE_SEETHROUGH)
depart(src)
else
addtimer(CALLBACK(src, .proc/depart, holder), departureDelay) //Finish up the pod's duties after a certain amount of time
if(!stay_after_drop) // Departing should be handled manually
addtimer(CALLBACK(src, .proc/depart, holder), departureDelay) //Finish up the pod's duties after a certain amount of time
/obj/structure/closet/supplypod/proc/depart(atom/movable/holder)
if (leavingSound)
@@ -187,20 +230,18 @@
qdel(holder)
/obj/structure/closet/supplypod/centcompod/close(atom/movable/holder) //Closes the supplypod and sends it back to centcom. Should only ever be called if the "reversing" variable is true
opened = FALSE
INVOKE_ASYNC(holder, .proc/setClosed) //Use the INVOKE_ASYNC proc to call setClosed() on whatever the holder may be, without giving the atom/movable base class a setClosed() proc definition
for (var/atom/movable/O in get_turf(holder))
if (ismob(O) && !isliving(O)) //We dont want to take ghosts with us
continue
O.forceMove(holder) //Put objects inside before we close
var/obj/effect/temp_visual/risingPod = new /obj/effect/abstract/DPfall(get_turf(holder), src) //Make a nice animation of flying back up
risingPod.pixel_z = 0 //The initial value of risingPod's pixel_z is 200 because it normally comes down from a high spot
holder.forceMove(bay) //Move the pod back to centcom, where it belongs
animate(risingPod, pixel_z = 200, time = 10, easing = LINEAR_EASING) //Animate our rising pod
QDEL_IN(risingPod, 10)
reversing = FALSE //Now that we're done reversing, we set this to false (otherwise we would get stuck in an infinite loop of calling the close proc at the bottom of open() )
bluespace = TRUE //Make it so that the pod doesn't stay in centcom forever
open(holder, forced = TRUE)
handleReturningClose(holder, TRUE)
/obj/structure/closet/supplypod/extractionpod/close(atom/movable/holder) //handles closing, and returns pod - deletes itself when returned
. = ..()
return
/obj/structure/closet/supplypod/extractionpod/proc/send_up(atom/movable/holder)
if(!holder)
holder = src
if(leavingSound)
playsound(get_turf(holder), leavingSound, soundVolume, 0, 0)
handleReturningClose(holder, FALSE)
/obj/structure/closet/supplypod/proc/setOpened() //Proc exists here, as well as in any atom that can assume the role of a "holder" of a supplypod. Check the open() proc for more details
update_icon()
+16
View File
@@ -75,6 +75,22 @@
icon_state = "syndicate-black"
item_state = "syndicate-black"
//Black-red syndicate contract varient
/obj/item/clothing/head/helmet/space/syndicate/contract
name = "contractor helmet"
desc = "A specialised black and gold helmet that's more compact than its standard Syndicate counterpart. Can be ultra-compressed into even the tightest of spaces."
slowdown = 0.55
w_class = WEIGHT_CLASS_SMALL
icon_state = "syndicate-contract-helm"
item_state = "syndicate-contract-helm"
/obj/item/clothing/suit/space/syndicate/contract
name = "contractor space suit"
desc = "A specialised black and gold space suit that's quicker, and more compact than its standard Syndicate counterpart. Can be ultra-compressed into even the tightest of spaces."
slowdown = 0.55
w_class = WEIGHT_CLASS_SMALL
icon_state = "syndicate-contract"
item_state = "syndicate-contract"
//Black-green syndicate space suit
/obj/item/clothing/head/helmet/space/syndicate/black/green
+1 -4
View File
@@ -13,7 +13,4 @@
/datum/round_event/grid_check/start()
for(var/P in GLOB.apcs_list)
var/obj/machinery/power/apc/C = P
if(C.cell && is_station_level(C.z))
C.energy_fail(rand(30,120))
power_fail(30, 120)
@@ -140,7 +140,7 @@
/obj/item/reagent_containers/food/snacks/snowcones/blue
name = "bluecherry snowcone"
desc = "Bluecherry syrup drizzled over a snowball in a paper cup, how rare!"
icon_state = "blue_sc"
icon_state = "red_sc"
list_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/bluecherryjelly = 5)
tastes = list("ice" = 1, "water" = 1, "blue" = 5, "cherries" = 5)
foodtype = FRUIT
@@ -148,7 +148,7 @@
/obj/item/reagent_containers/food/snacks/snowcones/red
name = "cherry snowcone"
desc = "Cherry syrup drizzled over a snowball in a paper cup."
icon_state = "red_sc"
icon_state = "blue_sc"
list_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/cherryjelly = 5)
tastes = list("ice" = 1, "water" = 1, "red" = 5, "cherries" = 5)
foodtype = FRUIT
@@ -223,7 +223,7 @@
tastes = list("ice" = 1, "water" = 1, "cola" = 5)
/obj/item/reagent_containers/food/snacks/snowcones/spacemountainwind
name = "Space Mountain Wind snowcone"
name = "\improper Space Mountain Wind snowcone"
desc = "Space Mountain Wind drizzled over a snowball in a paper cup."
icon_state = "kiwi_sc"
list_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/spacemountainwind = 5)
@@ -201,10 +201,10 @@
/obj/item/reagent_containers/food/snacks/donut/jelly/choco
name = "chocolate jelly donut"
desc = "Goes great with a glass of warm milk."
icon_state = "jelly_choc"
icon_state = "jelly_choco"
bonus_reagents = list(/datum/reagent/consumable/hot_coco = 3, /datum/reagent/consumable/sprinkles = 1, /datum/reagent/consumable/nutriment/vitamin = 1) //the coco reagent is just bitter.
tastes = list("jelly" = 1, "donut" = 4, "bitterness" = 1)
decorated_icon = "jelly_choc_sprinkles"
decorated_icon = "jelly_choco_sprinkles"
filling_color = "#4F230D"
/obj/item/reagent_containers/food/snacks/donut/jelly/blumpkin
@@ -620,7 +620,7 @@
results = list(/datum/reagent/consumable/ethanol/quintuple_sec = 15)
required_reagents = list(/datum/reagent/consumable/ethanol/quadruple_sec = 5, /datum/reagent/consumable/clownstears = 5, /datum/reagent/consumable/ethanol/syndicatebomb = 5)
mix_message = "Judgement is upon you."
mix_message = 'sound/items/airhorn2.ogg'
mix_sound = 'sound/items/airhorn2.ogg'
/datum/chemical_reaction/bastion_bourbon
name = "Bastion Bourbon"
+3 -3
View File
@@ -27,9 +27,6 @@
mutatelist = list()
rarity = 20
/obj/item/grown/log
seed = /obj/item/seeds/tower
name = "tower-cap log"
@@ -275,6 +272,9 @@
else if(istype(A, /obj/item) && prob(20))
var/obj/item/O = A
O.microwave_act()
else if(istype(A, /obj/item/grown/log))
qdel(A)
new /obj/item/stack/sheet/mineral/coal(loc, 1)
/obj/structure/bonfire/process()
if(!CheckOxygen())
+1
View File
@@ -16,6 +16,7 @@
QDEL_LIST(stomach_contents)
QDEL_LIST(bodyparts)
QDEL_LIST(implants)
hand_bodyparts = null //Just references out bodyparts, don't need to delete twice.
remove_from_all_data_huds()
QDEL_NULL(dna)
GLOB.carbon_list -= src
@@ -1,15 +1,3 @@
/mob/living/carbon/movement_delay()
. = ..()
. += grab_state * 3 //can't go fast while grabbing something.
if(!get_leg_ignore()) //ignore the fact we lack legs
var/leg_amount = get_num_legs()
. += 6 - 3*leg_amount //the fewer the legs, the slower the mob
if(!leg_amount)
. += 6 - 3*get_num_arms() //crawling is harder with fewer arms
if(legcuffed)
. += legcuffed.slowdown
/mob/living/carbon/slip(knockdown_amount, obj/O, lube)
if(movement_type & FLYING && !(lube & FLYING_DOESNT_HELP))
return FALSE
@@ -948,6 +948,22 @@
if(is_type_in_typecache(active_item, GLOB.shove_disarming_types))
visible_message("<span class='warning'>[src.name] regains their grip on \the [active_item]!</span>", "<span class='warning'>You regain your grip on \the [active_item]</span>", null, COMBAT_MESSAGE_RANGE)
/mob/living/carbon/human/updatehealth()
. = ..()
if(HAS_TRAIT(src, TRAIT_IGNORESLOWDOWN))
remove_movespeed_modifier(MOVESPEED_ID_DAMAGE_SLOWDOWN)
remove_movespeed_modifier(MOVESPEED_ID_DAMAGE_SLOWDOWN_FLYING)
return
var/stambufferinfluence = (bufferedstam*(100/stambuffer))*0.2 //CIT CHANGE - makes stamina buffer influence movedelay
var/health_deficiency = ((100 + stambufferinfluence) - health + (getStaminaLoss()*0.75))//CIT CHANGE - reduces the impact of staminaloss and makes stamina buffer influence it
if(health_deficiency >= 40)
add_movespeed_modifier(MOVESPEED_ID_DAMAGE_SLOWDOWN, override = TRUE, multiplicative_slowdown = ((health_deficiency-39) / 75), blacklisted_movetypes = FLOATING|FLYING)
add_movespeed_modifier(MOVESPEED_ID_DAMAGE_SLOWDOWN_FLYING, override = TRUE, multiplicative_slowdown = ((health_deficiency-39) / 25), movetypes = FLOATING)
else
remove_movespeed_modifier(MOVESPEED_ID_DAMAGE_SLOWDOWN)
remove_movespeed_modifier(MOVESPEED_ID_DAMAGE_SLOWDOWN_FLYING)
/mob/living/carbon/human/do_after_coefficent()
. = ..()
. *= physiology.do_after_speed
@@ -9,8 +9,8 @@
/mob/living/carbon/human/movement_delay()
. = ..()
if(dna && dna.species)
. += dna.species.movement_delay(src)
if (m_intent == MOVE_INTENT_WALK && HAS_TRAIT(src, TRAIT_SPEEDY_STEP))
. -= 1.5
/mob/living/carbon/human/slip(knockdown_amount, obj/O, lube)
if(HAS_TRAIT(src, TRAIT_NOSLIPALL))
@@ -145,6 +145,12 @@
return not_handled //For future deeper overrides
/mob/living/carbon/human/equipped_speed_mods()
. = ..()
for(var/sloties in get_all_slots())
var/obj/item/thing = sloties
. += thing?.slowdown
/mob/living/carbon/human/doUnEquip(obj/item/I, force, newloc, no_move, invdrop = TRUE)
var/index = get_held_index_of_item(I)
. = ..() //See mob.dm for an explanation on this and some rage about people copypasting instead of calling ..() like they should.
+26 -53
View File
@@ -71,6 +71,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/fixed_mut_color = "" //to use MUTCOLOR with a fixed color that's independent of dna.feature["mcolor"]
var/list/special_step_sounds //Sounds to override barefeet walkng
var/grab_sound //Special sound for grabbing
var/datum/outfit/outfit_important_for_life // A path to an outfit that is important for species life e.g. plasmaman outfit
// species-only traits. Can be found in DNA.dm
var/list/species_traits = list()
@@ -1019,6 +1020,15 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
H.apply_overlay(BODY_TAUR_LAYER) // CITADEL EDIT
/*
* Equip the outfit required for life. Replaces items currently worn.
*/
/datum/species/proc/give_important_for_life(mob/living/carbon/human/human_to_equip)
if(!outfit_important_for_life)
return
outfit_important_for_life= new()
outfit_important_for_life.equip(human_to_equip)
//This exists so sprite accessories can still be per-layer without having to include that layer's
//number in their sprite name, which causes issues when those numbers change.
/datum/species/proc/mutant_bodyparts_layertext(layer)
@@ -1286,12 +1296,14 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(H.overeatduration < 100)
to_chat(H, "<span class='notice'>You feel fit again!</span>")
REMOVE_TRAIT(H, TRAIT_FAT, OBESITY)
H.remove_movespeed_modifier(MOVESPEED_ID_FAT)
H.update_inv_w_uniform()
H.update_inv_wear_suit()
else
if(H.overeatduration >= 100)
to_chat(H, "<span class='danger'>You suddenly feel blubbery!</span>")
ADD_TRAIT(H, TRAIT_FAT, OBESITY)
H.add_movespeed_modifier(MOVESPEED_ID_FAT, multiplicative_slowdown = 1.5)
H.update_inv_w_uniform()
H.update_inv_wear_suit()
@@ -1342,6 +1354,15 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
to_chat(H, "<span class='notice'>You no longer feel vigorous.</span>")
H.metabolism_efficiency = 1
//Hunger slowdown for if mood isn't enabled
if(CONFIG_GET(flag/disable_human_mood))
if(!HAS_TRAIT(H, TRAIT_NOHUNGER))
var/hungry = (500 - H.nutrition) / 5 //So overeat would be 100 and default level would be 80
if(hungry >= 70)
H.add_movespeed_modifier(MOVESPEED_ID_HUNGRY, override = TRUE, multiplicative_slowdown = (hungry / 50))
else
H.remove_movespeed_modifier(MOVESPEED_ID_HUNGRY)
switch(H.nutrition)
if(NUTRITION_LEVEL_FULL to INFINITY)
H.throw_alert("nutrition", /obj/screen/alert/fat)
@@ -1391,59 +1412,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
H.hair_style = "Bald"
H.update_hair()
////////////////
// MOVE SPEED //
////////////////
/datum/species/proc/movement_delay(mob/living/carbon/human/H)
. = 0 //We start at 0.
var/flight = 0 //Check for flight and flying items
var/gravity = 0
if(H.movement_type & FLYING)
flight = 1
gravity = H.has_gravity()
if (H.m_intent == MOVE_INTENT_WALK && HAS_TRAIT(H, TRAIT_SPEEDY_STEP))
. -= 1.5
if(!HAS_TRAIT(H, TRAIT_IGNORESLOWDOWN) && gravity)
if(H.wear_suit)
. += H.wear_suit.slowdown
if(H.shoes)
. += H.shoes.slowdown
if(H.back)
. += H.back.slowdown
for(var/obj/item/I in H.held_items)
if(I.item_flags & SLOWS_WHILE_IN_HAND)
. += I.slowdown
var/stambufferinfluence = (H.bufferedstam*(100/H.stambuffer))*0.2 //CIT CHANGE - makes stamina buffer influence movedelay
var/health_deficiency = ((100 + stambufferinfluence) - H.health + (H.getStaminaLoss()*0.75))//CIT CHANGE - reduces the impact of staminaloss on movement speed and makes stamina buffer influence movedelay
if(health_deficiency >= 40)
if(flight)
. += ((health_deficiency-39) / 75) // CIT CHANGE - adds -39 to health deficiency penalty to make the transition to low health movement a little less jarring
else
. += ((health_deficiency-39) / 25) // CIT CHANGE - ditto
if(CONFIG_GET(flag/disable_human_mood))
var/hungry = (500 - H.nutrition) / 5 //So overeat would be 100 and default level would be 80
if((hungry >= 70) && !flight) //Being hungry will still allow you to use a flightsuit/wings.
. += hungry / 50
//Moving in high gravity is very slow (Flying too)
if(gravity > STANDARD_GRAVITY)
var/grav_force = min(gravity - STANDARD_GRAVITY,3)
. += 1 + grav_force
if(HAS_TRAIT(H, TRAIT_FAT))
. += (1.5 - flight)
if(H.bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT && !HAS_TRAIT(H, TRAIT_RESISTCOLD))
. += (BODYTEMP_COLD_DAMAGE_LIMIT - H.bodytemperature) / COLD_SLOWDOWN_FACTOR
return .
//////////////////
// ATTACK PROCS //
//////////////////
//////////////////
// ATTACK PROCS //
//////////////////
@@ -2060,6 +2028,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "cold")
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "hot", /datum/mood_event/hot)
H.remove_movespeed_modifier(MOVESPEED_ID_COLD)
var/burn_damage
var/firemodifier = H.fire_stacks / 50
if (H.on_fire)
@@ -2075,6 +2045,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
else if(H.bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT && !HAS_TRAIT(H, TRAIT_RESISTCOLD))
SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "hot")
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "cold", /datum/mood_event/cold)
//Sorry for the nasty oneline but I don't want to assign a variable on something run pretty frequently
H.add_movespeed_modifier(MOVESPEED_ID_COLD, override = TRUE, multiplicative_slowdown = ((BODYTEMP_COLD_DAMAGE_LIMIT - H.bodytemperature) / COLD_SLOWDOWN_FACTOR))
switch(H.bodytemperature)
if(200 to BODYTEMP_COLD_DAMAGE_LIMIT)
H.apply_damage(COLD_DAMAGE_LEVEL_1*coldmod*H.physiology.cold_mod, BURN)
@@ -2084,6 +2056,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
H.apply_damage(COLD_DAMAGE_LEVEL_3*coldmod*H.physiology.cold_mod, BURN)
else
H.remove_movespeed_modifier(MOVESPEED_ID_COLD)
SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "cold")
SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "hot")
@@ -20,6 +20,7 @@
var/internal_fire = FALSE //If the bones themselves are burning clothes won't help you much
disliked_food = FRUIT
liked_food = VEGETABLES
outfit_important_for_life = /datum/outfit/plasmaman
/datum/species/plasmaman/spec_life(mob/living/carbon/human/H)
var/datum/gas_mixture/environment = H.loc.return_air()
+1 -1
View File
@@ -441,7 +441,7 @@
to_chat(user, "You cannot send IC messages (muted).")
return FALSE
else if(!params)
var/custom_emote = stripped_multiline_input("Choose an emote to display.", "Custom Emote", null, MAX_MESSAGE_LEN)
var/custom_emote = stripped_multiline_input(user, "Choose an emote to display.", "Custom Emote", null, MAX_MESSAGE_LEN)
if(custom_emote && !check_invalid(user, custom_emote))
var/type = input("Is this a visible or hearable emote?") as null|anything in list("Visible", "Hearable")
switch(type)
+2 -1
View File
@@ -295,7 +295,7 @@
if(!iscarbon(src))
M.LAssailant = null
else
M.LAssailant = usr
M.LAssailant = WEAKREF(usr)
if(isliving(M))
var/mob/living/L = M
//Share diseases that are spread by touch
@@ -727,6 +727,7 @@
return name
/mob/living/update_gravity(has_gravity,override = 0)
. = ..()
if(!SSticker.HasRoundStarted())
return
if(has_gravity)
+1 -1
View File
@@ -250,7 +250,7 @@
return 0
if(user.voremode && user.grab_state == GRAB_AGGRESSIVE)
return 0
user.grab_state++
user.setGrabState(user.grab_state + 1)
switch(user.grab_state)
if(GRAB_AGGRESSIVE)
var/add_log = ""
@@ -152,4 +152,17 @@
if(CHECK_MOBILITY(src, MOBILITY_MOVE) && !intentionalresting && canstand_involuntary && iscarbon(src) && client?.prefs?.autostand)//CIT CHANGE - adds autostanding as a preference
addtimer(CALLBACK(src, .proc/resist_a_rest, TRUE), 0) //CIT CHANGE - ditto
// Movespeed mods based on arms/legs quantity
if(!get_leg_ignore())
var/limbless_slowdown = 0
// These checks for <2 should be swapped out for something else if we ever end up with a species with more than 2
if(has_legs < 2)
limbless_slowdown += 6 - (has_legs * 3)
if(!has_legs && has_arms < 2)
limbless_slowdown += 6 - (has_arms * 3)
if(limbless_slowdown)
add_movespeed_modifier(MOVESPEED_ID_LIVING_LIMBLESS, update=TRUE, priority=100, override=TRUE, multiplicative_slowdown=limbless_slowdown, movetypes=GROUND)
else
remove_movespeed_modifier(MOVESPEED_ID_LIVING_LIMBLESS, update=TRUE)
return mobility_flags
@@ -275,7 +275,7 @@
H.dna.add_mutation(DWARFISM)
/obj/effect/mob_spawn/human/corpse/damaged/legioninfested/Initialize()
var/type = pickweight(list("Miner" = 66, "Ashwalker" = 10, "Golem" = 10,"Clown" = 10, pick(list("Shadow", "YeOlde","Operative", "Cultist", "Lavaknight")) = 4)) //CIT CHANGE: Lavaknights
var/type = pickweight(list("Miner" = 45, "Ashwalker" = 10, "Golem" = 10,"Clown" = 10, pick(list("Shadow", "YeOlde","Operative", "Cultist", "Lavaknight")) = 4, "Assistant" = 20, "Beelegion" = 1))
switch(type)
if("Miner")
mob_species = pickweight(list(/datum/species/human = 70, /datum/species/lizard = 26, /datum/species/fly = 2, /datum/species/plasmaman = 2))
@@ -374,13 +374,47 @@
l_pocket = /obj/item/melee/cultblade/dagger
glasses = /obj/item/clothing/glasses/hud/health/night/cultblind
backpack_contents = list(/obj/item/reagent_containers/glass/beaker/unholywater = 1, /obj/item/cult_shift = 1, /obj/item/flashlight/flare/culttorch = 1, /obj/item/stack/sheet/runed_metal = 15)
if("Lavaknight") //START OF CIT CHANGE
if("Lavaknight")
uniform = /obj/item/clothing/under/assistantformal
mask = /obj/item/clothing/mask/breath
shoes = /obj/item/clothing/shoes/sneakers/black
r_pocket = /obj/item/melee/transforming/energy/sword/cx/broken
suit = /obj/item/clothing/suit/space/hardsuit/lavaknight
suit_store = /obj/item/tank/internals/oxygen
id = /obj/item/card/id/knight //END OF CIT CHANGE
id = /obj/item/card/id/knight
id_job = "Knight"
if("Assistant")
uniform = /obj/item/clothing/under/color/grey
belt = /obj/item/tank/internals/emergency_oxygen
mask = /obj/item/clothing/mask/gas
ears = /obj/item/radio/headset
gloves = /obj/item/clothing/gloves/color/fyellow
id = /obj/item/card/id/silver/reaper //looks cool and has a fancy name but only a 1% chance
back = /obj/item/storage/backpack
backpack_contents = list(/obj/item/stack/cable_coil = 12, /obj/item/assembly/flash = 1, /obj/item/storage/fancy/donut_box = 1, /obj/item/storage/fancy/cigarettes/cigpack_shadyjims = 1, /obj/item/lighter = 1)
if(prob(99))
id = /obj/item/card/id
id_job = "Assisant"
if(prob(95))
head = /obj/item/clothing/head/hardhat/red
if(prob(5))
gloves = /obj/item/clothing/gloves/color/yellow
if(prob(10))
back = /obj/item/twohanded/spear
backpack_contents = null
if(prob(90))
r_pocket = /obj/item/kitchen/knife
if(prob(60))
l_pocket = /obj/item/soap/homemade
if("Beelegion")
uniform = /obj/item/clothing/under/color/yellow
suit = /obj/item/clothing/suit/hooded/bee_costume
shoes = /obj/item/clothing/shoes/sneakers/yellow
gloves = /obj/item/clothing/gloves/color/yellow
ears = /obj/item/radio/headset
belt = /obj/item/storage/belt/fannypack/yellow
id_job = "Assisant"
id = /obj/item/card/id
l_pocket = /obj/item/reagent_containers/food/drinks/soda_cans/buzz_fuzz
mask = /obj/item/clothing/mask/rat/bee
. = ..()
@@ -186,12 +186,13 @@
if(M.stat == DEAD) // our victim died
if(!client)
if(!rabid && !attacked)
if(M.LAssailant && M.LAssailant != M)
var/mob/living/carbon/their_attacker = M.getLAssailant()
if(their_attacker != M)
if(prob(50))
if(!(M.LAssailant in Friends))
Friends[M.LAssailant] = 1
if(!(their_attacker in Friends))
Friends[their_attacker] = 1
else
++Friends[M.LAssailant]
++Friends[their_attacker]
else
to_chat(src, "<i>This subject does not have a strong enough life energy anymore...</i>")
@@ -70,7 +70,8 @@
var/colour = "grey"
var/coretype = /obj/item/slime_extract/grey
var/list/slime_mutation[4]
var/list/slime_mutation
var/static/list/color_mutation_cache = list()
var/static/list/slime_colours = list("rainbow", "grey", "purple", "metal", "orange",
"blue", "dark blue", "dark purple", "yellow", "silver", "pink", "red",
@@ -84,6 +85,7 @@
/mob/living/simple_animal/slime/Initialize(mapload, new_colour="grey", new_is_adult=FALSE)
initialize_mutations()
var/datum/action/innate/slime/feed/F = new
F.Grant(src)
@@ -108,10 +110,16 @@
AC.Remove(src)
return ..()
/mob/living/simple_animal/slime/proc/initialize_mutations()
var/list/cached = color_mutation_cache[colour]
if(!cached)
cached = color_mutation_cache[colour] = mutation_table(colour)
slime_mutation = cached
/mob/living/simple_animal/slime/proc/set_colour(new_colour)
colour = new_colour
update_name()
slime_mutation = mutation_table(colour)
initialize_mutations()
var/sanitizedcolour = replacetext(colour, " ", "")
coretype = text2path("/obj/item/slime_extract/[sanitizedcolour]")
regenerate_icons()
+27
View File
@@ -5,6 +5,8 @@
GLOB.all_clockwork_mobs -= src
GLOB.mob_directory -= tag
focus = null
LAssailant = null
movespeed_modification = null
for (var/alert in alerts)
clear_alert(alert, TRUE)
if(observers && observers.len)
@@ -952,3 +954,28 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
/mob/setMovetype(newval)
. = ..()
update_movespeed(FALSE)
/mob/proc/getLAssailant()
return LAssailant?.resolve()
/// Updates the grab state of the mob and updates movespeed
/mob/setGrabState(newstate)
. = ..()
if(grab_state == GRAB_PASSIVE)
remove_movespeed_modifier(MOVESPEED_ID_MOB_GRAB_STATE, update=TRUE)
else
add_movespeed_modifier(MOVESPEED_ID_MOB_GRAB_STATE, update=TRUE, priority=100, override=TRUE, multiplicative_slowdown=grab_state*3, blacklisted_movetypes=FLOATING)
/mob/proc/update_equipment_speed_mods()
var/speedies = equipped_speed_mods()
if(!speedies)
remove_movespeed_modifier(MOVESPEED_ID_MOB_EQUIPMENT, update=TRUE)
else
add_movespeed_modifier(MOVESPEED_ID_MOB_EQUIPMENT, update=TRUE, priority=100, override=TRUE, multiplicative_slowdown=speedies, blacklisted_movetypes=FLOATING)
/// Gets the combined speed modification of all worn items
/// Except base mob type doesnt really wear items
/mob/proc/equipped_speed_mods()
for(var/obj/item/I in held_items)
if(I.item_flags & SLOWS_WHILE_IN_HAND)
. += I.slowdown
+2 -2
View File
@@ -80,8 +80,8 @@
var/list/faction = list("neutral") //A list of factions that this mob is currently in, for hostile mob targetting, amongst other things
var/move_on_shuttle = 1 // Can move on the shuttle.
//The last mob/living/carbon to push/drag/grab this mob (mostly used by slimes friend recognition)
var/mob/living/carbon/LAssailant = null
/// The last mob/living/carbon to push/drag/grab this mob (mostly used by slimes friend recognition)
var/datum/weakref/LAssailant
var/list/obj/user_movement_hooks //Passes movement in client/Move() to these!
+6 -2
View File
@@ -249,8 +249,12 @@
/mob/proc/slip(s_amount, w_amount, obj/O, lube)
return
/mob/proc/update_gravity()
return
/mob/proc/update_gravity(has_gravity, override=FALSE)
var/speed_change = max(0, has_gravity - STANDARD_GRAVITY)
if(!speed_change)
remove_movespeed_modifier(MOVESPEED_ID_MOB_GRAVITY, update=TRUE)
else
add_movespeed_modifier(MOVESPEED_ID_MOB_GRAVITY, update=TRUE, priority=100, override=TRUE, multiplicative_slowdown=speed_change, blacklisted_movetypes=FLOATING)
//bodypart selection - Cyberboss
//8 toggles through head - eyes - mouth
@@ -12,12 +12,26 @@
slot_flags = ITEM_SLOT_ID | ITEM_SLOT_BELT
has_light = TRUE //LED flashlight!
comp_light_luminosity = 2.3 //Same as the PDA
var/has_variants = TRUE
var/finish_color = null
/obj/item/modular_computer/tablet/update_icon()
..()
if(!finish_color)
finish_color = pick("red","blue","brown","green","black")
icon_state = "tablet-[finish_color]"
icon_state_unpowered = "tablet-[finish_color]"
icon_state_powered = "tablet-[finish_color]"
if(has_variants)
if(!finish_color)
finish_color = pick("red","blue","brown","green","black")
icon_state = "tablet-[finish_color]"
icon_state_unpowered = "tablet-[finish_color]"
icon_state_powered = "tablet-[finish_color]"
/obj/item/modular_computer/tablet/syndicate_contract_uplink
name = "contractor tablet"
icon = 'icons/obj/contractor_tablet.dmi'
icon_state = "tablet-red"
icon_state_unpowered = "tablet"
icon_state_powered = "tablet"
icon_state_menu = "assign"
w_class = WEIGHT_CLASS_SMALL
slot_flags = ITEM_SLOT_ID | ITEM_SLOT_BELT
comp_light_luminosity = 6.3
has_variants = FALSE
@@ -27,3 +27,18 @@
install_component(new /obj/item/computer_hardware/hard_drive/small)
install_component(new /obj/item/computer_hardware/network_card)
install_component(new /obj/item/computer_hardware/printer/mini)
/obj/item/modular_computer/tablet/syndicate_contract_uplink/preset/uplink/Initialize() // Given by the syndicate as part of the contract uplink bundle - loads in the Contractor Uplink.
. = ..()
var/obj/item/computer_hardware/hard_drive/small/syndicate/hard_drive = new
var/datum/computer_file/program/contract_uplink/uplink = new
active_program = uplink
uplink.program_state = PROGRAM_STATE_ACTIVE
uplink.computer = src
hard_drive.store_file(uplink)
install_component(new /obj/item/computer_hardware/processor_unit/small)
install_component(new /obj/item/computer_hardware/battery(src, /obj/item/stock_parts/cell/computer))
install_component(hard_drive)
install_component(new /obj/item/computer_hardware/network_card)
install_component(new /obj/item/computer_hardware/card_slot)
install_component(new /obj/item/computer_hardware/printer/mini)
@@ -0,0 +1,175 @@
/datum/computer_file/program/contract_uplink
filename = "contractor uplink"
filedesc = "Syndicate Contract Uplink"
program_icon_state = "assign"
extended_desc = "A standard, Syndicate issued system for handling important contracts while on the field."
size = 10
requires_ntnet = 0
available_on_ntnet = 0
unsendable = 1
undeletable = 1
tgui_id = "synd_contract"
ui_style = "syndicate"
ui_x = 600
ui_y = 600
var/error = ""
var/page = CONTRACT_UPLINK_PAGE_CONTRACTS
var/assigned = FALSE
/datum/computer_file/program/contract_uplink/run_program(var/mob/living/user)
. = ..(user)
/datum/computer_file/program/contract_uplink/ui_act(action, params)
if(..())
return 1
var/mob/living/user = usr
var/obj/item/computer_hardware/hard_drive/small/syndicate/hard_drive = computer.all_components[MC_HDD]
switch(action)
if("PRG_contract-accept")
var/contract_id = text2num(params["contract_id"])
// Set as the active contract
hard_drive.traitor_data.contractor_hub.assigned_contracts[contract_id].status = CONTRACT_STATUS_ACTIVE
hard_drive.traitor_data.contractor_hub.current_contract = hard_drive.traitor_data.contractor_hub.assigned_contracts[contract_id]
program_icon_state = "single_contract"
return 1
if("PRG_login")
var/datum/antagonist/traitor/traitor_data = user.mind.has_antag_datum(/datum/antagonist/traitor)
if(traitor_data) // Bake their data right into the hard drive, or we don't allow non-antags gaining access to unused contract system. We also create their contracts at this point.
if(!traitor_data.contractor_hub) // Only play greet sound, and handle contractor hub when assigning for the first time.
traitor_data.contractor_hub = new
traitor_data.contractor_hub.create_hub_items()
user.playsound_local(user, 'sound/effects/contractstartup.ogg', 100, 0)
// Stops any topic exploits such as logging in multiple times on a single system.
if(!assigned)
traitor_data.contractor_hub.create_contracts(traitor_data.owner)
hard_drive.traitor_data = traitor_data
program_icon_state = "contracts"
assigned = TRUE
else
error = "Incorrect login details."
return 1
if("PRG_call_extraction")
if(hard_drive.traitor_data.contractor_hub.current_contract.status != CONTRACT_STATUS_EXTRACTING)
if(hard_drive.traitor_data.contractor_hub.current_contract.handle_extraction(user))
user.playsound_local(user, 'sound/effects/confirmdropoff.ogg', 100, 1)
hard_drive.traitor_data.contractor_hub.current_contract.status = CONTRACT_STATUS_EXTRACTING
program_icon_state = "extracted"
else
user.playsound_local(user, 'sound/machines/uplinkerror.ogg', 50)
error = "Either both you or your target aren't at the dropoff location, or the pod hasn't got a valid place to land. Clear space, or make sure you're both inside."
else
user.playsound_local(user, 'sound/machines/uplinkerror.ogg', 50)
error = "Already extracting... Place the target into the pod. If the pod was destroyed, you will need to cancel this contract."
return 1
if("PRG_contract_abort")
var/contract_id = hard_drive.traitor_data.contractor_hub.current_contract.id
hard_drive.traitor_data.contractor_hub.current_contract = null
hard_drive.traitor_data.contractor_hub.assigned_contracts[contract_id].status = CONTRACT_STATUS_ABORTED
program_icon_state = "contracts"
return 1
if("PRG_redeem_TC")
if(hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem)
var/obj/item/stack/telecrystal/crystals = new /obj/item/stack/telecrystal(get_turf(user), hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem)
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(H.put_in_hands(crystals))
to_chat(H, "<span class='notice'>Your payment materializes into your hands!</span>")
else
to_chat(user, "<span class='notice'>Your payment materializes onto the floor.</span>")
hard_drive.traitor_data.contractor_hub.contract_TC_payed_out += hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem
hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem = 0
return 1
else
user.playsound_local(user, 'sound/machines/uplinkerror.ogg', 50)
return 1
if("PRG_clear_error")
error = ""
if("PRG_contractor_hub")
page = CONTRACT_UPLINK_PAGE_HUB
program_icon_state = "store"
if("PRG_hub_back")
page = CONTRACT_UPLINK_PAGE_CONTRACTS
program_icon_state = "contracts"
if("buy_hub")
if(hard_drive.traitor_data.owner.current == user)
var/item = params["item"]
for (var/datum/contractor_item/hub_item in hard_drive.traitor_data.contractor_hub.hub_items)
if (hub_item.name == item)
hub_item.handle_purchase(hard_drive.traitor_data.contractor_hub, user)
else
error = "Invalid user... You weren't recognised as the user of this system."
/datum/computer_file/program/contract_uplink/ui_data(mob/user)
var/list/data = list()
var/obj/item/computer_hardware/hard_drive/small/syndicate/hard_drive = computer.all_components[MC_HDD]
var/screen_to_be = null
if(hard_drive && hard_drive.traitor_data != null)
var/datum/antagonist/traitor/traitor_data = hard_drive.traitor_data
error = ""
data = get_header_data()
if(traitor_data.contractor_hub.current_contract)
data["ongoing_contract"] = TRUE
screen_to_be = "single_contract"
if(traitor_data.contractor_hub.current_contract.status == CONTRACT_STATUS_EXTRACTING)
data["extraction_enroute"] = TRUE
screen_to_be = "extracted"
data["logged_in"] = TRUE
data["station_name"] = GLOB.station_name
data["redeemable_tc"] = traitor_data.contractor_hub.contract_TC_to_redeem
data["contract_rep"] = traitor_data.contractor_hub.contract_rep
data["page"] = page
data["error"] = error
for(var/datum/contractor_item/hub_item in traitor_data.contractor_hub.hub_items)
data["contractor_hub_items"] += list(list(
"name" = hub_item.name,
"desc" = hub_item.desc,
"cost" = hub_item.cost,
"limited" = hub_item.limited,
"item_icon" = hub_item.item_icon
))
for(var/datum/syndicate_contract/contract in traitor_data.contractor_hub.assigned_contracts)
var/target_rank = ""
if(contract.contract.target)
var/datum/data/record/record = find_record("name", contract.contract.target.current.real_name, GLOB.data_core.general)
if(record)
target_rank = record.fields["rank"]
else
target_rank = "Unknown"
data["contracts"] += list(list(
"target" = contract.contract.target,
"target_rank" = target_rank,
"payout" = contract.contract.payout,
"payout_bonus" = contract.contract.payout_bonus,
"dropoff" = contract.contract.dropoff,
"id" = contract.id,
"status" = contract.status
))
var/direction
if(traitor_data.contractor_hub.current_contract)
var/turf/curr = get_turf(user)
var/turf/dropoff_turf
data["current_location"] = "[get_area_name(curr, TRUE)]"
for(var/turf/content in traitor_data.contractor_hub.current_contract.contract.dropoff.contents)
if(isturf(content))
dropoff_turf = content
break
if(curr.z == dropoff_turf.z) //Direction calculations for same z-level only
direction = uppertext(dir2text(get_dir(curr, dropoff_turf))) //Direction text (East, etc). Not as precise, but still helpful.
if(get_area(user) == traitor_data.contractor_hub.current_contract.contract.dropoff)
direction = "LOCATION CONFIRMED"
else
direction = "???"
data["dropoff_direction"] = direction
if (page == CONTRACT_UPLINK_PAGE_HUB)
screen_to_be = "store"
if (!screen_to_be)
screen_to_be = "contracts"
else
data["logged_in"] = FALSE
if (!screen_to_be)
screen_to_be = "assign"
program_icon_state = screen_to_be
update_computer_icon()
return data
@@ -158,6 +158,12 @@
icon_state = "ssd_mini"
w_class = WEIGHT_CLASS_TINY
/obj/item/computer_hardware/hard_drive/small/syndicate // Syndicate variant - very slight better
desc = "An efficient SSD for portable devices developed by a rival organisation."
power_usage = 8
max_capacity = 70
var/datum/antagonist/traitor/traitor_data // Syndicate hard drive has the user's data baked directly into it on creation
/obj/item/computer_hardware/hard_drive/micro
name = "micro solid state drive"
desc = "A highly efficient SSD chip for portable devices."
+1 -2
View File
@@ -37,8 +37,7 @@
var/mindrain = 200
var/maxdrain = 400
var/stunforce = 140 //Same as stunbaton, adjustable.
var/stunforce = 100
/obj/item/clothing/gloves/space_ninja/Touch(atom/A,proximity)
if(!candrain || draining)
+2 -2
View File
@@ -22,7 +22,7 @@ Contents:
/obj/item/clothing/mask/gas/space_ninja/handle_speech(datum/source, list/speech_args)
var/message = speech_args[SPEECH_MESSAGE]
if(message[1] != "*")
var/list/temp_message = text2list(message, " ")
var/list/temp_message = splittext(message, " ")
var/list/pick_list = list()
for(var/i in 1 to temp_message.len)
pick_list += i
@@ -32,7 +32,7 @@ Contents:
continue
temp_message[H] = ninjaspeak(temp_message[H])
pick_list -= H
message = list2text(temp_message, " ")
message = temp_message.Join(" ")
//The Alternate speech mod is now the main one.
message = replacetext(message, "l", "r")
@@ -53,12 +53,10 @@ It is possible to destroy the net by the occupant or someone else.
if(ishuman(affecting))
var/mob/living/carbon/human/H = affecting
for(var/obj/item/W in H)
if(W == H.w_uniform)
if(W == H.w_uniform || W == H.shoes)
continue//So all they're left with are shoes and uniform.
if(W == H.shoes)
continue
H.dropItemToGround(W)
H.dna.species.give_important_for_life(H) // After we remove items, at least give them what they need to live.
var/datum/antagonist/antag_datum
for(var/datum/antagonist/ninja/AD in GLOB.antagonists) //Because only ninjas get capture objectives; They're not doable without the suit.
if(AD.owner == master)
-1
View File
@@ -264,7 +264,6 @@ They *could* go in their appropriate files, but this is supposed to be modular
electrocute_act(15, H)
DefaultCombatKnockdown(G.stunforce)
adjustStaminaLoss(G.stunforce*0.1, affected_zone = (istype(H) ? H.zone_selected : BODY_ZONE_CHEST))
apply_effect(EFFECT_STUTTER, G.stunforce)
SEND_SIGNAL(src, COMSIG_LIVING_MINOR_SHOCK)
+3 -2
View File
@@ -79,6 +79,7 @@
linked_filter = null
linked_turfs.Cut()
mobs_in_pool.Cut()
mist_off()
return ..()
/obj/machinery/pool/controller/proc/scan_things()
@@ -411,6 +412,7 @@
/obj/machinery/pool/controller/proc/mist_on() //Spawn /obj/effect/mist (from the shower) on all linked pool tiles
if(mist_state)
return
mist_off() //make sure it cycles and deletes everything
mist_state = TRUE
for(var/X in linked_turfs)
var/turf/open/pool/W = X
@@ -419,6 +421,5 @@
linked_mist += M
/obj/machinery/pool/controller/proc/mist_off() //Delete all /obj/effect/mist from all linked pool tiles.
for(var/M in linked_mist)
qdel(M)
QDEL_LIST(linked_mist)
mist_state = FALSE
+2 -3
View File
@@ -136,7 +136,7 @@
reagents.reaction(target, TOUCH)
else if(bartender_check(target) && thrown)
visible_message("<span class='notice'>[src] lands onto the [target.name] without spilling a single drop.</span>")
visible_message("<span class='notice'>[src] lands without spilling a single drop.</span>")
transform = initial(transform)
addtimer(CALLBACK(src, .proc/ForceResetRotation), 1)
@@ -153,11 +153,10 @@
log_reagent("SPLASH - [src] object SplashReagents() onto [target] at [T] ([AREACOORD(T)])[throwerstring] - [reagents.log_list()]")
visible_message("<span class='notice'>[src] spills its contents all over [target].</span>")
reagents.reaction(target, TOUCH)
reagents.clear_reagents()
if(QDELETED(src))
return
reagents.clear_reagents()
//melts plastic beakers
/obj/item/reagent_containers/microwave_act(obj/machinery/microwave/M)
reagents.expose_temperature(1000)
@@ -354,6 +354,14 @@
return
return ..()
/obj/item/reagent_containers/glass/bucket/wood
name = "wooden bucket"
desc = "It's a bucket made of wood."
icon_state = "bucket_wooden"
custom_materials = null
slot_flags = NONE
item_flags = NO_MAT_REDEMPTION
/obj/item/reagent_containers/glass/beaker/waterbottle
name = "bottle of water"
desc = "A bottle of water filled at an old Earth bottling facility."
+1 -1
View File
@@ -137,7 +137,7 @@
else
target.visible_message("<span class='danger'>[user] has placed [target] in [src].</span>", "<span class='userdanger'>[user] has placed [target] in [src].</span>")
log_combat(user, target, "stuffed", addition="into [src]")
target.LAssailant = user
target.LAssailant = WEAKREF(user)
update_icon()
/obj/machinery/disposal/proc/can_stuff_mob_in(mob/living/target, mob/living/user, pushing = FALSE)
@@ -27,7 +27,7 @@
rogue_types = list(/datum/nanite_program/toxic, /datum/nanite_program/nerve_decay)
/datum/nanite_program/adrenaline/on_trigger()
host_mob.do_adrenaline(-10, TRUE, TRUE, FALSE, TRUE, list(/datum/reagent/medicine/stimulants = 1.5), "<span class='notice'>You feel a sudden surge of energy!</span>", FALSE, FALSE, FALSE)
host_mob.do_adrenaline(50, TRUE, TRUE, FALSE, TRUE, list(), "<span class='notice'>You feel a sudden surge of energy!</span>", 25)
/datum/nanite_program/hardening
name = "Dermal Hardening"
@@ -236,7 +236,7 @@
if(X.monkeys >= 1)
var/mob/living/carbon/monkey/food = new /mob/living/carbon/monkey(remote_eye.loc, TRUE, owner)
if (!QDELETED(food))
food.LAssailant = C
food.LAssailant = WEAKREF(C)
X.monkeys --
to_chat(owner, "<span class='notice'>[X] now has [X.monkeys] monkey(s) left.</span>")
else
@@ -474,7 +474,7 @@
if(X.monkeys >= 1)
var/mob/living/carbon/monkey/food = new /mob/living/carbon/monkey(T, TRUE, C)
if (!QDELETED(food))
food.LAssailant = C
food.LAssailant = WEAKREF(C)
X.monkeys--
X.monkeys = round(X.monkeys, 0.1) //Prevents rounding errors
to_chat(C, "<span class='notice'>[X] now has [X.monkeys] monkey(s) stored.</span>")
@@ -30,6 +30,17 @@
cost = 14 // normally 16
include_modes = list(/datum/game_mode/nuclear)
/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 \
standard contractor gear to help with your mission - comes supplied with the tablet, specialised space suit, chameleon jumpsuit and mask, \
specialised contractor baton, and three randomly selected low cost items. Can include otherwise unobtainable items."
item = /obj/item/storage/box/syndie_kit/contract_kit
cost = 20
player_minimum = 20
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
/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."
+4 -2
View File
@@ -161,6 +161,8 @@
SSbellies.belly_list -= src
if(owner?.vore_organs)
owner.vore_organs -= src
if(owner.vore_selected == src)
owner.vore_selected = null
owner = null
. = ..()
@@ -413,7 +415,7 @@
if("em")
raw_messages = examine_messages
var/messages = list2text(raw_messages,delim)
var/messages = raw_messages.Join(delim)
return messages
// The next function sets the messages on the belly, from human-readable var
@@ -422,7 +424,7 @@
/obj/belly/proc/set_messages(var/raw_text, var/type, var/delim = "\n\n")
ASSERT(type == "smo" || type == "smi" || type == "dmo" || type == "dmp" || type == "em")
var/list/raw_list = text2list(html_encode(raw_text),delim)
var/list/raw_list = splittext(html_encode(raw_text),delim)
if(raw_list.len > 10)
raw_list.Cut(11)
testing("[owner] tried to set [lowertext(name)] with 11+ messages")
+1 -1
View File
@@ -574,7 +574,7 @@
if(new_bulge == 0) //Disable.
selected.bulge_size = 0
to_chat(user,"<span class='notice'>Your stomach will not be seen on examine.</span>")
else if (!IsInRange(new_bulge,25,200))
else if (!ISINRANGE(new_bulge,25,200))
selected.bulge_size = 0.25 //Set it to the default.
to_chat(user,"<span class='notice'>Invalid size.</span>")
else if(new_bulge)
@@ -0,0 +1,4 @@
author: "Trilbyspaceclone"
delete-after: True
changes:
- rscadd: "Two new legion drop. Assistant and Bee-Activist"
@@ -0,0 +1,7 @@
author: "Trilbyspaceclone"
delete-after: True
changes:
- rscadd: "Well contruction, grubs to ash walker home, more seeds for ash walkers."
- rscadd: "Wooden buckets can be made from 2 planks of wood, Tower caps also can be used on a fire to make coal"
- tweak: "Makes all ashwalker round start seeds 5 yield and 50 harvest so that they can get good crops in rather then failing after 1 harvest"
- bugfix: "arrow crafting has been fixed"
@@ -1,5 +0,0 @@
author: "ancientpower"
delete-after: True
changes:
- imageadd: "Snazzier sprites for paramedic gear."
- rscadd: "Unused paramedic gear added for future use."
@@ -0,0 +1,26 @@
author: "Kraseo"
delete-after: True
changes:
- rscadd: "Syndicate Contracts. Use the new contract uplink to select a contract, and bring the assigned target dead or alive to the designated drop off. Call for the extraction pod and send them off for your TC payment, with much higher rewards for keeping them alive. A high risk, high reward choice for a traitor who wants a real challenge."
- rscadd: "New 20 TC contract kit - supplies you with your contractor loadout and uplink."
- rscadd: "Targets successfully extracted will be held for ransom by the Syndicate after their use to them is fulfilled. Central command covers the cost, but they'll be taking a cut out of station funds to offset their loss..."
- rscadd: "Adds a third random item, as well as a small guide on using the contract kit. Also added new possible items that can appear."
- tweak: "Supplied space suit in the contract kit is now an improved variant on the normal Syndicate version."
- balance: "TC payouts adjusted to be a bit more fair to the contractor. Total payout can never be below a certain threshold."
- bugfix: "Broken dropoff locations work again, and general bugfixes."
- rscadd: "Contract kit comes with a contractor baton - a unique, lightly electrified weapon to help complete your contracts."
- tweak: "Finalized payment system for contracts; much more balanced for contractors. No more extremely low paying contract sets."
- tweak: "Generated contracts will all have unique targets, no more duplicates."
- tweak: "Extraction droppod explosion has been removed, it'll only damage the tile it lands on."
- bugfix: "Extraction pods get sent to the jail immediately again."
- refactor: "Refactored classic_baton code."
- rscadd: "Contractor Hub. A unique store for contractors to buy items with Contractor Rep, with two Rep being given when completing a contract."
- rscadd: "Contractor pinpointer, available through the Hub. A very inaccurate pinpointer that ignores suit sensors."
- rscadd: "Call reinforcements, available through the Hub. Limited to a one-time buy for a contractor, you can purchase an agent to be sent down to help in your mission. Role is polled to ghosts."
- rscadd: "Blackout, available through the Hub. Disable station power for a small duration - an expensive, but powerful option of getting into secure areas."
- rscadd: "Fulton extraction, available through the Hub. Purchase a fulton extraction kit to help move your targets across the station for those difficult dropoffs."
- tweak: "Assigning yourself to another tablet will give you another contract set."
- rscadd: "Contractors can now reroll their contracts a small number of times."
- rscadd: "Brand new sprites! A redesign of the specialist space suit, and the kit's own unique tablet. Done by Mey Ha Zah."
- tweak: "Displays contract target jobs under their name."
- tweak: "New locations, such as maintenance, are now possible dropoff locations."
@@ -0,0 +1,5 @@
author: "Putnam3145"
delete-after: True
changes:
- balance: "Power sink objective is 10x as easy to get"
- bugfix: "Processing objectives now properly stop once won"
@@ -0,0 +1,4 @@
author: "Putnam3145"
delete-after: True
changes:
- rscdel: "MKUltra no longer explodes into lovegas when it fermi explodes, instead causing a regular ol' fireball."
@@ -0,0 +1,4 @@
author: "Crystal9156"
delete-after: True
changes:
- bugfix: "Fixes Chocolate Jelly Donut icon"
@@ -0,0 +1,4 @@
author: "MrJWhit"
delete-after: True
changes:
- tweak: "Evens both sides of the gas containers TEG with reinforced windows"
@@ -0,0 +1,5 @@
author: "actioninja, ninjanomnom"
delete-after: True
changes:
- tweak: "Being fat is no longer lessened by flying."
- bugfix: "The slowdown from grabbing someone no longer applies when you're floating."
@@ -0,0 +1,4 @@
author: "kevinz000"
delete-after: True
changes:
- balance: "Nanite adrenals have been nerfed."
@@ -0,0 +1,4 @@
author: "kevinz000"
delete-after: True
changes:
- balance: "Ninja stungloves nerfed 49 stamina to 25 (so they're basically just better than stunbatons)."
@@ -0,0 +1,5 @@
author: "bunny232"
delete-after: True
changes:
- rscadd: "Box bar now has a lightswitch."
- bugfix: "fixes several piping issues around box station"
@@ -0,0 +1,4 @@
author: "Trilbyspaceclone"
delete-after: True
changes:
- imageadd: "Corrects snowcones names and a pixle. Corrects Space Wind snowcone as well"
@@ -0,0 +1,4 @@
author: "kevinz000"
delete-after: True
changes:
- tweak: "Batons now also trigger disarm behavior in disarm intent and not just on right click."
@@ -0,0 +1,4 @@
author: "Ragolution"
delete-after: True
changes:
- tweak: "Adjusted Bartender's Drink Flinging print message to not include name of target turf and save immersion."
@@ -0,0 +1,4 @@
author: "zeroisthebiggay"
delete-after: True
changes:
- rscadd: "kilo shuttle less bad"
@@ -0,0 +1,4 @@
author: "Trilbyspaceclone"
delete-after: True
changes:
- bugfix: "Arrow crafting has been fixed... Again..."
@@ -0,0 +1,4 @@
author: "Putnam3145"
delete-after: True
changes:
- tweak: "Eigenstasium OD flavor text less restrictive"
@@ -0,0 +1,4 @@
author: "Putnam3145"
delete-after: True
changes:
- bugfix: "Dynamic voting should work absent of a config."
Binary file not shown.

Before

Width:  |  Height:  |  Size: 216 KiB

After

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

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