Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into Ghommie-cit610
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -4,11 +4,8 @@
|
||||
/// Hard materials, such as iron or metal
|
||||
#define MAT_CATEGORY_RIGID "rigid material"
|
||||
|
||||
|
||||
/// Gets the reference for the material type that was given
|
||||
#define getmaterialref(A) (SSmaterials.materials[A] || A)
|
||||
|
||||
/// Flag for atoms, this flag ensures it isn't re-colored by materials. Useful for snowflake icons such as default toolboxes.
|
||||
#define MATERIAL_COLOR (1<<0)
|
||||
#define MATERIAL_ADD_PREFIX (1<<1)
|
||||
#define MATERIAL_NO_EFFECTS (1<<2)
|
||||
#define MATERIAL_AFFECT_STATISTICS (1<<3)
|
||||
@@ -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"
|
||||
@@ -56,7 +56,6 @@
|
||||
#define INIT_ORDER_SERVER_MAINT 93
|
||||
#define INIT_ORDER_INPUT 85
|
||||
#define INIT_ORDER_VIS 80
|
||||
#define INIT_ORDER_MATERIALS 76
|
||||
#define INIT_ORDER_RESEARCH 75
|
||||
#define INIT_ORDER_EVENTS 70
|
||||
#define INIT_ORDER_JOBS 65
|
||||
|
||||
@@ -174,6 +174,15 @@
|
||||
L[T] = TRUE
|
||||
return L
|
||||
|
||||
/proc/typecacheof_assoc_list(list/pathlist, ignore_root_path = FALSE)
|
||||
. = list()
|
||||
if(!istype(pathlist))
|
||||
return
|
||||
for(var/P in pathlist)
|
||||
var/value = pathlist[P]
|
||||
for(var/T in (ignore_root_path ? subtypesof(P) : typesof(P)))
|
||||
.[T] = value
|
||||
|
||||
//Empties the list by setting the length to 0. Hopefully the elements get garbage collected
|
||||
/proc/clearlist(list/list)
|
||||
if(istype(list))
|
||||
@@ -579,4 +588,4 @@
|
||||
var/list/ret = list()
|
||||
for(var/key in input)
|
||||
ret += key
|
||||
return ret
|
||||
return ret
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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))
|
||||
@@ -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
@@ -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
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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())
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
//Sleeping in here prevents future fires until returned.
|
||||
/datum/controller/subsystem/proc/fire(resumed = 0)
|
||||
flags |= SS_NO_FIRE
|
||||
throw EXCEPTION("Subsystem [src]([type]) does not fire() but did not set the SS_NO_FIRE flag. Please add the SS_NO_FIRE flag to any subsystem that doesn't fire so it doesn't get added to the processing list and waste cpu.")
|
||||
CRASH("Subsystem [src]([type]) does not fire() but did not set the SS_NO_FIRE flag. Please add the SS_NO_FIRE flag to any subsystem that doesn't fire so it doesn't get added to the processing list and waste cpu.")
|
||||
|
||||
/datum/controller/subsystem/Destroy()
|
||||
dequeue()
|
||||
|
||||
@@ -83,15 +83,15 @@ SUBSYSTEM_DEF(jukeboxes)
|
||||
return
|
||||
for(var/list/jukeinfo in activejukeboxes)
|
||||
if(!jukeinfo.len)
|
||||
EXCEPTION("Active jukebox without any associated metadata.")
|
||||
stack_trace("Active jukebox without any associated metadata.")
|
||||
continue
|
||||
var/datum/track/juketrack = jukeinfo[1]
|
||||
if(!istype(juketrack))
|
||||
EXCEPTION("Invalid jukebox track datum.")
|
||||
stack_trace("Invalid jukebox track datum.")
|
||||
continue
|
||||
var/obj/jukebox = jukeinfo[3]
|
||||
if(!istype(jukebox))
|
||||
EXCEPTION("Nonexistant or invalid object associated with jukebox.")
|
||||
stack_trace("Nonexistant or invalid object associated with jukebox.")
|
||||
continue
|
||||
var/sound/song_played = sound(juketrack.song_path)
|
||||
var/area/currentarea = get_area(jukebox)
|
||||
|
||||
@@ -5,23 +5,25 @@ These materials call on_applied() on whatever item they are applied to, common e
|
||||
|
||||
SUBSYSTEM_DEF(materials)
|
||||
name = "Materials"
|
||||
flags = SS_NO_FIRE
|
||||
init_order = INIT_ORDER_MATERIALS
|
||||
flags = SS_NO_FIRE | SS_NO_INIT
|
||||
///Dictionary of material.type || material ref
|
||||
var/list/materials = list()
|
||||
var/list/materials
|
||||
///Dictionary of category || list of material refs
|
||||
var/list/materials_by_category = list()
|
||||
var/list/materials_by_category
|
||||
///List of stackcrafting recipes for materials using rigid materials
|
||||
var/list/rigid_stack_recipes = list(new/datum/stack_recipe("chair", /obj/structure/chair/greyscale, one_per_turf = TRUE, on_floor = TRUE, applies_mats = TRUE))
|
||||
|
||||
/datum/controller/subsystem/materials/Initialize(timeofday)
|
||||
InitializeMaterials()
|
||||
return ..()
|
||||
|
||||
///Ran on initialize, populated the materials and materials_by_category dictionaries with their appropiate vars (See these variables for more info)
|
||||
/datum/controller/subsystem/materials/proc/InitializeMaterials(timeofday)
|
||||
/datum/controller/subsystem/materials/proc/InitializeMaterials()
|
||||
materials = list()
|
||||
materials_by_category = list()
|
||||
for(var/type in subtypesof(/datum/material))
|
||||
var/datum/material/ref = new type
|
||||
materials[type] = ref
|
||||
for(var/c in ref.categories)
|
||||
materials_by_category[c] += list(ref)
|
||||
|
||||
/datum/controller/subsystem/materials/proc/GetMaterialRef(datum/material/fakemat)
|
||||
if(!materials)
|
||||
InitializeMaterials()
|
||||
return materials[fakemat] || fakemat
|
||||
@@ -113,11 +113,8 @@ SUBSYSTEM_DEF(shuttle)
|
||||
qdel(T, force=TRUE)
|
||||
CheckAutoEvac()
|
||||
|
||||
//Cargo stuff start
|
||||
var/fire_time_diff = max(0, world.time - last_fire) //Don't want this to be below 0, seriously.
|
||||
var/point_gain = (fire_time_diff / 600) * passive_supply_points_per_minute
|
||||
points += point_gain
|
||||
//Cargo stuff end
|
||||
if(!(times_fired % CEILING(600/wait, 1)))
|
||||
points += passive_supply_points_per_minute
|
||||
|
||||
var/esETA = emergency?.getModeStr()
|
||||
emergency_shuttle_stat_text = "[esETA? "[esETA] [emergency.getTimerStr()]" : ""]"
|
||||
@@ -185,14 +182,13 @@ SUBSYSTEM_DEF(shuttle)
|
||||
WARNING("requestEvac(): There is no emergency shuttle, but the \
|
||||
shuttle was called. Using the backup shuttle instead.")
|
||||
if(!backup_shuttle)
|
||||
throw EXCEPTION("requestEvac(): There is no emergency shuttle, \
|
||||
CRASH("requestEvac(): There is no emergency shuttle, \
|
||||
or backup shuttle! The game will be unresolvable. This is \
|
||||
possibly a mapping error, more likely a bug with the shuttle \
|
||||
manipulation system, or badminry. It is possible to manually \
|
||||
resolve this problem by loading an emergency shuttle template \
|
||||
manually, and then calling register() on the mobile docking port. \
|
||||
Good luck.")
|
||||
return
|
||||
emergency = backup_shuttle
|
||||
var/srd = CONFIG_GET(number/shuttle_refuel_delay)
|
||||
if(world.time - SSticker.round_start_time < srd)
|
||||
@@ -420,7 +416,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/request_transit_dock(obj/docking_port/mobile/M)
|
||||
if(!istype(M))
|
||||
throw EXCEPTION("[M] is not a mobile docking port")
|
||||
CRASH("[M] is not a mobile docking port")
|
||||
|
||||
if(M.assigned_transit)
|
||||
return
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -119,18 +119,6 @@
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
|
||||
/datum/crafting_recipe/switchblade_ms
|
||||
name = "Switchblade"
|
||||
result = /obj/item/switchblade/crafted
|
||||
reqs = list(/obj/item/weaponcrafting/stock = 1,
|
||||
/obj/item/weaponcrafting/receiver = 1,
|
||||
/obj/item/kitchen/knife = 1,
|
||||
/obj/item/stack/cable_coil = 2)
|
||||
tools = list(TOOL_WELDER)
|
||||
time = 45
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
|
||||
//////////////////
|
||||
///BOMB CRAFTING//
|
||||
//////////////////
|
||||
@@ -310,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
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/OnExamine)
|
||||
|
||||
for(var/mat in mat_list) //Make the assoc list ref | amount
|
||||
var/datum/material/M = getmaterialref(mat) || mat
|
||||
var/datum/material/M = SSmaterials.GetMaterialRef(mat)
|
||||
materials[M] = 0
|
||||
|
||||
/datum/component/material_container/proc/OnExamine(datum/source, mob/user, list/examine_list)
|
||||
@@ -130,7 +130,7 @@
|
||||
/// For inserting an amount of material
|
||||
/datum/component/material_container/proc/insert_amount_mat(amt, var/datum/material/mat)
|
||||
if(!istype(mat))
|
||||
mat = getmaterialref(mat)
|
||||
mat = SSmaterials.GetMaterialRef(mat)
|
||||
if(amt > 0 && has_space(amt))
|
||||
var/total_amount_saved = total_amount
|
||||
if(mat)
|
||||
@@ -145,7 +145,7 @@
|
||||
/// Uses an amount of a specific material, effectively removing it.
|
||||
/datum/component/material_container/proc/use_amount_mat(amt, var/datum/material/mat)
|
||||
if(!istype(mat))
|
||||
mat = getmaterialref(mat)
|
||||
mat = SSmaterials.GetMaterialRef(mat)
|
||||
var/amount = materials[mat]
|
||||
if(mat)
|
||||
if(amount >= amt)
|
||||
@@ -157,7 +157,7 @@
|
||||
/// Proc for transfering materials to another container.
|
||||
/datum/component/material_container/proc/transer_amt_to(var/datum/component/material_container/T, amt, var/datum/material/mat)
|
||||
if(!istype(mat))
|
||||
mat = getmaterialref(mat)
|
||||
mat = SSmaterials.GetMaterialRef(mat)
|
||||
if((amt==0)||(!T)||(!mat))
|
||||
return FALSE
|
||||
if(amt<0)
|
||||
@@ -190,7 +190,7 @@
|
||||
for(var/x in mats) //Loop through all required materials
|
||||
var/datum/material/req_mat = x
|
||||
if(!istype(req_mat))
|
||||
req_mat = getmaterialref(req_mat) //Get the ref if necesary
|
||||
req_mat = SSmaterials.GetMaterialRef(req_mat) //Get the ref if necesary
|
||||
if(!materials[req_mat]) //Do we have the resource?
|
||||
return FALSE //Can't afford it
|
||||
var/amount_required = mats[x] * multiplier
|
||||
@@ -251,7 +251,7 @@
|
||||
var/datum/material/req_mat = x
|
||||
if(!istype(req_mat))
|
||||
if(ispath(req_mat)) //Is this an actual material, or is it a category?
|
||||
req_mat = getmaterialref(req_mat) //Get the ref
|
||||
req_mat = SSmaterials.GetMaterialRef(req_mat) //Get the ref
|
||||
|
||||
else // Its a category. (For example MAT_CATEGORY_RIGID)
|
||||
if(!has_enough_of_category(req_mat, mats[req_mat], multiplier)) //Do we have enough of this category?
|
||||
@@ -316,5 +316,5 @@
|
||||
/// Returns the amount of a specific material in this container.
|
||||
/datum/component/material_container/proc/get_material_amount(var/datum/material/mat)
|
||||
if(!istype(mat))
|
||||
mat = getmaterialref(mat)
|
||||
mat = SSmaterials.GetMaterialRef(mat)
|
||||
return(materials[mat])
|
||||
|
||||
+14
-16
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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>")
|
||||
|
||||
@@ -41,20 +41,21 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
|
||||
///This proc is called when the material is added to an object specifically.
|
||||
/datum/material/proc/on_applied_obj(var/obj/o, amount, material_flags)
|
||||
var/new_max_integrity = CEILING(o.max_integrity * integrity_modifier, 1)
|
||||
o.modify_max_integrity(new_max_integrity)
|
||||
o.force *= strength_modifier
|
||||
o.throwforce *= strength_modifier
|
||||
if(material_flags & MATERIAL_AFFECT_STATISTICS)
|
||||
var/new_max_integrity = CEILING(o.max_integrity * integrity_modifier, 1)
|
||||
o.modify_max_integrity(new_max_integrity)
|
||||
o.force *= strength_modifier
|
||||
o.throwforce *= strength_modifier
|
||||
|
||||
var/list/temp_armor_list = list() //Time to add armor modifiers!
|
||||
var/list/temp_armor_list = list() //Time to add armor modifiers!
|
||||
|
||||
if(!istype(o.armor))
|
||||
return
|
||||
var/list/current_armor = o.armor?.getList()
|
||||
if(!istype(o.armor))
|
||||
return
|
||||
var/list/current_armor = o.armor?.getList()
|
||||
|
||||
for(var/i in current_armor)
|
||||
temp_armor_list[i] = current_armor[i] * armor_modifiers[i]
|
||||
o.armor = getArmor(arglist(temp_armor_list))
|
||||
for(var/i in current_armor)
|
||||
temp_armor_list[i] = current_armor[i] * armor_modifiers[i]
|
||||
o.armor = getArmor(arglist(temp_armor_list))
|
||||
|
||||
///This proc is called when the material is removed from an object.
|
||||
/datum/material/proc/on_removed(atom/source, material_flags)
|
||||
@@ -71,7 +72,8 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
|
||||
///This proc is called when the material is removed from an object specifically.
|
||||
/datum/material/proc/on_removed_obj(var/obj/o, amount, material_flags)
|
||||
var/new_max_integrity = initial(o.max_integrity)
|
||||
o.modify_max_integrity(new_max_integrity)
|
||||
o.force = initial(o.force)
|
||||
o.throwforce = initial(o.throwforce)
|
||||
if(material_flags & MATERIAL_AFFECT_STATISTICS)
|
||||
var/new_max_integrity = initial(o.max_integrity)
|
||||
o.modify_max_integrity(new_max_integrity)
|
||||
o.force = initial(o.force)
|
||||
o.throwforce = initial(o.throwforce)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
/datum/progressbar/New(mob/User, goal_number, atom/target)
|
||||
. = ..()
|
||||
if (!istype(target))
|
||||
EXCEPTION("Invalid target given")
|
||||
CRASH("Invalid target given")
|
||||
if (goal_number)
|
||||
goal = goal_number
|
||||
bar = image('icons/effects/progessbar.dmi', target, "prog_bar_0", HUD_LAYER)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+49
-3
@@ -97,7 +97,7 @@
|
||||
|
||||
var/temp_list = list()
|
||||
for(var/i in custom_materials)
|
||||
temp_list[getmaterialref(i)] = custom_materials[i] //Get the proper instanced version
|
||||
temp_list[SSmaterials.GetMaterialRef(i)] = custom_materials[i] //Get the proper instanced version
|
||||
custom_materials = null //Null the list to prepare for applying the materials properly
|
||||
set_custom_materials(temp_list)
|
||||
|
||||
@@ -904,7 +904,7 @@ Proc for attack log creation, because really why not
|
||||
|
||||
if(custom_materials) //Only runs if custom materials existed at first. Should usually be the case but check anyways
|
||||
for(var/i in custom_materials)
|
||||
var/datum/material/custom_material = getmaterialref(i)
|
||||
var/datum/material/custom_material = SSmaterials.GetMaterialRef(i)
|
||||
custom_material.on_removed(src, material_flags) //Remove the current materials
|
||||
|
||||
if(!length(materials))
|
||||
@@ -913,8 +913,54 @@ Proc for attack log creation, because really why not
|
||||
custom_materials = list() //Reset the list
|
||||
|
||||
for(var/x in materials)
|
||||
var/datum/material/custom_material = getmaterialref(x)
|
||||
var/datum/material/custom_material = SSmaterials.GetMaterialRef(x)
|
||||
|
||||
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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -746,7 +746,7 @@
|
||||
Mind.add_antag_datum(ninjadatum)
|
||||
|
||||
if(Ninja.mind != Mind) //something has gone wrong!
|
||||
throw EXCEPTION("Ninja created with incorrect mind")
|
||||
stack_trace("Ninja created with incorrect mind")
|
||||
|
||||
message_admins("[ADMIN_LOOKUPFLW(Ninja)] has been made into a ninja by dynamic.")
|
||||
log_game("[key_name(Ninja)] was spawned as a ninja by dynamic.")
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -140,7 +140,7 @@
|
||||
/obj/machinery/autolathe/proc/AfterMaterialInsert(obj/item/item_inserted, id_inserted, amount_inserted)
|
||||
if(istype(item_inserted, /obj/item/stack/ore/bluespace_crystal))
|
||||
use_power(MINERAL_MATERIAL_AMOUNT / 10)
|
||||
else if(item_inserted.custom_materials?.len && item_inserted.custom_materials[getmaterialref(/datum/material/glass)])
|
||||
else if(item_inserted.custom_materials?.len && item_inserted.custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)])
|
||||
flick("autolathe_r",src)//plays glass insertion animation by default otherwise
|
||||
else
|
||||
flick("autolathe_o",src)//plays metal insertion animation
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
if(!charging)
|
||||
return
|
||||
|
||||
. += image(charging.icon, charging.icon_state)
|
||||
. += mutable_appearance(charging.icon, charging.icon_state)
|
||||
. += "ccharger-on"
|
||||
if(!(stat & (BROKEN|NOPOWER)))
|
||||
var/newlevel = round(charging.percent() * 4 / 100)
|
||||
|
||||
@@ -491,29 +491,29 @@
|
||||
/obj/machinery/clonepod/update_overlays()
|
||||
. = ..()
|
||||
if(mess)
|
||||
var/image/gib1 = image(CRYOMOBS, "gibup")
|
||||
var/image/gib2 = image(CRYOMOBS, "gibdown")
|
||||
var/mutable_appearance/gib1 = mutable_appearance(CRYOMOBS, "gibup")
|
||||
var/mutable_appearance/gib2 = mutable_appearance(CRYOMOBS, "gibdown")
|
||||
gib1.pixel_y = 27 + round(sin(world.time) * 3)
|
||||
gib1.pixel_x = round(sin(world.time * 3))
|
||||
gib2.pixel_y = 27 + round(cos(world.time) * 3)
|
||||
gib2.pixel_x = round(cos(world.time * 3))
|
||||
. += gib2
|
||||
. += gib1
|
||||
. += "cover-on"
|
||||
else if(occupant)
|
||||
var/image/occupant_overlay
|
||||
var/mutable_appearance/occupant_overlay
|
||||
var/completion = (flesh_number - unattached_flesh.len) / flesh_number
|
||||
|
||||
if(unattached_flesh.len <= 0)
|
||||
occupant_overlay = image(occupant.icon, occupant.icon_state)
|
||||
occupant_overlay = mutable_appearance(occupant.icon, occupant.icon_state)
|
||||
occupant_overlay.copy_overlays(occupant)
|
||||
. += "cover-on"
|
||||
else
|
||||
occupant_overlay = image(CRYOMOBS, "clone_meat")
|
||||
occupant_overlay = mutable_appearance(CRYOMOBS, "clone_meat")
|
||||
var/matrix/tform = matrix()
|
||||
tform.Scale(completion)
|
||||
tform.Turn(cos(world.time * 2) * 3)
|
||||
occupant_overlay.transform = tform
|
||||
occupant_overlay.appearance_flags = 0
|
||||
occupant_overlay.appearance_flags = NONE
|
||||
|
||||
occupant_overlay.dir = SOUTH
|
||||
occupant_overlay.pixel_y = 27 + round(sin(world.time) * 3)
|
||||
|
||||
@@ -287,6 +287,7 @@
|
||||
#define CRYO_PRESERVE 1
|
||||
#define CRYO_OBJECTIVE 2
|
||||
#define CRYO_IGNORE 3
|
||||
#define CRYO_DESTROY_LATER 4
|
||||
|
||||
/obj/machinery/cryopod/proc/should_preserve_item(obj/item/I)
|
||||
for(var/datum/objective_item/steal/T in control_computer.theft_cache)
|
||||
@@ -308,8 +309,8 @@
|
||||
if(iscyborg(mob_occupant))
|
||||
var/mob/living/silicon/robot/R = mob_occupant
|
||||
if(R.mmi?.brain)
|
||||
cryo_items[R.mmi] = CRYO_IGNORE
|
||||
cryo_items[R.mmi.brain] = CRYO_IGNORE
|
||||
cryo_items[R.mmi] = CRYO_DESTROY_LATER
|
||||
cryo_items[R.mmi.brain] = CRYO_DESTROY_LATER
|
||||
for(var/obj/item/I in R.module) // the tools the borg has; metal, glass, guns etc
|
||||
for(var/obj/item/O in I) // the things inside the tools, if anything; mainly for janiborg trash bags
|
||||
cryo_items[O] = should_preserve_item(O)
|
||||
@@ -318,7 +319,7 @@
|
||||
|
||||
//Drop all items into the pod.
|
||||
for(var/obj/item/I in mob_occupant)
|
||||
if(cryo_items[I] == CRYO_IGNORE)
|
||||
if(cryo_items[I] == CRYO_IGNORE || cryo_items[I] ==CRYO_DESTROY_LATER)
|
||||
continue
|
||||
cryo_items[I] = should_preserve_item(I)
|
||||
mob_occupant.transferItemToLoc(I, src, TRUE)
|
||||
@@ -334,17 +335,19 @@
|
||||
if(QDELETED(I)) //edge cases and DROPDEL.
|
||||
continue
|
||||
var/preserve = cryo_items[I]
|
||||
if(preserve == CRYO_IGNORE)
|
||||
if(preserve == CRYO_DESTROY_LATER)
|
||||
continue
|
||||
else if(preserve == CRYO_DESTROY)
|
||||
qdel(I)
|
||||
else if(control_computer?.allow_items)
|
||||
control_computer.frozen_items += I
|
||||
if(preserve == CRYO_OBJECTIVE)
|
||||
control_computer.objective_items += I
|
||||
I.moveToNullspace()
|
||||
else
|
||||
I.forceMove(loc)
|
||||
if(preserve != CRYO_IGNORE)
|
||||
if(preserve == CRYO_DESTROY)
|
||||
qdel(I)
|
||||
else if(control_computer?.allow_items)
|
||||
control_computer.frozen_items += I
|
||||
if(preserve == CRYO_OBJECTIVE)
|
||||
control_computer.objective_items += I
|
||||
I.moveToNullspace()
|
||||
else
|
||||
I.forceMove(loc)
|
||||
cryo_items -= I
|
||||
|
||||
//Update any existing objectives involving this mob.
|
||||
for(var/datum/objective/O in GLOB.objectives)
|
||||
@@ -405,6 +408,10 @@
|
||||
mob_occupant.ghostize(FALSE, penalize = TRUE)
|
||||
|
||||
QDEL_NULL(occupant)
|
||||
for(var/I in cryo_items) //only "CRYO_DESTROY_LATER" atoms are left)
|
||||
var/atom/A = I
|
||||
if(!QDELETED(A))
|
||||
qdel(A)
|
||||
open_machine()
|
||||
name = initial(name)
|
||||
|
||||
@@ -412,6 +419,7 @@
|
||||
#undef CRYO_PRESERVE
|
||||
#undef CRYO_OBJECTIVE
|
||||
#undef CRYO_IGNORE
|
||||
#undef CRYO_DESTROY_LATER
|
||||
|
||||
/obj/machinery/cryopod/MouseDrop_T(mob/living/target, mob/user)
|
||||
if(!istype(target) || user.incapacitated() || !target.Adjacent(user) || !Adjacent(user) || !ismob(target) || (!ishuman(user) && !iscyborg(user)) || !istype(user.loc, /turf) || target.buckled)
|
||||
|
||||
@@ -705,7 +705,7 @@
|
||||
|
||||
/obj/machinery/porta_turret/syndicate/energy/pirate
|
||||
max_integrity = 260
|
||||
integrity_failure = 20
|
||||
integrity_failure = 0.08
|
||||
armor = list("melee" = 50, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
|
||||
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@
|
||||
return ..()
|
||||
|
||||
/obj/machinery/autoylathe/proc/AfterMaterialInsert(obj/item/item_inserted, id_inserted, amount_inserted)
|
||||
if(item_inserted.custom_materials?.len && item_inserted.custom_materials[getmaterialref(/datum/material/glass)])
|
||||
if(item_inserted.custom_materials?.len && item_inserted.custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)])
|
||||
flick("autolathe_r",src)//plays glass insertion animation by default otherwise
|
||||
else
|
||||
flick("autolathe_o",src)//plays metal insertion animation
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
if(gibs_reagent_id)
|
||||
reagents.add_reagent(gibs_reagent_id, 5)
|
||||
if(gibs_bloodtype)
|
||||
add_blood_DNA(list("Non-human DNA" = gibs_bloodtype, diseases))
|
||||
add_blood_DNA(list("Non-human DNA" = gibs_bloodtype), diseases)
|
||||
update_icon()
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/update_icon()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
name = "rapid cable layer"
|
||||
desc = "A device used to rapidly deploy cables. It has screws on the side which can be removed to slide off the cables. Do not use without insulation!"
|
||||
icon = 'icons/obj/tools.dmi'
|
||||
icon_state = "rcl-empty"
|
||||
item_state = "rcl-0"
|
||||
icon_state = "rcl"
|
||||
item_state = "rcl"
|
||||
var/obj/structure/cable/last
|
||||
var/obj/item/stack/cable_coil/loaded
|
||||
opacity = FALSE
|
||||
@@ -23,6 +23,10 @@
|
||||
var/datum/radial_menu/persistent/wiring_gui_menu
|
||||
var/mob/listeningTo
|
||||
|
||||
/obj/item/twohanded/rcl/Initialize()
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/obj/item/twohanded/rcl/ComponentInitialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/update_icon_updates_onmob)
|
||||
@@ -105,7 +109,15 @@
|
||||
. = ..()
|
||||
if(!loaded || !loaded.amount)
|
||||
return
|
||||
var/mutable_appearance/cable_overlay = mutable_appearance(icon, "rcl-[max(CEILING(loaded.amount/(max_amount/3), 1), 3)]")
|
||||
var/mutable_appearance/cable_overlay = mutable_appearance(icon, "[initial(icon_state)]-[CEILING(loaded.amount/(max_amount/3), 1)]")
|
||||
cable_overlay.color = GLOB.cable_colors[colors[current_color_index]]
|
||||
. += cable_overlay
|
||||
|
||||
/obj/item/twohanded/rcl/worn_overlays(isinhands, icon_file, style_flags = NONE)
|
||||
. = ..()
|
||||
if(!isinhands || !(loaded?.amount))
|
||||
return
|
||||
var/mutable_appearance/cable_overlay = mutable_appearance(icon, "rcl-[CEILING(loaded.amount/(max_amount/3), 1)]")
|
||||
cable_overlay.color = GLOB.cable_colors[colors[current_color_index]]
|
||||
. += cable_overlay
|
||||
|
||||
@@ -279,18 +291,6 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook)
|
||||
|
||||
wiringGuiUpdate(user)
|
||||
|
||||
|
||||
/obj/item/twohanded/rcl/pre_loaded/Initialize() //Comes preloaded with cable, for testing stuff
|
||||
. = ..()
|
||||
loaded = new()
|
||||
loaded.max_amount = max_amount
|
||||
loaded.amount = max_amount
|
||||
update_icon()
|
||||
|
||||
/obj/item/twohanded/rcl/Initialize()
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/obj/item/twohanded/rcl/ui_action_click(mob/user, action)
|
||||
if(istype(action, /datum/action/item_action/rcl_col))
|
||||
current_color_index++;
|
||||
@@ -309,10 +309,15 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook)
|
||||
else //open the menu
|
||||
showWiringGui(user)
|
||||
|
||||
/obj/item/twohanded/rcl/pre_loaded/Initialize() //Comes preloaded with cable, for testing stuff
|
||||
loaded = new()
|
||||
loaded.max_amount = max_amount
|
||||
loaded.amount = max_amount
|
||||
return ..()
|
||||
|
||||
/obj/item/twohanded/rcl/ghetto
|
||||
actions_types = list()
|
||||
max_amount = 30
|
||||
name = "makeshift rapid cable layer"
|
||||
icon_state = "rclg"
|
||||
item_state = "rclg"
|
||||
ghetto = TRUE
|
||||
|
||||
@@ -66,8 +66,8 @@
|
||||
if(iswallturf(T))
|
||||
T.attackby(src, user, params)
|
||||
|
||||
var/metal_amt = round(custom_materials[getmaterialref(/datum/material/iron)]/MINERAL_MATERIAL_AMOUNT)
|
||||
var/glass_amt = round(custom_materials[getmaterialref(/datum/material/glass)]/MINERAL_MATERIAL_AMOUNT)
|
||||
var/metal_amt = round(custom_materials[SSmaterials.GetMaterialRef(/datum/material/iron)]/MINERAL_MATERIAL_AMOUNT)
|
||||
var/glass_amt = round(custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)]/MINERAL_MATERIAL_AMOUNT)
|
||||
|
||||
if(istype(W, /obj/item/wrench) && (metal_amt || glass_amt))
|
||||
to_chat(user, "<span class='notice'>You dismantle [src].</span>")
|
||||
|
||||
@@ -9,7 +9,6 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
#define PDA_SCANNER_HALOGEN 4
|
||||
#define PDA_SCANNER_GAS 5
|
||||
#define PDA_SPAM_DELAY 2 MINUTES
|
||||
#define PDA_STANDARD_OVERLAYS list("pda-r", "blank", "id_overlay", "insert_overlay", "light_overlay", "pai_overlay")
|
||||
|
||||
//pda icon overlays list defines
|
||||
#define PDA_OVERLAY_ALERT 1
|
||||
@@ -33,14 +32,14 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
|
||||
|
||||
//Main variables
|
||||
var/owner = null // String name of owner
|
||||
var/default_cartridge = 0 // Access level defined by cartridge
|
||||
var/obj/item/cartridge/cartridge = null //current cartridge
|
||||
var/mode = 0 //Controls what menu the PDA will display. 0 is hub; the rest are either built in or based on cartridge.
|
||||
var/list/overlays_icons = list('icons/obj/pda_alt.dmi' = list("pda-r", "screen_default", "id_overlay", "insert_overlay", "light_overlay", "pai_overlay"))
|
||||
var/current_overlays = PDA_STANDARD_OVERLAYS
|
||||
var/static/list/standard_overlays_icons = list("pda-r", "blank", "id_overlay", "insert_overlay", "light_overlay", "pai_overlay")
|
||||
var/list/current_overlays //set on Initialize.
|
||||
|
||||
//variables exclusively used on 'update_overlays' (which should never be called directly, and 'update_icon' doesn't use args anyway)
|
||||
var/new_overlays = FALSE
|
||||
@@ -164,7 +163,7 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
overlays_x_offset = new_offsets[1]
|
||||
overlays_y_offset = new_offsets[2]
|
||||
if(!(icon in overlays_icons))
|
||||
current_overlays = PDA_STANDARD_OVERLAYS
|
||||
current_overlays = standard_overlays_icons
|
||||
return
|
||||
current_overlays = overlays_icons[icon]
|
||||
|
||||
@@ -228,8 +227,11 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
if(new_overlays)
|
||||
set_new_overlays()
|
||||
. += new_alert ? current_overlays[PDA_OVERLAY_ALERT] : current_overlays[PDA_OVERLAY_SCREEN]
|
||||
var/mutable_appearance/overlay = new()
|
||||
var/screen_state = new_alert ? current_overlays[PDA_OVERLAY_ALERT] : current_overlays[PDA_OVERLAY_SCREEN]
|
||||
var/mutable_appearance/overlay = mutable_appearance(icon, screen_state)
|
||||
overlay.pixel_x = overlays_x_offset
|
||||
overlay.pixel_y = overlays_y_offset
|
||||
. += overlay
|
||||
if(id)
|
||||
overlay.icon_state = current_overlays[PDA_OVERLAY_ID]
|
||||
. += new /mutable_appearance(overlay)
|
||||
@@ -1223,7 +1225,6 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
#undef PDA_SCANNER_HALOGEN
|
||||
#undef PDA_SCANNER_GAS
|
||||
#undef PDA_SPAM_DELAY
|
||||
#undef PDA_STANDARD_OVERLAYS
|
||||
|
||||
#undef PDA_OVERLAY_ALERT
|
||||
#undef PDA_OVERLAY_SCREEN
|
||||
|
||||
@@ -193,8 +193,6 @@
|
||||
/obj/item/pda/curator
|
||||
name = "curator PDA"
|
||||
icon_state = "pda-library"
|
||||
overlays_icons = list('icons/obj/pda.dmi' = list("pda-r-library","blank","id_overlay","insert_overlay", "light_overlay", "pai_overlay"),
|
||||
'icons/obj/pda_alt.dmi' = list("pda-r","screen_default","id_overlay","insert_overlay", "light_overlay", "pai_overlay"))
|
||||
current_overlays = list("pda-r-library","blank","id_overlay","insert_overlay", "light_overlay", "pai_overlay")
|
||||
default_cartridge = /obj/item/cartridge/curator
|
||||
inserted_item = /obj/item/pen/fountain
|
||||
|
||||
@@ -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."
|
||||
@@ -515,7 +621,7 @@
|
||||
item_state = "mace_greyscale"
|
||||
lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR //Material type changes the prefix as well as the color.
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS //Material type changes the prefix as well as the color.
|
||||
custom_materials = list(/datum/material/iron = 12000) //Defaults to an Iron Mace.
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
force = 14
|
||||
|
||||
@@ -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, \
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
merge_type = type
|
||||
if(custom_materials && custom_materials.len)
|
||||
for(var/i in custom_materials)
|
||||
custom_materials[getmaterialref(i)] = mats_per_stack * amount
|
||||
custom_materials[SSmaterials.GetMaterialRef(i)] = mats_per_stack * amount
|
||||
. = ..()
|
||||
if(merge)
|
||||
for(var/obj/item/stack/S in loc)
|
||||
@@ -57,7 +57,7 @@
|
||||
var/list/temp_recipes = get_main_recipes()
|
||||
recipes = temp_recipes.Copy()
|
||||
if(material_type)
|
||||
var/datum/material/M = getmaterialref(material_type) //First/main material
|
||||
var/datum/material/M = SSmaterials.GetMaterialRef(material_type) //First/main material
|
||||
for(var/i in M.categories)
|
||||
switch(i)
|
||||
if(MAT_CATEGORY_RIGID)
|
||||
@@ -225,7 +225,7 @@
|
||||
if(R.applies_mats && custom_materials && custom_materials.len)
|
||||
var/list/used_materials = list()
|
||||
for(var/i in custom_materials)
|
||||
used_materials[getmaterialref(i)] = R.req_amount / R.res_amount * (MINERAL_MATERIAL_AMOUNT / custom_materials.len)
|
||||
used_materials[SSmaterials.GetMaterialRef(i)] = R.req_amount / R.res_amount * (MINERAL_MATERIAL_AMOUNT / custom_materials.len)
|
||||
O.set_custom_materials(used_materials)
|
||||
|
||||
//START: oh fuck i'm so sorry
|
||||
@@ -347,7 +347,7 @@
|
||||
src.amount += amount
|
||||
if(custom_materials && custom_materials.len)
|
||||
for(var/i in custom_materials)
|
||||
custom_materials[getmaterialref(i)] = MINERAL_MATERIAL_AMOUNT * src.amount
|
||||
custom_materials[SSmaterials.GetMaterialRef(i)] = MINERAL_MATERIAL_AMOUNT * src.amount
|
||||
set_custom_materials() //Refresh
|
||||
update_icon()
|
||||
update_weight()
|
||||
|
||||
@@ -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
|
||||
@@ -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))
|
||||
|
||||
@@ -347,25 +347,6 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
user.visible_message("<span class='suicide'>[user] is slitting [user.p_their()] own throat with [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
return (BRUTELOSS)
|
||||
|
||||
/obj/item/switchblade/crafted
|
||||
icon_state = "switchblade_ms"
|
||||
desc = "A concealable spring-loaded knife."
|
||||
force = 2
|
||||
throwforce = 3
|
||||
extended_force = 15
|
||||
extended_throwforce = 18
|
||||
extended_icon_state = "switchblade_ext_ms"
|
||||
retracted_icon_state = "switchblade_ms"
|
||||
|
||||
/obj/item/switchblade/crafted/attackby(obj/item/I, mob/user, params)
|
||||
. = ..()
|
||||
if(istype(I, /obj/item/stack/sheet/mineral/silver))
|
||||
icon_state = extended ? "switchblade_ext_msf" : "switchblade_msf"
|
||||
extended_icon_state = "switchblade_ext_msf"
|
||||
retracted_icon_state = "switchblade_msf"
|
||||
icon_state = "switchblade_msf"
|
||||
to_chat(user, "<span class='notice'>You use part of the silver to improve your Switchblade. Stylish!</span>")
|
||||
|
||||
/obj/item/phone
|
||||
name = "red phone"
|
||||
desc = "Should anything ever go wrong..."
|
||||
|
||||
@@ -153,7 +153,7 @@
|
||||
///Material chair
|
||||
/obj/structure/chair/greyscale
|
||||
icon_state = "chair_greyscale"
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS
|
||||
item_chair = /obj/item/chair/greyscale
|
||||
buildstacktype = null //Custom mats handle this
|
||||
|
||||
@@ -383,7 +383,7 @@
|
||||
/obj/item/chair/greyscale
|
||||
icon_state = "chair_greyscale_toppled"
|
||||
item_state = "chair_greyscale"
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS
|
||||
origin_type = /obj/structure/chair/greyscale
|
||||
|
||||
/obj/item/chair/stool
|
||||
|
||||
@@ -83,9 +83,12 @@
|
||||
desc = "It's a burial receptacle for the dearly departed."
|
||||
icon_state = "coffin"
|
||||
resistance_flags = FLAMMABLE
|
||||
can_weld_shut = FALSE
|
||||
breakout_time = 200
|
||||
max_integrity = 70
|
||||
material_drop = /obj/item/stack/sheet/mineral/wood
|
||||
material_drop_amount = 5
|
||||
var/pryLidTimer = 250
|
||||
|
||||
/obj/structure/closet/crate/coffin/examine(mob/user)
|
||||
. = ..()
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
make_new_table(material.tableVariant)
|
||||
else
|
||||
if(material.get_amount() < 1)
|
||||
to_chat(user, "<span class='warning'>You need one metal sheet to do this!</span>")
|
||||
to_chat(user, "<span class='warning'>You need one sheet to do this!</span>")
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You start adding [material] to [src]...</span>")
|
||||
if(do_after(user, 20, target = src) && material.use(1))
|
||||
|
||||
@@ -211,7 +211,7 @@
|
||||
/obj/structure/table/greyscale
|
||||
icon = 'icons/obj/smooth_structures/table_greyscale.dmi'
|
||||
icon_state = "table"
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS
|
||||
buildstack = null //No buildstack, so generate from mat datums
|
||||
|
||||
/*
|
||||
|
||||
@@ -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"
|
||||
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
/proc/playsound(atom/source, soundin, vol as num, vary, extrarange as num, falloff, frequency = null, channel = 0, pressure_affected = TRUE, ignore_walls = TRUE, soundenvwet = -10000, soundenvdry = 0)
|
||||
if(isarea(source))
|
||||
throw EXCEPTION("playsound(): source is an area")
|
||||
return
|
||||
CRASH("playsound(): source is an area")
|
||||
|
||||
var/turf/turf_source = get_turf(source)
|
||||
|
||||
|
||||
@@ -23,8 +23,7 @@ GLOBAL_PROTECT(protected_ranks)
|
||||
name = init_name
|
||||
if(!name)
|
||||
qdel(src)
|
||||
throw EXCEPTION("Admin rank created without name.")
|
||||
return
|
||||
CRASH("Admin rank created without name.")
|
||||
if(init_rights)
|
||||
rights = init_rights
|
||||
include_rights = rights
|
||||
|
||||
@@ -39,12 +39,10 @@ GLOBAL_PROTECT(href_token)
|
||||
return
|
||||
if(!ckey)
|
||||
QDEL_IN(src, 0)
|
||||
throw EXCEPTION("Admin datum created without a ckey")
|
||||
return
|
||||
CRASH("Admin datum created without a ckey")
|
||||
if(!istype(R))
|
||||
QDEL_IN(src, 0)
|
||||
throw EXCEPTION("Admin datum created without a rank")
|
||||
return
|
||||
CRASH("Admin datum created without a rank")
|
||||
target = ckey
|
||||
name = "[ckey]'s admin datum ([R])"
|
||||
rank = R
|
||||
|
||||
@@ -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>"
|
||||
|
||||
@@ -218,11 +218,16 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobbernaut/Initialize()
|
||||
. = ..()
|
||||
if(!independent) //no pulling people deep into the blob
|
||||
verbs -= /mob/living/verb/pulled
|
||||
else
|
||||
if(independent)
|
||||
pass_flags &= ~PASSBLOB
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobbernaut/start_pulling(atom/movable/AM, state, force = pull_force, supress_message = FALSE)
|
||||
if(!independent && ismob(AM))
|
||||
if(!supress_message)
|
||||
to_chat(src, "<span class='warning'>You are unable to grasp people in this form.</span>")
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobbernaut/Life()
|
||||
if(..())
|
||||
var/list/blobs_in_area = range(2, src)
|
||||
|
||||
@@ -303,8 +303,7 @@
|
||||
|
||||
/obj/structure/blob/proc/change_to(type, controller)
|
||||
if(!ispath(type))
|
||||
throw EXCEPTION("change_to(): invalid type for blob")
|
||||
return
|
||||
CRASH("change_to(): invalid type for blob")
|
||||
var/obj/structure/blob/B = new type(src.loc, controller)
|
||||
B.creation_action()
|
||||
B.update_icon()
|
||||
|
||||
@@ -42,25 +42,18 @@
|
||||
/obj/structure/closet/crate
|
||||
var/mob/living/resident // This lets bloodsuckers claim any "closet" as a Coffin, so long as they could get into it and close it. This locks it in place, too.
|
||||
|
||||
/obj/structure/closet/crate/coffin
|
||||
var/pryLidTimer = 250
|
||||
can_weld_shut = FALSE
|
||||
breakout_time = 200
|
||||
|
||||
|
||||
/obj/structure/closet/crate/coffin/blackcoffin
|
||||
name = "black coffin"
|
||||
desc = "For those departed who are not so dear."
|
||||
icon_state = "coffin"
|
||||
icon = 'icons/obj/vamp_obj.dmi'
|
||||
can_weld_shut = FALSE
|
||||
resistance_flags = 0 // Start off with no bonuses.
|
||||
open_sound = 'sound/bloodsucker/coffin_open.ogg'
|
||||
close_sound = 'sound/bloodsucker/coffin_close.ogg'
|
||||
breakout_time = 600
|
||||
pryLidTimer = 400
|
||||
resistance_flags = NONE
|
||||
integrity_failure = 70
|
||||
max_integrity = 100
|
||||
integrity_failure = 0.5
|
||||
armor = list("melee" = 50, "bullet" = 20, "laser" = 30, "energy" = 0, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 60)
|
||||
|
||||
/obj/structure/closet/crate/coffin/meatcoffin
|
||||
@@ -68,8 +61,6 @@
|
||||
desc = "When you're ready to meat your maker, the steaks can never be too high."
|
||||
icon_state = "meatcoffin"
|
||||
icon = 'icons/obj/vamp_obj.dmi'
|
||||
can_weld_shut = FALSE
|
||||
resistance_flags = 0 // Start off with no bonuses.
|
||||
open_sound = 'sound/effects/footstep/slime1.ogg'
|
||||
close_sound = 'sound/effects/footstep/slime1.ogg'
|
||||
breakout_time = 200
|
||||
@@ -77,24 +68,23 @@
|
||||
resistance_flags = NONE
|
||||
material_drop = /obj/item/reagent_containers/food/snacks/meat/slab
|
||||
material_drop_amount = 3
|
||||
integrity_failure = 40
|
||||
integrity_failure = 0.57
|
||||
armor = list("melee" = 70, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 70, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 100)
|
||||
|
||||
|
||||
/obj/structure/closet/crate/coffin/metalcoffin
|
||||
name = "metal coffin"
|
||||
desc = "A big metal sardine can inside of another big metal sardine can, in space."
|
||||
icon_state = "metalcoffin"
|
||||
icon = 'icons/obj/vamp_obj.dmi'
|
||||
can_weld_shut = FALSE
|
||||
resistance_flags = FIRE_PROOF | LAVA_PROOF
|
||||
open_sound = 'sound/effects/pressureplate.ogg'
|
||||
close_sound = 'sound/effects/pressureplate.ogg'
|
||||
breakout_time = 300
|
||||
pryLidTimer = 200
|
||||
resistance_flags = NONE
|
||||
material_drop = /obj/item/stack/sheet/metal
|
||||
material_drop_amount = 5
|
||||
integrity_failure = 60
|
||||
max_integrity = 200
|
||||
integrity_failure = 0.25
|
||||
armor = list("melee" = 40, "bullet" = 15, "laser" = 50, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 60)
|
||||
|
||||
//////////////////////////////////////////////
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
if(istype(our_target, /datum/cellular_emporium))
|
||||
cellular_emporium = our_target
|
||||
else
|
||||
throw EXCEPTION("cellular_emporium action created with non emporium")
|
||||
CRASH("cellular_emporium action created with non emporium")
|
||||
|
||||
/datum/action/innate/cellular_emporium/Activate()
|
||||
cellular_emporium.ui_interact(owner)
|
||||
|
||||
@@ -477,7 +477,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
|
||||
if(SOULVALUE >= ARCH_THRESHOLD && ascendable)
|
||||
A.convert_to_archdevil()
|
||||
else
|
||||
throw EXCEPTION("Unable to find a blobstart landmark for hellish resurrection")
|
||||
CRASH("Unable to find a blobstart landmark for hellish resurrection")
|
||||
|
||||
|
||||
/datum/antagonist/devil/proc/update_hud()
|
||||
|
||||
@@ -191,7 +191,7 @@
|
||||
return 0
|
||||
|
||||
/obj/item/IntegrateAmount() //returns the amount of resources gained when eating this item
|
||||
if(custom_materials[getmaterialref(/datum/material/iron)] || custom_materials[getmaterialref(/datum/material/glass)])
|
||||
if(custom_materials[SSmaterials.GetMaterialRef(/datum/material/iron)] || custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)])
|
||||
return 1
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -144,7 +144,7 @@
|
||||
for(var/i in 1 to device_type)
|
||||
var/datum/pipeline/parent = parents[i]
|
||||
if(!parent)
|
||||
throw EXCEPTION("Component is missing a pipenet! Rebuilding...")
|
||||
stack_trace("Component is missing a pipenet! Rebuilding...")
|
||||
build_network()
|
||||
parent.update = 1
|
||||
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
if(!isitem(O))
|
||||
return 0
|
||||
var/obj/item/I = O
|
||||
if(!(getmaterialref(material_id) in I.custom_materials))
|
||||
if(!(SSmaterials.GetMaterialRef(material_id) in I.custom_materials))
|
||||
return 0
|
||||
|
||||
var/amount = I.custom_materials[getmaterialref(material_id)]
|
||||
var/amount = I.custom_materials[SSmaterials.GetMaterialRef(material_id)]
|
||||
|
||||
if(istype(I, /obj/item/stack/ore))
|
||||
amount *= 0.8 // Station's ore redemption equipment is really goddamn good.
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -243,7 +243,7 @@
|
||||
icon_state = "knight_greyscale"
|
||||
item_state = "knight_greyscale"
|
||||
armor = list("melee" = 35, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 10, "bio" = 10, "rad" = 10, "fire" = 40, "acid" = 40)
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR //Can change color and add prefix
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS //Can change color and add prefix
|
||||
|
||||
/obj/item/clothing/head/helmet/skull
|
||||
name = "skull helmet"
|
||||
|
||||
@@ -455,6 +455,18 @@
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
|
||||
clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT | ALLOWINTERNALS | SCAN_REAGENTS
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/medical/equipped(mob/living/carbon/human/user, slot)
|
||||
..()
|
||||
if (slot == SLOT_HEAD)
|
||||
var/datum/atom_hud/DHUD = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
|
||||
DHUD.add_hud_to(user)
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/medical/dropped(mob/living/carbon/human/user)
|
||||
..()
|
||||
if (user.head == src)
|
||||
var/datum/atom_hud/DHUD = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
|
||||
DHUD.remove_hud_from(user)
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/medical
|
||||
icon_state = "hardsuit-medical"
|
||||
name = "medical hardsuit"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -267,7 +267,7 @@
|
||||
icon_state = "knight_greyscale"
|
||||
item_state = "knight_greyscale"
|
||||
armor = list("melee" = 35, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 10, "bio" = 10, "rad" = 10, "fire" = 40, "acid" = 40)
|
||||
material_flags = MATERIAL_ADD_PREFIX //Can change color and add prefix
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS //Can change color and add prefix
|
||||
|
||||
/obj/item/clothing/suit/armor/vest/durathread
|
||||
name = "makeshift vest"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -310,7 +310,7 @@
|
||||
for(var/obj/item/O in ingredients)
|
||||
O.microwave_act(src)
|
||||
if(O.custom_materials?.len)
|
||||
metal += O.custom_materials[getmaterialref(/datum/material/iron)]
|
||||
metal += O.custom_materials[SSmaterials.GetMaterialRef(/datum/material/iron)]
|
||||
|
||||
if(metal)
|
||||
spark()
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -4,6 +4,10 @@ GLOBAL_LIST_INIT(duplicate_forbidden_vars,list(
|
||||
"power_supply", "contents", "reagents", "stat", "x", "y", "z", "group", "atmos_adjacent_turfs", "comp_lookup"
|
||||
))
|
||||
|
||||
GLOBAL_LIST_INIT(duplicate_forbidden_vars_by_type, typecacheof_assoc_list(list(
|
||||
/obj/item/gun/energy = "ammo_type"
|
||||
)))
|
||||
|
||||
/proc/DuplicateObject(atom/original, perfectcopy = TRUE, sameloc = FALSE, atom/newloc = null, nerf = FALSE, holoitem=FALSE)
|
||||
RETURN_TYPE(original.type)
|
||||
if(!original)
|
||||
@@ -16,7 +20,7 @@ GLOBAL_LIST_INIT(duplicate_forbidden_vars,list(
|
||||
O = new original.type(newloc)
|
||||
|
||||
if(perfectcopy && O && original)
|
||||
for(var/V in original.vars - GLOB.duplicate_forbidden_vars)
|
||||
for(var/V in original.vars - GLOB.duplicate_forbidden_vars - GLOB.duplicate_forbidden_vars_by_type[O.type])
|
||||
if(islist(original.vars[V]))
|
||||
var/list/L = original.vars[V]
|
||||
O.vars[V] = L.Copy()
|
||||
|
||||
@@ -196,7 +196,7 @@
|
||||
dat += "<A href='?src=[REF(src)];create=[D.id];amount=5'>x5</A>"
|
||||
if(ispath(D.build_path, /obj/item/stack))
|
||||
dat += "<A href='?src=[REF(src)];create=[D.id];amount=10'>x10</A>"
|
||||
dat += "([D.materials[getmaterialref(/datum/material/biomass)]/efficiency])<br>"
|
||||
dat += "([D.materials[SSmaterials.GetMaterialRef(/datum/material/biomass)]/efficiency])<br>"
|
||||
dat += "</div>"
|
||||
else
|
||||
dat += "<div class='statusDisplay'>No container inside, please insert container.</div>"
|
||||
@@ -233,14 +233,14 @@
|
||||
menustat = "void"
|
||||
|
||||
/obj/machinery/biogenerator/proc/check_cost(list/materials, multiplier = 1, remove_points = TRUE)
|
||||
if(materials.len != 1 || materials[1] != getmaterialref(/datum/material/biomass))
|
||||
if(materials.len != 1 || materials[1] != SSmaterials.GetMaterialRef(/datum/material/biomass))
|
||||
return FALSE
|
||||
if (materials[getmaterialref(/datum/material/biomass)]*multiplier/efficiency > points)
|
||||
if (materials[SSmaterials.GetMaterialRef(/datum/material/biomass)]*multiplier/efficiency > points)
|
||||
menustat = "nopoints"
|
||||
return FALSE
|
||||
else
|
||||
if(remove_points)
|
||||
points -= materials[getmaterialref(/datum/material/biomass)]*multiplier/efficiency
|
||||
points -= materials[SSmaterials.GetMaterialRef(/datum/material/biomass)]*multiplier/efficiency
|
||||
update_icon()
|
||||
updateUsrDialog()
|
||||
return TRUE
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -190,10 +190,10 @@
|
||||
var/cost = 400
|
||||
if(ispath(build_type, /obj/item/electronic_assembly))
|
||||
var/obj/item/electronic_assembly/E = SScircuit.cached_assemblies[build_type]
|
||||
cost = E.custom_materials[getmaterialref(/datum/material/iron)]
|
||||
cost = E.custom_materials[SSmaterials.GetMaterialRef(/datum/material/iron)]
|
||||
else if(ispath(build_type, /obj/item/integrated_circuit))
|
||||
var/obj/item/integrated_circuit/IC = SScircuit.cached_components[build_type]
|
||||
cost = IC.custom_materials[getmaterialref(/datum/material/iron)]
|
||||
cost = IC.custom_materials[SSmaterials.GetMaterialRef(/datum/material/iron)]
|
||||
else if(!(build_type in SScircuit.circuit_fabricator_recipe_list["Tools"]))
|
||||
return
|
||||
|
||||
|
||||
@@ -260,7 +260,7 @@
|
||||
blocks["max_space"] = assembly.max_components
|
||||
|
||||
// Start keeping track of total metal cost
|
||||
blocks["metal_cost"] = assembly.custom_materials[getmaterialref(/datum/material/iron)]
|
||||
blocks["metal_cost"] = assembly.custom_materials[SSmaterials.GetMaterialRef(/datum/material/iron)]
|
||||
|
||||
|
||||
// Block 2. Components.
|
||||
@@ -291,7 +291,7 @@
|
||||
// Update estimated assembly complexity, taken space and material cost
|
||||
blocks["complexity"] += component.complexity
|
||||
blocks["used_space"] += component.size
|
||||
blocks["metal_cost"] += component.custom_materials[getmaterialref(/datum/material/iron)]
|
||||
blocks["metal_cost"] += component.custom_materials[SSmaterials.GetMaterialRef(/datum/material/iron)]
|
||||
|
||||
// Check if the assembly requires printer upgrades
|
||||
if(!(component.spawn_flags & IC_SPAWN_DEFAULT))
|
||||
|
||||
@@ -414,7 +414,7 @@
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
set_pin_data(IC_OUTPUT, 2, materials.total_amount)
|
||||
for(var/I in 1 to mtypes.len)
|
||||
var/datum/material/M = materials.materials[getmaterialref(I)]
|
||||
var/datum/material/M = materials.materials[SSmaterials.GetMaterialRef(I)]
|
||||
var/amount = materials[M]
|
||||
if(M)
|
||||
set_pin_data(IC_OUTPUT, I+2, amount)
|
||||
@@ -452,7 +452,7 @@
|
||||
continue
|
||||
if(!mt) //Invalid input
|
||||
if(U>0)
|
||||
if(materials.retrieve_sheets(U, getmaterialref(mtypes[I]), T))
|
||||
if(materials.retrieve_sheets(U, SSmaterials.GetMaterialRef(mtypes[I]), T))
|
||||
suc = TRUE
|
||||
else
|
||||
if(mt.transer_amt_to(materials, U, mtypes[I]))
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
return
|
||||
template = SSmapping.shelter_templates[template_id]
|
||||
if(!template)
|
||||
throw EXCEPTION("Shelter template ([template_id]) not found!")
|
||||
stack_trace("Shelter template ([template_id]) not found!")
|
||||
qdel(src)
|
||||
|
||||
/obj/item/survivalcapsule/Destroy()
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
proximity_monitor = new(src, 1)
|
||||
AddComponent(/datum/component/material_container, list(/datum/material/iron, /datum/material/glass, /datum/material/silver, /datum/material/gold, /datum/material/diamond, /datum/material/plasma, /datum/material/uranium, /datum/material/bananium, /datum/material/titanium, /datum/material/bluespace), INFINITY, TRUE, /obj/item/stack)
|
||||
stored_research = new /datum/techweb/specialized/autounlocking/smelter
|
||||
selected_material = getmaterialref(/datum/material/iron)
|
||||
selected_material = SSmaterials.GetMaterialRef(/datum/material/iron)
|
||||
|
||||
/obj/machinery/mineral/processing_unit/Destroy()
|
||||
CONSOLE = null
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
/datum/material/plastic,
|
||||
/datum/material/runite
|
||||
), MINERAL_MATERIAL_AMOUNT * 50, FALSE, /obj/item/stack)
|
||||
chosen = getmaterialref(chosen)
|
||||
chosen = SSmaterials.GetMaterialRef(chosen)
|
||||
|
||||
/obj/machinery/mineral/mint/process()
|
||||
var/turf/T = get_step(src, input_dir)
|
||||
|
||||
@@ -320,7 +320,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
|
||||
throwforce = 2
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
custom_materials = list(/datum/material/iron = 400)
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS
|
||||
var/string_attached
|
||||
var/list/sideslist = list("heads","tails")
|
||||
var/cooldown = 0
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user