@@ -2981,14 +2981,14 @@
|
||||
/turf/open/floor/plating,
|
||||
/area/security/main)
|
||||
"afS" = (
|
||||
/obj/machinery/door/airlock/security/glass{
|
||||
name = "Brig EVA Storage";
|
||||
req_access_txt = "3"
|
||||
},
|
||||
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
|
||||
dir = 4
|
||||
},
|
||||
/obj/machinery/door/firedoor,
|
||||
/obj/machinery/door/airlock/security{
|
||||
name = "Brig EVA Storage";
|
||||
req_access_txt = "1"
|
||||
},
|
||||
/turf/open/floor/plasteel/dark,
|
||||
/area/security/brig)
|
||||
"afT" = (
|
||||
@@ -37536,33 +37536,21 @@
|
||||
/area/maintenance/aft)
|
||||
"bKK" = (
|
||||
/obj/effect/decal/cleanable/cobweb/cobweb2,
|
||||
/obj/structure/cable{
|
||||
icon_state = "0-8"
|
||||
},
|
||||
/obj/machinery/power/apc{
|
||||
areastring = "/area/medical/medbay/central";
|
||||
dir = 4;
|
||||
name = "Medbay APC";
|
||||
pixel_x = 24
|
||||
},
|
||||
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
|
||||
/turf/open/floor/plating,
|
||||
/area/maintenance/aft)
|
||||
"bKL" = (
|
||||
/obj/structure/disposalpipe/segment{
|
||||
dir = 10
|
||||
/obj/machinery/power/apc{
|
||||
areastring = "/area/medical/medbay/central";
|
||||
dir = 1;
|
||||
name = "Medbay Central APC";
|
||||
pixel_y = 24
|
||||
},
|
||||
/obj/structure/cable{
|
||||
icon_state = "2-8"
|
||||
icon_state = "0-2"
|
||||
},
|
||||
/obj/structure/cable{
|
||||
icon_state = "4-8"
|
||||
},
|
||||
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
|
||||
dir = 10
|
||||
},
|
||||
/turf/open/floor/plating,
|
||||
/area/maintenance/aft)
|
||||
/turf/open/floor/plasteel/white,
|
||||
/area/medical/medbay/central)
|
||||
"bKM" = (
|
||||
/obj/machinery/atmospherics/components/unary/vent_pump/on{
|
||||
dir = 4
|
||||
@@ -46386,7 +46374,6 @@
|
||||
/obj/effect/turf_decal/bot{
|
||||
dir = 1
|
||||
},
|
||||
/obj/structure/reagent_dispensers/fueltank,
|
||||
/obj/structure/extinguisher_cabinet{
|
||||
pixel_x = -5;
|
||||
pixel_y = 30
|
||||
@@ -46394,6 +46381,7 @@
|
||||
/obj/structure/cable{
|
||||
icon_state = "4-8"
|
||||
},
|
||||
/obj/structure/reagent_dispensers/fueltank/high,
|
||||
/turf/open/floor/plasteel,
|
||||
/area/engine/engineering)
|
||||
"cig" = (
|
||||
@@ -46553,7 +46541,6 @@
|
||||
icon_state = "1-2"
|
||||
},
|
||||
/obj/structure/disposalpipe/segment,
|
||||
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
|
||||
/turf/open/floor/plasteel,
|
||||
/area/maintenance/disposal/incinerator)
|
||||
"ciF" = (
|
||||
@@ -53254,27 +53241,6 @@
|
||||
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
|
||||
/turf/open/floor/plating,
|
||||
/area/maintenance/department/medical/morgue)
|
||||
"cTL" = (
|
||||
/obj/structure/cable{
|
||||
icon_state = "1-2"
|
||||
},
|
||||
/obj/structure/cable{
|
||||
icon_state = "2-4"
|
||||
},
|
||||
/turf/open/floor/plasteel/dark,
|
||||
/area/medical/morgue)
|
||||
"cTM" = (
|
||||
/obj/machinery/power/apc{
|
||||
areastring = "/area/maintenance/department/medical/morgue";
|
||||
dir = 4;
|
||||
name = "Morgue Maintenance APC";
|
||||
pixel_x = 26
|
||||
},
|
||||
/obj/structure/cable{
|
||||
icon_state = "0-8"
|
||||
},
|
||||
/turf/open/floor/plasteel/dark,
|
||||
/area/medical/morgue)
|
||||
"cTO" = (
|
||||
/obj/structure/disposalpipe/segment{
|
||||
dir = 4
|
||||
@@ -55873,7 +55839,6 @@
|
||||
"juy" = (
|
||||
/obj/structure/mopbucket,
|
||||
/obj/item/mop,
|
||||
/obj/item/reagent_containers/spray/cleaner,
|
||||
/turf/open/floor/plating,
|
||||
/area/maintenance/port/fore)
|
||||
"juG" = (
|
||||
@@ -98153,9 +98118,9 @@ cCQ
|
||||
cCS
|
||||
chg
|
||||
cCS
|
||||
bLK
|
||||
bLK
|
||||
bLK
|
||||
bMK
|
||||
bMK
|
||||
bMK
|
||||
gXs
|
||||
aaa
|
||||
aaa
|
||||
@@ -98667,9 +98632,9 @@ aaf
|
||||
bMK
|
||||
chg
|
||||
bMK
|
||||
bLK
|
||||
bLK
|
||||
bLK
|
||||
bMK
|
||||
bMK
|
||||
bMK
|
||||
aaf
|
||||
aoV
|
||||
aoV
|
||||
@@ -99399,8 +99364,8 @@ bfK
|
||||
bfK
|
||||
bfK
|
||||
bof
|
||||
bhh
|
||||
bsx
|
||||
bKL
|
||||
brf
|
||||
btV
|
||||
bvh
|
||||
bwH
|
||||
@@ -99671,7 +99636,7 @@ bDR
|
||||
bDR
|
||||
bIn
|
||||
bJC
|
||||
bKL
|
||||
bUZ
|
||||
bLT
|
||||
bLT
|
||||
bLT
|
||||
@@ -101965,7 +101930,7 @@ bfL
|
||||
bhp
|
||||
biB
|
||||
biB
|
||||
cTL
|
||||
biB
|
||||
bkU
|
||||
bmX
|
||||
bpE
|
||||
@@ -102222,7 +102187,7 @@ bfL
|
||||
bhq
|
||||
bhm
|
||||
bkb
|
||||
cTM
|
||||
bhm
|
||||
bla
|
||||
bmZ
|
||||
bpH
|
||||
|
||||
@@ -21880,7 +21880,7 @@
|
||||
/obj/effect/turf_decal/stripes/line{
|
||||
dir = 4
|
||||
},
|
||||
/obj/structure/reagent_dispensers/fueltank,
|
||||
/obj/structure/reagent_dispensers/fueltank/high,
|
||||
/turf/open/floor/plasteel,
|
||||
/area/engine/secure_construction)
|
||||
"aVY" = (
|
||||
@@ -70916,8 +70916,9 @@
|
||||
/area/science/mixing)
|
||||
"guK" = (
|
||||
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
|
||||
/obj/structure/lattice,
|
||||
/turf/open/space/basic,
|
||||
/area/space)
|
||||
/area/space/nearstation)
|
||||
"gDY" = (
|
||||
/obj/machinery/light,
|
||||
/obj/machinery/atmospherics/pipe/simple/cyan/visible,
|
||||
|
||||
@@ -49390,7 +49390,7 @@
|
||||
},
|
||||
/obj/machinery/door/airlock/security/glass{
|
||||
name = "Security E.V.A. Storage";
|
||||
req_access_txt = "3"
|
||||
req_access_txt = "1"
|
||||
},
|
||||
/obj/effect/turf_decal/stripes/line{
|
||||
dir = 8
|
||||
@@ -81571,12 +81571,12 @@
|
||||
/turf/open/floor/plasteel,
|
||||
/area/engine/storage)
|
||||
"cHt" = (
|
||||
/obj/structure/reagent_dispensers/fueltank,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/obj/machinery/status_display/ai{
|
||||
pixel_y = -32
|
||||
},
|
||||
/obj/effect/turf_decal/bot,
|
||||
/obj/structure/reagent_dispensers/fueltank/high,
|
||||
/turf/open/floor/plasteel,
|
||||
/area/engine/storage)
|
||||
"cHu" = (
|
||||
@@ -110341,8 +110341,8 @@
|
||||
},
|
||||
/obj/effect/turf_decal/stripes/line,
|
||||
/obj/machinery/atmospherics/components/binary/pump/on{
|
||||
name = "Space Loop Out";
|
||||
dir = 4
|
||||
dir = 4;
|
||||
name = "Space Loop Out"
|
||||
},
|
||||
/turf/open/floor/plasteel,
|
||||
/area/science/mixing)
|
||||
|
||||
@@ -14492,7 +14492,6 @@
|
||||
/turf/open/floor/plating,
|
||||
/area/maintenance/starboard)
|
||||
"aym" = (
|
||||
/obj/structure/reagent_dispensers/fueltank,
|
||||
/obj/effect/turf_decal/delivery,
|
||||
/obj/effect/turf_decal/tile/neutral{
|
||||
dir = 1
|
||||
@@ -14503,6 +14502,7 @@
|
||||
/obj/effect/turf_decal/tile/neutral{
|
||||
dir = 8
|
||||
},
|
||||
/obj/structure/reagent_dispensers/fueltank/high,
|
||||
/turf/open/floor/plasteel/dark,
|
||||
/area/engine/engineering)
|
||||
"ayn" = (
|
||||
@@ -85507,8 +85507,8 @@
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/obj/effect/decal/cleanable/cobweb/cobweb2,
|
||||
/obj/machinery/atmospherics/components/binary/pump/on{
|
||||
name = "Space Loop Out";
|
||||
dir = 8
|
||||
dir = 8;
|
||||
name = "Space Loop Out"
|
||||
},
|
||||
/turf/open/floor/plating{
|
||||
icon_state = "panelscorched"
|
||||
|
||||
@@ -53981,8 +53981,8 @@
|
||||
pixel_y = -26
|
||||
},
|
||||
/obj/structure/cable,
|
||||
/obj/structure/reagent_dispensers/fueltank,
|
||||
/obj/effect/turf_decal/bot,
|
||||
/obj/structure/reagent_dispensers/fueltank/high,
|
||||
/turf/open/floor/plasteel,
|
||||
/area/engine/storage_shared)
|
||||
"cvh" = (
|
||||
@@ -67078,12 +67078,12 @@
|
||||
/area/engine/atmos)
|
||||
"kgv" = (
|
||||
/obj/structure/railing{
|
||||
icon_state = "railing";
|
||||
dir = 4
|
||||
dir = 4;
|
||||
icon_state = "railing"
|
||||
},
|
||||
/obj/structure/railing{
|
||||
icon_state = "railing";
|
||||
dir = 8
|
||||
dir = 8;
|
||||
icon_state = "railing"
|
||||
},
|
||||
/turf/open/floor/plasteel/stairs/old,
|
||||
/area/maintenance/department/medical)
|
||||
@@ -71237,12 +71237,12 @@
|
||||
"tcW" = (
|
||||
/obj/structure/stairs/west,
|
||||
/obj/structure/railing{
|
||||
icon_state = "railing";
|
||||
dir = 4
|
||||
dir = 4;
|
||||
icon_state = "railing"
|
||||
},
|
||||
/obj/structure/railing{
|
||||
icon_state = "railing";
|
||||
dir = 8
|
||||
dir = 8;
|
||||
icon_state = "railing"
|
||||
},
|
||||
/turf/open/floor/plating,
|
||||
/area/maintenance/department/medical)
|
||||
|
||||
@@ -4548,7 +4548,7 @@
|
||||
/obj/machinery/door/firedoor,
|
||||
/obj/machinery/door/airlock/security/glass{
|
||||
name = "Security E.V.A. Storage";
|
||||
req_access_txt = "3"
|
||||
req_access_txt = "1"
|
||||
},
|
||||
/obj/structure/cable/yellow{
|
||||
icon_state = "4-8"
|
||||
@@ -15223,7 +15223,6 @@
|
||||
/turf/open/floor/plating,
|
||||
/area/maintenance/starboard/fore)
|
||||
"aCN" = (
|
||||
/obj/structure/reagent_dispensers/fueltank,
|
||||
/obj/item/radio/intercom{
|
||||
name = "Station Intercom (General)";
|
||||
pixel_x = -30
|
||||
@@ -15231,6 +15230,7 @@
|
||||
/obj/effect/turf_decal/bot{
|
||||
dir = 1
|
||||
},
|
||||
/obj/structure/reagent_dispensers/fueltank/high,
|
||||
/turf/open/floor/plasteel{
|
||||
dir = 1
|
||||
},
|
||||
@@ -48921,7 +48921,7 @@
|
||||
/turf/open/floor/plating,
|
||||
/area/maintenance/starboard)
|
||||
"bTi" = (
|
||||
/obj/machinery/vending/wardrobe/atmos_wardrobe,
|
||||
/obj/machinery/portable_atmospherics/canister,
|
||||
/turf/open/floor/plasteel/dark,
|
||||
/area/engine/atmos)
|
||||
"bTk" = (
|
||||
@@ -82905,8 +82905,8 @@
|
||||
/area/medical/morgue)
|
||||
"tID" = (
|
||||
/obj/machinery/atmospherics/components/binary/pump/on{
|
||||
name = "Space Loop Out";
|
||||
dir = 4
|
||||
dir = 4;
|
||||
name = "Space Loop Out"
|
||||
},
|
||||
/turf/open/floor/plasteel/white,
|
||||
/area/science/circuit)
|
||||
@@ -83325,8 +83325,8 @@
|
||||
/area/maintenance/port/aft)
|
||||
"xHA" = (
|
||||
/obj/machinery/atmospherics/components/binary/pump/on{
|
||||
name = "Space Loop In";
|
||||
dir = 8
|
||||
dir = 8;
|
||||
name = "Space Loop In"
|
||||
},
|
||||
/turf/open/floor/plasteel/white,
|
||||
/area/science/circuit)
|
||||
|
||||
@@ -24502,10 +24502,6 @@
|
||||
/obj/effect/turf_decal/loading_area{
|
||||
dir = 1
|
||||
},
|
||||
/obj/effect/turf_decal/stripes/corner,
|
||||
/obj/effect/turf_decal/stripes/corner{
|
||||
dir = 1
|
||||
},
|
||||
/obj/effect/turf_decal/tile/yellow{
|
||||
dir = 1
|
||||
},
|
||||
@@ -25146,13 +25142,13 @@
|
||||
/turf/open/floor/plasteel,
|
||||
/area/engine/engineering)
|
||||
"aNg" = (
|
||||
/obj/structure/reagent_dispensers/fueltank,
|
||||
/obj/structure/sign/warning/nosmoking{
|
||||
pixel_y = -32
|
||||
},
|
||||
/obj/effect/turf_decal/stripes/line{
|
||||
dir = 5
|
||||
},
|
||||
/obj/structure/reagent_dispensers/fueltank/high,
|
||||
/turf/open/floor/plasteel,
|
||||
/area/engine/engineering)
|
||||
"aNh" = (
|
||||
|
||||
@@ -46837,7 +46837,7 @@
|
||||
/obj/effect/turf_decal/tile/yellow{
|
||||
dir = 8
|
||||
},
|
||||
/obj/structure/reagent_dispensers/fueltank,
|
||||
/obj/structure/reagent_dispensers/fueltank/high,
|
||||
/turf/open/floor/plasteel,
|
||||
/area/engine/engineering)
|
||||
"cdL" = (
|
||||
@@ -54462,8 +54462,8 @@
|
||||
/area/maintenance/department/security/brig)
|
||||
"gjv" = (
|
||||
/obj/machinery/atmospherics/components/binary/pump/on{
|
||||
name = "Space Loop In";
|
||||
dir = 1
|
||||
dir = 1;
|
||||
name = "Space Loop In"
|
||||
},
|
||||
/turf/open/floor/plating,
|
||||
/area/maintenance/department/science)
|
||||
|
||||
@@ -14395,7 +14395,6 @@
|
||||
/obj/machinery/light{
|
||||
dir = 1
|
||||
},
|
||||
/obj/structure/reagent_dispensers/fueltank,
|
||||
/obj/machinery/camera{
|
||||
c_tag = "Engineering Access"
|
||||
},
|
||||
@@ -14403,6 +14402,7 @@
|
||||
name = "Station Intercom (General)";
|
||||
pixel_y = 20
|
||||
},
|
||||
/obj/structure/reagent_dispensers/fueltank/high,
|
||||
/turf/open/floor/plasteel/dark/corner{
|
||||
dir = 1
|
||||
},
|
||||
|
||||
@@ -1235,3 +1235,18 @@ GLOBAL_DATUM_INIT(dummySave, /savefile, new("tmp/dummySave.sav")) //Cache of ico
|
||||
var/icon/I = getFlatIcon(thing)
|
||||
return icon2html(I, target, sourceonly = sourceonly)
|
||||
|
||||
/* Gives the result RGB of a RGB string after a matrix transformation. No alpha.
|
||||
* Input: rr, rg, rb, gr, gg, gb, br, bg, bb, cr, cg, cb
|
||||
* Output: RGB string
|
||||
*/
|
||||
/proc/RGBMatrixTransform(list/color, list/cm)
|
||||
ASSERT(cm.len >= 9)
|
||||
if(cm.len < 12) // fill in the rest
|
||||
for(var/i in 1 to (12 - cm.len))
|
||||
cm += 0
|
||||
if(!islist(color))
|
||||
color = ReadRGB(color)
|
||||
color[1] = color[1] * cm[1] + color[2] * cm[2] + color[3] * cm[3] + cm[10] * 255
|
||||
color[2] = color[1] * cm[4] + color[2] * cm[5] + color[3] * cm[6] + cm[11] * 255
|
||||
color[3] = color[1] * cm[7] + color[2] * cm[8] + color[3] * cm[9] + cm[12] * 255
|
||||
return rgb(color[1], color[2], color[3])
|
||||
|
||||
@@ -177,3 +177,9 @@ round(cos_inv_third+sqrt3_sin, 0.001), round(cos_inv_third-sqrt3_sin, 0.001), ro
|
||||
for(x in 1 to 4)
|
||||
output[offset+x] = round(A[offset+1]*B[x] + A[offset+2]*B[x+4] + A[offset+3]*B[x+8] + A[offset+4]*B[x+12]+(y==5?B[x+16]:0), 0.001)
|
||||
return output
|
||||
|
||||
/**
|
||||
* Assembles a color matrix, defaulting to identity
|
||||
*/
|
||||
/proc/rgb_construct_color_matrix(rr = 1, rg, rb, gr, gg = 1, gb, br, bg, bb = 1, cr, cg, cb)
|
||||
return list(rr, rg, rb, gr, gg, gb, br, bg, bb, cr, cg, cb)
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
var/err_file = ""
|
||||
var/static/list/interpreters = list("[MS_WINDOWS]" = "cmd /c", "[UNIX]" = "sh -c")
|
||||
var/interpreter = interpreters["[world.system_type]"]
|
||||
log_subsystem("SHELL", "Executing command [command]")
|
||||
if(interpreter)
|
||||
for(var/seo_id in shelleo_ids)
|
||||
if(!shelleo_ids[seo_id])
|
||||
@@ -36,6 +37,7 @@
|
||||
else
|
||||
CRASH("Operating System: [world.system_type] not supported") // If you encounter this error, you are encouraged to update this proc with support for the new operating system
|
||||
. = list(errorcode, stdout, stderr)
|
||||
log_subsystem("SHELL", "Finished execution: [errorcode], [stdout], [stderr]")
|
||||
#undef SHELLEO_NAME
|
||||
#undef SHELLEO_ERR
|
||||
#undef SHELLEO_OUT
|
||||
|
||||
@@ -388,6 +388,8 @@ Example config:
|
||||
var/list/probabilities = Get(/datum/config_entry/keyed_list/storyteller_weight)
|
||||
var/list/repeated_mode_adjust = Get(/datum/config_entry/number_list/repeated_mode_adjust)
|
||||
var/list/min_player_counts = Get(/datum/config_entry/keyed_list/storyteller_min_players)
|
||||
var/list/storyteller_min_chaos = Get(/datum/config_entry/keyed_list/storyteller_min_chaos)
|
||||
var/list/storyteller_max_chaos = Get(/datum/config_entry/keyed_list/storyteller_max_chaos)
|
||||
for(var/T in storyteller_cache)
|
||||
var/datum/dynamic_storyteller/S = T
|
||||
var/config_tag = initial(S.config_tag)
|
||||
@@ -399,6 +401,13 @@ Example config:
|
||||
continue
|
||||
if(length(GLOB.player_list) < min_players)
|
||||
continue
|
||||
if(!Get(/datum/config_entry/flag/no_storyteller_threat_removal))
|
||||
var/min_chaos = (probabilities in storyteller_min_chaos) ? storyteller_min_chaos[config_tag] : initial(S.min_chaos)
|
||||
var/max_chaos = (probabilities in storyteller_max_chaos) ? storyteller_max_chaos[config_tag] : initial(S.max_chaos)
|
||||
if(SSpersistence.average_dynamic_threat < min_chaos)
|
||||
continue
|
||||
if(SSpersistence.average_dynamic_threat > max_chaos)
|
||||
continue
|
||||
if(SSpersistence.saved_storytellers.len == repeated_mode_adjust.len)
|
||||
var/name = initial(S.name)
|
||||
var/recent_round = min(SSpersistence.saved_storytellers.Find(name),3)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
/datum/config_entry/flag/dynamic_voting
|
||||
|
||||
/datum/config_entry/flag/no_storyteller_threat_removal
|
||||
|
||||
/datum/config_entry/number/dynamic_high_pop_limit
|
||||
config_entry_value = 55
|
||||
min_val = 1
|
||||
@@ -67,6 +69,9 @@
|
||||
/datum/config_entry/number/dynamic_third_rule_high_pop_requirement
|
||||
config_entry_value = 70
|
||||
|
||||
/datum/config_entry/number/dynamic_threat_baseline
|
||||
config_entry_value = 50
|
||||
|
||||
/datum/config_entry/number_list/dynamic_hijack_requirements
|
||||
|
||||
/datum/config_entry/number/dynamic_hijack_high_population_requirement
|
||||
@@ -74,7 +79,7 @@
|
||||
|
||||
/datum/config_entry/number/dynamic_hijack_cost
|
||||
config_entry_value = 5
|
||||
|
||||
|
||||
/datum/config_entry/number/dynamic_glorious_death_cost
|
||||
config_entry_value = 5
|
||||
|
||||
@@ -96,3 +101,11 @@
|
||||
/datum/config_entry/keyed_list/storyteller_min_players
|
||||
key_mode = KEY_MODE_TEXT
|
||||
value_mode = VALUE_MODE_NUM
|
||||
|
||||
/datum/config_entry/keyed_list/storyteller_min_chaos
|
||||
key_mode = KEY_MODE_TEXT
|
||||
value_mode = VALUE_MODE_NUM
|
||||
|
||||
/datum/config_entry/keyed_list/storyteller_max_chaos
|
||||
key_mode = KEY_MODE_TEXT
|
||||
value_mode = VALUE_MODE_NUM
|
||||
|
||||
@@ -98,6 +98,7 @@ SUBSYSTEM_DEF(input)
|
||||
var/client/C = clients[i]
|
||||
C.keyLoop()
|
||||
|
||||
#define NONSENSICAL_VERB "NONSENSICAL_VERB_THAT_DOES_NOTHING"
|
||||
/// *sigh
|
||||
/client/verb/NONSENSICAL_VERB_THAT_DOES_NOTHING()
|
||||
set name = "NONSENSICAL_VERB_THAT_DOES_NOTHING"
|
||||
|
||||
@@ -422,7 +422,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
saved_storytellers[3] = saved_storytellers[2]
|
||||
saved_storytellers[2] = saved_storytellers[1]
|
||||
saved_storytellers[1] = mode.storyteller.name
|
||||
average_dynamic_threat = (mode.threat_average + average_dynamic_threat) / 2
|
||||
average_dynamic_threat = (mode.max_threat + average_dynamic_threat) / 2
|
||||
var/json_file = file("data/RecentStorytellers.json")
|
||||
var/list/file_data = list()
|
||||
file_data["data"] = saved_storytellers + average_dynamic_threat
|
||||
|
||||
@@ -492,7 +492,7 @@ SUBSYSTEM_DEF(vote)
|
||||
if("dynamic")
|
||||
GLOB.master_mode = "dynamic"
|
||||
var/list/probabilities = CONFIG_GET(keyed_list/storyteller_weight)
|
||||
for(var/T in config.storyteller_cache)
|
||||
for(var/T in config.get_runnable_storytellers())
|
||||
var/datum/dynamic_storyteller/S = T
|
||||
var/probability = ((initial(S.config_tag) in probabilities) ? probabilities[initial(S.config_tag)] : initial(S.weight))
|
||||
if(probability > 0)
|
||||
|
||||
@@ -16,6 +16,32 @@
|
||||
to_chat(M, "<span class='warning'>[parent] only accepts machine parts!</span>")
|
||||
return FALSE
|
||||
|
||||
/datum/component/storage/concrete/rped/quick_empty(mob/M)
|
||||
var/atom/A = parent
|
||||
if(!M.canUseStorage() || !A.Adjacent(M) || M.incapacitated())
|
||||
return
|
||||
if(check_locked(null, M, TRUE))
|
||||
return FALSE
|
||||
A.add_fingerprint(M)
|
||||
var/list/things = contents()
|
||||
var/lowest_rating = INFINITY
|
||||
for(var/obj/item/B in things)
|
||||
if(B.get_part_rating() < lowest_rating)
|
||||
lowest_rating = B.get_part_rating()
|
||||
for(var/obj/item/B in things)
|
||||
if(B.get_part_rating() > lowest_rating)
|
||||
things.Remove(B)
|
||||
if(lowest_rating == INFINITY)
|
||||
to_chat(M, "<span class='notice'>There's no parts to dump out from [parent].</span>")
|
||||
return
|
||||
to_chat(M, "<span class='notice'>You start dumping out tier/cell rating [lowest_rating] parts from [parent].</span>")
|
||||
var/turf/T = get_turf(A)
|
||||
var/datum/progressbar/progress = new(M, length(things), T)
|
||||
while (do_after(M, 10, TRUE, T, FALSE, CALLBACK(src, .proc/mass_remove_from_storage, T, things, progress)))
|
||||
stoplag(1)
|
||||
qdel(progress)
|
||||
A.do_squish(0.8, 1.2)
|
||||
|
||||
/datum/component/storage/concrete/bluespace/rped
|
||||
collection_mode = COLLECT_EVERYTHING
|
||||
allow_quick_gather = TRUE
|
||||
@@ -33,5 +59,29 @@
|
||||
to_chat(M, "<span class='warning'>[parent] only accepts machine parts!</span>")
|
||||
return FALSE
|
||||
|
||||
/datum/component/storage/concrete/cyborg/rped
|
||||
max_items = 150
|
||||
|
||||
/datum/component/storage/concrete/bluespace/rped/quick_empty(mob/M)
|
||||
var/atom/A = parent
|
||||
if(!M.canUseStorage() || !A.Adjacent(M) || M.incapacitated())
|
||||
return
|
||||
if(check_locked(null, M, TRUE))
|
||||
return FALSE
|
||||
A.add_fingerprint(M)
|
||||
var/list/things = contents()
|
||||
var/lowest_rating = INFINITY
|
||||
for(var/obj/item/B in things)
|
||||
if(B.get_part_rating() < lowest_rating)
|
||||
lowest_rating = B.get_part_rating()
|
||||
for(var/obj/item/B in things)
|
||||
if(B.get_part_rating() > lowest_rating)
|
||||
things.Remove(B)
|
||||
if(lowest_rating == INFINITY)
|
||||
to_chat(M, "<span class='notice'>There's no parts to dump out from [parent].</span>")
|
||||
return
|
||||
to_chat(M, "<span class='notice'>You start dumping out tier/cell rating [lowest_rating] parts from [parent].</span>")
|
||||
var/turf/T = get_turf(A)
|
||||
var/datum/progressbar/progress = new(M, length(things), T)
|
||||
while (do_after(M, 10, TRUE, T, FALSE, CALLBACK(src, .proc/mass_remove_from_storage, T, things, progress)))
|
||||
stoplag(1)
|
||||
qdel(progress)
|
||||
A.do_squish(0.8, 1.2)
|
||||
|
||||
@@ -134,6 +134,28 @@
|
||||
return BULLET_ACT_FORCE_PIERCE
|
||||
return BULLET_ACT_HIT
|
||||
|
||||
/datum/block_parry_data/sleeping_carp
|
||||
parry_time_windup = 0
|
||||
parry_time_active = 25
|
||||
parry_time_spindown = 0
|
||||
// we want to signal to players the most dangerous phase, the time when automatic counterattack is a thing.
|
||||
parry_time_windup_visual_override = 1
|
||||
parry_time_active_visual_override = 3
|
||||
parry_time_spindown_visual_override = 12
|
||||
parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK //can attack while
|
||||
parry_time_perfect = 2.5 // first ds isn't perfect
|
||||
parry_time_perfect_leeway = 1.5
|
||||
parry_imperfect_falloff_percent = 5
|
||||
parry_efficiency_to_counterattack = 100
|
||||
parry_efficiency_considered_successful = 65 // VERY generous
|
||||
parry_efficiency_perfect = 100
|
||||
parry_failed_stagger_duration = 4 SECONDS
|
||||
parry_cooldown = 0.5 SECONDS
|
||||
|
||||
/mob/living/carbon/human/UseStaminaBuffer(amount, warn = FALSE, considered_action = TRUE)
|
||||
amount *= physiology? physiology.stamina_buffer_mod : 1
|
||||
return ..()
|
||||
|
||||
/datum/martial_art/the_sleeping_carp/teach(mob/living/carbon/human/H, make_temporary = FALSE)
|
||||
. = ..()
|
||||
if(!.)
|
||||
@@ -144,12 +166,12 @@
|
||||
ADD_TRAIT(H, TRAIT_TASED_RESISTANCE, SLEEPING_CARP_TRAIT)
|
||||
H.physiology.brute_mod *= 0.4 //brute is really not gonna cut it
|
||||
H.physiology.burn_mod *= 0.7 //burn is distinctly more useful against them than brute but they're still resistant
|
||||
H.physiology.stamina_mod *= 0.5 //You take less stamina damage overall, but you do not reduce the damage from stun batons
|
||||
H.physiology.stamina_mod *= 0.4 //You take less stamina damage overall, but you do not reduce the damage from stun batons as much
|
||||
H.physiology.stun_mod *= 0.3 //for those rare stuns
|
||||
H.physiology.pressure_mod *= 0.3 //go hang out with carp
|
||||
H.physiology.cold_mod *= 0.3 //cold mods are different to burn mods, they do stack however
|
||||
H.physiology.heat_mod *= 2 //this is mostly so sleeping carp has a viable weakness. Cooking them alive. Setting them on fire and heating them will be their biggest weakness. The reason for this is....filet jokes.
|
||||
|
||||
H.physiology.stamina_buffer_mod *= 0.75 //to help with some stamina
|
||||
H.faction |= "carp" //:D
|
||||
|
||||
/datum/martial_art/the_sleeping_carp/on_remove(mob/living/carbon/human/H)
|
||||
@@ -165,7 +187,7 @@
|
||||
H.physiology.pressure_mod = initial(H.physiology.pressure_mod) //no more carpies
|
||||
H.physiology.cold_mod = initial(H.physiology.cold_mod)
|
||||
H.physiology.heat_mod = initial(H.physiology.heat_mod)
|
||||
|
||||
H.physiology.stamina_buffer_mod = initial(H.physiology.stamina_buffer_mod)
|
||||
H.faction -= "carp" //:(
|
||||
|
||||
/mob/living/carbon/human/proc/sleeping_carp_help()
|
||||
|
||||
@@ -64,6 +64,8 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
var/threat_average_weight = 0
|
||||
/// Last time a threat average sample was taken. Used for weighting the rolling average.
|
||||
var/last_threat_sample_time = 0
|
||||
/// Maximum threat recorded so far, for cross-round chaos adjustment.
|
||||
var/max_threat = 0
|
||||
/// Things that cause a rolling threat adjustment to be displayed at roundend.
|
||||
var/list/threat_tallies = list()
|
||||
/// Running information about the threat. Can store text or datum entries.
|
||||
@@ -145,6 +147,7 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
third_rule_req = list(101, 101, 101, 101, 101, 100, 90, 80, 70, 60)
|
||||
high_pop_second_rule_req = CONFIG_GET(number/dynamic_second_rule_high_pop_requirement)
|
||||
high_pop_third_rule_req = CONFIG_GET(number/dynamic_third_rule_high_pop_requirement)
|
||||
added_threat = CONFIG_GET(number/dynamic_threat_baseline)
|
||||
GLOB.dynamic_high_pop_limit = CONFIG_GET(number/dynamic_high_pop_limit)
|
||||
GLOB.dynamic_latejoin_delay_min = CONFIG_GET(number/dynamic_latejoin_delay_min)*600
|
||||
GLOB.dynamic_latejoin_delay_max = CONFIG_GET(number/dynamic_latejoin_delay_max)*600
|
||||
@@ -415,7 +418,7 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
/datum/game_mode/dynamic/post_setup(report)
|
||||
update_playercounts()
|
||||
if(minor_ruleset_start)
|
||||
addtimer(CALLBACK(src, /datum/game_mode/dynamic/.proc/minor_roundstart),rand(1 MINUTES,5 MINUTES))
|
||||
addtimer(CALLBACK(src, /datum/game_mode/dynamic/.proc/minor_roundstart),rand(1 MINUTES,3 MINUTES))
|
||||
else
|
||||
for(var/datum/dynamic_ruleset/roundstart/rule in executed_rules)
|
||||
addtimer(CALLBACK(src, /datum/game_mode/dynamic/.proc/execute_roundstart_rule, rule), rule.delay)
|
||||
@@ -439,7 +442,7 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
potential_minor_rulesets -= rule
|
||||
update_playercounts()
|
||||
iterations++
|
||||
message_admins("Minor antag roundstart rolls completed, with [num_rulesets_executed] antags or antag teams made.")
|
||||
message_admins("Minor antag roundstart rolls completed, with [iterations] rolls done and [num_rulesets_executed] antags or antag teams made.")
|
||||
log_game("DYNAMIC: Minor antag roundstart made [num_rulesets_executed] antags or antag teams.")
|
||||
|
||||
|
||||
@@ -612,6 +615,7 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
latejoin_rules = remove_from_list(latejoin_rules, rule.type)
|
||||
else if(rule.ruletype == "Midround")
|
||||
midround_rules = remove_from_list(midround_rules, rule.type)
|
||||
message_admins("DYNAMIC: Picked [rule]; executing soon...")
|
||||
addtimer(CALLBACK(src, /datum/game_mode/dynamic/.proc/execute_midround_latejoin_rule, rule), rule.delay)
|
||||
return TRUE
|
||||
|
||||
@@ -663,6 +667,7 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
/datum/game_mode/dynamic/proc/execute_midround_latejoin_rule(sent_rule)
|
||||
var/datum/dynamic_ruleset/rule = sent_rule
|
||||
if (rule.execute())
|
||||
message_admins("DYNAMIC: Injected a [rule.ruletype == "latejoin" ? "latejoin" : "midround"] ruleset [rule.name].")
|
||||
log_game("DYNAMIC: Injected a [rule.ruletype == "latejoin" ? "latejoin" : "midround"] ruleset [rule.name].")
|
||||
log_threat("[rule.ruletype] [rule.name] added [rule.cost]", verbose = TRUE)
|
||||
if(rule.flags & HIGHLANDER_RULESET)
|
||||
@@ -741,6 +746,7 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
|
||||
if(!M.voluntary_ghosted)
|
||||
current_players[CURRENT_DEAD_PLAYERS].Add(M) // Players who actually died (and admins who ghosted, would be nice to avoid counting them somehow)
|
||||
threat = storyteller.calculate_threat() + added_threat
|
||||
max_threat = max(max_threat,threat)
|
||||
if(threat_average_weight)
|
||||
var/cur_sample_weight = world.time - last_threat_sample_time
|
||||
threat_average = ((threat_average * threat_average_weight) + (threat * cur_sample_weight)) / (threat_average_weight + cur_sample_weight)
|
||||
|
||||
@@ -48,6 +48,9 @@
|
||||
if (!M.client) // Are they connected?
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
if(M.client.prefs && M.client.prefs.toggles & MIDROUND_ANTAG)
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
if(!mode.check_age(M.client, minimum_required_age))
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
|
||||
@@ -1,3 +1,46 @@
|
||||
/datum/dynamic_ruleset/minor/proc/trim_list(list/L = list())
|
||||
var/list/trimmed_list = L.Copy()
|
||||
for(var/mob/M in trimmed_list)
|
||||
if (!ishuman(M))
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
if (HAS_TRAIT(M, TRAIT_NO_MIDROUND_ANTAG))
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
if (!M.client) // Are they connected?
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
if(!mode.check_age(M.client, minimum_required_age))
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
if(antag_flag_override)
|
||||
if(!(antag_flag_override in M.client.prefs.be_special) || jobban_isbanned(M.ckey, antag_flag_override))
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
else
|
||||
if(!(antag_flag in M.client.prefs.be_special) || jobban_isbanned(M.ckey, antag_flag))
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
if (M.mind)
|
||||
if ((M.mind.assigned_role in GLOB.exp_specialmap[EXP_TYPE_SPECIAL])) // Are they playing a ghost role?
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
if (M.mind.assigned_role in restricted_roles) // Does their job allow it?
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
if ((exclusive_roles.len > 0) && !(M.mind.assigned_role in exclusive_roles)) // Is the rule exclusive to their job?
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
return trimmed_list
|
||||
|
||||
/datum/dynamic_ruleset/minor/trim_candidates()
|
||||
//
|
||||
// All you need to know is that here, the candidates list contains 4 lists itself, indexed with the following defines:
|
||||
// Candidates = list(CURRENT_LIVING_PLAYERS, CURRENT_LIVING_ANTAGS, CURRENT_DEAD_PLAYERS, CURRENT_OBSERVERS)
|
||||
// So for example you can get the list of all current dead players with var/list/dead_players = candidates[CURRENT_DEAD_PLAYERS]
|
||||
// Make sure to properly typecheck the mobs in those lists, as the dead_players list could contain ghosts, or dead players still in their bodies.
|
||||
// We're still gonna trim the obvious (mobs without clients, jobbanned players, etc)
|
||||
candidates = trim_list(mode.current_players[CURRENT_LIVING_PLAYERS])
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
/datum/dynamic_ruleset/roundstart/traitor
|
||||
name = "Traitors"
|
||||
config_tag = "traitor"
|
||||
persistent = TRUE
|
||||
antag_flag = ROLE_TRAITOR
|
||||
antag_datum = /datum/antagonist/traitor/
|
||||
minimum_required_age = 0
|
||||
@@ -34,15 +33,6 @@
|
||||
M.mind.restricted_roles = restricted_roles
|
||||
return TRUE
|
||||
|
||||
/datum/dynamic_ruleset/roundstart/traitor/rule_process()
|
||||
if (autotraitor_cooldown > 0)
|
||||
autotraitor_cooldown--
|
||||
else
|
||||
autotraitor_cooldown = 450 // 15 minutes
|
||||
message_admins("Checking if we can turn someone into a traitor.")
|
||||
log_game("DYNAMIC: Checking if we can turn someone into a traitor.")
|
||||
mode.picking_specific_rule(/datum/dynamic_ruleset/midround/autotraitor)
|
||||
|
||||
//////////////////////////////////////////
|
||||
// //
|
||||
// BLOOD BROTHERS //
|
||||
|
||||
@@ -15,10 +15,13 @@
|
||||
*/
|
||||
var/flags = 0
|
||||
var/dead_player_weight = 1 // How much dead players matter for threat calculation
|
||||
var/weight = 3 // Weights for randomly picking storyteller. Multiplied by score after voting.
|
||||
var/weight = 0 // Weights for randomly picking storyteller. Multiplied by score after voting.
|
||||
var/min_chaos = -1000 // Won't show up if recent rounds have been below this chaotic on average
|
||||
var/max_chaos = 1000 // Won't show up if recent rounds have been above this chaotic on average
|
||||
var/event_frequency_lower = 6 MINUTES // How rare events will be, at least.
|
||||
var/event_frequency_upper = 20 MINUTES // How rare events will be, at most.
|
||||
var/min_players = -1 // How many players are required for this one to start.
|
||||
var/soft_antag_ratio_cap = 4 // how many players-per-antag there should be
|
||||
var/datum/game_mode/dynamic/mode = null // Cached as soon as it's made, by dynamic.
|
||||
|
||||
/**
|
||||
@@ -101,8 +104,10 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
|
||||
/datum/dynamic_storyteller/proc/should_inject_antag(dry_run = FALSE)
|
||||
if(mode.forced_injection)
|
||||
mode.forced_injection = !dry_run
|
||||
mode.forced_injection = dry_run
|
||||
return TRUE
|
||||
if(mode.current_players[CURRENT_LIVING_PLAYERS].len < (mode.current_players[CURRENT_LIVING_ANTAGS].len * soft_antag_ratio_cap))
|
||||
return FALSE
|
||||
return mode.threat < mode.threat_level
|
||||
|
||||
/datum/dynamic_storyteller/proc/roundstart_draft()
|
||||
@@ -126,11 +131,10 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
|
||||
/datum/dynamic_storyteller/proc/minor_rule_draft()
|
||||
var/list/drafted_rules = list()
|
||||
for (var/datum/dynamic_ruleset/minor/rule in mode.minor_rules)
|
||||
for (var/datum/dynamic_ruleset/rule in mode.minor_rules)
|
||||
if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level))
|
||||
rule.candidates = mode.candidates.Copy()
|
||||
rule.trim_candidates()
|
||||
if (rule.ready() && rule.candidates.len > 0)
|
||||
if (rule.ready())
|
||||
var/property_weight = 0
|
||||
for(var/property in property_weights)
|
||||
if(property in rule.property_weights) // just treat it as 0 if it's not in there
|
||||
@@ -213,6 +217,8 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
weight = 1
|
||||
event_frequency_lower = 2 MINUTES
|
||||
event_frequency_upper = 10 MINUTES
|
||||
max_chaos = 50
|
||||
soft_antag_ratio_cap = 1
|
||||
flags = WAROPS_ALWAYS_ALLOWED | FORCE_IF_WON
|
||||
min_players = 30
|
||||
var/refund_cooldown = 0
|
||||
@@ -235,12 +241,13 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
desc = "Modes where the crew must band together. Nukies, xenos, blob. Only one antag threat at once."
|
||||
curve_centre = 2
|
||||
curve_width = 1.5
|
||||
weight = 2
|
||||
weight = 4
|
||||
max_chaos = 75
|
||||
min_players = 20
|
||||
flags = WAROPS_ALWAYS_ALLOWED | USE_PREV_ROUND_WEIGHTS
|
||||
property_weights = list("valid" = 3, "trust" = 5)
|
||||
|
||||
/datum/dynamic_storyteller/chaotic/minor_start_chance()
|
||||
/datum/dynamic_storyteller/team/minor_start_chance()
|
||||
return 0
|
||||
|
||||
/datum/dynamic_storyteller/team/should_inject_antag(dry_run = FALSE)
|
||||
@@ -256,13 +263,15 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
flags = WAROPS_ALWAYS_ALLOWED
|
||||
property_weights = list("valid" = 1, "conversion" = 20)
|
||||
|
||||
/datum/dynamic_storyteller/chaotic/minor_start_chance()
|
||||
/datum/dynamic_storyteller/conversion/minor_start_chance()
|
||||
return 0
|
||||
|
||||
/datum/dynamic_storyteller/random
|
||||
name = "Random"
|
||||
config_tag = "random"
|
||||
weight = 1
|
||||
max_chaos = 60
|
||||
soft_antag_ratio_cap = 1
|
||||
desc = "No weighting at all; every ruleset has the same chance of happening. Cooldowns vary wildly. As random as it gets."
|
||||
|
||||
/datum/dynamic_storyteller/random/on_start()
|
||||
@@ -275,7 +284,7 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
/datum/dynamic_storyteller/random/should_inject_antag()
|
||||
return prob(50)
|
||||
|
||||
/datum/dynamic_storyteller/chaotic/minor_start_chance()
|
||||
/datum/dynamic_storyteller/random/minor_start_chance()
|
||||
return 20
|
||||
|
||||
/datum/dynamic_storyteller/random/roundstart_draft()
|
||||
@@ -331,7 +340,7 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
name = "Story"
|
||||
config_tag = "story"
|
||||
desc = "Antags with options for loadouts and gimmicks. Traitor, wizard, nukies."
|
||||
weight = 2
|
||||
weight = 4
|
||||
curve_width = 2
|
||||
flags = USE_PREV_ROUND_WEIGHTS
|
||||
property_weights = list("story_potential" = 2)
|
||||
@@ -339,6 +348,7 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
/datum/dynamic_storyteller/classic
|
||||
name = "Classic"
|
||||
config_tag = "classic"
|
||||
weight = 8
|
||||
desc = "No special antagonist weights. Good variety, but not like random. Uses your chaos preference to weight."
|
||||
flags = USE_PREF_WEIGHTS | USE_PREV_ROUND_WEIGHTS
|
||||
|
||||
@@ -346,7 +356,7 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
name = "Intrigue"
|
||||
config_tag = "intrigue"
|
||||
desc = "Antags that instill distrust in the crew. Traitors, bloodsuckers."
|
||||
weight = 2
|
||||
weight = 4
|
||||
curve_width = 2
|
||||
dead_player_weight = 2
|
||||
flags = USE_PREV_ROUND_WEIGHTS
|
||||
@@ -358,8 +368,8 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
/datum/dynamic_storyteller/grabbag
|
||||
name = "Grab Bag"
|
||||
config_tag = "grabbag"
|
||||
desc = "Crew antags (e.g. traitor, changeling, bloodsucker, heretic) only, all mixed together."
|
||||
weight = 2
|
||||
desc = "Crew antags (e.g. traitor, changeling, bloodsucker, heretic) only at round start, all mixed together."
|
||||
weight = 4
|
||||
flags = USE_PREF_WEIGHTS | USE_PREV_ROUND_WEIGHTS
|
||||
|
||||
/datum/dynamic_storyteller/grabbag/minor_start_chance()
|
||||
@@ -372,12 +382,14 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
curve_centre = -3
|
||||
curve_width = 0.5
|
||||
flags = NO_ASSASSIN
|
||||
weight = 1
|
||||
min_chaos = 30
|
||||
weight = 3
|
||||
dead_player_weight = 5
|
||||
soft_antag_ratio_cap = 8
|
||||
property_weights = list("extended" = 2, "chaos" = -1, "valid" = -1, "conversion" = -10)
|
||||
|
||||
/datum/dynamic_storyteller/liteextended/minor_start_chance()
|
||||
return 100
|
||||
return 90
|
||||
|
||||
/datum/dynamic_storyteller/no_antag
|
||||
name = "Extended"
|
||||
@@ -385,6 +397,7 @@ Property weights are added to the config weight of the ruleset. They are:
|
||||
desc = "No standard antags."
|
||||
curve_centre = -5
|
||||
curve_width = 0.5
|
||||
min_chaos = 40
|
||||
flags = NO_ASSASSIN | FORCE_IF_WON
|
||||
weight = 1
|
||||
property_weights = list("extended" = 2)
|
||||
|
||||
@@ -46,17 +46,17 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
|
||||
var/startx
|
||||
switch(startSide)
|
||||
if(NORTH)
|
||||
starty = world.maxy-(TRANSITIONEDGE+1)
|
||||
startx = rand((TRANSITIONEDGE+1), world.maxx-(TRANSITIONEDGE+1))
|
||||
starty = world.maxy-(TRANSITIONEDGE+2)
|
||||
startx = rand((TRANSITIONEDGE+2), world.maxx-(TRANSITIONEDGE+2))
|
||||
if(EAST)
|
||||
starty = rand((TRANSITIONEDGE+1),world.maxy-(TRANSITIONEDGE+1))
|
||||
startx = world.maxx-(TRANSITIONEDGE+1)
|
||||
starty = rand((TRANSITIONEDGE+2),world.maxy-(TRANSITIONEDGE+2))
|
||||
startx = world.maxx-(TRANSITIONEDGE+2)
|
||||
if(SOUTH)
|
||||
starty = (TRANSITIONEDGE+1)
|
||||
startx = rand((TRANSITIONEDGE+1), world.maxx-(TRANSITIONEDGE+1))
|
||||
starty = (TRANSITIONEDGE+2)
|
||||
startx = rand((TRANSITIONEDGE+2), world.maxx-(TRANSITIONEDGE+2))
|
||||
if(WEST)
|
||||
starty = rand((TRANSITIONEDGE+1), world.maxy-(TRANSITIONEDGE+1))
|
||||
startx = (TRANSITIONEDGE+1)
|
||||
starty = rand((TRANSITIONEDGE+2), world.maxy-(TRANSITIONEDGE+2))
|
||||
startx = (TRANSITIONEDGE+2)
|
||||
. = locate(startx, starty, Z)
|
||||
|
||||
/proc/spaceDebrisFinishLoc(startSide, Z)
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
/obj/machinery/gear_painter
|
||||
name = "\improper Color Mate"
|
||||
desc = "A machine to give your apparel a fresh new color! Recommended to use with white items for best results."
|
||||
icon = 'icons/obj/vending.dmi'
|
||||
icon_state = "colormate"
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
circuit = /obj/item/circuitboard/machine/colormate
|
||||
var/obj/item/inserted
|
||||
var/activecolor = "#FFFFFF"
|
||||
var/list/color_matrix_last
|
||||
var/matrix_mode = FALSE
|
||||
/// Minimum lightness for normal mode
|
||||
var/minimum_normal_lightness = 50
|
||||
/// Minimum lightness for matrix mode, tested using 4 test colors of full red, green, blue, white.
|
||||
var/minimum_matrix_lightness = 75
|
||||
/// Minimum matrix tests that must pass for something to be considered a valid color (see above)
|
||||
var/minimum_matrix_tests = 2
|
||||
var/list/allowed_types = list(
|
||||
/obj/item/clothing,
|
||||
/obj/item/storage/backpack,
|
||||
/obj/item/storage/belt
|
||||
)
|
||||
|
||||
/obj/machinery/gear_painter/Initialize(mapload)
|
||||
. = ..()
|
||||
color_matrix_last = list(
|
||||
1, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 1,
|
||||
0, 0, 0
|
||||
)
|
||||
|
||||
/obj/machinery/gear_painter/update_icon_state()
|
||||
if(panel_open)
|
||||
icon_state = "colormate_open"
|
||||
else if(!is_operational())
|
||||
icon_state = "colormate_off"
|
||||
else if(inserted)
|
||||
icon_state = "colormate_active"
|
||||
else
|
||||
icon_state = "colormate"
|
||||
|
||||
/obj/machinery/gear_painter/Destroy()
|
||||
inserted.forceMove(drop_location())
|
||||
return ..()
|
||||
|
||||
/obj/machinery/gear_painter/attackby(obj/item/I, mob/living/user)
|
||||
if(inserted)
|
||||
to_chat(user, "<span class='warning'>The machine is already loaded.</span>")
|
||||
return
|
||||
if(default_deconstruction_screwdriver(user, "colormate_open", "colormate", I))
|
||||
return
|
||||
if(default_deconstruction_crowbar(I))
|
||||
return
|
||||
if(default_unfasten_wrench(user, I, 40))
|
||||
return
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
return ..()
|
||||
|
||||
if(is_type_in_list(I, allowed_types) && is_operational())
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
to_chat(user, "<span class='warning'>[I] is stuck to your hand!</span>")
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] inserts [I] into [src]'s receptable.</span>")
|
||||
|
||||
inserted = I
|
||||
update_icon()
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/gear_painter/AllowDrop()
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/gear_painter/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.CanReach(src))
|
||||
return
|
||||
if(!inserted)
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You remove [inserted] from [src]")
|
||||
inserted.forceMove(drop_location())
|
||||
inserted = null
|
||||
update_icon()
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/gear_painter/ui_interact(mob/user)
|
||||
if(!is_operational())
|
||||
return
|
||||
user.set_machine(src)
|
||||
var/list/dat = list("<TITLE>Color Mate Control Panel</TITLE><BR>")
|
||||
if(!inserted)
|
||||
dat += "No item inserted."
|
||||
else
|
||||
dat += "Item inserted: [inserted]<HR>"
|
||||
dat += "<a href='?src=[REF(src)];toggle_matrix_mode=1'>Matrix mode: [matrix_mode? "On" : "Off"]</a>"
|
||||
if(!matrix_mode)
|
||||
dat += "<A href='?src=\ref[src];select=1'>Select new color.</A><BR>"
|
||||
dat += "Color: <font color='[activecolor]'>⚫</font>"
|
||||
dat += "<A href='?src=\ref[src];paint=1'>Apply new color.</A><BR><BR>"
|
||||
else
|
||||
// POGGERS
|
||||
#define MATRIX_FIELD(field, default) "<b><label for='[##field]'>[##field]</label></b> <input type='number' step='0.001' name='[field]' value='[default]'>"
|
||||
dat += "<br><form name='matrix paint' action='?src=[REF(src)]'>"
|
||||
dat += "<input type='hidden' name='src' value='[REF(src)]'>"
|
||||
dat += "<input type='hidden' name='matrix_paint' value='1'"
|
||||
dat += "<br><br>"
|
||||
dat += MATRIX_FIELD("rr", color_matrix_last[1])
|
||||
dat += MATRIX_FIELD("rg", color_matrix_last[2])
|
||||
dat += MATRIX_FIELD("rb", color_matrix_last[3])
|
||||
dat += "<br><br>"
|
||||
dat += MATRIX_FIELD("gr", color_matrix_last[4])
|
||||
dat += MATRIX_FIELD("gg", color_matrix_last[5])
|
||||
dat += MATRIX_FIELD("gb", color_matrix_last[6])
|
||||
dat += "<br><br>"
|
||||
dat += MATRIX_FIELD("br", color_matrix_last[7])
|
||||
dat += MATRIX_FIELD("bg", color_matrix_last[8])
|
||||
dat += MATRIX_FIELD("bb", color_matrix_last[9])
|
||||
dat += "<br><br>"
|
||||
dat += MATRIX_FIELD("cr", color_matrix_last[10])
|
||||
dat += MATRIX_FIELD("cg", color_matrix_last[11])
|
||||
dat += MATRIX_FIELD("cb", color_matrix_last[12])
|
||||
dat += "<br><br>"
|
||||
dat += "<input type='submit' value='Matrix Paint'>"
|
||||
dat += "</form><br>"
|
||||
#undef MATRIX_FIELD
|
||||
dat += "<A href='?src=\ref[src];clear=1'>Remove paintjob.</A><BR><BR>"
|
||||
dat += "<A href='?src=\ref[src];eject=1'>Eject item.</A><BR><BR>"
|
||||
|
||||
var/datum/browser/menu = new(user, "colormate","Color Mate Control Panel", 800, 600, src)
|
||||
menu.set_content(dat.Join(""))
|
||||
menu.open()
|
||||
|
||||
/obj/machinery/gear_painter/Topic(href, href_list)
|
||||
if((. = ..()))
|
||||
return
|
||||
|
||||
add_fingerprint(usr)
|
||||
|
||||
if(href_list["close"])
|
||||
usr << browse(null, "window=colormate")
|
||||
return
|
||||
|
||||
if(href_list["select"])
|
||||
var/newcolor = input(usr, "Choose a color.", "", activecolor) as color|null
|
||||
if(newcolor)
|
||||
activecolor = newcolor
|
||||
updateUsrDialog()
|
||||
|
||||
if(href_list["paint"])
|
||||
if(!inserted)
|
||||
return
|
||||
if(!check_valid_color(activecolor, usr))
|
||||
return
|
||||
inserted.add_atom_colour(activecolor, FIXED_COLOUR_PRIORITY)
|
||||
playsound(src, 'sound/effects/spray3.ogg', 50, 1)
|
||||
updateUsrDialog()
|
||||
|
||||
if(href_list["toggle_matrix_mode"])
|
||||
matrix_mode = !matrix_mode
|
||||
updateUsrDialog()
|
||||
|
||||
if(href_list["matrix_paint"])
|
||||
if(!inserted)
|
||||
return
|
||||
// assemble matrix
|
||||
var/list/cm = rgb_construct_color_matrix(
|
||||
text2num(href_list["rr"]),
|
||||
text2num(href_list["rg"]),
|
||||
text2num(href_list["rb"]),
|
||||
text2num(href_list["gr"]),
|
||||
text2num(href_list["gg"]),
|
||||
text2num(href_list["gb"]),
|
||||
text2num(href_list["br"]),
|
||||
text2num(href_list["bg"]),
|
||||
text2num(href_list["bb"]),
|
||||
text2num(href_list["cr"]),
|
||||
text2num(href_list["cg"]),
|
||||
text2num(href_list["cb"])
|
||||
)
|
||||
color_matrix_last = cm.Copy()
|
||||
if(!check_valid_color(cm, usr))
|
||||
return
|
||||
inserted.add_atom_colour(cm, FIXED_COLOUR_PRIORITY)
|
||||
playsound(src, 'sound/effects/spray3.ogg', 50, 1)
|
||||
updateUsrDialog()
|
||||
|
||||
if(href_list["clear"])
|
||||
if(!inserted)
|
||||
return
|
||||
inserted.remove_atom_colour(FIXED_COLOUR_PRIORITY)
|
||||
playsound(src, 'sound/effects/spray3.ogg', 50, 1)
|
||||
updateUsrDialog()
|
||||
|
||||
if(href_list["eject"])
|
||||
if(!inserted)
|
||||
return
|
||||
inserted.forceMove(drop_location())
|
||||
inserted = null
|
||||
update_icon()
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/gear_painter/proc/check_valid_color(list/cm, mob/user)
|
||||
if(!islist(cm)) // normal
|
||||
var/list/HSV = ReadHSV(RGBtoHSV(cm))
|
||||
if(HSV[3] < minimum_normal_lightness)
|
||||
to_chat(user, "<span class='warning'>[cm] is far too dark (min lightness [minimum_normal_lightness]!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
else // matrix
|
||||
// We test using full red, green, blue, and white
|
||||
// A predefined number of them must pass to be considered valid
|
||||
var/passed = 0
|
||||
#define COLORTEST(thestring, thematrix) passed += (ReadHSV(RGBtoHSV(RGBMatrixTransform(thestring, thematrix)))[3] >= minimum_matrix_lightness)
|
||||
COLORTEST("FF0000", cm)
|
||||
COLORTEST("00FF00", cm)
|
||||
COLORTEST("0000FF", cm)
|
||||
COLORTEST("FFFFFF", cm)
|
||||
#undef COLORTEST
|
||||
if(passed < minimum_matrix_tests)
|
||||
to_chat(user, "<span class='warning'>[english_list(color)] is not allowed (pased [passed] out of 4, minimum [minimum_matrix_tests], minimum lightness [minimum_matrix_lightness]).</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
@@ -24,19 +24,24 @@
|
||||
var/selected_category
|
||||
var/screen = 1
|
||||
var/list/categories = list(
|
||||
"human",
|
||||
"lizard",
|
||||
"fly",
|
||||
"insect",
|
||||
"plasmaman",
|
||||
"mammal",
|
||||
"xeno",
|
||||
"other"
|
||||
"human" = /datum/species/human,
|
||||
"lizard" = /datum/species/lizard,
|
||||
"mammal" = /datum/species/mammal,
|
||||
"insect" = /datum/species/insect,
|
||||
"fly" = /datum/species/fly,
|
||||
"plasmaman" = /datum/species/plasmaman,
|
||||
"xeno" = /datum/species/xeno,
|
||||
"other" = /datum/species,
|
||||
)
|
||||
var/list/stored_species = list()
|
||||
var/obj/item/disk/data/dna_disk
|
||||
|
||||
/obj/machinery/limbgrower/Initialize()
|
||||
create_reagents(100, OPENCONTAINER)
|
||||
stored_research = new /datum/techweb/specialized/autounlocking/limbgrower
|
||||
for(var/i in categories)
|
||||
var/species = categories[i]
|
||||
stored_species[i] = new species()
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/limbgrower/ui_interact(mob/user)
|
||||
@@ -64,8 +69,8 @@
|
||||
..()
|
||||
|
||||
/obj/machinery/limbgrower/attackby(obj/item/O, mob/user, params)
|
||||
if (busy)
|
||||
to_chat(user, "<span class=\"alert\">The Limb Grower is busy. Please wait for completion of previous operation.</span>")
|
||||
if(busy)
|
||||
to_chat(user, "<span class=\"alert\">\The [src] is busy. Please wait for completion of previous operation.</span>")
|
||||
return
|
||||
|
||||
if(default_deconstruction_screwdriver(user, "limbgrower_panelopen", "limbgrower_idleoff", O))
|
||||
@@ -78,6 +83,16 @@
|
||||
if(user.a_intent == INTENT_HARM) //so we can hit the machine
|
||||
return ..()
|
||||
|
||||
if(istype(O, /obj/item/disk))
|
||||
if(dna_disk)
|
||||
to_chat(user, "<span class='warning'>\The [src] already has a dna disk, take it out first!</span>")
|
||||
return
|
||||
else
|
||||
O.forceMove(src)
|
||||
dna_disk = O
|
||||
to_chat(user, "<span class='notice'>You insert \the [O] into \the [src].</span>")
|
||||
return
|
||||
|
||||
/obj/machinery/limbgrower/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
@@ -110,8 +125,24 @@
|
||||
icon_state = "limbgrower_idleon"
|
||||
addtimer(CALLBACK(src, .proc/build_item),32*prod_coeff)
|
||||
|
||||
if(href_list["dna_disk"])
|
||||
var/mob/living/carbon/user = usr
|
||||
if(istype(user))
|
||||
if(!dna_disk)
|
||||
var/obj/item/disk/diskette = user.get_active_held_item()
|
||||
if(istype(diskette))
|
||||
diskette.forceMove(src)
|
||||
dna_disk = diskette
|
||||
to_chat(user, "<span class='notice'>You insert \the [diskette] into \the [src].</span>")
|
||||
else
|
||||
dna_disk.forceMove(src.loc)
|
||||
user.put_in_active_hand(dna_disk)
|
||||
to_chat(user, "<span class='notice'>You remove \the [dna_disk] from \the [src].</span>")
|
||||
dna_disk = null
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You are unable to grasp \the [dna_disk] disk from \the [src].</span>")
|
||||
else
|
||||
to_chat(usr, "<span class=\"alert\">The limb grower is busy. Please wait for completion of previous operation.</span>")
|
||||
to_chat(usr, "<span class=\"alert\">\The [src] is busy. Please wait for completion of previous operation.</span>")
|
||||
|
||||
updateUsrDialog()
|
||||
return
|
||||
@@ -120,8 +151,10 @@
|
||||
if(reagents.has_reagent(/datum/reagent/medicine/synthflesh, being_built.reagents_list[/datum/reagent/medicine/synthflesh]*prod_coeff)) //sanity check, if this happens we are in big trouble
|
||||
reagents.remove_reagent(/datum/reagent/medicine/synthflesh, being_built.reagents_list[/datum/reagent/medicine/synthflesh]*prod_coeff)
|
||||
var/buildpath = being_built.build_path
|
||||
if(ispath(buildpath, /obj/item/bodypart)) //This feels like spatgheti code, but i need to initilise a limb somehow
|
||||
if(ispath(buildpath, /obj/item/bodypart)) //This feels like spaghetti code, but i need to initiliaze a limb somehow
|
||||
build_limb(buildpath)
|
||||
else if(ispath(buildpath, /obj/item/organ/genital)) //genitals are uhh... customizable
|
||||
build_genital(buildpath)
|
||||
else
|
||||
//Just build whatever it is
|
||||
new buildpath(loc)
|
||||
@@ -135,19 +168,65 @@
|
||||
/obj/machinery/limbgrower/proc/build_limb(buildpath)
|
||||
//i need to create a body part manually using a set icon (otherwise it doesnt appear)
|
||||
var/obj/item/bodypart/limb
|
||||
var/datum/species/selected = stored_species[selected_category]
|
||||
limb = new buildpath(loc)
|
||||
if(selected_category=="human" || selected_category=="lizard") //Species with greyscale parts should be included here
|
||||
limb.icon = 'icons/mob/human_parts_greyscale.dmi'
|
||||
limb.base_bp_icon = DEFAULT_BODYPART_ICON_ORGANIC
|
||||
limb.color_src = MUTCOLORS
|
||||
else
|
||||
limb.icon = 'icons/mob/human_parts.dmi'
|
||||
// Set this limb up using the specias name and body zone
|
||||
limb.icon_state = "[selected_category]_[limb.body_zone]"
|
||||
limb.name = "\improper synthetic [selected_category] [parse_zone(limb.body_zone)]"
|
||||
limb.desc = "A synthetic [selected_category] limb that will morph on its first use in surgery. This one is for the [parse_zone(limb.body_zone)]."
|
||||
limb.species_id = selected_category
|
||||
limb.base_bp_icon = selected.icon_limbs || DEFAULT_BODYPART_ICON_ORGANIC
|
||||
limb.species_id = selected.limbs_id
|
||||
limb.color_src = (MUTCOLORS in selected.species_traits ? MUTCOLORS : (selected.use_skintones ? SKINTONE : FALSE))
|
||||
limb.should_draw_gender = (selected.sexes && (limb.body_zone in list(BODY_ZONE_HEAD, BODY_ZONE_CHEST)))
|
||||
limb.update_limb(TRUE)
|
||||
limb.update_icon_dropped()
|
||||
limb.name = "\improper synthetic [lowertext(selected.name)] [limb.name]"
|
||||
limb.desc = "A synthetic [selected_category] limb that will morph on its first use in surgery. This one is for the [parse_zone(limb.body_zone)]."
|
||||
for(var/obj/item/bodypart/BP in limb)
|
||||
BP.base_bp_icon = selected.icon_limbs || DEFAULT_BODYPART_ICON_ORGANIC
|
||||
BP.species_id = selected.limbs_id
|
||||
BP.color_src = (MUTCOLORS in selected.species_traits ? MUTCOLORS : (selected.use_skintones ? SKINTONE : FALSE))
|
||||
BP.should_draw_gender = (selected.sexes && (limb.body_zone in list(BODY_ZONE_HEAD, BODY_ZONE_CHEST)))
|
||||
BP.update_limb(TRUE)
|
||||
BP.update_icon_dropped()
|
||||
BP.name = "\improper synthetic [lowertext(selected.name)] [limb.name]"
|
||||
BP.desc = "A synthetic [selected_category] limb that will morph on its first use in surgery. This one is for the [parse_zone(limb.body_zone)]."
|
||||
|
||||
/obj/machinery/limbgrower/proc/build_genital(buildpath)
|
||||
//i needed to create a way to customize gene tools using dna
|
||||
var/list/features = dna_disk?.fields["features"]
|
||||
if(length(features))
|
||||
switch(buildpath)
|
||||
if(/obj/item/organ/genital/penis)
|
||||
var/obj/item/organ/genital/penis/penis = new(loc)
|
||||
if(features["has_cock"])
|
||||
penis.shape = features["cock_shape"]
|
||||
penis.length = features["cock_shape"]
|
||||
penis.diameter_ratio = features["cock_diameter_ratio"]
|
||||
penis.color = sanitize_hexcolor(features["cock_color"], 6)
|
||||
penis.update_icon()
|
||||
if(/obj/item/organ/genital/testicles)
|
||||
var/obj/item/organ/genital/testicles/balls = new(loc)
|
||||
if(features["has_balls"])
|
||||
balls.color = sanitize_hexcolor(features["balls_color"], 6)
|
||||
balls.shape = features["balls_shape"]
|
||||
balls.size = features["balls_size"]
|
||||
balls.fluid_rate = features["balls_cum_rate"]
|
||||
balls.fluid_mult = features["balls_cum_mult"]
|
||||
balls.fluid_efficiency = features["balls_efficiency"]
|
||||
if(/obj/item/organ/genital/vagina)
|
||||
var/obj/item/organ/genital/vagina/vegana = new(loc)
|
||||
if(features["has_vagina"])
|
||||
vegana.color = sanitize_hexcolor(features["vag_color"], 6)
|
||||
vegana.shape = features["vag_shape"]
|
||||
if(/obj/item/organ/genital/breasts)
|
||||
var/obj/item/organ/genital/breasts/boobs = new(loc)
|
||||
if(features["has_breasts"])
|
||||
boobs.color = sanitize_hexcolor(features["breasts_color"], 6)
|
||||
boobs.size = features["breasts_size"]
|
||||
boobs.shape = features["breasts_shape"]
|
||||
if(!features["breasts_producing"])
|
||||
boobs.genital_flags &= ~(GENITAL_FUID_PRODUCTION|CAN_CLIMAX_WITH|CAN_MASTURBATE_WITH)
|
||||
else
|
||||
new buildpath(loc)
|
||||
else
|
||||
new buildpath(loc)
|
||||
|
||||
/obj/machinery/limbgrower/RefreshParts()
|
||||
reagents.maximum_volume = 0
|
||||
@@ -165,7 +244,9 @@
|
||||
. += "<span class='notice'>The status display reads: Storing up to <b>[reagents.maximum_volume]u</b> of synthflesh.<br>Synthflesh consumption at <b>[prod_coeff*100]%</b>.<span>"
|
||||
|
||||
/obj/machinery/limbgrower/proc/main_win(mob/user)
|
||||
var/dat = "<div class='statusDisplay'><h3>Limb Grower Menu:</h3><br>"
|
||||
var/dat = "<div class='statusDisplay'><h3>[src] Menu:</h3><br>"
|
||||
dat += "<A href='?src=[REF(src)];dna_disk=1'>[dna_disk ? "Remove" : "Insert"] cloning data disk</A>"
|
||||
dat += "<hr>"
|
||||
dat += "<A href='?src=[REF(src)];menu=[LIMBGROWER_CHEMICAL_MENU]'>Chemical Storage</A>"
|
||||
dat += materials_printout()
|
||||
dat += "<table style='width:100%' align='center'><tr>"
|
||||
@@ -218,7 +299,7 @@
|
||||
|
||||
/obj/machinery/limbgrower/proc/get_design_cost(datum/design/D)
|
||||
var/dat
|
||||
if(D.reagents_list["synthflesh"])
|
||||
if(D.reagents_list[/datum/reagent/medicine/synthflesh])
|
||||
dat += "[D.reagents_list[/datum/reagent/medicine/synthflesh] * prod_coeff] Synthetic flesh "
|
||||
return dat
|
||||
|
||||
@@ -233,3 +314,47 @@
|
||||
to_chat(user, "<span class='warning'>A warning flashes onto the screen, stating that safety overrides have been deactivated!</span>")
|
||||
obj_flags |= EMAGGED
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/limbgrower/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
if(istype(user) && user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
if(busy)
|
||||
to_chat(user, "<span class=\"alert\">\The [src] is busy. Please wait for completion of previous operation.</span>")
|
||||
else
|
||||
if(dna_disk)
|
||||
dna_disk.forceMove(src.loc)
|
||||
user.put_in_active_hand(dna_disk)
|
||||
to_chat(user, "<span class='notice'>You remove \the [dna_disk] from \the [src].</span>")
|
||||
dna_disk = null
|
||||
else
|
||||
to_chat(user, "<span class='warning'>\The [src] has doesn't have a disk on it!")
|
||||
|
||||
//Defines some vars that makes limbs appears, TO-DO: define every single species.
|
||||
|
||||
/datum/species/human
|
||||
limbs_id = SPECIES_HUMAN
|
||||
icon_limbs = 'icons/mob/human_parts_greyscale.dmi'
|
||||
|
||||
/datum/species/lizard
|
||||
limbs_id = SPECIES_LIZARD
|
||||
icon_limbs = 'icons/mob/human_parts_greyscale.dmi'
|
||||
|
||||
/datum/species/mammal
|
||||
limbs_id = SPECIES_MAMMAL
|
||||
icon_limbs = 'icons/mob/human_parts_greyscale.dmi'
|
||||
|
||||
/datum/species/insect
|
||||
limbs_id = SPECIES_INSECT
|
||||
icon_limbs = 'icons/mob/human_parts_greyscale.dmi'
|
||||
|
||||
/datum/species/fly
|
||||
limbs_id = SPECIES_FLY
|
||||
icon_limbs = 'icons/mob/human_parts.dmi'
|
||||
|
||||
/datum/species/plasmaman
|
||||
limbs_id = SPECIES_PLASMAMAN
|
||||
icon_limbs = 'icons/mob/human_parts.dmi'
|
||||
|
||||
/datum/species/xeno
|
||||
limbs_id = SPECIES_XENOHYBRID
|
||||
icon_limbs = 'icons/mob/human_parts_greyscale.dmi'
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
return
|
||||
. = ..()
|
||||
|
||||
if(AM.movement_type & FLYING)
|
||||
if(AM.movement_type & FLYING || iseffect(AM))
|
||||
return
|
||||
|
||||
triggermine(AM)
|
||||
|
||||
@@ -243,6 +243,12 @@
|
||||
/obj/item/stack/sheet/glass = 1)
|
||||
def_components = list(/obj/item/stack/ore/bluespace_crystal = /obj/item/stack/ore/bluespace_crystal/artificial)
|
||||
|
||||
/obj/item/circuitboard/machine/colormate
|
||||
name = "Colormate (Machine Board)"
|
||||
build_path = /obj/machinery/gear_painter
|
||||
req_components = list()
|
||||
def_components = list()
|
||||
|
||||
/obj/item/circuitboard/machine/vendor
|
||||
name = "Custom Vendor (Machine Board)"
|
||||
desc = "You can turn the \"brand selection\" dial using a screwdriver."
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
else
|
||||
if(zero_amount())
|
||||
return
|
||||
chosen_circuit = input("What type of circuit would you like to remove?", "Choose a Circuit Type", chosen_circuit) in list("airlock","firelock","fire alarm","air alarm","APC")
|
||||
if(zero_amount())
|
||||
chosen_circuit = input("What type of circuit would you like to remove?", "Choose a Circuit Type", chosen_circuit) as null|anything in list("airlock","firelock","fire alarm","air alarm","APC")
|
||||
if(zero_amount() || !chosen_circuit || !in_range(src,user))
|
||||
return
|
||||
switch(chosen_circuit)
|
||||
if("airlock")
|
||||
|
||||
@@ -853,8 +853,8 @@
|
||||
/obj/item/storage/belt/sabre/twin
|
||||
name = "twin sheath"
|
||||
desc = "Two sheaths. One is capable of holding a katana (or bokken) and the other a wakizashi. You could put two wakizashis in if you really wanted to. Now you can really roleplay as a samurai."
|
||||
icon_state = "twinsheath"
|
||||
item_state = "quiver" //this'll do.
|
||||
icon_state = "2sheath"
|
||||
item_state = "katana" //this'll do.
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
fitting_swords = list(/obj/item/melee/smith/wakizashi, /obj/item/melee/smith/twohand/katana, /obj/item/melee/bokken)
|
||||
starting_sword = null
|
||||
@@ -865,6 +865,42 @@
|
||||
STR.max_items = 2
|
||||
STR.max_w_class = WEIGHT_CLASS_BULKY + WEIGHT_CLASS_NORMAL //katana and waki.
|
||||
|
||||
/obj/item/melee/smith/twohand/katana/on_exit_storage(datum/component/storage/S)
|
||||
var/obj/item/storage/belt/sabre/twin/B = S.parent
|
||||
if(istype(B))
|
||||
playsound(B, 'sound/items/unsheath.ogg', 25, 1)
|
||||
. = ..()
|
||||
|
||||
/obj/item/melee/smith/twohand/katana/on_enter_storage(datum/component/storage/S)
|
||||
var/obj/item/storage/belt/sabre/twin/B = S.parent
|
||||
if(istype(B))
|
||||
playsound(B, 'sound/items/sheath.ogg', 25, 1)
|
||||
. = ..()
|
||||
|
||||
/obj/item/melee/smith/wakizashi/on_exit_storage(datum/component/storage/S)
|
||||
var/obj/item/storage/belt/sabre/twin/B = S.parent
|
||||
if(istype(B))
|
||||
playsound(B, 'sound/items/unsheath.ogg', 25, 1)
|
||||
. = ..()
|
||||
|
||||
/obj/item/melee/smith/wakizashi/on_enter_storage(datum/component/storage/S)
|
||||
var/obj/item/storage/belt/sabre/twin/B = S.parent
|
||||
if(istype(B))
|
||||
playsound(B, 'sound/items/sheath.ogg', 25, 1)
|
||||
. = ..()
|
||||
|
||||
/obj/item/melee/bokken/on_exit_storage(datum/component/storage/S)
|
||||
var/obj/item/storage/belt/sabre/twin/B = S.parent
|
||||
if(istype(B))
|
||||
playsound(B, 'sound/items/unsheath.ogg', 25, 1)
|
||||
. = ..()
|
||||
|
||||
/obj/item/melee/bokken/on_enter_storage(datum/component/storage/S)
|
||||
var/obj/item/storage/belt/sabre/twin/B = S.parent
|
||||
if(istype(B))
|
||||
playsound(B, 'sound/items/sheath.ogg', 25, 1)
|
||||
. = ..()
|
||||
|
||||
/obj/item/storage/belt/plant
|
||||
name = "botanical belt"
|
||||
desc = "A belt used to hold most hydroponics supplies. Suprisingly, not green."
|
||||
|
||||
@@ -520,3 +520,9 @@
|
||||
new /obj/item/storage/fancy/cigarettes/cigpack_syndicate(src)
|
||||
new /obj/item/lighter(src)
|
||||
|
||||
/obj/item/storage/box/syndie_kit/scarp
|
||||
|
||||
/obj/item/storage/box/syndie_kit/scarp/PopulateContents()
|
||||
new /obj/item/book/granter/martial/carp(src)
|
||||
new /obj/item/clothing/suit/hooded/carp_costume(src)
|
||||
new /obj/item/staff/bostaff(src)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
objective_count += forge_single_objective()
|
||||
|
||||
for(var/i = objective_count, i < CONFIG_GET(number/traitor_objectives_amount), i++)
|
||||
var/datum/objective/assassinate/kill_objective = new
|
||||
var/datum/objective/assassinate/once/kill_objective = new
|
||||
kill_objective.owner = T.owner
|
||||
kill_objective.find_target()
|
||||
T.add_objective(kill_objective)
|
||||
|
||||
@@ -261,6 +261,8 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
|
||||
return //prevent the AI from activating an already active doomsday
|
||||
if (owner_AI.shunted)
|
||||
return //prevent AI from activating doomsday while shunted.
|
||||
if (istype(owner.loc, /obj/item/aicard))
|
||||
return //prevent AI from activating doomsday while carded. If the AI gets carded after doomsdaying, there's already code to stop it then.
|
||||
active = TRUE
|
||||
set_us_up_the_bomb(owner)
|
||||
|
||||
@@ -327,6 +329,10 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
|
||||
sleep(30)
|
||||
if(QDELETED(owner) || owner.stat == DEAD)
|
||||
return
|
||||
if(istype(owner.loc, /obj/item/aicard))
|
||||
to_chat(owner, "<span class='boldnotice'>Error: Signal transmission failed. Reason: Lost connection to network.</span>")
|
||||
to_chat(owner, "<span class='warning'>You can't activate the doomsday device while inside an intelliCard!</span>")
|
||||
return
|
||||
priority_announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", "aimalf")
|
||||
set_security_level("delta")
|
||||
var/obj/machinery/doomsday_device/DOOM = new(owner_AI)
|
||||
|
||||
@@ -17,16 +17,16 @@
|
||||
threat = 3
|
||||
|
||||
/datum/antagonist/xeno/threat()
|
||||
. = 1
|
||||
. = 3
|
||||
if(isalienhunter(owner))
|
||||
. = 2
|
||||
. = 6
|
||||
else if(isaliensentinel(owner))
|
||||
. = 4
|
||||
. = 12
|
||||
else if(isalienroyal(owner))
|
||||
if(isalienqueen(owner))
|
||||
. = 8
|
||||
. = 24
|
||||
else
|
||||
. = 6
|
||||
. = 18
|
||||
|
||||
/datum/antagonist/xeno/create_team(datum/team/xeno/new_team)
|
||||
if(!new_team)
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
if(!panel_open)
|
||||
return
|
||||
anchored = !anchored
|
||||
move_resist = anchored? INFINITY : 100
|
||||
I.play_tool_sound(src)
|
||||
if(generator)
|
||||
disconnectFromGenerator()
|
||||
|
||||
@@ -206,7 +206,7 @@
|
||||
. = other_airs + air
|
||||
if(null in .)
|
||||
stack_trace("[src]([REF(src)]) has one or more null gas mixtures, which may cause bugs. Null mixtures will not be considered in reconcile_air().")
|
||||
return listclearnulls(.)
|
||||
listclearnulls(.)
|
||||
|
||||
/datum/pipeline/proc/empty()
|
||||
for(var/datum/gas_mixture/GM in get_all_connected_airs())
|
||||
|
||||
@@ -280,7 +280,7 @@
|
||||
body_parts_covered = CHEST|GROIN|ARMS|LEGS|FEET
|
||||
cold_protection = CHEST|GROIN|ARMS
|
||||
min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT //Space carp like space, so you should too
|
||||
allowed = list(/obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/gun/ballistic/automatic/speargun)
|
||||
allowed = list(/obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/gun/ballistic/automatic/speargun, /obj/item/staff/bostaff)
|
||||
hoodtype = /obj/item/clothing/head/hooded/carp_hood
|
||||
|
||||
/obj/item/clothing/head/hooded/carp_hood
|
||||
|
||||
@@ -168,7 +168,15 @@
|
||||
desc = "A simple, inconspicuous harness replacement for a jumpsuit."
|
||||
icon_state = "gear_harness"
|
||||
item_state = "gear_harness"
|
||||
can_adjust = FALSE
|
||||
can_adjust = TRUE
|
||||
body_parts_covered = CHEST|GROIN
|
||||
|
||||
/obj/item/clothing/under/misc/gear_harness/toggle_jumpsuit_adjust()
|
||||
adjusted = !adjusted
|
||||
if(adjusted)
|
||||
body_parts_covered = NONE
|
||||
else
|
||||
body_parts_covered = CHEST|GROIN
|
||||
|
||||
/obj/item/clothing/under/misc/durathread
|
||||
name = "durathread jumpsuit"
|
||||
@@ -324,7 +332,7 @@
|
||||
desc = "A blue bathrobe."
|
||||
icon_state = "bathrobe"
|
||||
item_state = "bathrobe"
|
||||
|
||||
|
||||
/obj/item/clothing/under/misc/mechsuitred
|
||||
name = "red mech suit"
|
||||
desc = "What are you, stupid?"
|
||||
@@ -336,10 +344,10 @@
|
||||
desc = "...Mom?"
|
||||
icon_state = "white_mech_suit"
|
||||
item_state = "white_mech_suit"
|
||||
|
||||
|
||||
/obj/item/clothing/under/misc/mechsuitblue
|
||||
name = "blue mech suit"
|
||||
desc = "Get in the damn robot already!"
|
||||
icon_state = "blue_mech_suit"
|
||||
item_state = "blue_mech_suit"
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
typepath = /datum/round_event/ghost_role/nightmare
|
||||
max_occurrences = 1
|
||||
min_players = 20
|
||||
gamemode_blacklist = list("dynamic")
|
||||
|
||||
/datum/round_event/ghost_role/nightmare
|
||||
minimum_required = 1
|
||||
|
||||
@@ -32,7 +32,10 @@
|
||||
|
||||
/obj/item/integrated_circuit/proc/get_pin_data(pin_type, pin_number)
|
||||
var/datum/integrated_io/pin = get_pin_ref(pin_type, pin_number)
|
||||
return pin.get_data()
|
||||
var/data = pin.get_data()
|
||||
if(istext(data))
|
||||
data = sanitize_text(data)
|
||||
return data
|
||||
|
||||
/obj/item/integrated_circuit/proc/get_pin_data_as_type(pin_type, pin_number, as_type)
|
||||
var/datum/integrated_io/pin = get_pin_ref(pin_type, pin_number)
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
/obj/item/integrated_circuit/proc/load(list/component_params)
|
||||
// Load name
|
||||
if(component_params["name"])
|
||||
displayed_name = component_params["name"]
|
||||
displayed_name = html_encode(component_params["name"])
|
||||
|
||||
// Load input values
|
||||
if(component_params["inputs"])
|
||||
@@ -104,7 +104,7 @@
|
||||
|
||||
var/datum/integrated_io/pin = inputs[index]
|
||||
// The pins themselves validate the data.
|
||||
pin.write_data_to_pin(input_value)
|
||||
pin.write_data_to_pin(istext(input_value)? html_encode(input_value) : input_value)
|
||||
// TODO: support for special input types, such as internal refs and maybe typepaths
|
||||
|
||||
if(!isnull(component_params["special"]))
|
||||
@@ -152,19 +152,17 @@
|
||||
/obj/item/electronic_assembly/proc/load(list/assembly_params)
|
||||
// Load modified name, if any.
|
||||
if(assembly_params["name"])
|
||||
name = assembly_params["name"]
|
||||
name = html_encode(assembly_params["name"])
|
||||
|
||||
// Load modified description, if any.
|
||||
if(assembly_params["desc"])
|
||||
desc = assembly_params["desc"]
|
||||
desc = html_encode(assembly_params["desc"])
|
||||
|
||||
if(assembly_params["detail_color"])
|
||||
detail_color = assembly_params["detail_color"]
|
||||
|
||||
update_icon()
|
||||
|
||||
|
||||
|
||||
// Attempts to save an assembly into a save file format.
|
||||
// Returns null if assembly is not complete enough to be saved.
|
||||
/datum/controller/subsystem/processing/circuit/proc/save_electronic_assembly(obj/item/electronic_assembly/assembly)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
/datum/keybinding/client/communication/say
|
||||
hotkey_keys = list("CtrlT")
|
||||
classic_keys = list("Unbound")
|
||||
name = "Say"
|
||||
full_name = "IC Say"
|
||||
clientside = "say"
|
||||
@@ -15,6 +16,7 @@
|
||||
|
||||
/datum/keybinding/client/communication/me
|
||||
hotkey_keys = list("CtrlM")
|
||||
classic_keys = list("Unbound")
|
||||
name = "Me"
|
||||
full_name = "Me (emote)"
|
||||
clientside = "me"
|
||||
@@ -22,7 +24,6 @@
|
||||
//indicators
|
||||
/datum/keybinding/client/communication/say_with_indicator
|
||||
hotkey_keys = list("T")
|
||||
classic_keys = list()
|
||||
name = "say_with_indicator"
|
||||
full_name = "Say with Typing Indicator"
|
||||
|
||||
@@ -33,7 +34,6 @@
|
||||
|
||||
/datum/keybinding/client/communication/me_with_indicator
|
||||
hotkey_keys = list("M")
|
||||
classic_keys = list()
|
||||
name = "me_with_indicator"
|
||||
full_name = "Me (emote) with Typing Indicator"
|
||||
|
||||
@@ -44,28 +44,24 @@
|
||||
|
||||
/datum/keybinding/client/communication/subtle
|
||||
hotkey_keys = list("5")
|
||||
classic_keys = list()
|
||||
name = "Subtle"
|
||||
full_name = "Subtle Emote"
|
||||
clientside = "subtle"
|
||||
|
||||
/datum/keybinding/client/communication/subtler
|
||||
hotkey_keys = list("6")
|
||||
classic_keys = list()
|
||||
name = "Subtler"
|
||||
full_name = "Subtler Anti-Ghost Emote"
|
||||
clientside = "subtler-anti-ghost"
|
||||
|
||||
/datum/keybinding/client/communication/whisper
|
||||
hotkey_keys = list("Y")
|
||||
classic_keys = list()
|
||||
name = "Whisper"
|
||||
full_name = "Whisper"
|
||||
clientside = "whisper"
|
||||
|
||||
/datum/keybinding/client/communication/looc
|
||||
hotkey_keys = list("L")
|
||||
classic_keys = list()
|
||||
name = "LOOC"
|
||||
full_name = "Local Out of Character chat"
|
||||
clientside = "looc"
|
||||
|
||||
@@ -22,12 +22,15 @@
|
||||
full_macro_assert()
|
||||
|
||||
// removes all the existing macros
|
||||
/client/proc/erase_all_macros()
|
||||
/client/proc/erase_all_macros(datum/preferences/prefs_override = prefs)
|
||||
var/erase_output = ""
|
||||
var/list/set_text = list()
|
||||
for(var/macroset in SSinput.all_macrosets)
|
||||
set_text += "[macroset].*"
|
||||
set_text = set_text.Join(";")
|
||||
if(!prefs_override)
|
||||
for(var/macroset in SSinput.all_macrosets)
|
||||
set_text += "[macroset].*"
|
||||
set_text = set_text.Join(";")
|
||||
else
|
||||
set_text = prefs_override.hotkeys? "[SKIN_MACROSET_HOTKEYS].*" : "[SKIN_MACROSET_CLASSIC_INPUT].*;[SKIN_MACROSET_CLASSIC_HOTKEYS].*"
|
||||
var/list/macro_set = params2list(winget(src, "[set_text]", "command"))
|
||||
for(var/k in 1 to length(macro_set))
|
||||
var/list/split_name = splittext(macro_set[k], ".")
|
||||
@@ -44,13 +47,6 @@
|
||||
var/command = macroset[key]
|
||||
winset(src, "[name]-[REF(key)]", "parent=[name];name=[key];command=[command]")
|
||||
|
||||
/client/proc/set_macros(datum/preferences/prefs_override = prefs)
|
||||
keys_held.Cut()
|
||||
|
||||
apply_macro_set(SKIN_MACROSET_HOTKEYS, SSinput.macroset_hotkey)
|
||||
apply_macro_set(SKIN_MACROSET_CLASSIC_HOTKEYS, SSinput.macroset_classic_hotkey)
|
||||
apply_macro_set(SKIN_MACROSET_CLASSIC_INPUT, SSinput.macroset_classic_input)
|
||||
|
||||
/client/proc/set_hotkeys_preference(datum/preferences/prefs_override = prefs)
|
||||
if(prefs_override.hotkeys)
|
||||
winset(src, null, "map.focus=true input.background-color=[COLOR_INPUT_DISABLED] mainwindow.macro=[SKIN_MACROSET_HOTKEYS]")
|
||||
@@ -64,27 +60,97 @@
|
||||
/client/proc/full_macro_assert(datum/preferences/prefs_override = prefs)
|
||||
INVOKE_ASYNC(src, .proc/do_full_macro_assert, prefs_override) // winget sleeps.
|
||||
|
||||
// TODO: OVERHAUL ALL OF THIS AGAIN. While this works this is flatout horrid with the "use list but also don't use lists" crap. I hate my life.
|
||||
/client/proc/do_full_macro_assert(datum/preferences/prefs_override = prefs)
|
||||
erase_all_macros()
|
||||
set_macros(prefs_override)
|
||||
update_special_keybinds(prefs_override)
|
||||
// First, wipe
|
||||
erase_all_macros(prefs_override)
|
||||
keys_held.Cut()
|
||||
// First, collect sets. Make sure to COPY, as we are modifying these!
|
||||
var/list/macrosets = prefs_override.hotkeys? list(
|
||||
SKIN_MACROSET_HOTKEYS = SSinput.macroset_hotkey.Copy()
|
||||
) : list(
|
||||
SKIN_MACROSET_CLASSIC_INPUT = SSinput.macroset_classic_input.Copy(),
|
||||
SKIN_MACROSET_CLASSIC_HOTKEYS = SSinput.macroset_classic_hotkey.Copy()
|
||||
)
|
||||
// Collect special clientside keybinds
|
||||
var/list/clientside = update_special_keybinds(prefs_override)
|
||||
// ANTI COLLISION SYSTEM:
|
||||
// If hotkey, do "standard" anti collision permutation
|
||||
// We fully permutate alt/ctrl/shift with the key and then subtract the key's actual binding.
|
||||
// Then, we set all the permutations BUT the actual binding to nonsensical things to force BYOND to not
|
||||
// be "greedy" with key matching, aka matching Shift+T for T when Shift+T isn't EXPLICITLY defined.
|
||||
// This is extremely ugly, but the alternative is arguably worse (manually binding every key instead of using ANY)
|
||||
if(prefs_override.hotkeys)
|
||||
for(var/keybind in clientside)
|
||||
var/command = clientside[keybind]
|
||||
var/alt = findtext(keybind, "Alt")
|
||||
if(alt)
|
||||
keybind = copytext(keybind, 1, alt) + copytext(keybind, alt + 3, 0)
|
||||
var/ctrl = findtext(keybind, "Ctrl")
|
||||
if(ctrl)
|
||||
keybind = copytext(keybind, 1, ctrl) + copytext(keybind, ctrl + 4, 0)
|
||||
var/shift = findtext(keybind, "Shift")
|
||||
if(shift)
|
||||
keybind = copytext(keybind, 1, shift) + copytext(keybind, shift + 5, 0)
|
||||
var/actual = "[alt? "Alt+" : ""][ctrl? "Ctrl+" : ""][shift? "Shift+" : ""][keybind]"
|
||||
var/list/overriding = keybind_modifier_permutation(keybind, alt, ctrl, shift, TRUE)
|
||||
overriding -= actual
|
||||
for(var/macroset in macrosets)
|
||||
var/list/the_set = macrosets[macroset]
|
||||
the_set[actual] = command
|
||||
for(var/i in overriding)
|
||||
the_set[i] = NONSENSICAL_VERB
|
||||
else
|
||||
// For classic mode, we just directly set things because BYOND is so jank why do we even bother?
|
||||
// What we want is to force Ctrl on for all keybinds without Ctrl or Alt set, to preserve old behavior
|
||||
for(var/keybind in clientside)
|
||||
var/command = clientside[keybind]
|
||||
var/alt = findtext(keybind, "Alt")
|
||||
if(alt)
|
||||
keybind = copytext(keybind, 1, alt) + copytext(keybind, alt + 3, 0)
|
||||
var/ctrl = findtext(keybind, "Ctrl")
|
||||
if(ctrl)
|
||||
keybind = copytext(keybind, 1, ctrl) + copytext(keybind, ctrl + 4, 0)
|
||||
var/shift = findtext(keybind, "Shift")
|
||||
if(shift)
|
||||
keybind = copytext(keybind, 1, shift) + copytext(keybind, shift + 5, 0)
|
||||
var/actual
|
||||
if(!alt && !ctrl)
|
||||
actual = "Ctrl+[keybind]"
|
||||
else
|
||||
actual = "[alt? "Alt+" : ""][ctrl? "Ctrl+" : ""][shift? "Shift+" : ""][keybind]"
|
||||
macrosets[SKIN_MACROSET_CLASSIC_HOTKEYS]["[alt? "Alt+" : ""][ctrl? "Ctrl+" : ""][shift? "Shift+" : ""][keybind]"] = command
|
||||
macrosets[SKIN_MACROSET_CLASSIC_INPUT][actual] = command
|
||||
for(var/macroset in macrosets)
|
||||
var/list/the_set = macrosets[macroset]
|
||||
the_set[actual] = command
|
||||
|
||||
// Lastly, set the actual macros.
|
||||
for(var/macroset in macrosets)
|
||||
apply_macro_set(macroset, macrosets[macroset])
|
||||
// Finally, set hotkeys.
|
||||
set_hotkeys_preference(prefs_override)
|
||||
|
||||
/client/proc/do_special_keybind(key, command, datum/preferences/prefs_override = prefs)
|
||||
var/alt = findtext(key, "Alt")
|
||||
if(alt)
|
||||
key = copytext(key, 1, alt) + copytext(key, alt + 3, 0)
|
||||
var/ctrl = findtext(key, "Ctrl")
|
||||
if(ctrl)
|
||||
key = copytext(key, 1, ctrl) + copytext(key, ctrl + 4, 0)
|
||||
var/shift = findtext(key, "Shift")
|
||||
if(shift)
|
||||
key = copytext(key, 1, shift) + copytext(key, shift + 5, 0)
|
||||
if(!alt && !ctrl && !shift && !prefs_override.hotkeys)
|
||||
return /// DO NOT.
|
||||
key = "[alt? "Alt+":""][ctrl? "Ctrl+":""][shift? "Shift+":""][key]"
|
||||
for(var/macroset in SSinput.all_macrosets)
|
||||
winset(src, "[macroset]-[REF(key)]", "parent=[macroset];name=[key];command=[command]")
|
||||
/proc/keybind_modifier_permutation(key, alt = FALSE, ctrl = FALSE, shift = FALSE, self = TRUE)
|
||||
var/list/permutations = list()
|
||||
if(!shift)
|
||||
permutations += "Shift"
|
||||
if(!ctrl)
|
||||
permutations += "Ctrl"
|
||||
if(!alt)
|
||||
permutations += "Alt"
|
||||
// ALT + CTRL + SHIFT
|
||||
. = list()
|
||||
do_keybind_modifier_permutations(key, permutations, .)
|
||||
if(self)
|
||||
. += key
|
||||
|
||||
/proc/do_keybind_modifier_permutations(key, list/permutations = list(), list/out = list())
|
||||
. = out
|
||||
for(var/mod in permutations.Copy())
|
||||
permutations -= mod
|
||||
. += "[mod]+[key]"
|
||||
do_keybind_modifier_permutations("[mod]+[key]", permutations.Copy(), .)
|
||||
|
||||
/**
|
||||
* Updates the keybinds for special keys
|
||||
@@ -94,12 +160,15 @@
|
||||
* At the time of writing this, communication(OOC, Say, IC) require macros
|
||||
* Arguments:
|
||||
* * direct_prefs - the preference we're going to get keybinds from
|
||||
*
|
||||
* Returns list of special keybind in key = Mod1Mod2Mod3Key format, NOT Mod1+Mod2+Mod3+Key format.
|
||||
*/
|
||||
/client/proc/update_special_keybinds(datum/preferences/direct_prefs)
|
||||
var/datum/preferences/D = direct_prefs || prefs
|
||||
if(!D?.key_bindings)
|
||||
return
|
||||
movement_keys = list()
|
||||
. = list()
|
||||
for(var/key in D.key_bindings)
|
||||
for(var/kb_name in D.key_bindings[key])
|
||||
switch(kb_name)
|
||||
@@ -115,4 +184,4 @@
|
||||
var/datum/keybinding/KB = GLOB.keybindings_by_name[kb_name]
|
||||
if(!KB.clientside)
|
||||
continue
|
||||
do_special_keybind(key, KB.clientside, D)
|
||||
.[key] = KB.clientside
|
||||
|
||||
@@ -20,16 +20,20 @@
|
||||
ckeys_allowed = list("poojawa")
|
||||
extra = TRUE
|
||||
extra_color_src = MUTCOLORS3
|
||||
matrixed_sections = MATRIX_RED_GREEN
|
||||
|
||||
/datum/sprite_accessory/tails/mam_tails/sabresune
|
||||
name = "Sabresune"
|
||||
icon_state = "sabresune"
|
||||
ckeys_allowed = list("poojawa")
|
||||
matrixed_sections = MATRIX_RED_GREEN
|
||||
|
||||
/datum/sprite_accessory/tails_animated/mam_tails_animated/sabresune
|
||||
name = "Sabresune"
|
||||
icon_state = "sabresune"
|
||||
ckeys_allowed = list("poojawa")
|
||||
color_src = MATRIXED
|
||||
matrixed_sections = MATRIX_RED_GREEN
|
||||
|
||||
/datum/sprite_accessory/mam_body_markings/sabresune
|
||||
name = "Sabresune"
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
var/oxy_mod = 1 // % of oxygen damage taken from all sources
|
||||
var/clone_mod = 1 // % of clone damage taken from all sources
|
||||
var/stamina_mod = 1 // % of stamina damage taken from all sources
|
||||
var/stamina_buffer_mod = 1 // % of stamina buffer
|
||||
var/brain_mod = 1 // % of brain damage taken from all sources
|
||||
|
||||
var/pressure_mod = 1 // % of brute damage taken from low or high pressure (stacks with brute_mod)
|
||||
|
||||
@@ -254,16 +254,16 @@ They *could* go in their appropriate files, but this is supposed to be modular
|
||||
. = DRAIN_MOB_SHOCK_FAILED
|
||||
|
||||
//Default cell = 10,000 charge, 10,000/1000 = 10 uses without charging/upgrading
|
||||
if(S.cell && S.cell.charge && S.cell.use(1000))
|
||||
if(S.cell && S.cell.charge && S.cell.use(500))
|
||||
. = DRAIN_MOB_SHOCK
|
||||
//Got that electric touch
|
||||
var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread()
|
||||
spark_system.set_up(5, 0, loc)
|
||||
playsound(src, "sparks", 50, 1)
|
||||
visible_message("<span class='danger'>[H] electrocutes [src] with [H.p_their()] touch!</span>", "<span class='userdanger'>[H] electrocutes you with [H.p_their()] touch!</span>")
|
||||
electrocute_act(15, H)
|
||||
electrocute_act(15, H, flags = SHOCK_NOSTUN)
|
||||
|
||||
DefaultCombatKnockdown(G.stunforce)
|
||||
DefaultCombatKnockdown(G.stunforce, override_hardstun = 0)
|
||||
apply_effect(EFFECT_STUTTER, G.stunforce)
|
||||
SEND_SIGNAL(src, COMSIG_LIVING_MINOR_SHOCK)
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
|
||||
/obj/item/ammo_casing/energy/xray
|
||||
projectile_type = /obj/item/projectile/beam/xray
|
||||
e_cost = 50
|
||||
e_cost = 100
|
||||
fire_sound = 'sound/weapons/laser3.ogg'
|
||||
|
||||
/obj/item/ammo_casing/energy/mindflayer
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
name = "\improper X-ray beam"
|
||||
icon_state = "xray"
|
||||
damage = 15
|
||||
irradiate = 300
|
||||
irradiate = 100
|
||||
range = 15
|
||||
pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE | PASSCLOSEDTURF
|
||||
|
||||
|
||||
+6
@@ -102,6 +102,12 @@ Borg Hypospray
|
||||
if(!istype(M))
|
||||
return
|
||||
if(R.total_volume && M.can_inject(user, 1, user.zone_selected,bypass_protection))
|
||||
if(user.a_intent == INTENT_HELP) //Prevents mediborgs from OD'ing people unless on harm intent
|
||||
for(var/datum/reagent/RG in R.reagent_list)
|
||||
if(M.reagents.has_reagent(RG.type) && !RG.overdose_threshold == 0)
|
||||
if(((M.reagents.get_reagent_amount(RG.type)) + amount_per_transfer_from_this > RG.overdose_threshold))
|
||||
to_chat(user, "<span class='warning'>Injecting [M] with more [RG] would overdose them.</span>")
|
||||
return
|
||||
to_chat(M, "<span class='warning'>You feel a tiny prick!</span>")
|
||||
to_chat(user, "<span class='notice'>You inject [M] with the injector.</span>")
|
||||
var/fraction = min(amount_per_transfer_from_this/R.total_volume, 1)
|
||||
@@ -41,3 +41,162 @@
|
||||
reagents_list = list(/datum/reagent/medicine/synthflesh = 75)
|
||||
build_path = /obj/item/melee/synthetic_arm_blade
|
||||
category = list("other","emagged")
|
||||
|
||||
//Extra limbs
|
||||
|
||||
/datum/design/chest
|
||||
name = "Chest"
|
||||
id = "chest"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/synthflesh = 50)
|
||||
build_path = /obj/item/bodypart/chest
|
||||
category = list("initial","human","lizard","fly","insect","plasmaman","mammal","xeno")
|
||||
|
||||
/datum/design/head
|
||||
name = "Head"
|
||||
id = "head"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/synthflesh = 75)
|
||||
build_path = /obj/item/bodypart/head
|
||||
category = list("initial","human","lizard","fly","insect","plasmaman","mammal","xeno")
|
||||
|
||||
//Organs
|
||||
/datum/design/brain
|
||||
name = "Brain"
|
||||
id = "brain"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/synthflesh = 50)
|
||||
build_path = /obj/item/organ/brain
|
||||
category = list("initial","human","lizard","fly","insect","plasmaman","mammal","xeno")
|
||||
|
||||
/datum/design/heart
|
||||
name = "Heart"
|
||||
id = "heart"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/synthflesh = 25)
|
||||
build_path = /obj/item/organ/heart
|
||||
category = list("initial","human","lizard","fly","insect","plasmaman","mammal","xeno")
|
||||
|
||||
/datum/design/lungs
|
||||
name = "Lungs"
|
||||
id = "lungs"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/synthflesh = 25)
|
||||
build_path = /obj/item/organ/lungs
|
||||
category = list("initial","human","lizard","fly","insect","plasmaman","mammal","xeno")
|
||||
|
||||
/datum/design/liver
|
||||
name = "Liver"
|
||||
id = "liver"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/synthflesh = 25)
|
||||
build_path = /obj/item/organ/liver
|
||||
category = list("initial","human","lizard","fly","insect","plasmaman","mammal","xeno")
|
||||
|
||||
/datum/design/stomach
|
||||
name = "Stomach"
|
||||
id = "stomach"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/synthflesh = 25)
|
||||
build_path = /obj/item/organ/stomach
|
||||
category = list("initial","human","lizard","fly","insect","plasmaman","mammal","xeno")
|
||||
|
||||
/datum/design/appendix
|
||||
name = "Appendix"
|
||||
id = "appendix"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/synthflesh = 10)
|
||||
build_path = /obj/item/organ/appendix
|
||||
category = list("initial","human","lizard","fly","insect","plasmaman","mammal","xeno")
|
||||
|
||||
/datum/design/tail
|
||||
name = "Tail"
|
||||
id = "tail"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/synthflesh = 25)
|
||||
build_path = /obj/item/organ/tail
|
||||
category = list("initial","human","lizard","fly","insect","plasmaman","mammal","xeno")
|
||||
|
||||
/datum/design/ears
|
||||
name = "Ears"
|
||||
id = "ears"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/synthflesh = 25)
|
||||
build_path = /obj/item/organ/ears
|
||||
category = list("initial","human","lizard","fly","insect","plasmaman","mammal","xeno")
|
||||
|
||||
/datum/design/eyes
|
||||
name = "Eyes"
|
||||
id = "eyes"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/synthflesh = 30)
|
||||
build_path = /obj/item/organ/eyes
|
||||
category = list("initial","human","lizard","fly","insect","plasmaman","mammal","xeno")
|
||||
|
||||
/datum/design/tongue
|
||||
name = "Tongue"
|
||||
id = "tongue"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/synthflesh = 25)
|
||||
build_path = /obj/item/organ/tongue
|
||||
category = list("initial","human","lizard","fly","insect","plasmaman","mammal","xeno")
|
||||
|
||||
/datum/design/vocal_cords
|
||||
name = "Vocal cords"
|
||||
id = "vocal_cords"
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/synthflesh = 25)
|
||||
build_path = /obj/item/organ/vocal_cords
|
||||
category = list("initial","human","lizard","fly","insect","plasmaman","mammal","xeno")
|
||||
|
||||
//genitals
|
||||
|
||||
/datum/design/penis
|
||||
name = "Penis"
|
||||
id = "penis"
|
||||
build_type = LIMBGROWER
|
||||
research_icon_state = "penis_human_3_s"
|
||||
research_icon = 'icons/obj/genitals/penis.dmi'
|
||||
reagents_list = list(/datum/reagent/medicine/synthflesh = 25)
|
||||
build_path = /obj/item/organ/genital/penis
|
||||
category = list("initial","human","lizard","fly","insect","plasmaman","mammal","xeno")
|
||||
|
||||
/datum/design/vagina
|
||||
name = "Vagina"
|
||||
id = "vagina"
|
||||
research_icon_state = "vagina-s"
|
||||
research_icon = 'icons/obj/genitals/vagina.dmi'
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/synthflesh = 25)
|
||||
build_path = /obj/item/organ/genital/vagina
|
||||
category = list("initial","human","lizard","fly","insect","plasmaman","mammal","xeno")
|
||||
|
||||
/datum/design/womb
|
||||
name = "Womb"
|
||||
id = "womb"
|
||||
research_icon_state = "womb"
|
||||
research_icon = 'icons/obj/genitals/vagina.dmi'
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/synthflesh = 25)
|
||||
build_path = /obj/item/organ/genital/womb
|
||||
category = list("initial","human","lizard","fly","insect","plasmaman","mammal","xeno")
|
||||
|
||||
/datum/design/testicles
|
||||
name = "Testicles"
|
||||
id = "testicles"
|
||||
research_icon_state = "testicles_single_3_s"
|
||||
research_icon = 'icons/obj/genitals/testicles.dmi'
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/synthflesh = 25)
|
||||
build_path = /obj/item/organ/genital/testicles
|
||||
category = list("initial","human","lizard","fly","insect","plasmaman","mammal","xeno")
|
||||
|
||||
/datum/design/breasts
|
||||
name = "Breasts"
|
||||
id = "breasts"
|
||||
research_icon_state = "breasts_pair_e_s"
|
||||
research_icon = 'icons/obj/genitals/breasts.dmi'
|
||||
build_type = LIMBGROWER
|
||||
reagents_list = list(/datum/reagent/medicine/synthflesh = 25)
|
||||
build_path = /obj/item/organ/genital/breasts
|
||||
category = list("initial","human","lizard","fly","insect","plasmaman","mammal","xeno")
|
||||
|
||||
@@ -163,3 +163,10 @@
|
||||
category = list ("Misc. Machinery")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_ALL
|
||||
|
||||
/datum/design/board/colormate
|
||||
name = "ColorMate"
|
||||
desc = "This machine lets you paint your gear."
|
||||
id = "colormate"
|
||||
build_path = /obj/item/circuitboard/machine/colormate
|
||||
category = list ("Misc. Machinery")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_ALL
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
design_ids = list("solarcontrol", "recharger", "powermonitor", "rped", "pacman", "adv_capacitor", "adv_scanning", "emitter", "high_cell", "adv_matter_bin",
|
||||
"atmosalerts", "atmos_control", "recycler", "autolathe", "autolathe_secure", "high_micro_laser", "nano_mani", "mesons", "thermomachine", "rad_collector", "tesla_coil", "grounding_rod",
|
||||
"apc_control", "power control", "airlock_board", "firelock_board", "airalarm_electronics", "firealarm_electronics", "cell_charger", "stack_console", "stack_machine", "rcd_ammo","oxygen_tank",
|
||||
"plasma_tank", "emergency_oxygen", "emergency_oxygen_engi", "plasmaman_tank_belt")
|
||||
"plasma_tank", "emergency_oxygen", "emergency_oxygen_engi", "plasmaman_tank_belt", "colormate")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 6000)
|
||||
|
||||
/datum/techweb_node/adv_engi
|
||||
|
||||
@@ -52,6 +52,15 @@
|
||||
cost = 20
|
||||
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs)
|
||||
|
||||
/datum/uplink_item/bundles_TC/scarp_bundle
|
||||
name = "Sleeping Carp Bundle"
|
||||
desc = "Become one with your inner carp! Your ancient fish masters leave behind their legacy, and bestow to you their teachings, sacred uniform, and staff. \
|
||||
Please be aware that you will not be able to use dishonerable ranged weapons."
|
||||
item = /obj/item/storage/box/syndie_kit/scarp
|
||||
cost = 20
|
||||
player_minimum = 20
|
||||
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs)
|
||||
|
||||
/datum/uplink_item/suits/infiltrator_bundle
|
||||
name = "Insidious Infiltration Gear Case"
|
||||
desc = "Developed by Roseus Galactic in conjunction with the Gorlex Marauders to produce a functional suit for urban operations, \
|
||||
|
||||
@@ -60,7 +60,6 @@
|
||||
cost = 15
|
||||
restricted_roles = list("Clown")
|
||||
|
||||
/*
|
||||
/datum/uplink_item/role_restricted/clowncar
|
||||
name = "Clown Car"
|
||||
desc = "The Clown Car is the ultimate transportation method for any worthy clown! \
|
||||
@@ -69,9 +68,8 @@
|
||||
someone saves them or they manage to crawl out. Be sure not to ram into any walls or vending machines, as the springloaded seats \
|
||||
are very sensetive. Now with our included lube defense mechanism which will protect you against any angry shitcurity!"
|
||||
item = /obj/vehicle/sealed/car/clowncar
|
||||
cost = 15
|
||||
cost = 16
|
||||
restricted_roles = list("Clown")
|
||||
*/
|
||||
|
||||
/datum/uplink_item/role_restricted/haunted_magic_eightball
|
||||
name = "Haunted Magic Eightball"
|
||||
|
||||
@@ -18,6 +18,14 @@
|
||||
. = ..()
|
||||
initialize_controller_action_type(/datum/action/vehicle/sealed/horn/clowncar, VEHICLE_CONTROL_DRIVE)
|
||||
|
||||
|
||||
/obj/vehicle/sealed/car/clowncar/driver_move(mob/user, direction) //Prevent it from moving onto space
|
||||
if(isspaceturf(get_step(src, direction)))
|
||||
return FALSE
|
||||
else
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/vehicle/sealed/car/clowncar/auto_assign_occupant_flags(mob/M)
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
@@ -56,7 +64,7 @@
|
||||
L.visible_message("<span class='warning'>[src] rams into [L] and sucks him up!</span>") //fuck off shezza this isn't ERP.
|
||||
mob_forced_enter(L)
|
||||
playsound(src, pick('sound/vehicles/clowncar_ram1.ogg', 'sound/vehicles/clowncar_ram2.ogg', 'sound/vehicles/clowncar_ram3.ogg'), 75)
|
||||
else if(istype(M, /turf/closed))
|
||||
else if(istype(M, /turf/closed) || istype(M, /obj/machinery/door/airlock/external))
|
||||
visible_message("<span class='warning'>[src] rams into [M] and crashes!</span>")
|
||||
playsound(src, pick('sound/vehicles/clowncar_crash1.ogg', 'sound/vehicles/clowncar_crash2.ogg'), 75)
|
||||
playsound(src, 'sound/vehicles/clowncar_crashpins.ogg', 75)
|
||||
|
||||
@@ -13,6 +13,9 @@ STORYTELLER_WEIGHT EXTENDED 0
|
||||
STORYTELLER_MIN_PLAYERS CHAOTIC 30
|
||||
STORYTELLER_MIN_PLAYERS TEAMWORK 30
|
||||
|
||||
## If this is uncommented, Dynamic won't disable certain storytellers based on recent round threats
|
||||
#NO_STORYTELLER_THREAT_REMOVAL
|
||||
|
||||
## Injection delays: how long (in minutes) will pass before a midround or latejoin antag is injected.
|
||||
DYNAMIC_MIDROUND_DELAY_MIN 5
|
||||
DYNAMIC_MIDROUND_DELAY_MAX 15
|
||||
@@ -171,8 +174,8 @@ DYNAMIC_COST LATEJOIN_REVOLUTION 20
|
||||
DYNAMIC_COST LATEJOIN_BLOODSUCKER 10
|
||||
DYNAMIC_COST LATEJOIN_COLLECTOR 1
|
||||
|
||||
## Rule will not be generated with threat levels below requirement at a pop value. Pop values are determined by dynamic's pop-per-requirement.
|
||||
## By default it's 0-8, 9-17, 18-26, 27-35, 36-44, 45-53, 54-60, 61-69, 70-78, 79+.
|
||||
## Rule will not be generated with threat levels below requirement at a pop value. Pop values are determined by dynamic's pop-per-requirement.
|
||||
## By default it's 0-8, 9-17, 18-26, 27-35, 36-44, 45-53, 54-60, 61-69, 70-78, 79+.
|
||||
## This means that 40 30 30 20 20 20 15 15 15 10 will not generate below 40 at 0-8, 30 at 9-17 etc.
|
||||
DYNAMIC_REQUIREMENTS TRAITOR 50 50 50 50 50 50 50 50 50 50
|
||||
DYNAMIC_REQUIREMENTS TRAITORBRO 101 101 101 101 101 101 101 101 101 101
|
||||
@@ -301,6 +304,6 @@ DYNAMIC_GLORIOUS_DEATH_COST 5
|
||||
DYNAMIC_ASSASSINATE_COST 2
|
||||
|
||||
## This requirement uses threat level, rather than current threat, which is why it's higher.
|
||||
DYNAMIC_WAROPS_REQUIREMENT 60
|
||||
DYNAMIC_WAROPS_REQUIREMENT 60
|
||||
|
||||
DYNAMIC_WAROPS_COST 10
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "silicons"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "keybinds generate anti-collision bindings where necessary automatically now"
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "silicons"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscadd: "colormates"
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "Hatterhat"
|
||||
delete-after: True
|
||||
changes:
|
||||
- tweak: "RPEDs now drop their lowest part tier first when quick-emptied (used inhand)."
|
||||
@@ -0,0 +1,6 @@
|
||||
author: "keronshb"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscadd: "Re-adds the Clown Car to the clown uplink"
|
||||
- balance: "15 >16 TC cost"
|
||||
- balance: "bonks on external airlocks"
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "DeltaFire15"
|
||||
delete-after: True
|
||||
changes:
|
||||
- tweak: "AIs now only have to kill people once instead of permanently."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "MrJWhit"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Effects can no longer trigger landmines"
|
||||
@@ -0,0 +1,5 @@
|
||||
author: "Putnam3145"
|
||||
delete-after: True
|
||||
changes:
|
||||
- tweak: "Grab bag works as advertised."
|
||||
- balance: "Xeno threat in dynamic tripled."
|
||||
@@ -0,0 +1,5 @@
|
||||
author: "MrJWhit"
|
||||
delete-after: True
|
||||
changes:
|
||||
- tweak: "Replaced engineering fuel tank with a large fuel tank"
|
||||
- tweak: "Changed access to sec suit storage from armory access in every map to other security access"
|
||||
@@ -0,0 +1,9 @@
|
||||
author: "keronshb"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscadd: "Adds a reduced stamina buffer for SCarp users"
|
||||
- rscadd: "Gives SCarp users a better parry"
|
||||
- rscadd: "Adds the SCarp bundle which includes a bo staff"
|
||||
- rscadd: "Lets Carp costumes carry Bo Staffs"
|
||||
- balance: "reduces the stamina damage of scarp slightly"
|
||||
- balance: "reduced the blockchance of the bo staff"
|
||||
@@ -0,0 +1,5 @@
|
||||
author: "silicons"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "ninja gloves no longer hardstun"
|
||||
- balance: "ninja gloves now cost half as much to use to compensate"
|
||||
@@ -0,0 +1,5 @@
|
||||
author: "SandPoot"
|
||||
delete-after: True
|
||||
changes:
|
||||
- refactor: "Changes the limb grower a lot."
|
||||
- bugfix: "\"Limb\" costs on limbgrower are actually displayed like it was meant to all along."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "BlueWildrose"
|
||||
delete-after: True
|
||||
changes:
|
||||
- balance: "The traitor AI can no longer activate the doomsday device while carded."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "timothyteakettle"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "circuits get pin data proc is sanitized when text is returned as data"
|
||||
@@ -0,0 +1,5 @@
|
||||
author: "Putnam3145"
|
||||
delete-after: True
|
||||
changes:
|
||||
- tweak: "You can now exit polycircuit input"
|
||||
- bugfix: "Polycircuits now check for range"
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "Putnam3145"
|
||||
delete-after: True
|
||||
changes:
|
||||
- tweak: "Gear harness now covers nothing."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "BlackMajor"
|
||||
delete-after: True
|
||||
changes:
|
||||
- tweak: "Cyborg hypospray no longer injects if it means OD'ing while on help intent."
|
||||
@@ -0,0 +1,5 @@
|
||||
author: "silicons"
|
||||
delete-after: True
|
||||
changes:
|
||||
- tweak: "command headsets are 120% instead of 160%"
|
||||
- bugfix: "no more emote italics"
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "Xantholne"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Twin Sword Sheaths have an equipment icon and icon when worn now and make a sound when sheathed/unsheathed"
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 111 KiB |
@@ -64,7 +64,7 @@ em {font-style: normal; font-weight: bold;}
|
||||
.alert {color: #ff0000;}
|
||||
h1.alert, h2.alert {color: #000000;}
|
||||
|
||||
.emote { font-style: italic;}
|
||||
.emote { }
|
||||
.selecteddna {color: #ffffff; background-color: #001B1B}
|
||||
|
||||
.attack {color: #ff0000;}
|
||||
|
||||
+2
-1
@@ -793,6 +793,7 @@
|
||||
#include "code\game\machinery\buttons.dm"
|
||||
#include "code\game\machinery\cell_charger.dm"
|
||||
#include "code\game\machinery\cloning.dm"
|
||||
#include "code\game\machinery\colormate.dm"
|
||||
#include "code\game\machinery\constructable_frame.dm"
|
||||
#include "code\game\machinery\cryopod.dm"
|
||||
#include "code\game\machinery\dance_machine.dm"
|
||||
@@ -3143,7 +3144,7 @@
|
||||
#include "code\modules\reagents\chemistry\recipes\special.dm"
|
||||
#include "code\modules\reagents\chemistry\recipes\toxins.dm"
|
||||
#include "code\modules\reagents\reagent_containers\blood_pack.dm"
|
||||
#include "code\modules\reagents\reagent_containers\borghydro.dm"
|
||||
#include "code\modules\reagents\reagent_containers\borghypo.dm"
|
||||
#include "code\modules\reagents\reagent_containers\bottle.dm"
|
||||
#include "code\modules\reagents\reagent_containers\chem_pack.dm"
|
||||
#include "code\modules\reagents\reagent_containers\dropper.dm"
|
||||
|
||||
@@ -11,7 +11,7 @@ export const IMPL_LOCAL_STORAGE = 1;
|
||||
export const IMPL_INDEXED_DB = 2;
|
||||
|
||||
const INDEXED_DB_VERSION = 1;
|
||||
const INDEXED_DB_NAME = 'tgui';
|
||||
const INDEXED_DB_NAME = 'tgui-citadel-main';
|
||||
const INDEXED_DB_STORE_NAME = 'storage-v1';
|
||||
|
||||
const READ_ONLY = 'readonly';
|
||||
|
||||
@@ -418,7 +418,7 @@ em {
|
||||
}
|
||||
|
||||
.emote {
|
||||
font-style: italic;
|
||||
|
||||
}
|
||||
|
||||
.userdanger {
|
||||
@@ -840,7 +840,7 @@ em {
|
||||
|
||||
.command_headset {
|
||||
font-weight: bold;
|
||||
font-size: 160%;
|
||||
font-size: 125%;
|
||||
}
|
||||
|
||||
.small {
|
||||
@@ -876,7 +876,7 @@ em {
|
||||
|
||||
.clown {
|
||||
color: #ff70c1;
|
||||
font-size: 160%;
|
||||
font-size: 125%;
|
||||
font-family: "Comic Sans MS", cursive, sans-serif;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@@ -881,7 +881,7 @@ h1.alert, h2.alert {
|
||||
|
||||
.command_headset {
|
||||
font-weight: bold;
|
||||
font-size: 160%;
|
||||
font-size: 125%;
|
||||
}
|
||||
|
||||
.small {
|
||||
@@ -917,7 +917,7 @@ h1.alert, h2.alert {
|
||||
|
||||
.clown {
|
||||
color: #FF69Bf;
|
||||
font-size: 160%;
|
||||
font-size: 125%;
|
||||
font-family: "Comic Sans MS", cursive, sans-serif;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user