Merge remote-tracking branch 'refs/remotes/origin/master' into upstream-merge-26822
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
[Note]: # (Please enter the commit hash and active testmerge numbers from the "Show Server Revision" verb if you can. If you believe the issue to be caused by a testmerge, please report it in its relative PR thread. State what the issue is from a "whats wrong" prospective. Issue reports should clearly allow maintainers to understand whats wrong and how to test/reproduce if that is not obvious. Avoid ambiguity. Start your issue report below both of these lines (or remove them))
|
||||
[Note]: # (State what the issue is from a "whats wrong" perspective. Issue reports should clearly allow maintainers to understand whats wrong and how to test/reproduce if that is not obvious. Avoid ambiguity. Please enter the commit hash from the "Show Server Revision" verb if you can. Remove these notes before submitting your report.)
|
||||
|
||||
[Admins]: # (If you are reporting a bug that occured AFTER you used varedit/admin buttons to alter an object out of normal operating conditions, please verify that you can re-create the bug without the varedit usage/admin buttons before reporting the issue.)
|
||||
[GameAdmins]: # (If you are reporting a bug that occurred AFTER you used varedit/admin buttons to alter an object out of normal operating conditions, please verify that you can re-create the bug without the varedit usage/admin buttons before reporting the issue.)
|
||||
|
||||
@@ -7034,8 +7034,8 @@
|
||||
"anI" = (
|
||||
/obj/docking_port/stationary/random{
|
||||
dir = 1;
|
||||
id = "pod_asteroid1";
|
||||
name = "asteroid"
|
||||
id = "pod_lavaland1";
|
||||
name = "lavaland"
|
||||
},
|
||||
/turf/open/space,
|
||||
/area/space)
|
||||
@@ -8103,7 +8103,7 @@
|
||||
/obj/machinery/computer/shuttle/pod{
|
||||
pixel_x = -32;
|
||||
pixel_y = 0;
|
||||
possible_destinations = "pod_asteroid1";
|
||||
possible_destinations = "pod_lavaland1";
|
||||
shuttleId = "pod1"
|
||||
},
|
||||
/obj/machinery/light/small{
|
||||
@@ -40738,7 +40738,7 @@
|
||||
/obj/machinery/computer/shuttle/pod{
|
||||
pixel_x = 0;
|
||||
pixel_y = 32;
|
||||
possible_destinations = "pod_asteroid3";
|
||||
possible_destinations = "pod_lavaland3";
|
||||
shuttleId = "pod3"
|
||||
},
|
||||
/obj/item/device/radio/intercom{
|
||||
@@ -40760,8 +40760,8 @@
|
||||
"btw" = (
|
||||
/obj/docking_port/stationary/random{
|
||||
dir = 4;
|
||||
id = "pod_asteroid3";
|
||||
name = "asteroid"
|
||||
id = "pod_lavaland3";
|
||||
name = "lavaland"
|
||||
},
|
||||
/turf/open/space,
|
||||
/area/space)
|
||||
@@ -68963,8 +68963,8 @@
|
||||
"crd" = (
|
||||
/obj/docking_port/stationary/random{
|
||||
dir = 8;
|
||||
id = "pod_asteroid2";
|
||||
name = "asteroid"
|
||||
id = "pod_lavaland2";
|
||||
name = "lavaland"
|
||||
},
|
||||
/turf/open/space,
|
||||
/area/space)
|
||||
@@ -68979,7 +68979,7 @@
|
||||
/obj/machinery/computer/shuttle/pod{
|
||||
pixel_x = 0;
|
||||
pixel_y = -32;
|
||||
possible_destinations = "pod_asteroid2";
|
||||
possible_destinations = "pod_lavaland2";
|
||||
shuttleId = "pod2"
|
||||
},
|
||||
/obj/structure/chair{
|
||||
|
||||
@@ -142,15 +142,15 @@
|
||||
/area/solar/auxstarboard)
|
||||
"aap" = (
|
||||
/obj/docking_port/stationary/random{
|
||||
id = "pod_asteroid1";
|
||||
name = "asteroid"
|
||||
id = "pod_lavaland1";
|
||||
name = "lavaland"
|
||||
},
|
||||
/turf/open/space,
|
||||
/area/space)
|
||||
"aaq" = (
|
||||
/obj/docking_port/stationary/random{
|
||||
id = "pod_asteroid2";
|
||||
name = "asteroid"
|
||||
id = "pod_lavaland2";
|
||||
name = "lavaland"
|
||||
},
|
||||
/turf/open/space,
|
||||
/area/space)
|
||||
@@ -203,7 +203,7 @@
|
||||
},
|
||||
/obj/machinery/computer/shuttle/pod{
|
||||
pixel_x = -32;
|
||||
possible_destinations = "pod_asteroid1";
|
||||
possible_destinations = "pod_lavaland1";
|
||||
shuttleId = "pod1"
|
||||
},
|
||||
/obj/effect/turf_decal/stripes/line{
|
||||
@@ -226,7 +226,7 @@
|
||||
},
|
||||
/obj/machinery/computer/shuttle/pod{
|
||||
pixel_x = -32;
|
||||
possible_destinations = "pod_asteroid2";
|
||||
possible_destinations = "pod_lavaland2";
|
||||
shuttleId = "pod2"
|
||||
},
|
||||
/obj/effect/turf_decal/stripes/line{
|
||||
@@ -25977,7 +25977,7 @@
|
||||
},
|
||||
/obj/machinery/computer/shuttle/pod{
|
||||
pixel_y = -32;
|
||||
possible_destinations = "pod_asteroid3";
|
||||
possible_destinations = "pod_lavaland3";
|
||||
shuttleId = "pod3"
|
||||
},
|
||||
/obj/effect/turf_decal/stripes/line{
|
||||
@@ -25996,8 +25996,8 @@
|
||||
"aXK" = (
|
||||
/obj/docking_port/stationary/random{
|
||||
dir = 4;
|
||||
id = "pod_asteroid4";
|
||||
name = "asteroid"
|
||||
id = "pod_lavaland4";
|
||||
name = "lavaland"
|
||||
},
|
||||
/turf/open/space,
|
||||
/area/space)
|
||||
@@ -34793,7 +34793,6 @@
|
||||
dir = 4
|
||||
},
|
||||
/turf/open/floor/plasteel{
|
||||
desc = "";
|
||||
icon_state = "L14"
|
||||
},
|
||||
/area/hallway/primary/central)
|
||||
@@ -70986,7 +70985,6 @@
|
||||
"cDW" = (
|
||||
/obj/machinery/atmospherics/pipe/manifold/supply/hidden,
|
||||
/turf/open/floor/plasteel{
|
||||
desc = "";
|
||||
icon_state = "L13";
|
||||
name = "floor"
|
||||
},
|
||||
@@ -79512,8 +79510,13 @@
|
||||
name = "Medbay Central"
|
||||
})
|
||||
"cUf" = (
|
||||
/obj/machinery/smartfridge/chemistry,
|
||||
/turf/closed/wall,
|
||||
/obj/structure/grille,
|
||||
/obj/machinery/door/poddoor/shutters/preopen{
|
||||
id = "chemisttop";
|
||||
name = "Chemisty Lobby Shutters"
|
||||
},
|
||||
/obj/structure/window/reinforced/fulltile,
|
||||
/turf/open/floor/plating,
|
||||
/area/medical/medbay{
|
||||
name = "Medbay Central"
|
||||
})
|
||||
@@ -79536,14 +79539,9 @@
|
||||
name = "Medbay Central"
|
||||
})
|
||||
"cUh" = (
|
||||
/obj/structure/grille,
|
||||
/obj/structure/window/reinforced/fulltile,
|
||||
/obj/machinery/door/poddoor/shutters/preopen{
|
||||
id = "chemisttop";
|
||||
name = "Chemisty Lobby Shutters"
|
||||
},
|
||||
/obj/structure/disposalpipe/segment,
|
||||
/turf/open/floor/plating,
|
||||
/obj/machinery/smartfridge/chemistry,
|
||||
/turf/closed/wall,
|
||||
/area/medical/medbay{
|
||||
name = "Medbay Central"
|
||||
})
|
||||
@@ -82189,6 +82187,7 @@
|
||||
/obj/item/weapon/grenade/chem_grenade,
|
||||
/obj/item/weapon/grenade/chem_grenade,
|
||||
/obj/item/weapon/grenade/chem_grenade,
|
||||
/obj/item/weapon/screwdriver,
|
||||
/turf/open/floor/plasteel/whiteyellow/corner{
|
||||
icon_state = "whiteyellowcorner";
|
||||
dir = 8
|
||||
@@ -96353,7 +96352,6 @@
|
||||
},
|
||||
/area/medical/morgue)
|
||||
"dAn" = (
|
||||
/turf/open/floor/plating,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
|
||||
icon_state = "manifold";
|
||||
|
||||
@@ -1910,8 +1910,8 @@
|
||||
/area/shuttle/pod_3)
|
||||
"adG" = (
|
||||
/obj/docking_port/stationary/random{
|
||||
id = "pod_asteroid2";
|
||||
name = "asteroid"
|
||||
id = "pod_lavaland2";
|
||||
name = "lavaland"
|
||||
},
|
||||
/turf/open/space,
|
||||
/area/space)
|
||||
@@ -1927,7 +1927,7 @@
|
||||
},
|
||||
/obj/machinery/computer/shuttle/pod{
|
||||
pixel_x = -32;
|
||||
possible_destinations = "pod_asteroid2";
|
||||
possible_destinations = "pod_lavaland2";
|
||||
shuttleId = "pod2"
|
||||
},
|
||||
/turf/open/floor/mineral/titanium/blue,
|
||||
@@ -23696,7 +23696,7 @@
|
||||
},
|
||||
/obj/machinery/computer/shuttle/pod{
|
||||
pixel_y = -32;
|
||||
possible_destinations = "pod_asteroid3";
|
||||
possible_destinations = "pod_lavaland3";
|
||||
shuttleId = "pod3"
|
||||
},
|
||||
/turf/open/floor/mineral/titanium/blue,
|
||||
@@ -27963,7 +27963,6 @@
|
||||
dir = 4
|
||||
},
|
||||
/turf/open/floor/plasteel{
|
||||
desc = "";
|
||||
icon_state = "L13";
|
||||
name = "floor"
|
||||
},
|
||||
@@ -28813,7 +28812,6 @@
|
||||
icon_state = "4-8"
|
||||
},
|
||||
/turf/open/floor/plasteel{
|
||||
desc = "";
|
||||
icon_state = "L14"
|
||||
},
|
||||
/area/hallway/primary/central)
|
||||
@@ -34140,8 +34138,8 @@
|
||||
"bii" = (
|
||||
/obj/docking_port/stationary/random{
|
||||
dir = 4;
|
||||
id = "pod_asteroid3";
|
||||
name = "asteroid"
|
||||
id = "pod_lavaland3";
|
||||
name = "lavaland"
|
||||
},
|
||||
/turf/open/space,
|
||||
/area/space)
|
||||
@@ -86084,8 +86082,8 @@
|
||||
/area/toxins/xenobiology)
|
||||
"cSP" = (
|
||||
/obj/docking_port/stationary/random{
|
||||
id = "pod_asteroid1";
|
||||
name = "asteroid"
|
||||
id = "pod_lavaland1";
|
||||
name = "lavaland"
|
||||
},
|
||||
/turf/open/space,
|
||||
/area/space)
|
||||
@@ -86175,7 +86173,7 @@
|
||||
},
|
||||
/obj/machinery/computer/shuttle/pod{
|
||||
pixel_x = -32;
|
||||
possible_destinations = "pod_asteroid1";
|
||||
possible_destinations = "pod_lavaland1";
|
||||
shuttleId = "pod1"
|
||||
},
|
||||
/turf/open/floor/mineral/titanium/blue,
|
||||
@@ -86368,7 +86366,7 @@
|
||||
},
|
||||
/obj/machinery/computer/shuttle/pod{
|
||||
pixel_y = -32;
|
||||
possible_destinations = "pod_asteroid4";
|
||||
possible_destinations = "pod_lavaland4";
|
||||
shuttleId = "pod4"
|
||||
},
|
||||
/turf/open/floor/mineral/titanium/blue,
|
||||
@@ -87162,8 +87160,8 @@
|
||||
"cUL" = (
|
||||
/obj/docking_port/stationary/random{
|
||||
dir = 4;
|
||||
id = "pod_asteroid4";
|
||||
name = "asteroid"
|
||||
id = "pod_lavaland4";
|
||||
name = "lavaland"
|
||||
},
|
||||
/turf/open/space,
|
||||
/area/space)
|
||||
|
||||
@@ -7303,7 +7303,6 @@
|
||||
icon_state = "1-2"
|
||||
},
|
||||
/turf/open/floor/plasteel{
|
||||
desc = "";
|
||||
icon_state = "L14"
|
||||
},
|
||||
/area/hallway/primary/central{
|
||||
@@ -16523,6 +16522,9 @@
|
||||
/obj/machinery/status_display{
|
||||
pixel_x = -32
|
||||
},
|
||||
/obj/machinery/light{
|
||||
dir = 8
|
||||
},
|
||||
/turf/open/floor/mineral/plastitanium/brig,
|
||||
/area/shuttle/escape)
|
||||
"aAb" = (
|
||||
@@ -16558,6 +16560,9 @@
|
||||
"aAf" = (
|
||||
/obj/structure/table/reinforced,
|
||||
/obj/item/weapon/storage/fancy/donut_box,
|
||||
/obj/machinery/light{
|
||||
dir = 4
|
||||
},
|
||||
/turf/open/floor/plasteel/vault{
|
||||
dir = 8
|
||||
},
|
||||
@@ -24133,6 +24138,9 @@
|
||||
},
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/obj/effect/turf_decal/delivery,
|
||||
/obj/machinery/light{
|
||||
dir = 8
|
||||
},
|
||||
/turf/open/floor/plasteel,
|
||||
/area/shuttle/escape)
|
||||
"aME" = (
|
||||
@@ -24187,6 +24195,9 @@
|
||||
/obj/machinery/status_display{
|
||||
pixel_x = 32
|
||||
},
|
||||
/obj/machinery/light{
|
||||
dir = 4
|
||||
},
|
||||
/turf/open/floor/plasteel/whiteblue/side{
|
||||
dir = 5
|
||||
},
|
||||
@@ -25964,7 +25975,6 @@
|
||||
icon_state = "4-8"
|
||||
},
|
||||
/turf/open/floor/plasteel{
|
||||
desc = "";
|
||||
icon_state = "L13";
|
||||
name = "floor"
|
||||
},
|
||||
@@ -41920,6 +41930,38 @@
|
||||
/area/ruin/unpowered{
|
||||
name = "Asteroid"
|
||||
})
|
||||
"bvO" = (
|
||||
/obj/machinery/light{
|
||||
dir = 1
|
||||
},
|
||||
/turf/open/floor/plasteel/neutral/side{
|
||||
dir = 1
|
||||
},
|
||||
/area/shuttle/escape)
|
||||
"bvP" = (
|
||||
/obj/structure/chair{
|
||||
dir = 8
|
||||
},
|
||||
/obj/effect/turf_decal/bot,
|
||||
/obj/machinery/light/small{
|
||||
dir = 4
|
||||
},
|
||||
/turf/open/floor/plasteel,
|
||||
/area/shuttle/escape)
|
||||
"bvQ" = (
|
||||
/obj/structure/chair{
|
||||
dir = 4
|
||||
},
|
||||
/obj/effect/turf_decal/bot,
|
||||
/obj/machinery/light/small{
|
||||
dir = 8
|
||||
},
|
||||
/turf/open/floor/plasteel,
|
||||
/area/shuttle/escape)
|
||||
"bvR" = (
|
||||
/obj/machinery/light,
|
||||
/turf/open/floor/plasteel/neutral/side,
|
||||
/area/shuttle/escape)
|
||||
|
||||
(1,1,1) = {"
|
||||
aaa
|
||||
@@ -94203,7 +94245,7 @@ aAb
|
||||
axY
|
||||
aDl
|
||||
aEi
|
||||
aEi
|
||||
bvP
|
||||
aEi
|
||||
aEi
|
||||
aEi
|
||||
@@ -94715,13 +94757,13 @@ axY
|
||||
aAc
|
||||
axY
|
||||
aCp
|
||||
aDl
|
||||
bvO
|
||||
aEk
|
||||
aEj
|
||||
aGd
|
||||
aEl
|
||||
aEk
|
||||
aJf
|
||||
bvR
|
||||
aKn
|
||||
aLz
|
||||
axY
|
||||
@@ -95231,7 +95273,7 @@ aAd
|
||||
aCq
|
||||
aDl
|
||||
aEm
|
||||
aEm
|
||||
bvQ
|
||||
aEm
|
||||
aEm
|
||||
aEm
|
||||
|
||||
@@ -32850,10 +32850,6 @@
|
||||
/turf/open/floor/plasteel/white,
|
||||
/area/toxins/xenobiology)
|
||||
"bnU" = (
|
||||
/obj/machinery/door/airlock/research{
|
||||
name = "Kill Room Access";
|
||||
req_access_txt = "55"
|
||||
},
|
||||
/obj/structure/disposalpipe/segment{
|
||||
dir = 4
|
||||
},
|
||||
|
||||
@@ -2501,7 +2501,7 @@
|
||||
"afq" = (
|
||||
/obj/machinery/computer/shuttle/pod{
|
||||
pixel_y = -32;
|
||||
possible_destinations = "pod_asteroid3";
|
||||
possible_destinations = "pod_lavaland3";
|
||||
shuttleId = "pod3"
|
||||
},
|
||||
/obj/structure/chair{
|
||||
@@ -7787,8 +7787,8 @@
|
||||
"aqG" = (
|
||||
/obj/docking_port/stationary/random{
|
||||
dir = 4;
|
||||
id = "pod_asteroid3";
|
||||
name = "asteroid"
|
||||
id = "pod_lavaland3";
|
||||
name = "lavaland"
|
||||
},
|
||||
/turf/open/space,
|
||||
/area/space)
|
||||
@@ -17330,7 +17330,6 @@
|
||||
/area/hallway/primary/central)
|
||||
"aMf" = (
|
||||
/turf/open/floor/plasteel{
|
||||
desc = "";
|
||||
icon_state = "L13";
|
||||
name = "floor"
|
||||
},
|
||||
@@ -17836,7 +17835,6 @@
|
||||
/area/hallway/primary/central)
|
||||
"aNB" = (
|
||||
/turf/open/floor/plasteel{
|
||||
desc = "";
|
||||
icon_state = "L14"
|
||||
},
|
||||
/area/hallway/primary/central)
|
||||
@@ -53823,8 +53821,8 @@
|
||||
"cpe" = (
|
||||
/obj/docking_port/stationary/random{
|
||||
dir = 8;
|
||||
id = "pod_asteroid2";
|
||||
name = "asteroid"
|
||||
id = "pod_lavaland2";
|
||||
name = "lavaland"
|
||||
},
|
||||
/turf/open/space,
|
||||
/area/space)
|
||||
@@ -54079,7 +54077,7 @@
|
||||
/obj/machinery/computer/shuttle/pod{
|
||||
pixel_x = 0;
|
||||
pixel_y = -32;
|
||||
possible_destinations = "pod_asteroid2";
|
||||
possible_destinations = "pod_lavaland2";
|
||||
shuttleId = "pod2"
|
||||
},
|
||||
/obj/structure/chair{
|
||||
@@ -57394,8 +57392,8 @@
|
||||
"cwV" = (
|
||||
/obj/docking_port/stationary/random{
|
||||
dir = 8;
|
||||
id = "pod_asteroid1";
|
||||
name = "asteroid"
|
||||
id = "pod_lavaland1";
|
||||
name = "lavaland"
|
||||
},
|
||||
/turf/open/space,
|
||||
/area/space)
|
||||
@@ -57508,7 +57506,7 @@
|
||||
/obj/machinery/computer/shuttle/pod{
|
||||
pixel_x = 0;
|
||||
pixel_y = -32;
|
||||
possible_destinations = "pod_asteroid1";
|
||||
possible_destinations = "pod_lavaland1";
|
||||
shuttleId = "pod1"
|
||||
},
|
||||
/obj/structure/chair{
|
||||
@@ -58424,7 +58422,7 @@
|
||||
"czL" = (
|
||||
/obj/machinery/computer/shuttle/pod{
|
||||
pixel_y = -32;
|
||||
possible_destinations = "pod_asteroid4";
|
||||
possible_destinations = "pod_lavaland4";
|
||||
shuttleId = "pod4"
|
||||
},
|
||||
/obj/structure/chair{
|
||||
@@ -58455,8 +58453,8 @@
|
||||
"czN" = (
|
||||
/obj/docking_port/stationary/random{
|
||||
dir = 4;
|
||||
id = "pod_asteroid4";
|
||||
name = "asteroid"
|
||||
id = "pod_lavaland4";
|
||||
name = "lavaland"
|
||||
},
|
||||
/turf/open/space,
|
||||
/area/space)
|
||||
|
||||
@@ -37,15 +37,15 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us
|
||||
#define JUDGEMENT_CV_REQ 300
|
||||
|
||||
//general component/cooldown things
|
||||
#define SLAB_PRODUCTION_TIME 900 //how long(deciseconds) slabs require to produce a single component; defaults to 1 minute 30 seconds
|
||||
#define SLAB_PRODUCTION_TIME 450 //how long(deciseconds) slabs require to produce a single component; defaults to 45 seconds
|
||||
|
||||
#define SLAB_SERVANT_SLOWDOWN 300 //how much each servant above 5 slows down slab-based generation; defaults to 30 seconds per sevant
|
||||
#define SLAB_SERVANT_SLOWDOWN 150 //how much each servant above 5 slows down slab-based generation; defaults to 15 seconds per sevant
|
||||
|
||||
#define SLAB_SLOWDOWN_MAXIMUM 2700 //maximum slowdown from additional servants; defaults to 4 minutes 30 seconds
|
||||
#define SLAB_SLOWDOWN_MAXIMUM 1350 //maximum slowdown from additional servants; defaults to 2 minutes 15 seconds
|
||||
|
||||
#define CACHE_PRODUCTION_TIME 600 //how long(deciseconds) caches require to produce a component; defaults to 1 minute
|
||||
#define CACHE_PRODUCTION_TIME 300 //how long(deciseconds) caches require to produce a component; defaults to 30 seconds
|
||||
|
||||
#define ACTIVE_CACHE_SLOWDOWN 100 //how many additional deciseconds caches take to produce a component for each linked cache; defaults to 10 seconds
|
||||
#define ACTIVE_CACHE_SLOWDOWN 50 //how many additional deciseconds caches take to produce a component for each linked cache; defaults to 5 seconds
|
||||
|
||||
#define LOWER_PROB_PER_COMPONENT 10 //how much each component in the cache reduces the weight of getting another of that component type
|
||||
|
||||
@@ -87,9 +87,9 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us
|
||||
|
||||
#define GATEWAY_RATVAR_ARRIVAL 300 //when progress is at or above this, game over ratvar's here everybody go home
|
||||
|
||||
#define ARK_SUMMON_COST 3 //how many of each component an Ark costs to summon
|
||||
#define ARK_SUMMON_COST 5 //how many of each component an Ark costs to summon
|
||||
|
||||
#define ARK_CONSUME_COST 7 //how many of each component an Ark needs to consume to activate
|
||||
#define ARK_CONSUME_COST 15 //how many of each component an Ark needs to consume to activate
|
||||
|
||||
//Objective text define
|
||||
#define CLOCKCULT_OBJECTIVE "Construct the Ark of the Clockwork Justicar and free Ratvar."
|
||||
|
||||
@@ -1342,6 +1342,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
|
||||
//This prevents RCEs from badmins
|
||||
//kevinz000 if you touch this I will hunt you down
|
||||
GLOBAL_VAR_INIT(valid_HTTPSGet, FALSE)
|
||||
GLOBAL_PROTECT(valid_HTTPSGet)
|
||||
/proc/HTTPSGet(url)
|
||||
if(findtext(url, "\""))
|
||||
GLOB.valid_HTTPSGet = FALSE
|
||||
|
||||
@@ -29,6 +29,7 @@ GLOBAL_LIST_EMPTY(zombie_infection_list) // A list of all zombie_infection org
|
||||
GLOBAL_LIST_EMPTY(meteor_list) // List of all meteors.
|
||||
GLOBAL_LIST_EMPTY(active_jammers) // List of active radio jammers
|
||||
GLOBAL_LIST_EMPTY(ladders)
|
||||
GLOBAL_LIST_EMPTY(trophy_cases)
|
||||
|
||||
GLOBAL_LIST_EMPTY(wire_color_directory)
|
||||
GLOBAL_LIST_EMPTY(wire_name_directory)
|
||||
@@ -11,10 +11,14 @@ SUBSYSTEM_DEF(persistence)
|
||||
var/list/saved_messages = list()
|
||||
var/savefile/chisel_messages_sav
|
||||
|
||||
var/savefile/trophy_sav
|
||||
var/list/saved_trophies = list()
|
||||
|
||||
/datum/controller/subsystem/persistence/Initialize()
|
||||
LoadSatchels()
|
||||
LoadPoly()
|
||||
LoadChiselMessages()
|
||||
LoadTrophies()
|
||||
..()
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadSatchels()
|
||||
@@ -105,10 +109,49 @@ SUBSYSTEM_DEF(persistence)
|
||||
M.persists = FALSE
|
||||
qdel(M)
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadTrophies()
|
||||
trophy_sav = new /savefile("data/npc_saves/TrophyItems.sav")
|
||||
var/saved_json
|
||||
trophy_sav >> saved_json
|
||||
|
||||
var/decoded_json = json_decode(saved_json)
|
||||
|
||||
if(!islist(decoded_json))
|
||||
return
|
||||
|
||||
saved_trophies = decoded_json
|
||||
|
||||
SetUpTrophies(saved_trophies.Copy())
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/SetUpTrophies(list/trophy_items)
|
||||
for(var/A in GLOB.trophy_cases)
|
||||
var/obj/structure/displaycase/trophy/T = A
|
||||
T.added_roundstart = TRUE
|
||||
|
||||
var/trophy_data = pick_n_take(trophy_items)
|
||||
|
||||
if(!islist(trophy_data))
|
||||
continue
|
||||
|
||||
var/list/chosen_trophy = trophy_data
|
||||
|
||||
if(!chosen_trophy || isemptylist(chosen_trophy)) //Malformed
|
||||
continue
|
||||
|
||||
var/path = text2path(chosen_trophy["path"]) //If the item no longer exist, this returns null
|
||||
if(!path)
|
||||
continue
|
||||
|
||||
T.showpiece = new /obj/item/showpiece_dummy(T, path)
|
||||
T.trophy_message = chosen_trophy["message"]
|
||||
T.placer_key = chosen_trophy["placer_key"]
|
||||
T.update_icon()
|
||||
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/CollectData()
|
||||
CollectChiselMessages()
|
||||
CollectSecretSatchels()
|
||||
CollectTrophies()
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/CollectSecretSatchels()
|
||||
for(var/A in new_secret_satchels)
|
||||
@@ -135,4 +178,16 @@ SUBSYSTEM_DEF(persistence)
|
||||
chisel_messages_sav[SSmapping.config.map_name] << json_encode(saved_messages)
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/SaveChiselMessage(obj/structure/chisel_message/M)
|
||||
saved_messages += list(M.pack()) // dm eats one list.
|
||||
saved_messages += list(M.pack()) // dm eats one list
|
||||
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/CollectTrophies()
|
||||
trophy_sav << json_encode(saved_trophies)
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/SaveTrophy(obj/structure/displaycase/trophy/T)
|
||||
if(!T.added_roundstart && T.showpiece)
|
||||
var/list/data = list()
|
||||
data["path"] = T.showpiece.type
|
||||
data["message"] = T.trophy_message
|
||||
data["placer_key"] = T.placer_key
|
||||
saved_trophies += list(data)
|
||||
@@ -5,7 +5,7 @@ PROCESSING_SUBSYSTEM_DEF(flightpacks)
|
||||
stat_tag = "FM"
|
||||
flags = SS_NO_INIT|SS_TICKER|SS_KEEP_TIMING
|
||||
|
||||
var/flightsuit_processing = FLIGHTSUIT_PROCESSING_FULL
|
||||
var/flightsuit_processing = FLIGHTSUIT_PROCESSING_NONE
|
||||
|
||||
/datum/controller/subsystem/processing/flightpacks/Initialize()
|
||||
sync_flightsuit_processing()
|
||||
|
||||
@@ -625,8 +625,8 @@ SUBSYSTEM_DEF(ticker)
|
||||
if(selected_tip)
|
||||
m = selected_tip
|
||||
else
|
||||
var/list/randomtips = world.file2list("config/tips.txt")
|
||||
var/list/memetips = world.file2list("config/sillytips.txt")
|
||||
var/list/randomtips = world.file2list("strings/tips.txt")
|
||||
var/list/memetips = world.file2list("strings/sillytips.txt")
|
||||
if(randomtips.len && prob(95))
|
||||
m = pick(randomtips)
|
||||
else if(memetips.len)
|
||||
|
||||
@@ -8,13 +8,26 @@
|
||||
var/can_coexist_with_others = TRUE //Whether or not the person will be able to have more than one datum
|
||||
var/list/typecache_datum_blacklist = list() //List of datums this type can't coexist with
|
||||
|
||||
|
||||
/datum/antagonist/New(datum/mind/new_owner)
|
||||
. = ..()
|
||||
typecache_datum_blacklist = typecacheof(typecache_datum_blacklist)
|
||||
if(new_owner)
|
||||
owner = new_owner
|
||||
|
||||
/datum/antagonist/Destroy()
|
||||
if(owner)
|
||||
LAZYREMOVE(owner.antag_datums, src)
|
||||
owner = null
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/proc/can_be_owned(datum/mind/new_owner)
|
||||
. = TRUE
|
||||
if(owner.has_antag_datum(type))
|
||||
return FALSE
|
||||
for(var/i in owner.antag_datums)
|
||||
var/datum/antagonist/A = i
|
||||
if(is_type_in_typecache(src, A.typecache_datum_blacklist))
|
||||
return FALSE
|
||||
|
||||
/datum/antagonist/proc/on_body_transfer(mob/living/old_body, mob/living/new_body)
|
||||
remove_innate_effects(old_body)
|
||||
apply_innate_effects(new_body)
|
||||
@@ -37,7 +50,7 @@
|
||||
/datum/antagonist/proc/on_removal()
|
||||
remove_innate_effects()
|
||||
if(owner)
|
||||
owner.antag_datums -= src
|
||||
LAZYREMOVE(owner.antag_datums, src)
|
||||
if(!silent && owner.current)
|
||||
farewell()
|
||||
qdel(src)
|
||||
@@ -46,4 +59,4 @@
|
||||
return
|
||||
|
||||
/datum/antagonist/proc/farewell()
|
||||
return
|
||||
return
|
||||
|
||||
@@ -9,23 +9,49 @@
|
||||
qdel(hierophant_network)
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/clockcult/can_be_owned(datum/mind/new_owner)
|
||||
. = ..()
|
||||
if(.)
|
||||
if(iscyborg(new_owner.current))
|
||||
var/mob/living/silicon/robot/R = new_owner.current
|
||||
if(R.deployed)
|
||||
var/mob/living/silicon/ai/AI = R.mainframe
|
||||
R.undeploy()
|
||||
to_chat(AI, "<span class='userdanger'>Anomaly Detected. Returned to core!</span>") //The AI needs to be in its core to properly be converted
|
||||
. = is_eligible_servant(new_owner.current)
|
||||
if(!silent && new_owner.current)
|
||||
if(issilicon(new_owner.current))
|
||||
to_chat(new_owner.current, "<span class='heavy_brass'>You are unable to compute this truth. Your vision glows a brilliant yellow, and all at once it comes to you. Ratvar, the \
|
||||
Clockwork Justiciar, lies in exile, derelict and forgotten in an unseen realm.</span>")
|
||||
else
|
||||
to_chat(new_owner.current, "<span class='heavy_brass'>[iscarbon(new_owner.current) ? "Your mind is racing! Your body feels incredibly light! ":""]Your world glows a brilliant \
|
||||
yellow! All at once it comes to you. Ratvar, the Clockwork Justiciar, lies in exile, derelict and forgotten in an unseen realm.</span>")
|
||||
if(!.)
|
||||
new_owner.current.visible_message("<span class='boldwarning'>[new_owner.current] seems to resist an unseen force!</span>")
|
||||
to_chat(new_owner.current, "<span class='userdanger'>And yet, you somehow push it all away.</span>")
|
||||
|
||||
/datum/antagonist/clockcult/greet()
|
||||
if(!owner.current || silent)
|
||||
return
|
||||
owner.current.visible_message("<span class='heavy_brass'>[owner.current]'s eyes glow a blazing yellow!</span>")
|
||||
to_chat(owner.current, "<span class='heavy_brass'>Assist your new companions in their righteous efforts. Your goal is theirs, and theirs yours. You serve the Clockwork \
|
||||
Justiciar above all else. Perform his every whim without hesitation.</span>")
|
||||
|
||||
/datum/antagonist/clockcult/on_gain()
|
||||
if(!owner)
|
||||
return
|
||||
var/mob/living/current = owner.current
|
||||
if(!istype(current))
|
||||
return
|
||||
SSticker.mode.servants_of_ratvar += owner
|
||||
SSticker.mode.update_servant_icons_added(owner)
|
||||
if(jobban_isbanned(current, ROLE_SERVANT_OF_RATVAR))
|
||||
addtimer(CALLBACK(SSticker.mode, /datum/game_mode.proc/replace_jobbaned_player, owner, ROLE_SERVANT_OF_RATVAR, ROLE_SERVANT_OF_RATVAR), 0)
|
||||
addtimer(CALLBACK(SSticker.mode, /datum/game_mode.proc/replace_jobbaned_player, current, ROLE_SERVANT_OF_RATVAR, ROLE_SERVANT_OF_RATVAR), 0)
|
||||
owner.special_role = "Servant of Ratvar"
|
||||
owner.current.log_message("<font color=#BE8700>Has been converted to the cult of Ratvar!</font>", INDIVIDUAL_ATTACK_LOG)
|
||||
if(issilicon(current))
|
||||
var/mob/living/silicon/S = owner
|
||||
if(iscyborg(S) && !silent)
|
||||
to_chat(S, "<span class='boldwarning'>You have been desynced from your master AI.</span>")
|
||||
to_chat(S, "<span class='boldwarning'>In addition, your onboard camera is no longer active and you have gained additional equipment, including a limited clockwork slab.</span>")
|
||||
if(isAI(S))
|
||||
to_chat(S, "<span class='boldwarning'>You are able to use your cameras to listen in on conversations.</span>")
|
||||
to_chat(S, "<span class='heavy_brass'>You can communicate with other servants by using the Hierophant Network action button in the upper left.</span>")
|
||||
if(iscyborg(current) && !silent)
|
||||
to_chat(current, "<span class='boldwarning'>You have been desynced from your master AI.</span>")
|
||||
to_chat(current, "<span class='boldwarning'>In addition, your onboard camera is no longer active and you have gained additional equipment, including a limited clockwork slab.</span>")
|
||||
if(isAI(current))
|
||||
to_chat(current, "<span class='boldwarning'>You are able to use your cameras to listen in on conversations.</span>")
|
||||
to_chat(current, "<span class='heavy_brass'>You can communicate with other servants by using the Hierophant Network action button in the upper left.</span>")
|
||||
else if(isbrain(current) || isclockmob(current))
|
||||
to_chat(current, "<span class='nezbere'>You can communicate with other servants by using the Hierophant Network action button in the upper left.</span>")
|
||||
..()
|
||||
@@ -39,7 +65,6 @@
|
||||
if(istype(mob_override))
|
||||
current = mob_override
|
||||
GLOB.all_clockwork_mobs += current
|
||||
SSticker.mode.update_servant_icons_added(owner)
|
||||
current.faction |= "ratvar"
|
||||
current.grant_language(/datum/language/ratvar)
|
||||
current.update_action_buttons_icon() //because a few clockcult things are action buttons and we may be wearing/holding them for whatever reason, we need to update buttons
|
||||
@@ -47,11 +72,17 @@
|
||||
var/mob/living/silicon/S = current
|
||||
if(iscyborg(S))
|
||||
var/mob/living/silicon/robot/R = S
|
||||
R.UnlinkSelf()
|
||||
if(!R.shell)
|
||||
R.UnlinkSelf()
|
||||
R.module.rebuild_modules()
|
||||
else if(isAI(S))
|
||||
var/mob/living/silicon/ai/A = S
|
||||
A.can_be_carded = FALSE
|
||||
A.requires_power = POWER_REQ_CLOCKCULT
|
||||
var/list/AI_frame = list(mutable_appearance('icons/mob/clockwork_mobs.dmi', "aiframe")) //make the AI's cool frame
|
||||
for(var/d in GLOB.cardinal)
|
||||
AI_frame += image('icons/mob/clockwork_mobs.dmi', A, "eye[rand(1, 10)]", dir = d) //the eyes are randomly fast or slow
|
||||
A.add_overlay(AI_frame)
|
||||
if(!A.lacks_power())
|
||||
A.ai_restore_power()
|
||||
if(A.eyeobj)
|
||||
@@ -84,8 +115,6 @@
|
||||
current.throw_alert("clockinfo", /obj/screen/alert/clockwork/infodump)
|
||||
if(!GLOB.clockwork_gateway_activated)
|
||||
current.throw_alert("scripturereq", /obj/screen/alert/clockwork/scripture_reqs)
|
||||
update_slab_info()
|
||||
|
||||
|
||||
/datum/antagonist/clockcult/remove_innate_effects(mob/living/mob_override)
|
||||
var/mob/living/current = owner.current
|
||||
@@ -102,7 +131,9 @@
|
||||
var/mob/living/silicon/S = current
|
||||
if(isAI(S))
|
||||
var/mob/living/silicon/ai/A = S
|
||||
A.can_be_carded = initial(A.can_be_carded)
|
||||
A.requires_power = initial(A.requires_power)
|
||||
A.cut_overlays()
|
||||
S.make_laws()
|
||||
S.update_icons()
|
||||
S.show_laws()
|
||||
@@ -113,13 +144,16 @@
|
||||
R.module.rebuild_modules()
|
||||
if(temp_owner)
|
||||
temp_owner.update_action_buttons_icon() //because a few clockcult things are action buttons and we may be wearing/holding them, we need to update buttons
|
||||
update_slab_info()
|
||||
|
||||
/datum/antagonist/clockcult/on_removal()
|
||||
. = ..()
|
||||
SSticker.mode.servants_of_ratvar -= owner
|
||||
SSticker.mode.update_servant_icons_removed(owner)
|
||||
if(!silent)
|
||||
owner.current.visible_message("<span class='big'>[owner] seems to have remembered their true allegiance!</span>", \
|
||||
"<span class='userdanger'>A cold, cold darkness flows through your mind, extinguishing the Justiciar's light and all of your memories as his servant.</span>")
|
||||
owner.current.log_message("<font color=#BE8700>Has renounced the cult of Ratvar!</font>", INDIVIDUAL_ATTACK_LOG)
|
||||
owner.wipe_memory()
|
||||
owner.special_role = null
|
||||
if(iscyborg(owner.current))
|
||||
to_chat(owner.current, "<span class='warning'>Despite your freedom from Ratvar's influence, you are still irreparably damaged and no longer possess certain functions such as AI linking.</span>")
|
||||
to_chat(owner.current, "<span class='warning'>Despite your freedom from Ratvar's influence, you are still irreparably damaged and no longer possess certain functions such as AI linking.</span>")
|
||||
. = ..()
|
||||
|
||||
@@ -5,29 +5,46 @@
|
||||
qdel(communion)
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/cult/can_be_owned(datum/mind/new_owner)
|
||||
. = ..()
|
||||
if(.)
|
||||
. = is_convertable_to_cult(new_owner.current)
|
||||
|
||||
/datum/antagonist/cult/on_gain()
|
||||
. = ..()
|
||||
if(!owner)
|
||||
return
|
||||
SSticker.mode.cult += owner
|
||||
SSticker.mode.update_cult_icons_added(owner)
|
||||
if(istype(SSticker.mode, /datum/game_mode/cult))
|
||||
var/datum/game_mode/cult/C = SSticker.mode
|
||||
C.memorize_cult_objectives(owner)
|
||||
if(jobban_isbanned(owner.current, ROLE_CULTIST))
|
||||
addtimer(CALLBACK(SSticker.mode, /datum/game_mode.proc/replace_jobbaned_player, owner, ROLE_CULTIST, ROLE_CULTIST), 0)
|
||||
addtimer(CALLBACK(SSticker.mode, /datum/game_mode.proc/replace_jobbaned_player, owner.current, ROLE_CULTIST, ROLE_CULTIST), 0)
|
||||
owner.current.log_message("<font color=#960000>Has been converted to the cult of Nar'Sie!</font>", INDIVIDUAL_ATTACK_LOG)
|
||||
|
||||
/datum/antagonist/cult/apply_innate_effects()
|
||||
/datum/antagonist/cult/apply_innate_effects(mob/living/mob_override)
|
||||
. = ..()
|
||||
owner.current.faction |= "cult"
|
||||
owner.current.verbs += /mob/living/proc/cult_help
|
||||
communion.Grant(owner)
|
||||
var/mob/living/current = owner.current
|
||||
if(mob_override)
|
||||
current = mob_override
|
||||
current.faction |= "cult"
|
||||
current.verbs += /mob/living/proc/cult_help
|
||||
communion.Grant(current)
|
||||
|
||||
/datum/antagonist/cult/remove_innate_effects()
|
||||
/datum/antagonist/cult/remove_innate_effects(mob/living/mob_override)
|
||||
. = ..()
|
||||
owner.current.faction -= "cult"
|
||||
owner.current.verbs -= /mob/living/proc/cult_help
|
||||
|
||||
var/mob/living/current = owner.current
|
||||
if(mob_override)
|
||||
current = mob_override
|
||||
current.faction -= "cult"
|
||||
current.verbs -= /mob/living/proc/cult_help
|
||||
communion.Remove(current)
|
||||
|
||||
/datum/antagonist/cult/on_removal()
|
||||
. = ..()
|
||||
owner.wipe_memory()
|
||||
SSticker.mode.cult -= owner
|
||||
SSticker.mode.update_cult_icons_removed(owner)
|
||||
to_chat(owner, "<span class='userdanger'>An unfamiliar white light flashes through your mind, cleansing the taint of the Dark One and all your memories as its servant.</span>")
|
||||
owner.current.log_message("<font color=#960000>Has renounced the cult of Nar'Sie!</font>", INDIVIDUAL_ATTACK_LOG)
|
||||
if(!silent)
|
||||
owner.current.visible_message("<span class='big'>[owner] looks like [owner.current.p_they()] just reverted to their old faith!</span>")
|
||||
owner.current.visible_message("<span class='big'>[owner] looks like [owner.current.p_they()] just reverted to their old faith!</span>")
|
||||
. = ..()
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
#define HOLOPAD_MAX_DIAL_TIME 200
|
||||
|
||||
/mob/camera/aiEye/remote/holo/setLoc()
|
||||
. = ..()
|
||||
var/obj/machinery/holopad/H = origin
|
||||
H.move_hologram(eye_user, loc)
|
||||
|
||||
//this datum manages it's own references
|
||||
|
||||
/datum/holocall
|
||||
var/mob/living/user //the one that called
|
||||
var/obj/machinery/holopad/calling_holopad //the one that sent the call
|
||||
var/obj/machinery/holopad/connected_holopad //the one that answered the call (may be null)
|
||||
var/list/dialed_holopads //all things called, will be cleared out to just connected_holopad once answered
|
||||
|
||||
var/mob/camera/aiEye/remote/holo/eye //user's eye, once connected
|
||||
var/obj/effect/overlay/holo_pad_hologram/hologram //user's hologram, once connected
|
||||
|
||||
var/call_start_time
|
||||
|
||||
//creates a holocall made by `caller` from `calling_pad` to `callees`
|
||||
/datum/holocall/New(mob/living/caller, obj/machinery/holopad/calling_pad, list/callees)
|
||||
call_start_time = world.time
|
||||
user = caller
|
||||
calling_pad.outgoing_call = src
|
||||
calling_holopad = calling_pad
|
||||
dialed_holopads = list()
|
||||
|
||||
for(var/I in callees)
|
||||
var/obj/machinery/holopad/H = I
|
||||
if(!QDELETED(H) && H.is_operational())
|
||||
dialed_holopads += H
|
||||
LAZYADD(H.holo_calls, src)
|
||||
|
||||
if(!dialed_holopads.len)
|
||||
calling_pad.say("Connection failure.")
|
||||
qdel(src)
|
||||
|
||||
testing("Holocall started")
|
||||
|
||||
//cleans up ALL references :)
|
||||
/datum/holocall/Destroy()
|
||||
QDEL_NULL(eye)
|
||||
|
||||
user.reset_perspective()
|
||||
|
||||
user = null
|
||||
hologram.HC = null
|
||||
hologram = null
|
||||
calling_holopad.outgoing_call = null
|
||||
|
||||
for(var/I in dialed_holopads)
|
||||
var/obj/machinery/holopad/H = I
|
||||
LAZYREMOVE(H.holo_calls, src)
|
||||
dialed_holopads.Cut()
|
||||
|
||||
if(calling_holopad)
|
||||
calling_holopad.SetLightsAndPower()
|
||||
calling_holopad = null
|
||||
if(connected_holopad)
|
||||
connected_holopad.SetLightsAndPower()
|
||||
connected_holopad = null
|
||||
|
||||
testing("Holocall destroyed")
|
||||
|
||||
return ..()
|
||||
|
||||
//Gracefully disconnects a holopad `H` from a call. Pads not in the call are ignored. Notifies participants of the disconnection
|
||||
/datum/holocall/proc/Disconnect(obj/machinery/holopad/H)
|
||||
testing("Holocall disconnect")
|
||||
if(H == connected_holopad)
|
||||
calling_holopad.say("[usr] disconnected.")
|
||||
else if(H == calling_holopad && connected_holopad)
|
||||
connected_holopad.say("[usr] disconnected.")
|
||||
|
||||
ConnectionFailure(H, TRUE)
|
||||
|
||||
//Forcefully disconnects a holopad `H` from a call. Pads not in the call are ignored.
|
||||
/datum/holocall/proc/ConnectionFailure(obj/machinery/holopad/H, graceful = FALSE)
|
||||
testing("Holocall connection failure: graceful [graceful]")
|
||||
if(H == connected_holopad || H == calling_holopad)
|
||||
if(!graceful)
|
||||
calling_holopad.say("Connection failure.")
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
LAZYREMOVE(H.holo_calls, src)
|
||||
dialed_holopads -= H
|
||||
if(!dialed_holopads.len)
|
||||
if(graceful)
|
||||
calling_holopad.say("Call rejected.")
|
||||
testing("No recipients, terminating")
|
||||
qdel(src)
|
||||
|
||||
//Answers a call made to a holopad `H` which cannot be the calling holopad. Pads not in the call are ignored
|
||||
/datum/holocall/proc/Answer(obj/machinery/holopad/H)
|
||||
testing("Holocall answer")
|
||||
if(H == calling_holopad)
|
||||
CRASH("How cute, a holopad tried to answer itself.")
|
||||
|
||||
if(!(H in dialed_holopads))
|
||||
return
|
||||
|
||||
if(connected_holopad)
|
||||
CRASH("Multi-connection holocall")
|
||||
|
||||
connected_holopad = H
|
||||
for(var/I in dialed_holopads)
|
||||
if(I == H)
|
||||
continue
|
||||
var/obj/machinery/holopad/Holo = I
|
||||
LAZYREMOVE(Holo.holo_calls, src)
|
||||
dialed_holopads -= Holo
|
||||
|
||||
for(var/I in H.holo_calls)
|
||||
var/datum/holocall/HC = I
|
||||
if(HC != src)
|
||||
HC.Disconnect(H)
|
||||
|
||||
if(!Check())
|
||||
return
|
||||
|
||||
hologram = H.activate_holo(user)
|
||||
hologram.HC = src
|
||||
|
||||
//eyeobj code is horrid, this is the best copypasta I could make
|
||||
eye = new
|
||||
eye.origin = H
|
||||
eye.eye_initialized = TRUE
|
||||
eye.eye_user = user
|
||||
eye.name = "Camera Eye ([user.name])"
|
||||
user.remote_control = eye
|
||||
user.reset_perspective(eye)
|
||||
eye.setLoc(H.loc)
|
||||
|
||||
//Checks the validity of a holocall and qdels itself if it's not. Returns TRUE if valid, FALSE otherwise
|
||||
/datum/holocall/proc/Check()
|
||||
for(var/I in dialed_holopads)
|
||||
var/obj/machinery/holopad/H = I
|
||||
if(!H.is_operational())
|
||||
ConnectionFailure(H)
|
||||
|
||||
if(QDELETED(src))
|
||||
return FALSE
|
||||
|
||||
. = !QDELETED(user) && !user.incapacitated() && !QDELETED(calling_holopad) && calling_holopad.is_operational() && user.loc == calling_holopad.loc
|
||||
|
||||
if(.)
|
||||
if(connected_holopad)
|
||||
. = !QDELETED(connected_holopad) && connected_holopad.is_operational()
|
||||
else
|
||||
. = world.time < (call_start_time + HOLOPAD_MAX_DIAL_TIME)
|
||||
if(!.)
|
||||
calling_holopad.say("No answer recieved.")
|
||||
calling_holopad.temp = ""
|
||||
|
||||
if(!.)
|
||||
testing("Holocall Check fail")
|
||||
qdel(src)
|
||||
+13
-21
@@ -44,9 +44,7 @@
|
||||
var/datum/job/assigned_job
|
||||
|
||||
var/list/datum/objective/objectives = list()
|
||||
var/list/datum/objective/special_verbs = list()
|
||||
|
||||
var/list/cult_words = list()
|
||||
var/list/spell_list = list() // Wizard mode & "Give Spell" badmin button.
|
||||
|
||||
var/datum/faction/faction //associated faction
|
||||
@@ -54,7 +52,7 @@
|
||||
var/linglink
|
||||
|
||||
var/miming = 0 // Mime's vow of silence
|
||||
var/list/antag_datums = list()
|
||||
var/list/antag_datums
|
||||
var/antag_hud_icon_state = null //this mind's ANTAG_HUD should have this icon_state
|
||||
var/datum/atom_hud/antag/antag_hud = null //this mind's antag HUD
|
||||
var/datum/gang/gang_datum //Which gang this mind belongs to, if any
|
||||
@@ -71,6 +69,10 @@
|
||||
|
||||
/datum/mind/Destroy()
|
||||
SSticker.minds -= src
|
||||
if(islist(antag_datums))
|
||||
for(var/i in antag_datums)
|
||||
qdel(i)
|
||||
antag_datums = null
|
||||
return ..()
|
||||
|
||||
/datum/mind/proc/transfer_to(mob/new_character, var/force_key_move = 0)
|
||||
@@ -110,15 +112,16 @@
|
||||
memory = null
|
||||
|
||||
// Datum antag mind procs
|
||||
/datum/mind/proc/add_antag_datum(datum_type, on_gain = TRUE)
|
||||
/datum/mind/proc/add_antag_datum(datum_type)
|
||||
if(!datum_type)
|
||||
return
|
||||
if(!can_hold_antag_datum(datum_type))
|
||||
return
|
||||
var/datum/antagonist/A = new datum_type(src)
|
||||
antag_datums += A
|
||||
if(on_gain)
|
||||
A.on_gain()
|
||||
if(!A.can_be_owned(src))
|
||||
qdel(A)
|
||||
return
|
||||
LAZYADD(antag_datums, A)
|
||||
A.on_gain()
|
||||
return A
|
||||
|
||||
/datum/mind/proc/remove_antag_datum(datum_type)
|
||||
if(!datum_type)
|
||||
@@ -126,6 +129,7 @@
|
||||
var/datum/antagonist/A = has_antag_datum(datum_type)
|
||||
if(A)
|
||||
A.on_removal()
|
||||
return TRUE
|
||||
|
||||
/datum/mind/proc/remove_all_antag_datums() //For the Lazy amongst us.
|
||||
for(var/a in antag_datums)
|
||||
@@ -143,18 +147,6 @@
|
||||
else if(A.type == datum_type)
|
||||
return A
|
||||
|
||||
/datum/mind/proc/can_hold_antag_datum(datum_type)
|
||||
if(!datum_type)
|
||||
return
|
||||
. = TRUE
|
||||
if(has_antag_datum(datum_type))
|
||||
return FALSE
|
||||
for(var/i in antag_datums)
|
||||
var/datum/antagonist/A = i
|
||||
if(is_type_in_typecache(A, A.typecache_datum_blacklist))
|
||||
return FALSE
|
||||
|
||||
|
||||
/*
|
||||
Removes antag type's references from a mind.
|
||||
objectives, uplinks, powers etc are all handled.
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
However, all the inhabitants seem to do is grow drugs and guns."
|
||||
suffix = "lavaland_surface_seed_vault.dmm"
|
||||
cost = 10
|
||||
allow_duplicates = FALSE
|
||||
|
||||
/datum/map_template/ruin/lavaland/ash_walker
|
||||
name = "Ash Walker Nest"
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
var/status_type = STATUS_EFFECT_UNIQUE //How many of the effect can be on one mob, and what happens when you try to add another
|
||||
var/on_remove_on_mob_delete = FALSE //if we call on_remove() when the mob is deleted
|
||||
var/alert_type = /obj/screen/alert/status_effect //the alert thrown by the status effect, contains name and description
|
||||
var/obj/screen/alert/status_effect/linked_alert = null //the alert itself, if it exists
|
||||
|
||||
/datum/status_effect/New(mob/living/new_owner)
|
||||
if(new_owner)
|
||||
@@ -40,6 +41,7 @@
|
||||
if(alert_type)
|
||||
var/obj/screen/alert/status_effect/A = owner.throw_alert(id, alert_type)
|
||||
A.attached_effect = src //so the alert can reference us, if it needs to
|
||||
linked_alert = A //so we can reference the alert, if we need to
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
|
||||
/datum/status_effect/process()
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
var/req_dna = 0 //amount of dna needed to use this ability. Changelings always have atleast 1
|
||||
var/req_human = 0 //if you need to be human to use this ability
|
||||
var/req_stat = CONSCIOUS // CONSCIOUS, UNCONSCIOUS or DEAD
|
||||
var/genetic_damage = 0 // genetic damage caused by using the sting. Nothing to do with cloneloss.
|
||||
var/max_genetic_damage = 100 // hard counter for spamming abilities. Not used/balanced much yet.
|
||||
var/always_keep = 0 // important for abilities like revive that screw you if you lose them.
|
||||
var/ignores_fakedeath = FALSE // usable with the FAKEDEATH flag
|
||||
|
||||
@@ -39,7 +37,7 @@
|
||||
if(sting_action(user, target))
|
||||
SSblackbox.add_details("changeling_powers",name)
|
||||
sting_feedback(user, target)
|
||||
take_chemical_cost(c)
|
||||
c.chem_charges -= chemical_cost
|
||||
|
||||
/obj/effect/proc_holder/changeling/proc/sting_action(mob/user, mob/target)
|
||||
return 0
|
||||
@@ -47,10 +45,6 @@
|
||||
/obj/effect/proc_holder/changeling/proc/sting_feedback(mob/user, mob/target)
|
||||
return 0
|
||||
|
||||
/obj/effect/proc_holder/changeling/proc/take_chemical_cost(datum/changeling/changeling)
|
||||
changeling.chem_charges -= chemical_cost
|
||||
changeling.geneticdamage += genetic_damage
|
||||
|
||||
//Fairly important to remember to return 1 on success >.<
|
||||
/obj/effect/proc_holder/changeling/proc/can_sting(mob/user, mob/target)
|
||||
if(!ishuman(user) && !ismonkey(user)) //typecast everything from mob to carbon from this point onwards
|
||||
@@ -71,9 +65,6 @@
|
||||
if((user.status_flags & FAKEDEATH) && (!ignores_fakedeath))
|
||||
to_chat(user, "<span class='warning'>We are incapacitated.</span>")
|
||||
return 0
|
||||
if(c.geneticdamage > max_genetic_damage)
|
||||
to_chat(user, "<span class='warning'>Our genomes are still reassembling. We need time to recover first.</span>")
|
||||
return 0
|
||||
return 1
|
||||
|
||||
//used in /mob/Stat()
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
chemical_cost = 0
|
||||
dna_cost = 0
|
||||
req_human = 1
|
||||
max_genetic_damage = 100
|
||||
|
||||
/obj/effect/proc_holder/changeling/absorbDNA/can_sting(mob/living/carbon/user)
|
||||
if(!..())
|
||||
|
||||
@@ -5,9 +5,6 @@
|
||||
chemical_cost = 30 //High cost to prevent spam
|
||||
dna_cost = 2
|
||||
req_human = 1
|
||||
genetic_damage = 10
|
||||
max_genetic_damage = 0
|
||||
|
||||
|
||||
/obj/effect/proc_holder/changeling/biodegrade/sting_action(mob/living/carbon/human/user)
|
||||
var/used = FALSE // only one form of shackles removed per use
|
||||
|
||||
@@ -5,9 +5,6 @@
|
||||
dna_cost = 2
|
||||
chemical_cost = 25
|
||||
req_human = 1
|
||||
genetic_damage = 10
|
||||
max_genetic_damage = 50
|
||||
|
||||
|
||||
/obj/effect/proc_holder/changeling/chameleon_skin/sting_action(mob/user)
|
||||
var/mob/living/carbon/human/H = user //SHOULD always be human, because req_human = 1
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
dna_cost = 0
|
||||
req_dna = 1
|
||||
req_stat = DEAD
|
||||
max_genetic_damage = 100
|
||||
|
||||
|
||||
//Fake our own death and fully heal. You will appear to be dead but regenerate fully after a short delay.
|
||||
/obj/effect/proc_holder/changeling/fakedeath/sting_action(mob/living/user)
|
||||
|
||||
@@ -2,10 +2,7 @@
|
||||
name = "Human Form"
|
||||
desc = "We change into a human."
|
||||
chemical_cost = 5
|
||||
genetic_damage = 3
|
||||
req_dna = 1
|
||||
max_genetic_damage = 3
|
||||
|
||||
|
||||
//Transform into a human.
|
||||
/obj/effect/proc_holder/changeling/humanform/sting_action(mob/living/carbon/user)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
desc = "We debase ourselves and become lesser. We become a monkey."
|
||||
chemical_cost = 5
|
||||
dna_cost = 1
|
||||
genetic_damage = 3
|
||||
req_human = 1
|
||||
|
||||
//Transform into a monkey.
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
chemical_cost = 0
|
||||
dna_cost = 0
|
||||
req_human = 1
|
||||
max_genetic_damage = 100
|
||||
|
||||
/obj/effect/proc_holder/changeling/linglink/can_sting(mob/living/carbon/user)
|
||||
if(!..())
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
helptext = "Yell at Miauw and/or Perakp"
|
||||
chemical_cost = 1000
|
||||
dna_cost = -1
|
||||
genetic_damage = 1000
|
||||
|
||||
var/silent = FALSE
|
||||
var/weapon_type
|
||||
@@ -67,7 +66,6 @@
|
||||
helptext = "Yell at Miauw and/or Perakp"
|
||||
chemical_cost = 1000
|
||||
dna_cost = -1
|
||||
genetic_damage = 1000
|
||||
|
||||
var/helmet_type = /obj/item
|
||||
var/suit_type = /obj/item
|
||||
@@ -89,7 +87,7 @@
|
||||
return 1
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(istype(H.wear_suit, suit_type) || istype(H.head, helmet_type))
|
||||
H.visible_message("<span class='warning'>[H] casts off their [suit_name_simple]!</span>", "<span class='warning'>We cast off our [suit_name_simple][genetic_damage > 0 ? ", temporarily weakening our genomes." : "."]</span>", "<span class='italics'>You hear the organic matter ripping and tearing!</span>")
|
||||
H.visible_message("<span class='warning'>[H] casts off their [suit_name_simple]!</span>", "<span class='warning'>We cast off our [suit_name_simple].</span>", "<span class='italics'>You hear the organic matter ripping and tearing!</span>")
|
||||
H.temporarilyRemoveItemFromInventory(H.head, TRUE) //The qdel on dropped() takes care of it
|
||||
H.temporarilyRemoveItemFromInventory(H.wear_suit, TRUE)
|
||||
H.update_inv_wear_suit()
|
||||
@@ -100,7 +98,6 @@
|
||||
H.add_splatter_floor()
|
||||
playsound(H.loc, 'sound/effects/splat.ogg', 50, 1) //So real sounds
|
||||
|
||||
changeling.geneticdamage += genetic_damage //Casting off a space suit leaves you weak for a few seconds.
|
||||
changeling.chem_recharge_slowdown -= recharge_slowdown
|
||||
return 1
|
||||
|
||||
@@ -139,9 +136,7 @@
|
||||
helptext = "We may retract our armblade in the same manner as we form it. Cannot be used while in lesser form."
|
||||
chemical_cost = 20
|
||||
dna_cost = 2
|
||||
genetic_damage = 10
|
||||
req_human = 1
|
||||
max_genetic_damage = 20
|
||||
weapon_type = /obj/item/weapon/melee/arm_blade
|
||||
weapon_name_simple = "blade"
|
||||
|
||||
@@ -217,9 +212,7 @@
|
||||
and Harm will stun it, and stab it if we're also holding a sharp weapon. Cannot be used while in lesser form."
|
||||
chemical_cost = 10
|
||||
dna_cost = 2
|
||||
genetic_damage = 5
|
||||
req_human = 1
|
||||
max_genetic_damage = 10
|
||||
weapon_type = /obj/item/weapon/gun/magic/tentacle
|
||||
weapon_name_simple = "tentacle"
|
||||
silent = TRUE
|
||||
@@ -381,9 +374,7 @@
|
||||
helptext = "Organic tissue cannot resist damage forever; the shield will break after it is hit too much. The more genomes we absorb, the stronger it is. Cannot be used while in lesser form."
|
||||
chemical_cost = 20
|
||||
dna_cost = 1
|
||||
genetic_damage = 12
|
||||
req_human = 1
|
||||
max_genetic_damage = 20
|
||||
|
||||
weapon_type = /obj/item/weapon/shield/changeling
|
||||
weapon_name_simple = "shield"
|
||||
@@ -430,12 +421,10 @@
|
||||
/obj/effect/proc_holder/changeling/suit/organic_space_suit
|
||||
name = "Organic Space Suit"
|
||||
desc = "We grow an organic suit to protect ourselves from space exposure."
|
||||
helptext = "We must constantly repair our form to make it space-proof, reducing chemical production while we are protected. Retreating the suit damages our genomes. Cannot be used in lesser form."
|
||||
helptext = "We must constantly repair our form to make it space-proof, reducing chemical production while we are protected. Cannot be used in lesser form."
|
||||
chemical_cost = 20
|
||||
dna_cost = 2
|
||||
genetic_damage = 8
|
||||
req_human = 1
|
||||
max_genetic_damage = 20
|
||||
|
||||
suit_type = /obj/item/clothing/suit/space/changeling
|
||||
helmet_type = /obj/item/clothing/head/helmet/space/changeling
|
||||
@@ -477,12 +466,10 @@
|
||||
/obj/effect/proc_holder/changeling/suit/armor
|
||||
name = "Chitinous Armor"
|
||||
desc = "We turn our skin into tough chitin to protect us from damage."
|
||||
helptext = "Upkeep of the armor requires a low expenditure of chemicals. The armor is strong against brute force, but does not provide much protection from lasers. Retreating the armor damages our genomes. Cannot be used in lesser form."
|
||||
helptext = "Upkeep of the armor requires a low expenditure of chemicals. The armor is strong against brute force, but does not provide much protection from lasers. Cannot be used in lesser form."
|
||||
chemical_cost = 20
|
||||
dna_cost = 1
|
||||
genetic_damage = 11
|
||||
req_human = 1
|
||||
max_genetic_damage = 20
|
||||
recharge_slowdown = 0.25
|
||||
|
||||
suit_type = /obj/item/clothing/suit/armor/changeling
|
||||
|
||||
@@ -40,10 +40,9 @@
|
||||
return
|
||||
if(!AStar(user, target.loc, /turf/proc/Distance, user.mind.changeling.sting_range, simulated_only = 0))
|
||||
return
|
||||
if(target.mind && target.mind.changeling)
|
||||
sting_feedback(user,target)
|
||||
take_chemical_cost(user.mind.changeling)
|
||||
return
|
||||
if(target.mind && target.mind.changeling)
|
||||
sting_feedback(user, target)
|
||||
user.mind.changeling.chem_charges -= chemical_cost
|
||||
return 1
|
||||
|
||||
/obj/effect/proc_holder/changeling/sting/sting_feedback(mob/user, mob/target)
|
||||
@@ -62,7 +61,6 @@
|
||||
sting_icon = "sting_transform"
|
||||
chemical_cost = 40
|
||||
dna_cost = 3
|
||||
genetic_damage = 100
|
||||
var/datum/changelingprofile/selected_dna = null
|
||||
|
||||
/obj/effect/proc_holder/changeling/sting/transformation/Click()
|
||||
@@ -117,8 +115,6 @@
|
||||
sting_icon = "sting_armblade"
|
||||
chemical_cost = 20
|
||||
dna_cost = 1
|
||||
genetic_damage = 20
|
||||
max_genetic_damage = 10
|
||||
|
||||
/obj/item/weapon/melee/arm_blade/false
|
||||
desc = "A grotesque mass of flesh that used to be your arm. Although it looks dangerous at first, you can tell it's actually quite dull and useless."
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
dna_cost = 0
|
||||
req_dna = 1
|
||||
req_human = 1
|
||||
max_genetic_damage = 3
|
||||
|
||||
/obj/item/clothing/glasses/changeling
|
||||
name = "flesh"
|
||||
|
||||
@@ -54,8 +54,11 @@
|
||||
clockwork_desc = "A sigil that will stun the next non-Servant to cross it."
|
||||
icon_state = "sigildull"
|
||||
layer = HIGH_SIGIL_LAYER
|
||||
alpha = 60
|
||||
alpha = 75
|
||||
color = "#FAE48C"
|
||||
light_range = 1.4
|
||||
light_power = 0.4
|
||||
light_color = "#FAE48C"
|
||||
sigil_name = "Sigil of Transgression"
|
||||
|
||||
/obj/effect/clockwork/sigil/transgression/sigil_effects(mob/living/L)
|
||||
|
||||
@@ -326,13 +326,19 @@
|
||||
if(production_time != SLAB_PRODUCTION_TIME+SLAB_SLOWDOWN_MAXIMUM)
|
||||
production_text_addon = ", which increases for each human or silicon servant above <b>[SCRIPT_SERVANT_REQ]</b>"
|
||||
production_time = production_time/600
|
||||
var/production_text = "<b>[round(production_time)] minute\s"
|
||||
var/list/production_text
|
||||
if(round(production_time))
|
||||
production_text = list("<b>[round(production_time)] minute\s")
|
||||
if(production_time != round(production_time))
|
||||
production_time -= round(production_time)
|
||||
production_time *= 60
|
||||
production_text += " and [round(production_time, 1)] second\s"
|
||||
if(!LAZYLEN(production_text))
|
||||
production_text = list("<b>[round(production_time, 1)] second\s")
|
||||
else
|
||||
production_text += " and [round(production_time, 1)] second\s"
|
||||
production_text += "</b>"
|
||||
production_text += production_text_addon
|
||||
production_text = production_text.Join()
|
||||
|
||||
textlist = list("<font color=#BE8700 size=3><b><center>Chetr nyy hagehguf-naq-ubabe Ratvar.</center></b></font><br>\
|
||||
\
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
speak_emote = list("clanks", "clinks", "clunks", "clangs")
|
||||
verb_ask = "requests"
|
||||
verb_exclaim = "proclaims"
|
||||
verb_whisper = "imparts"
|
||||
verb_yell = "harangues"
|
||||
initial_languages = list(/datum/language/common, /datum/language/ratvar)
|
||||
only_speaks_language = /datum/language/ratvar
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
It will penetrate mindshield implants once before disappearing."
|
||||
invocations = list("Divinity, enslave...", "...all who trespass here!")
|
||||
channel_time = 70
|
||||
consumed_components = list(BELLIGERENT_EYE = 2, GEIS_CAPACITOR = 1, HIEROPHANT_ANSIBLE = 1)
|
||||
consumed_components = list(BELLIGERENT_EYE = 4, GEIS_CAPACITOR = 2, HIEROPHANT_ANSIBLE = 2)
|
||||
whispered = TRUE
|
||||
object_path = /obj/effect/clockwork/sigil/submission/accession
|
||||
prevent_path = /obj/effect/clockwork/sigil/submission
|
||||
@@ -32,7 +32,7 @@
|
||||
It grows faster to invoke with more adjacent Servants."
|
||||
invocations = list("Shield us...", "...with the...", "... fragments of Engine!")
|
||||
channel_time = 100
|
||||
consumed_components = list(VANGUARD_COGWHEEL = 2, REPLICANT_ALLOY = 1, HIEROPHANT_ANSIBLE = 1)
|
||||
consumed_components = list(VANGUARD_COGWHEEL = 4, REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 2)
|
||||
usage_tip = "This scripture will replace all weaker armor worn by affected Servants."
|
||||
tier = SCRIPTURE_APPLICATION
|
||||
multiple_invokers_used = TRUE
|
||||
@@ -99,7 +99,7 @@
|
||||
If it remains close to you, you will gradually regain health up to a low amount, but it will die if it goes too far from you."
|
||||
invocations = list("Fright's will...", "...call forth...")
|
||||
channel_time = 100
|
||||
consumed_components = list(BELLIGERENT_EYE = 1, VANGUARD_COGWHEEL = 1, GEIS_CAPACITOR = 2)
|
||||
consumed_components = list(BELLIGERENT_EYE = 2, VANGUARD_COGWHEEL = 2, GEIS_CAPACITOR = 4)
|
||||
usage_tip = "Marauders are useful as personal bodyguards and frontline warriors."
|
||||
tier = SCRIPTURE_APPLICATION
|
||||
primary_component = GEIS_CAPACITOR
|
||||
@@ -160,7 +160,7 @@
|
||||
and exceptional speed, though taking damage will temporarily slow it down."
|
||||
invocations = list("Call forth...", "...the soldiers of Armorer.")
|
||||
channel_time = 80
|
||||
consumed_components = list(BELLIGERENT_EYE = 1, VANGUARD_COGWHEEL = 1, REPLICANT_ALLOY = 2)
|
||||
consumed_components = list(BELLIGERENT_EYE = 2, VANGUARD_COGWHEEL = 2, REPLICANT_ALLOY = 4)
|
||||
object_path = /obj/structure/destructible/clockwork/shell/fragment
|
||||
creator_message = "<span class='brass'>You form an anima fragment, a powerful soul vessel receptacle.</span>"
|
||||
observer_message = "<span class='warning'>The slab disgorges a puddle of black metal that expands and forms into a strange shell!</span>"
|
||||
@@ -179,7 +179,7 @@
|
||||
desc = "Places a sigil that stores energy to power clockwork structures."
|
||||
invocations = list("Divinity...", "...power our creations!")
|
||||
channel_time = 70
|
||||
consumed_components = list(VANGUARD_COGWHEEL = 1, GEIS_CAPACITOR = 1, HIEROPHANT_ANSIBLE = 2)
|
||||
consumed_components = list(VANGUARD_COGWHEEL = 2, GEIS_CAPACITOR = 2, HIEROPHANT_ANSIBLE = 4)
|
||||
whispered = TRUE
|
||||
object_path = /obj/effect/clockwork/sigil/transmission
|
||||
creator_message = "<span class='brass'>A sigil silently appears below you. It will automatically power clockwork structures near it.</span>"
|
||||
@@ -199,7 +199,7 @@
|
||||
desc = "Creates a clockwork totem that sabotages nearby machinery and funnels drained power into nearby Sigils of Transmission or the area's APC."
|
||||
invocations = list("May this totem...", "...shroud the false suns!")
|
||||
channel_time = 80
|
||||
consumed_components = list(BELLIGERENT_EYE = 3, REPLICANT_ALLOY = 1, HIEROPHANT_ANSIBLE = 1)
|
||||
consumed_components = list(BELLIGERENT_EYE = 5, REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 2)
|
||||
object_path = /obj/structure/destructible/clockwork/powered/interdiction_lens
|
||||
creator_message = "<span class='brass'>You form an interdiction lens, which disrupts cameras and radios and drains power.</span>"
|
||||
observer_message = "<span class='warning'>A brass totem rises from the ground, a purple gem appearing in its center!</span>"
|
||||
@@ -221,7 +221,7 @@
|
||||
desc = "Creates a mania motor which will cause brain damage and hallucinations in nearby non-Servant humans. It will also try to convert humans directly adjecent to the motor."
|
||||
invocations = list("May this transmitter...", "...break the will of all who oppose us!")
|
||||
channel_time = 80
|
||||
consumed_components = list(GEIS_CAPACITOR = 3, REPLICANT_ALLOY = 1, HIEROPHANT_ANSIBLE = 1)
|
||||
consumed_components = list(GEIS_CAPACITOR = 5, REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 2)
|
||||
object_path = /obj/structure/destructible/clockwork/powered/mania_motor
|
||||
creator_message = "<span class='brass'>You form a mania motor which will cause brain damage and hallucinations in nearby humans while active.</span>"
|
||||
observer_message = "<span class='warning'>A two-pronged machine rises from the ground!</span>"
|
||||
@@ -244,7 +244,7 @@
|
||||
and there is at least one existing cache."
|
||||
invocations = list("May this generator...", "...collect Engine parts that yet hold greatness!")
|
||||
channel_time = 80
|
||||
consumed_components = list(BELLIGERENT_EYE = 1, GEIS_CAPACITOR = 1, REPLICANT_ALLOY = 3)
|
||||
consumed_components = list(BELLIGERENT_EYE = 2, GEIS_CAPACITOR = 2, REPLICANT_ALLOY = 5)
|
||||
object_path = /obj/structure/destructible/clockwork/powered/tinkerers_daemon
|
||||
creator_message = "<span class='brass'>You form a tinkerer's daemon which can rapidly collect components at a power cost.</span>"
|
||||
invokers_required = 2
|
||||
@@ -278,7 +278,7 @@
|
||||
desc = "Creates a clockwork obelisk that can broadcast messages over the Hierophant Network or open a Spatial Gateway to any living Servant or clockwork obelisk."
|
||||
invocations = list("May this obelisk...", "...take us to all places!")
|
||||
channel_time = 80
|
||||
consumed_components = list(BELLIGERENT_EYE = 1, VANGUARD_COGWHEEL = 1, HIEROPHANT_ANSIBLE = 3)
|
||||
consumed_components = list(BELLIGERENT_EYE = 2, VANGUARD_COGWHEEL = 2, HIEROPHANT_ANSIBLE = 5)
|
||||
object_path = /obj/structure/destructible/clockwork/powered/clockwork_obelisk
|
||||
creator_message = "<span class='brass'>You form a clockwork obelisk which can broadcast messages or produce Spatial Gateways.</span>"
|
||||
observer_message = "<span class='warning'>A brass obelisk appears hanging in midair!</span>"
|
||||
|
||||
@@ -272,7 +272,7 @@
|
||||
var/static/prev_cost = 0
|
||||
|
||||
/datum/clockwork_scripture/create_object/tinkerers_cache/creation_update()
|
||||
var/cache_cost_increase = min(round(GLOB.clockwork_caches*0.25), 5)
|
||||
var/cache_cost_increase = min(round(GLOB.clockwork_caches*0.4), 10)
|
||||
if(cache_cost_increase != prev_cost)
|
||||
prev_cost = cache_cost_increase
|
||||
consumed_components = list(BELLIGERENT_EYE = 0, VANGUARD_COGWHEEL = 0, GEIS_CAPACITOR = 0, REPLICANT_ALLOY = 1, HIEROPHANT_ANSIBLE = 0)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
desc = "Taps the limitless power of Inath-neq, one of Ratvar's four generals. The benevolence of Inath-Neq will grant complete invulnerability to all Servants in range for fifteen seconds."
|
||||
invocations = list("I call upon you, Vanguard!!", "Let the Resonant Cogs turn once more!!", "Grant me and my allies the strength to vanquish our foes!!")
|
||||
channel_time = 100
|
||||
consumed_components = list(VANGUARD_COGWHEEL = 4, GEIS_CAPACITOR = 2, REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 2)
|
||||
consumed_components = list(VANGUARD_COGWHEEL = 10, GEIS_CAPACITOR = 3, REPLICANT_ALLOY = 3, HIEROPHANT_ANSIBLE = 3)
|
||||
usage_tip = "Servants affected by this scripture are only weak to things that outright destroy bodies, such as bombs or the singularity."
|
||||
tier = SCRIPTURE_REVENANT
|
||||
primary_component = VANGUARD_COGWHEEL
|
||||
@@ -44,7 +44,7 @@
|
||||
for all non-servant humans on the same z-level as them. The power of this scripture falls off somewhat with distance, and certain things may reduce its effects."
|
||||
invocations = list("I call upon you, Fright!!", "Let your power shatter the sanity of the weak-minded!!", "Let your tendrils hold sway over all!!")
|
||||
channel_time = 150
|
||||
consumed_components = list(BELLIGERENT_EYE = 3, VANGUARD_COGWHEEL = 3, GEIS_CAPACITOR = 6, HIEROPHANT_ANSIBLE = 3)
|
||||
consumed_components = list(BELLIGERENT_EYE = 6, VANGUARD_COGWHEEL = 6, GEIS_CAPACITOR = 10, HIEROPHANT_ANSIBLE = 6)
|
||||
usage_tip = "Causes brain damage, hallucinations, confusion, and dizziness in massive amounts."
|
||||
tier = SCRIPTURE_REVENANT
|
||||
sort_priority = 3
|
||||
@@ -108,7 +108,7 @@
|
||||
clockwork proselytizers will charge very rapidly."
|
||||
invocations = list("I call upon you, Armorer!!", "Let your machinations reign on this miserable station!!", "Let your power flow through the tools of your master!!")
|
||||
channel_time = 150
|
||||
consumed_components = list(BELLIGERENT_EYE = 3, VANGUARD_COGWHEEL = 3, GEIS_CAPACITOR = 3, REPLICANT_ALLOY = 6)
|
||||
consumed_components = list(BELLIGERENT_EYE = 6, VANGUARD_COGWHEEL = 6, GEIS_CAPACITOR = 6, REPLICANT_ALLOY = 10)
|
||||
usage_tip = "Ocular wardens will become empowered, clockwork proselytizers will require no alloy, tinkerer's daemons will produce twice as quickly, \
|
||||
and interdiction lenses, mania motors, tinkerer's daemons, and clockwork obelisks will all require no power."
|
||||
tier = SCRIPTURE_REVENANT
|
||||
@@ -153,7 +153,7 @@
|
||||
will be struck by devastating lightning bolts."
|
||||
invocations = list("I call upon you, Amperage!!", "Let your energy flow through me!!", "Let your boundless power shatter stars!!")
|
||||
channel_time = 100
|
||||
consumed_components = list(BELLIGERENT_EYE = 2, GEIS_CAPACITOR = 2, REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 4)
|
||||
consumed_components = list(BELLIGERENT_EYE = 3, GEIS_CAPACITOR = 3, REPLICANT_ALLOY = 3, HIEROPHANT_ANSIBLE = 10)
|
||||
usage_tip = "Struck targets will also be knocked down for about sixteen seconds."
|
||||
tier = SCRIPTURE_REVENANT
|
||||
primary_component = HIEROPHANT_ANSIBLE
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
desc = "Forms an automatic short-range turret which will automatically attack nearby unrestrained non-Servants that can see it."
|
||||
invocations = list("Guardians...", "...of the Engine...", "...defend us!")
|
||||
channel_time = 120
|
||||
consumed_components = list(BELLIGERENT_EYE = 1, REPLICANT_ALLOY = 1)
|
||||
consumed_components = list(BELLIGERENT_EYE = 2, REPLICANT_ALLOY = 1)
|
||||
object_path = /obj/structure/destructible/clockwork/ocular_warden
|
||||
creator_message = "<span class='brass'>You form an ocular warden, which will automatically attack nearby unrestrained non-Servants that can see it.</span>"
|
||||
observer_message = "<span class='warning'>A brass eye takes shape and slowly rises into the air, its red iris glaring!</span>"
|
||||
@@ -36,7 +36,7 @@
|
||||
desc = "Creates a small shell fitted for soul vessels. Adding an active soul vessel to it results in a small construct with tools and an inbuilt proselytizer."
|
||||
invocations = list("Call forth...", "...the workers of Armorer.")
|
||||
channel_time = 60
|
||||
consumed_components = list(BELLIGERENT_EYE = 1, HIEROPHANT_ANSIBLE = 1)
|
||||
consumed_components = list(BELLIGERENT_EYE = 2, HIEROPHANT_ANSIBLE = 1)
|
||||
object_path = /obj/structure/destructible/clockwork/shell/cogscarab
|
||||
creator_message = "<span class='brass'>You form a cogscarab, a constructor soul vessel receptacle.</span>"
|
||||
observer_message = "<span class='warning'>The slab disgorges a puddle of black metal that contracts and forms into a strange shell!</span>"
|
||||
@@ -56,7 +56,7 @@
|
||||
Matrices have drained from non-Servants. Dead Servants can be revived by this sigil if there is vitality equal to the target Servant's non-oxygen damage."
|
||||
invocations = list("Divinity...", "...steal their life...", "...for these shells!")
|
||||
channel_time = 60
|
||||
consumed_components = list(BELLIGERENT_EYE = 1, VANGUARD_COGWHEEL = 1)
|
||||
consumed_components = list(BELLIGERENT_EYE = 1, VANGUARD_COGWHEEL = 2)
|
||||
whispered = TRUE
|
||||
object_path = /obj/effect/clockwork/sigil/vitality
|
||||
creator_message = "<span class='brass'>A vitality matrix appears below you. It will drain life from non-Servants and heal Servants that cross it.</span>"
|
||||
@@ -77,7 +77,7 @@
|
||||
chant_invocations = list("Mend our dents!", "Heal our scratches!", "Repair our gears!")
|
||||
chant_amount = 10
|
||||
chant_interval = 20
|
||||
consumed_components = list(VANGUARD_COGWHEEL = 1, REPLICANT_ALLOY = 1)
|
||||
consumed_components = list(VANGUARD_COGWHEEL = 2, REPLICANT_ALLOY = 1)
|
||||
usage_tip = "This is a very effective way to rapidly reinforce a base after an attack."
|
||||
tier = SCRIPTURE_SCRIPT
|
||||
primary_component = VANGUARD_COGWHEEL
|
||||
@@ -177,6 +177,7 @@
|
||||
new /obj/effect/overlay/temp/heal(T, "#1E8CE1")
|
||||
else
|
||||
break
|
||||
new /obj/effect/overlay/temp/ratvar/mending_mantra(get_turf(invoker))
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -187,7 +188,7 @@
|
||||
desc = "Places a luminous sigil that will enslave any valid beings standing on it after a time."
|
||||
invocations = list("Divinity, enlighten...", "...those who trespass here!")
|
||||
channel_time = 60
|
||||
consumed_components = list(BELLIGERENT_EYE = 1, GEIS_CAPACITOR = 1)
|
||||
consumed_components = list(BELLIGERENT_EYE = 1, GEIS_CAPACITOR = 2)
|
||||
whispered = TRUE
|
||||
object_path = /obj/effect/clockwork/sigil/submission
|
||||
creator_message = "<span class='brass'>A luminous sigil appears below you. The next non-servant to cross it will be enslaved after a brief time if they do not move.</span>"
|
||||
@@ -207,7 +208,7 @@
|
||||
desc = "Forms an ancient positronic brain with an overriding directive to serve Ratvar."
|
||||
invocations = list("Herd the souls of...", "...the blasphemous damned!")
|
||||
channel_time = 30
|
||||
consumed_components = list(VANGUARD_COGWHEEL = 1, GEIS_CAPACITOR = 1)
|
||||
consumed_components = list(VANGUARD_COGWHEEL = 1, GEIS_CAPACITOR = 2)
|
||||
whispered = TRUE
|
||||
object_path = /obj/item/device/mmi/posibrain/soul_vessel
|
||||
creator_message = "<span class='brass'>You form a soul vessel, which can be used in-hand to attract spirits, or used on an unconscious or dead human to extract their consciousness.</span>"
|
||||
@@ -227,7 +228,7 @@
|
||||
desc = "Forms a device that, when used on certain objects, converts them into their Ratvarian equivalents. It requires power to function."
|
||||
invocations = list("With this device...", "...his presence shall be made known.")
|
||||
channel_time = 20
|
||||
consumed_components = list(GEIS_CAPACITOR = 1, REPLICANT_ALLOY = 1)
|
||||
consumed_components = list(GEIS_CAPACITOR = 1, REPLICANT_ALLOY = 2)
|
||||
whispered = TRUE
|
||||
object_path = /obj/item/clockwork/clockwork_proselytizer/preloaded
|
||||
creator_message = "<span class='brass'>You form a clockwork proselytizer.</span>"
|
||||
@@ -248,7 +249,7 @@
|
||||
vanish three minutes after being summoned."
|
||||
invocations = list("Grant me...", "...the might of brass!")
|
||||
channel_time = 20
|
||||
consumed_components = list(REPLICANT_ALLOY = 1, HIEROPHANT_ANSIBLE = 1)
|
||||
consumed_components = list(REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 1)
|
||||
whispered = TRUE
|
||||
usage_tip = "You can impale human targets with the spear by pulling them, then attacking. Throwing the spear at a mob will do massive damage and stun them, but break the spear."
|
||||
tier = SCRIPTURE_SCRIPT
|
||||
@@ -307,7 +308,7 @@
|
||||
Each servant assisting in the invocation adds one additional use and four additional seconds to the gateway's uses and duration."
|
||||
invocations = list("Spatial Gateway...", "...activate!")
|
||||
channel_time = 80
|
||||
consumed_components = list(VANGUARD_COGWHEEL = 1, HIEROPHANT_ANSIBLE = 1)
|
||||
consumed_components = list(VANGUARD_COGWHEEL = 1, HIEROPHANT_ANSIBLE = 2)
|
||||
multiple_invokers_used = TRUE
|
||||
multiple_invokers_optional = TRUE
|
||||
usage_tip = "This gateway is strictly one-way and will only allow things through the invoker's portal."
|
||||
@@ -356,7 +357,7 @@
|
||||
chant_invocations = list("Use charge to kill!", "Slay with power!", "Hunt with energy!")
|
||||
chant_amount = 4
|
||||
chant_interval = 5
|
||||
consumed_components = list(GEIS_CAPACITOR = 1, HIEROPHANT_ANSIBLE = 1)
|
||||
consumed_components = list(GEIS_CAPACITOR = 1, HIEROPHANT_ANSIBLE = 2)
|
||||
usage_tip = "Though it requires you to stand still, this scripture can do massive damage."
|
||||
tier = SCRIPTURE_SCRIPT
|
||||
primary_component = HIEROPHANT_ANSIBLE
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
var/mutable_appearance/alert_overlay = mutable_appearance('icons/effects/clockwork_effects.dmi', "ratvar_alert")
|
||||
var/area/A = get_area(src)
|
||||
notify_ghosts("The Justiciar's light calls to you! Reach out to Ratvar in [A.name] to be granted a shell to spread his glory!", null, source = src, alert_overlay = alert_overlay)
|
||||
INVOKE_ASYNC(SSshuttle.emergency, /obj/docking_port/mobile/emergency..proc/request, null, 0)
|
||||
INVOKE_ASYNC(SSshuttle.emergency, /obj/docking_port/mobile/emergency..proc/request, null, 0, 0)
|
||||
|
||||
/obj/structure/destructible/clockwork/massive/ratvar/Destroy()
|
||||
GLOB.ratvar_awakens--
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
var/static/mutable_appearance/component_glow = mutable_appearance('icons/obj/clockwork_objects.dmi', "t_random_component")
|
||||
var/component_id_to_produce
|
||||
var/production_time = 0 //last time we produced a component
|
||||
var/production_cooldown = 120
|
||||
var/production_cooldown = 60
|
||||
|
||||
/obj/structure/destructible/clockwork/powered/tinkerers_daemon/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -133,7 +133,7 @@ This file contains the arcane tome files.
|
||||
text += "<font color='red'><b>Talisman of Armaments</b></font><br>The Talisman of Arming will equip the user with armored robes, a backpack, an eldritch longsword, an empowered bola, and a pair of boots. Any items that cannot \
|
||||
be equipped will not be summoned. Attacking a fellow cultist with it will instead equip them.<br><br>"
|
||||
|
||||
text += "<font color='red'><b>Talisman of Horrors</b></font><br>The Talisman of Horror must be applied directly to the victim, it will shatter your victim's mind with visions of the endtimes that may incapitate them.<br><br>"
|
||||
text += "<font color='red'><b>Talisman of Horrors</b></font><br>The Talisman of Horror, unlike other talismans, can be applied at range, without the victim noticing. It will cause the victim to have severe hallucinations after a short while.<br><br>"
|
||||
|
||||
text += "<font color='red'><b>Talisman of Shackling</b></font><br>The Talisman of Shackling must be applied directly to the victim, it has 4 uses and cuffs victims with magic shackles that disappear when removed.<br><br>"
|
||||
|
||||
|
||||
@@ -293,12 +293,12 @@
|
||||
invocation = "Lo'Nab Na'Dm!"
|
||||
creation_time = 80
|
||||
|
||||
/obj/item/weapon/paper/talisman/horror/attack(mob/living/target, mob/living/user)
|
||||
if(iscultist(user))
|
||||
to_chat(user, "<span class='cultitalic'>You disturb [target] with visons of the end!</span>")
|
||||
/obj/item/weapon/paper/talisman/horror/afterattack(mob/living/target, mob/living/user)
|
||||
if(iscultist(user) && (get_dist(user, target) < 7))
|
||||
to_chat(user, "<span class='cultitalic'>You disturb [target] with visions of madness!</span>")
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/H = target
|
||||
H.reagents.add_reagent("mindbreaker", 25)
|
||||
H.reagents.add_reagent("mindbreaker", 12)
|
||||
if(is_servant_of_ratvar(target))
|
||||
to_chat(target, "<span class='userdanger'>You see a brief but horrible vision of Ratvar, rusted and scrapped, being torn apart.</span>")
|
||||
target.emote("scream")
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
var/list/territory = list()
|
||||
var/list/territory_new = list()
|
||||
var/list/territory_lost = list()
|
||||
var/recalls = 1
|
||||
var/dom_attempts = 2
|
||||
var/points = 15
|
||||
var/datum/atom_hud/antag/gang/ganghud
|
||||
@@ -262,4 +263,4 @@
|
||||
ganghud = new()
|
||||
|
||||
/datum/gang/multiverse/income()
|
||||
return
|
||||
return
|
||||
|
||||
@@ -168,6 +168,9 @@
|
||||
if(recalling)
|
||||
to_chat(usr, "<span class='warning'>Error: Recall already in progress.</span>")
|
||||
return 0
|
||||
|
||||
if(!gang.recalls)
|
||||
to_chat(usr, "<span class='warning'>Error: Unable to access communication arrays. Firewall has logged our signature and is blocking all further attempts.</span>")
|
||||
|
||||
gang.message_gangtools("[usr] is attempting to recall the emergency shuttle.")
|
||||
recalling = 1
|
||||
@@ -209,6 +212,7 @@
|
||||
userturf = get_turf(user)
|
||||
if(userturf.z == 1) //Check one more time that they are on station.
|
||||
if(SSshuttle.cancelEvac(user))
|
||||
gang.recalls -= 1
|
||||
return 1
|
||||
|
||||
to_chat(loc, "<span class='info'>\icon[src]No response recieved. Emergency shuttle cannot be recalled at this time.</span>")
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
var/icon_reveal = "revenant_revealed"
|
||||
var/icon_stun = "revenant_stun"
|
||||
var/icon_drain = "revenant_draining"
|
||||
var/stasis = 0
|
||||
incorporeal_move = 3
|
||||
invisibility = INVISIBILITY_REVENANT
|
||||
health = INFINITY //Revenants don't use health, they use essence instead
|
||||
@@ -94,6 +95,8 @@
|
||||
|
||||
//Life, Stat, Hud Updates, and Say
|
||||
/mob/living/simple_animal/revenant/Life()
|
||||
if(stasis)
|
||||
return
|
||||
if(revealed && essence <= 0)
|
||||
death()
|
||||
if(unreveal_time && world.time >= unreveal_time)
|
||||
@@ -200,9 +203,8 @@
|
||||
death()
|
||||
|
||||
/mob/living/simple_animal/revenant/death()
|
||||
if(!revealed || stat == DEAD) //Revenants cannot die if they aren't revealed //or are already dead
|
||||
if(!revealed || stasis) //Revenants cannot die if they aren't revealed //or are already dead
|
||||
return 0
|
||||
..(1)
|
||||
to_chat(src, "<span class='revendanger'>NO! No... it's too late, you can feel your essence [pick("breaking apart", "drifting away")]...</span>")
|
||||
notransform = TRUE
|
||||
revealed = TRUE
|
||||
@@ -217,9 +219,12 @@
|
||||
var/reforming_essence = essence_regen_cap //retain the gained essence capacity
|
||||
var/obj/item/weapon/ectoplasm/revenant/R = new(get_turf(src))
|
||||
R.essence = max(reforming_essence - 15 * perfectsouls, 75) //minus any perfect souls
|
||||
R.client_to_revive = src.client //If the essence reforms, the old revenant is put back in the body
|
||||
ghostize()
|
||||
qdel(src)
|
||||
R.client_to_revive = client //If the essence reforms, the old revenant is put back in the body
|
||||
R.revenant = src
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
revealed = 0
|
||||
stasis = 1
|
||||
ghostize(0)//Don't re-enter invisible corpse
|
||||
return
|
||||
|
||||
|
||||
@@ -302,6 +307,18 @@
|
||||
to_chat(src, "<span class='revenminor'>Lost [essence_amt]E[source ? " from [source]":""].</span>")
|
||||
return 1
|
||||
|
||||
/mob/living/simple_animal/revenant/proc/death_reset()
|
||||
revealed = FALSE
|
||||
unreveal_time = 0
|
||||
notransform = 0
|
||||
unstun_time = 0
|
||||
inhibited = FALSE
|
||||
draining = FALSE
|
||||
incorporeal_move = 3
|
||||
invisibility = INVISIBILITY_REVENANT
|
||||
alpha=255
|
||||
stasis = 0
|
||||
|
||||
|
||||
//reforming
|
||||
/obj/item/weapon/ectoplasm/revenant
|
||||
@@ -314,11 +331,15 @@
|
||||
var/reforming = TRUE
|
||||
var/inert = FALSE
|
||||
var/client/client_to_revive
|
||||
var/mob/living/simple_animal/revenant/revenant
|
||||
|
||||
/obj/item/weapon/ectoplasm/revenant/New()
|
||||
..()
|
||||
addtimer(CALLBACK(src, .proc/try_reform), 600)
|
||||
|
||||
/obj/item/weapon/ectoplasm/revenant/proc/scatter()
|
||||
qdel(src)
|
||||
|
||||
/obj/item/weapon/ectoplasm/revenant/proc/try_reform()
|
||||
if(reforming)
|
||||
reforming = FALSE
|
||||
@@ -333,14 +354,14 @@
|
||||
user.visible_message("<span class='notice'>[user] scatters [src] in all directions.</span>", \
|
||||
"<span class='notice'>You scatter [src] across the area. The particles slowly fade away.</span>")
|
||||
user.drop_item()
|
||||
qdel(src)
|
||||
scatter()
|
||||
|
||||
/obj/item/weapon/ectoplasm/revenant/throw_impact(atom/hit_atom)
|
||||
..()
|
||||
if(inert)
|
||||
return
|
||||
visible_message("<span class='notice'>[src] breaks into particles upon impact, which fade away to nothingness.</span>")
|
||||
qdel(src)
|
||||
scatter()
|
||||
|
||||
/obj/item/weapon/ectoplasm/revenant/examine(mob/user)
|
||||
..()
|
||||
@@ -350,47 +371,51 @@
|
||||
to_chat(user, "<span class='revenwarning'>It is shifting and distorted. It would be wise to destroy this.</span>")
|
||||
|
||||
/obj/item/weapon/ectoplasm/revenant/proc/reform()
|
||||
if(QDELETED(src) || inert)
|
||||
if(QDELETED(src) || QDELETED(revenant) || inert)
|
||||
return
|
||||
var/key_of_revenant
|
||||
message_admins("Revenant ectoplasm was left undestroyed for 1 minute and is reforming into a new revenant.")
|
||||
loc = get_turf(src) //In case it's in a backpack or someone's hand
|
||||
var/mob/living/simple_animal/revenant/R = new(get_turf(src))
|
||||
revenant.forceMove(loc)
|
||||
if(client_to_revive)
|
||||
for(var/mob/M in GLOB.dead_mob_list)
|
||||
if(M.client == client_to_revive) //Only recreates the mob if the mob the client is in is dead
|
||||
R.client = client_to_revive
|
||||
revenant.client = client_to_revive
|
||||
key_of_revenant = client_to_revive.key
|
||||
if(!key_of_revenant)
|
||||
message_admins("The new revenant's old client either could not be found or is in a new, living mob - grabbing a random candidate instead...")
|
||||
var/list/candidates = get_candidates(ROLE_REVENANT)
|
||||
var/list/candidates = pollCandidatesForMob("Do you want to be [revenant.name] (reforming)?", "revenant", null, ROLE_REVENANT, 50, revenant)
|
||||
if(!candidates.len)
|
||||
qdel(R)
|
||||
qdel(revenant)
|
||||
message_admins("No candidates were found for the new revenant. Oh well!")
|
||||
inert = TRUE
|
||||
visible_message("<span class='revenwarning'>[src] settles down and seems lifeless.</span>")
|
||||
return
|
||||
var/client/C = pick(candidates)
|
||||
revenant.client = C
|
||||
key_of_revenant = C.key
|
||||
if(!key_of_revenant)
|
||||
qdel(R)
|
||||
qdel(revenant)
|
||||
message_admins("No ckey was found for the new revenant. Oh well!")
|
||||
inert = TRUE
|
||||
visible_message("<span class='revenwarning'>[src] settles down and seems lifeless.</span>")
|
||||
return
|
||||
var/datum/mind/player_mind = new /datum/mind(key_of_revenant)
|
||||
R.essence_regen_cap = essence
|
||||
R.essence = R.essence_regen_cap
|
||||
player_mind.active = 1
|
||||
player_mind.transfer_to(R)
|
||||
player_mind.assigned_role = "revenant"
|
||||
player_mind.special_role = "Revenant"
|
||||
SSticker.mode.traitors |= player_mind
|
||||
|
||||
message_admins("[key_of_revenant] has been [client_to_revive ? "re":""]made into a revenant by reforming ectoplasm.")
|
||||
log_game("[key_of_revenant] was [client_to_revive ? "re":""]made as a revenant by reforming ectoplasm.")
|
||||
visible_message("<span class='revenboldnotice'>[src] suddenly rises into the air before fading away.</span>")
|
||||
|
||||
revenant.essence = essence
|
||||
revenant.essence_regen_cap = essence
|
||||
revenant.death_reset()
|
||||
revenant.key = key_of_revenant
|
||||
revenant = null
|
||||
qdel(src)
|
||||
|
||||
/obj/item/weapon/ectoplasm/revenant/Destroy()
|
||||
if(!QDELETED(revenant))
|
||||
qdel(revenant)
|
||||
..()
|
||||
|
||||
//objectives
|
||||
/datum/objective/revenant
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
var/atom/movable/constant_target = null //The thing we're always focused on, if we're in the right mode
|
||||
var/target_x = 0 //The target coordinates if we're tracking those
|
||||
var/target_y = 0
|
||||
var/minimum_range = 0 //at what range the pinpointer declares you to be at your destination
|
||||
var/nuke_warning = FALSE // If we've set off a miniature alarm about an armed nuke
|
||||
var/mode = TRACK_NUKE_DISK //What are we looking for?
|
||||
|
||||
@@ -111,7 +112,7 @@
|
||||
var/mob/living/closest_operative = get_closest_atom(/mob/living/carbon/human, possible_targets, here)
|
||||
if(closest_operative)
|
||||
target = closest_operative
|
||||
if(TRACK_ATOM)
|
||||
if(TRACK_ATOM)
|
||||
if(constant_target)
|
||||
target = constant_target
|
||||
if(TRACK_COORDINATES)
|
||||
@@ -129,7 +130,7 @@
|
||||
if(here.z != there.z)
|
||||
icon_state = "pinon[nuke_warning ? "alert" : ""]null"
|
||||
return
|
||||
if(here == there)
|
||||
if(get_dist_euclidian(here,there)<=minimum_range)
|
||||
icon_state = "pinon[nuke_warning ? "alert" : ""]direct"
|
||||
else
|
||||
setDir(get_dir(here, there))
|
||||
@@ -171,3 +172,6 @@
|
||||
desc = "An integrated tracking device, jury-rigged to search for living Syndicate operatives."
|
||||
mode = TRACK_OPERATIVES
|
||||
flags = NODROP
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -67,7 +67,14 @@
|
||||
/datum/objective/proc/update_explanation_text()
|
||||
//Default does nothing, override where needed
|
||||
|
||||
/datum/objective/proc/give_special_equipment()
|
||||
/datum/objective/proc/give_special_equipment(special_equipment)
|
||||
if(owner && owner.current)
|
||||
if(ishuman(owner.current))
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
var/list/slots = list ("backpack" = slot_in_backpack)
|
||||
for(var/eq_path in special_equipment)
|
||||
var/obj/O = new eq_path
|
||||
H.equip_in_one_of_slots(O, slots)
|
||||
|
||||
/datum/objective/assassinate
|
||||
var/target_role_type=0
|
||||
@@ -94,6 +101,14 @@
|
||||
else
|
||||
explanation_text = "Free Objective"
|
||||
|
||||
/datum/objective/assassinate/internal
|
||||
var/stolen = 0 //Have we already eliminated this target?
|
||||
|
||||
/datum/objective/assassinate/internal/update_explanation_text()
|
||||
..()
|
||||
if(target && !target.current)
|
||||
explanation_text = "Assassinate [target.name], who was obliterated"
|
||||
|
||||
|
||||
/datum/objective/mutiny
|
||||
var/target_role_type=0
|
||||
@@ -468,7 +483,7 @@ GLOBAL_LIST_EMPTY(possible_items)
|
||||
steal_target = targetinfo.targetitem
|
||||
explanation_text = "Steal [targetinfo.name]."
|
||||
dangerrating = targetinfo.difficulty
|
||||
give_special_equipment()
|
||||
give_special_equipment(targetinfo.special_equipment)
|
||||
return steal_target
|
||||
else
|
||||
explanation_text = "Free objective"
|
||||
@@ -511,15 +526,6 @@ GLOBAL_LIST_EMPTY(possible_items)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/objective/steal/give_special_equipment()
|
||||
if(owner && owner.current && targetinfo)
|
||||
if(ishuman(owner.current))
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
var/list/slots = list ("backpack" = slot_in_backpack)
|
||||
for(var/eq_path in targetinfo.special_equipment)
|
||||
var/obj/O = new eq_path
|
||||
H.equip_in_one_of_slots(O, slots)
|
||||
|
||||
|
||||
GLOBAL_LIST_EMPTY(possible_items_special)
|
||||
/datum/objective/steal/special //ninjas are so special they get their own subtype good for them
|
||||
@@ -695,6 +701,9 @@ GLOBAL_LIST_EMPTY(possible_items_special)
|
||||
explanation_text = "Destroy [target.name], the experimental AI."
|
||||
else
|
||||
explanation_text = "Free Objective"
|
||||
|
||||
/datum/objective/destroy/internal
|
||||
var/stolen = FALSE //Have we already eliminated this target?
|
||||
|
||||
/datum/objective/steal_five_of_type
|
||||
explanation_text = "Steal at least five items!"
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
#define PINPOINTER_MINIMUM_RANGE 15
|
||||
#define PINPOINTER_EXTRA_RANDOM_RANGE 10
|
||||
#define PINPOINTER_PING_TIME 40
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs
|
||||
name = "Internal Affairs"
|
||||
config_tag = "internal_affairs"
|
||||
employer = "Internal Affairs"
|
||||
required_players = 25
|
||||
required_enemies = 5
|
||||
required_players = 25
|
||||
required_enemies = 5
|
||||
recommended_enemies = 8
|
||||
reroll_friendly = 0
|
||||
traitor_name = "Nanotrasen Internal Affairs Agent"
|
||||
@@ -18,15 +22,189 @@
|
||||
var/list/target_list = list()
|
||||
var/list/late_joining_list = list()
|
||||
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs/post_setup()
|
||||
var/i = 0
|
||||
for(var/datum/mind/traitor in traitors)
|
||||
i++
|
||||
if(i + 1 > traitors.len)
|
||||
i = 0
|
||||
target_list[traitor] = traitors[i + 1]
|
||||
target_list[traitor] = traitors[i+1]
|
||||
..()
|
||||
|
||||
|
||||
/datum/status_effect/agent_pinpointer
|
||||
id = "agent_pinpointer"
|
||||
duration = -1
|
||||
tick_interval = PINPOINTER_PING_TIME
|
||||
alert_type = /obj/screen/alert/status_effect/agent_pinpointer
|
||||
var/minimum_range = PINPOINTER_MINIMUM_RANGE
|
||||
var/mob/scan_target = null
|
||||
|
||||
/obj/screen/alert/status_effect/agent_pinpointer
|
||||
name = "Internal Affairs Integrated Pinpointer"
|
||||
desc = "Even stealthier than a normal implant."
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "pinon"
|
||||
|
||||
/datum/status_effect/agent_pinpointer/proc/point_to_target() //If we found what we're looking for, show the distance and direction
|
||||
if(!scan_target)
|
||||
linked_alert.icon_state = "pinonnull"
|
||||
return
|
||||
var/turf/here = get_turf(owner)
|
||||
var/turf/there = get_turf(scan_target)
|
||||
if(here.z != there.z)
|
||||
linked_alert.icon_state = "pinonnull"
|
||||
return
|
||||
if(get_dist_euclidian(here,there)<=minimum_range + rand(0, PINPOINTER_EXTRA_RANDOM_RANGE))
|
||||
linked_alert.icon_state = "pinondirect"
|
||||
else
|
||||
linked_alert.setDir(get_dir(here, there))
|
||||
switch(get_dist(here, there))
|
||||
if(1 to 8)
|
||||
linked_alert.icon_state = "pinonclose"
|
||||
if(9 to 16)
|
||||
linked_alert.icon_state = "pinonmedium"
|
||||
if(16 to INFINITY)
|
||||
linked_alert.icon_state = "pinonfar"
|
||||
|
||||
|
||||
/datum/status_effect/agent_pinpointer/proc/scan_for_target()
|
||||
scan_target = null
|
||||
if(owner)
|
||||
if(owner.mind)
|
||||
if(owner.mind.objectives)
|
||||
for(var/datum/objective/objective_ in owner.mind.objectives)
|
||||
if(!is_internal_objective(objective_))
|
||||
continue
|
||||
var/datum/objective/assassinate/internal/objective = objective_
|
||||
var/mob/current = objective.target.current
|
||||
if(current&¤t.stat!=DEAD)
|
||||
scan_target = current
|
||||
break
|
||||
|
||||
|
||||
/datum/status_effect/agent_pinpointer/tick()
|
||||
if(!owner)
|
||||
qdel(src)
|
||||
return
|
||||
scan_for_target()
|
||||
point_to_target()
|
||||
|
||||
/proc/give_pinpointer(datum/mind/owner)
|
||||
if(owner && owner.current)
|
||||
owner.current.apply_status_effect(/datum/status_effect/agent_pinpointer)
|
||||
|
||||
|
||||
/datum/internal_agent_state
|
||||
var/traitored = FALSE
|
||||
var/datum/mind/owner = null
|
||||
var/list/datum/mind/targets_stolen = list()
|
||||
|
||||
/proc/is_internal_objective(datum/objective/O)
|
||||
return (istype(O, /datum/objective/assassinate/internal)||istype(O, /datum/objective/destroy/internal))
|
||||
|
||||
/proc/replace_escape_objective(datum/mind/owner)
|
||||
if(!owner||!owner.objectives)
|
||||
return
|
||||
for (var/objective_ in owner.objectives)
|
||||
if(!(istype(objective_, /datum/objective/escape)||istype(objective_,/datum/objective/survive)))
|
||||
continue
|
||||
owner.objectives -= objective_
|
||||
var/datum/objective/martyr/martyr_objective = new
|
||||
martyr_objective.owner = owner
|
||||
owner.objectives += martyr_objective
|
||||
|
||||
/proc/reinstate_escape_objective(datum/mind/owner)
|
||||
if(!owner||!owner.objectives)
|
||||
return
|
||||
for (var/objective_ in owner.objectives)
|
||||
if(!istype(objective_, /datum/objective/martyr))
|
||||
continue
|
||||
owner.objectives -= objective_
|
||||
if(issilicon(owner))
|
||||
var/datum/objective/survive/survive_objective = new
|
||||
survive_objective.owner = owner
|
||||
owner.objectives += survive_objective
|
||||
else
|
||||
var/datum/objective/escape/escape_objective = new
|
||||
escape_objective.owner = owner
|
||||
owner.objectives += escape_objective
|
||||
|
||||
/datum/internal_agent_state/proc/steal_targets(datum/mind/victim)
|
||||
if(!owner.current||owner.current.stat==DEAD) //Should already be guaranteed if this is only called from steal_targets_timer_func, but better to be safe code than sorry code
|
||||
return
|
||||
var/already_traitored = traitored
|
||||
to_chat(owner.current, "<span class='userdanger'> Target eliminated: [victim.name]</span>")
|
||||
for(var/objective_ in victim.objectives)
|
||||
if(istype(objective_, /datum/objective/assassinate/internal))
|
||||
var/datum/objective/assassinate/internal/objective = objective_
|
||||
if(objective.target==owner)
|
||||
traitored = TRUE
|
||||
else if(targets_stolen.Find(objective.target) == 0)
|
||||
var/datum/objective/assassinate/internal/new_objective = new
|
||||
new_objective.owner = owner
|
||||
new_objective.target = objective.target
|
||||
new_objective.update_explanation_text()
|
||||
owner.objectives += new_objective
|
||||
targets_stolen += objective.target
|
||||
var/status_text = objective.check_completion() ? "neutralised" : "active"
|
||||
to_chat(owner.current, "<span class='userdanger'> New target added to database: [objective.target.name] ([status_text]) </span>")
|
||||
else if(istype(objective_, /datum/objective/destroy/internal))
|
||||
var/datum/objective/destroy/internal/objective = objective_
|
||||
var/datum/objective/destroy/internal/new_objective = new
|
||||
if(objective.target==owner)
|
||||
traitored = TRUE
|
||||
else if(targets_stolen.Find(objective.target) == 0)
|
||||
new_objective.owner = owner
|
||||
new_objective.target = objective.target
|
||||
new_objective.update_explanation_text()
|
||||
owner.objectives += new_objective
|
||||
targets_stolen += objective.target
|
||||
var/status_text = objective.check_completion() ? "neutralised" : "active"
|
||||
to_chat(owner.current, "<span class='userdanger'> New target added to database: [objective.target.name] ([status_text]) </span>")
|
||||
if(traitored&&!already_traitored)
|
||||
for(var/objective_ in owner.objectives)
|
||||
if(!is_internal_objective(objective_))
|
||||
continue
|
||||
var/datum/objective/assassinate/internal/objective = objective_
|
||||
if(!objective.check_completion())
|
||||
traitored = FALSE
|
||||
return
|
||||
to_chat(owner.current,"<span class='userdanger'> All the other agents are dead, and you're the last loose end. Stage a Syndicate terrorist attack to cover up for today's events. You no longer have any limits on collateral damage.</span>")
|
||||
replace_escape_objective(owner)
|
||||
|
||||
|
||||
|
||||
/datum/internal_agent_state/proc/steal_targets_timer_func()
|
||||
if(owner&&owner.current&&owner.current.stat!=DEAD)
|
||||
for(var/objective_ in owner.objectives)
|
||||
if(!is_internal_objective(objective_))
|
||||
continue
|
||||
var/datum/objective/assassinate/internal/objective = objective_
|
||||
if(!objective.target)
|
||||
continue
|
||||
if(objective.check_completion())
|
||||
if(objective.stolen)
|
||||
continue
|
||||
else
|
||||
steal_targets(objective.target)
|
||||
objective.stolen = TRUE
|
||||
else
|
||||
if(objective.stolen)
|
||||
var/fail_msg = "<span class='userdanger'>Your sensors tell you that [objective.target.current.real_name], one of the targets you were meant to have killed, pulled one over on you, and is still alive - do the job properly this time! </span>"
|
||||
if(traitored)
|
||||
fail_msg += "<span class='userdanger'> The truth could still slip out!</font><B><font size=5 color=red> Cease any terrorist actions as soon as possible, unneeded property damage or loss of employee life will lead to your contract being terminated.</span>"
|
||||
reinstate_escape_objective(owner)
|
||||
traitored = FALSE
|
||||
to_chat(owner.current, fail_msg)
|
||||
objective.stolen = FALSE
|
||||
add_steal_targets_timer(owner)
|
||||
|
||||
/datum/internal_agent_state/proc/add_steal_targets_timer()
|
||||
var/datum/callback/C = new(src, .steal_targets_timer_func)
|
||||
addtimer(C, 30)
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs/forge_traitor_objectives(datum/mind/traitor)
|
||||
|
||||
if(target_list.len && target_list[traitor]) // Is a double agent
|
||||
@@ -34,13 +212,13 @@
|
||||
// Assassinate
|
||||
var/datum/mind/target_mind = target_list[traitor]
|
||||
if(issilicon(target_mind.current))
|
||||
var/datum/objective/destroy/destroy_objective = new
|
||||
var/datum/objective/destroy/internal/destroy_objective = new
|
||||
destroy_objective.owner = traitor
|
||||
destroy_objective.target = target_mind
|
||||
destroy_objective.update_explanation_text()
|
||||
traitor.objectives += destroy_objective
|
||||
else
|
||||
var/datum/objective/assassinate/kill_objective = new
|
||||
var/datum/objective/assassinate/internal/kill_objective = new
|
||||
kill_objective.owner = traitor
|
||||
kill_objective.target = target_mind
|
||||
kill_objective.update_explanation_text()
|
||||
@@ -55,6 +233,11 @@
|
||||
var/datum/objective/escape/escape_objective = new
|
||||
escape_objective.owner = traitor
|
||||
traitor.objectives += escape_objective
|
||||
var/datum/internal_agent_state/state = new
|
||||
state.owner=traitor
|
||||
state.add_steal_targets_timer()
|
||||
if(!issilicon(traitor.current))
|
||||
give_pinpointer(traitor)
|
||||
|
||||
else
|
||||
..() // Give them standard objectives.
|
||||
@@ -106,14 +289,18 @@
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs/greet_traitor(datum/mind/traitor)
|
||||
var/crime = pick("distribution of contraband" , "unauthorized erotic action on duty", "embezzlement", "piloting under the influence", "dereliction of duty", "syndicate collaboration", "mutiny", "multiple homicides", "corporate espionage", "recieving bribes", "malpractice", "worship of prohbited life forms", "possession of profane texts", "murder", "arson", "insulting their manager", "grand theft", "conspiracy", "attempting to unionize", "vandalism", "gross incompetence")
|
||||
to_chat(traitor.current, "<B><font size=3 color=red>You are the [traitor_name].</font></B>")
|
||||
to_chat(traitor.current, "<B><font size=3 color=red>Your target is suspected of [crime], and you have been tasked with eliminating them by any means necessary to avoid a costly and embarrassing public trial.</font></B>")
|
||||
to_chat(traitor.current, "<span class='userdanger'>You are the [traitor_name].</span>")
|
||||
to_chat(traitor.current, "<span class='userdanger'>Your target is suspected of [crime], and you have been tasked with eliminating them by any means necessary to avoid a costly and embarrassing public trial.</span>")
|
||||
to_chat(traitor.current, "<B><font size=5 color=red>While you have a license to kill, unneeded property damage or loss of employee life will lead to your contract being terminated.</font></B>")
|
||||
to_chat(traitor.current, "<B><font size=3 color=red>For the sake of plausible deniability, you have been equipped with an array of captured Syndicate weaponry available via uplink.</font></B>")
|
||||
to_chat(traitor.current, "<B><font size=3 color=red>Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.</font></B>")
|
||||
to_chat(traitor.current, "<span class='userdanger'>For the sake of plausible deniability, you have been equipped with an array of captured Syndicate weaponry available via uplink.</span>")
|
||||
to_chat(traitor.current, "<span class='userdanger'>Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.</span>")
|
||||
traitor.announce_objectives()
|
||||
|
||||
|
||||
|
||||
/datum/game_mode/traitor/internal_affairs/give_codewords(mob/living/traitor_mob)
|
||||
return
|
||||
return
|
||||
|
||||
#undef PINPOINTER_EXTRA_RANDOM_RANGE
|
||||
#undef PINPOINTER_MINIMUM_RANGE
|
||||
#undef PINPOINTER_PING_TIME
|
||||
|
||||
@@ -58,7 +58,12 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
|
||||
|
||||
/obj/machinery/computer/telecrystals/uplinker/proc/donateTC(amt, addLog = 1)
|
||||
if(uplinkholder && linkedboss)
|
||||
if(amt <= uplinkholder.hidden_uplink.telecrystals)
|
||||
if(amt < 0)
|
||||
linkedboss.storedcrystals += uplinkholder.hidden_uplink.telecrystals
|
||||
if(addLog)
|
||||
linkedboss.logTransfer("[src] donated [uplinkholder.hidden_uplink.telecrystals] telecrystals to [linkedboss].")
|
||||
uplinkholder.hidden_uplink.telecrystals = 0
|
||||
else if(amt <= uplinkholder.hidden_uplink.telecrystals)
|
||||
uplinkholder.hidden_uplink.telecrystals -= amt
|
||||
linkedboss.storedcrystals += amt
|
||||
if(addLog)
|
||||
@@ -66,7 +71,12 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
|
||||
|
||||
/obj/machinery/computer/telecrystals/uplinker/proc/giveTC(amt, addLog = 1)
|
||||
if(uplinkholder && linkedboss)
|
||||
if(amt <= linkedboss.storedcrystals)
|
||||
if(amt < 0)
|
||||
uplinkholder.hidden_uplink.telecrystals += linkedboss.storedcrystals
|
||||
if(addLog)
|
||||
linkedboss.logTransfer("[src] received [linkedboss.storedcrystals] telecrystals from [linkedboss].")
|
||||
linkedboss.storedcrystals = 0
|
||||
else if(amt <= linkedboss.storedcrystals)
|
||||
uplinkholder.hidden_uplink.telecrystals += amt
|
||||
linkedboss.storedcrystals -= amt
|
||||
if(addLog)
|
||||
@@ -89,7 +99,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
|
||||
if(uplinkholder)
|
||||
dat += "[uplinkholder.hidden_uplink.telecrystals] telecrystals remain in this uplink.<BR>"
|
||||
if(linkedboss)
|
||||
dat += "Donate TC: <a href='byond://?src=\ref[src];donate1=1'>1</a> | <a href='byond://?src=\ref[src];donate5=1'>5</a>"
|
||||
dat += "Donate TC: <a href='byond://?src=\ref[src];donate=1'>1</a> | <a href='byond://?src=\ref[src];donate=5'>5</a> | <a href='byond://?src=\ref[src];donate=-1'>All</a>"
|
||||
dat += "<br><a href='byond://?src=\ref[src];eject=1'>Eject Uplink</a>"
|
||||
|
||||
|
||||
@@ -103,11 +113,9 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(href_list["donate1"])
|
||||
donateTC(1)
|
||||
|
||||
if(href_list["donate5"])
|
||||
donateTC(5)
|
||||
if(href_list["donate"])
|
||||
var/tcamt = text2num(href_list["donate"])
|
||||
donateTC(tcamt)
|
||||
|
||||
if(href_list["eject"])
|
||||
ejectuplink()
|
||||
@@ -162,7 +170,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
|
||||
|
||||
var/dat = ""
|
||||
dat += "<a href='byond://?src=\ref[src];scan=1'>Scan for TC stations.</a><BR>"
|
||||
dat += "This [src] has [storedcrystals] telecrystals available for distribution. <BR>"
|
||||
dat += "[storedcrystals] telecrystals are available for distribution. <BR>"
|
||||
dat += "<BR><BR>"
|
||||
|
||||
|
||||
@@ -171,10 +179,10 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
|
||||
if(A.uplinkholder)
|
||||
dat += "[A.uplinkholder.hidden_uplink.telecrystals] telecrystals."
|
||||
if(storedcrystals)
|
||||
dat+= "<BR>Add TC: <a href ='?src=\ref[src];give1=\ref[A]'>1</a> | <a href ='?src=\ref[src];give5=\ref[A]'>5</a>"
|
||||
dat+= "<BR>Add TC: <a href ='?src=\ref[src];target=\ref[A];give=1'>1</a> | <a href ='?src=\ref[src];target=\ref[A];give=5'>5</a> | <a href ='?src=\ref[src];target=\ref[A];give=10'>10</a> | <a href ='?src=\ref[src];target=\ref[A];give=-1'>All</a>"
|
||||
dat += "<BR>"
|
||||
|
||||
if(TCstations.len)
|
||||
if(TCstations.len && storedcrystals)
|
||||
dat += "<BR><BR><a href='byond://?src=\ref[src];distrib=1'>Evenly distribute remaining TC.</a><BR><BR>"
|
||||
|
||||
|
||||
@@ -195,13 +203,11 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
|
||||
if(href_list["scan"])
|
||||
scanUplinkers()
|
||||
|
||||
if(href_list["give1"])
|
||||
var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["give1"])
|
||||
A.giveTC(1)
|
||||
|
||||
if(href_list["give5"])
|
||||
var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["give5"])
|
||||
A.giveTC(5)
|
||||
if(href_list["give"])
|
||||
var/tcamt = text2num(href_list["give"])
|
||||
if(TCstations.len) // sanity
|
||||
var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["target"]) in TCstations
|
||||
A.giveTC(tcamt)
|
||||
|
||||
if(href_list["distrib"])
|
||||
var/sanity = 0
|
||||
|
||||
+220
-74
@@ -26,14 +26,13 @@ Possible to do for anyone motivated enough:
|
||||
|
||||
#define HOLOPAD_PASSIVE_POWER_USAGE 1
|
||||
#define HOLOGRAM_POWER_USAGE 2
|
||||
#define RANGE_BASED 4
|
||||
#define AREA_BASED 6
|
||||
|
||||
GLOBAL_LIST_EMPTY(holopads)
|
||||
#define HOLOPAD_MODE RANGE_BASED
|
||||
|
||||
/obj/machinery/holopad
|
||||
name = "\improper AI holopad"
|
||||
desc = "It's a floor-mounted device for projecting holographic images. It is activated remotely."
|
||||
name = "Holopad"
|
||||
desc = "It's a floor-mounted device for projecting holographic images."
|
||||
icon_state = "holopad0"
|
||||
layer = LOW_OBJ_LAYER
|
||||
flags = HEAR
|
||||
@@ -44,21 +43,32 @@ Possible to do for anyone motivated enough:
|
||||
obj_integrity = 300
|
||||
max_integrity = 300
|
||||
armor = list(melee = 50, bullet = 20, laser = 20, energy = 20, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 0)
|
||||
var/list/masters = list()//List of AIs that use the holopad
|
||||
var/list/masters = list()//List of living mobs that use the holopad
|
||||
var/last_request = 0 //to prevent request spam. ~Carn
|
||||
var/holo_range = 5 // Change to change how far the AI can move away from the holopad before deactivating.
|
||||
var/temp = ""
|
||||
var/list/holo_calls //array of /datum/holocalls
|
||||
var/datum/holocall/outgoing_call //do not modify the datums only check and call the public procs
|
||||
var/static/force_answer_call = FALSE //Calls will be automatically answered after a couple rings, here for debugging
|
||||
var/static/list/holopads = list()
|
||||
|
||||
/obj/machinery/holopad/New()
|
||||
/obj/machinery/holopad/Initialize()
|
||||
..()
|
||||
var/obj/item/weapon/circuitboard/machine/B = new /obj/item/weapon/circuitboard/machine/holopad(null)
|
||||
B.apply_default_parts(src)
|
||||
holopads += src
|
||||
|
||||
/obj/machinery/holopad/Destroy()
|
||||
for (var/mob/living/silicon/ai/master in masters)
|
||||
clear_holo(master)
|
||||
if(outgoing_call)
|
||||
LAZYADD(holo_calls, outgoing_call)
|
||||
|
||||
for(var/I in holo_calls)
|
||||
var/datum/holocall/HC = I
|
||||
HC.ConnectionFailure(src)
|
||||
LAZYCLEARLIST(holo_calls)
|
||||
|
||||
for (var/I in masters)
|
||||
clear_holo(I)
|
||||
holopads -= src
|
||||
return ..()
|
||||
|
||||
@@ -91,20 +101,58 @@ Possible to do for anyone motivated enough:
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/machinery/holopad/proc/CheckCallClose()
|
||||
for(var/I in holo_calls)
|
||||
var/datum/holocall/HC = I
|
||||
if(usr == HC.eye)
|
||||
HC.Disconnect(HC.calling_holopad) //disconnect via clicking the called holopad
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/holopad/Click(location,control,params)
|
||||
if(!CheckCallClose())
|
||||
return ..()
|
||||
|
||||
/obj/machinery/holopad/AltClick(mob/living/carbon/human/user)
|
||||
interact(user)
|
||||
if(!CheckCallClose())
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/holopad/interact(mob/living/carbon/human/user) //Carn: Hologram requests.
|
||||
if(!istype(user))
|
||||
return
|
||||
if(user.stat || !is_operational())
|
||||
|
||||
if(outgoing_call || user.incapacitated() || !is_operational())
|
||||
return
|
||||
|
||||
user.set_machine(src)
|
||||
var/dat
|
||||
if(temp)
|
||||
dat = temp
|
||||
else
|
||||
dat = "<A href='?src=\ref[src];AIrequest=1'>request an AI's presence.</A>"
|
||||
dat = "<a href='?src=\ref[src];AIrequest=1'>Request an AI's presence.</a><br>"
|
||||
dat += "<a href='?src=\ref[src];Holocall=1'>Call another holopad.</a><br>"
|
||||
|
||||
if(LAZYLEN(holo_calls))
|
||||
dat += "=====================================================<br>"
|
||||
|
||||
var/one_answered_call = FALSE
|
||||
var/one_unanswered_call = FALSE
|
||||
for(var/I in holo_calls)
|
||||
var/datum/holocall/HC = I
|
||||
if(HC.connected_holopad != src)
|
||||
dat += "<a href='?src=\ref[src];connectcall=\ref[HC]'>Answer call from [get_area(HC.calling_holopad)].</a><br>"
|
||||
one_unanswered_call = TRUE
|
||||
else
|
||||
one_answered_call = TRUE
|
||||
|
||||
if(one_answered_call && one_unanswered_call)
|
||||
dat += "=====================================================<br>"
|
||||
//we loop twice for formatting
|
||||
for(var/I in holo_calls)
|
||||
var/datum/holocall/HC = I
|
||||
if(HC.connected_holopad == src)
|
||||
dat += "<a href='?src=\ref[src];disconnectcall=\ref[HC]'>Disconnect call from [HC.user].</a><br>"
|
||||
|
||||
|
||||
var/datum/browser/popup = new(user, "holopad", name, 300, 130)
|
||||
popup.set_content(dat)
|
||||
@@ -112,7 +160,10 @@ Possible to do for anyone motivated enough:
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/holopad/Topic(href, href_list)
|
||||
if(..() || !is_operational())
|
||||
if(..() || isAI(usr))
|
||||
return
|
||||
add_fingerprint(usr)
|
||||
if(!is_operational())
|
||||
return
|
||||
if (href_list["AIrequest"])
|
||||
if(last_request + 200 < world.time)
|
||||
@@ -120,7 +171,7 @@ Possible to do for anyone motivated enough:
|
||||
temp = "You requested an AI's presence.<BR>"
|
||||
temp += "<A href='?src=\ref[src];mainmenu=1'>Main Menu</A>"
|
||||
var/area/area = get_area(src)
|
||||
for(var/mob/living/silicon/ai/AI in GLOB.living_mob_list)
|
||||
for(var/mob/living/silicon/ai/AI in GLOB.silicon_mobs)
|
||||
if(!AI.client)
|
||||
continue
|
||||
to_chat(AI, "<span class='info'>Your presence is requested at <a href='?src=\ref[AI];jumptoholopad=\ref[src]'>\the [area]</a>.</span>")
|
||||
@@ -128,12 +179,49 @@ Possible to do for anyone motivated enough:
|
||||
temp = "A request for AI presence was already sent recently.<BR>"
|
||||
temp += "<A href='?src=\ref[src];mainmenu=1'>Main Menu</A>"
|
||||
|
||||
else if(href_list["mainmenu"])
|
||||
else if(href_list["Holocall"])
|
||||
if(outgoing_call)
|
||||
return
|
||||
|
||||
temp = "You must stand on the holopad to make a call!<br>"
|
||||
temp += "<A href='?src=\ref[src];mainmenu=1'>Main Menu</A>"
|
||||
if(usr.loc == loc)
|
||||
var/list/callnames = list()
|
||||
for(var/I in holopads)
|
||||
var/area/A = get_area(I)
|
||||
if(A)
|
||||
LAZYADD(callnames[A], I)
|
||||
callnames -= get_area(src)
|
||||
|
||||
var/result = input(usr, "Choose an area to call", "Holocall") as null|anything in callnames
|
||||
if(QDELETED(usr) || !result || outgoing_call)
|
||||
return
|
||||
|
||||
if(usr.loc == loc)
|
||||
temp = "Dialing...<br>"
|
||||
temp += "<A href='?src=\ref[src];mainmenu=1'>Main Menu</A>"
|
||||
new /datum/holocall(usr, src, callnames[result])
|
||||
|
||||
else if(href_list["connectcall"])
|
||||
var/datum/holocall/call_to_connect = locate(href_list["connectcall"])
|
||||
if(!QDELETED(call_to_connect))
|
||||
call_to_connect.Answer(src)
|
||||
temp = ""
|
||||
|
||||
updateDialog()
|
||||
add_fingerprint(usr)
|
||||
else if(href_list["disconnectcall"])
|
||||
var/datum/holocall/call_to_disconnect = locate(href_list["disconnectcall"])
|
||||
if(!QDELETED(call_to_disconnect))
|
||||
call_to_disconnect.Disconnect(src)
|
||||
temp = ""
|
||||
|
||||
else if(href_list["mainmenu"])
|
||||
temp = ""
|
||||
if(outgoing_call)
|
||||
outgoing_call.Disconnect()
|
||||
|
||||
updateDialog()
|
||||
|
||||
//do not allow AIs to answer calls or people will use it to meta the AI sattelite
|
||||
/obj/machinery/holopad/attack_ai(mob/living/silicon/ai/user)
|
||||
if (!istype(user))
|
||||
return
|
||||
@@ -148,39 +236,75 @@ Possible to do for anyone motivated enough:
|
||||
clear_holo(user)
|
||||
|
||||
/obj/machinery/holopad/process()
|
||||
if(masters.len)//If there is a hologram.
|
||||
for (var/mob/living/silicon/ai/master in masters)
|
||||
if(master && !master.stat && master.client && master.eyeobj)//If there is an AI attached, it's not incapacitated, it has a client, and the client eye is centered on the projector.
|
||||
if(!(stat & NOPOWER))//If the machine has power.
|
||||
if(HOLOPAD_MODE == RANGE_BASED)
|
||||
if(get_dist(master.eyeobj, src) <= holo_range)
|
||||
return TRUE
|
||||
else
|
||||
var/obj/machinery/holopad/pad_close = get_closest_atom(/obj/machinery/holopad, holopads, master.eyeobj)
|
||||
if(get_dist(pad_close, master.eyeobj) <= holo_range)
|
||||
var/obj/effect/overlay/holo_pad_hologram/h = masters[master]
|
||||
unset_holo(master)
|
||||
pad_close.set_holo(master, h)
|
||||
return TRUE
|
||||
for(var/I in masters)
|
||||
var/mob/living/master = I
|
||||
var/mob/living/silicon/ai/AI = master
|
||||
if(!istype(AI))
|
||||
AI = null
|
||||
|
||||
else if (HOLOPAD_MODE == AREA_BASED)
|
||||
if(!QDELETED(master) && !master.incapacitated() && master.client && (!AI || AI.eyeobj))//If there is an AI attached, it's not incapacitated, it has a client, and the client eye is centered on the projector.
|
||||
if(is_operational())//If the machine has power.
|
||||
if(AI) //ais are range based
|
||||
if(get_dist(AI.eyeobj, src) <= holo_range)
|
||||
continue
|
||||
else
|
||||
var/obj/machinery/holopad/pad_close = get_closest_atom(/obj/machinery/holopad, holopads, AI.eyeobj)
|
||||
if(get_dist(pad_close, AI.eyeobj) <= holo_range)
|
||||
var/obj/effect/overlay/holo_pad_hologram/h = masters[master]
|
||||
unset_holo(master)
|
||||
pad_close.set_holo(master, h)
|
||||
continue
|
||||
else
|
||||
continue
|
||||
clear_holo(master)//If not, we want to get rid of the hologram.
|
||||
|
||||
var/area/holo_area = get_area(src)
|
||||
var/area/eye_area = get_area(master.eyeobj)
|
||||
if(outgoing_call)
|
||||
outgoing_call.Check()
|
||||
|
||||
if(eye_area in holo_area.related)
|
||||
return TRUE
|
||||
for(var/I in holo_calls)
|
||||
var/datum/holocall/HC = I
|
||||
if(HC.connected_holopad != src)
|
||||
if(force_answer_call && world.time > (HC.call_start_time + (HOLOPAD_MAX_DIAL_TIME / 2)))
|
||||
HC.Answer(src)
|
||||
break
|
||||
if(outgoing_call)
|
||||
HC.Disconnect(src)//can't answer calls while calling
|
||||
else
|
||||
playsound(src, 'sound/machines/twobeep.ogg', 100) //bring, bring!
|
||||
|
||||
clear_holo(master)//If not, we want to get rid of the hologram.
|
||||
return TRUE
|
||||
/obj/machinery/holopad/proc/activate_holo(mob/living/user)
|
||||
var/mob/living/silicon/ai/AI = user
|
||||
if(!istype(AI))
|
||||
AI = null
|
||||
|
||||
/obj/machinery/holopad/proc/activate_holo(mob/living/silicon/ai/user)
|
||||
if(!(stat & NOPOWER) && user.eyeobj.loc == src.loc)//If the projector has power and client eye is on it
|
||||
if (istype(user.current, /obj/machinery/holopad))
|
||||
if(is_operational() && (!AI || AI.eyeobj.loc == loc))//If the projector has power and client eye is on it
|
||||
if (AI && istype(AI.current, /obj/machinery/holopad))
|
||||
to_chat(user, "<span class='danger'>ERROR:</span> \black Image feed in progress.")
|
||||
return
|
||||
create_holo(user)//Create one.
|
||||
src.visible_message("A holographic image of [user] flicks to life right before your eyes!")
|
||||
|
||||
var/obj/effect/overlay/holo_pad_hologram/Hologram = new(loc)//Spawn a blank effect at the location.
|
||||
if(AI)
|
||||
Hologram.icon = AI.holo_icon
|
||||
else //make it like real life
|
||||
Hologram.icon = user.icon
|
||||
Hologram.icon_state = user.icon_state
|
||||
Hologram.copy_overlays(user, TRUE)
|
||||
//codersprite some holo effects here
|
||||
Hologram.alpha = 100
|
||||
Hologram.add_atom_colour("#77abff", FIXED_COLOUR_PRIORITY)
|
||||
Hologram.Impersonation = user
|
||||
|
||||
Hologram.languages = user.languages
|
||||
Hologram.mouse_opacity = 0//So you can't click on it.
|
||||
Hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
|
||||
Hologram.anchored = 1//So space wind cannot drag it.
|
||||
Hologram.name = "[user.name] (Hologram)"//If someone decides to right click.
|
||||
Hologram.set_light(2) //hologram lighting
|
||||
|
||||
set_holo(user, Hologram)
|
||||
visible_message("A holographic image of [user] flicks to life right before your eyes!")
|
||||
|
||||
return Hologram
|
||||
else
|
||||
to_chat(user, "<span class='danger'>ERROR:</span> \black Unable to project hologram.")
|
||||
|
||||
@@ -192,58 +316,80 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
|
||||
if(masters[master] && speaker != master)
|
||||
master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mode)
|
||||
|
||||
/obj/machinery/holopad/proc/create_holo(mob/living/silicon/ai/A, turf/T = loc)
|
||||
var/obj/effect/overlay/holo_pad_hologram/h = new(T)//Spawn a blank effect at the location.
|
||||
h.icon = A.holo_icon
|
||||
h.mouse_opacity = 0//So you can't click on it.
|
||||
h.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
|
||||
h.anchored = 1//So space wind cannot drag it.
|
||||
h.name = "[A.name] (Hologram)"//If someone decides to right click.
|
||||
h.set_light(2) //hologram lighting
|
||||
set_holo(A, h)
|
||||
for(var/I in holo_calls)
|
||||
var/datum/holocall/HC = I
|
||||
if(HC.connected_holopad == src && speaker != HC.hologram)
|
||||
HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mode)
|
||||
|
||||
if(outgoing_call && speaker == outgoing_call.user)
|
||||
outgoing_call.hologram.say(raw_message)
|
||||
|
||||
/obj/machinery/holopad/proc/SetLightsAndPower()
|
||||
var/total_users = masters.len + LAZYLEN(holo_calls)
|
||||
use_power = HOLOPAD_PASSIVE_POWER_USAGE + HOLOGRAM_POWER_USAGE * total_users
|
||||
if(total_users)
|
||||
set_light(2)
|
||||
icon_state = "holopad1"
|
||||
else
|
||||
set_light(0)
|
||||
icon_state = "holopad0"
|
||||
|
||||
/obj/machinery/holopad/proc/set_holo(mob/living/user, var/obj/effect/overlay/holo_pad_hologram/h)
|
||||
masters[user] = h
|
||||
var/mob/living/silicon/ai/AI = user
|
||||
if(istype(AI))
|
||||
AI.current = src
|
||||
SetLightsAndPower()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/holopad/proc/set_holo(mob/living/silicon/ai/A, var/obj/effect/overlay/holo_pad_hologram/h)
|
||||
masters[A] = h
|
||||
set_light(2) // pad lighting
|
||||
icon_state = "holopad1"
|
||||
A.current = src
|
||||
use_power += HOLOGRAM_POWER_USAGE
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/holopad/proc/clear_holo(mob/living/silicon/ai/user)
|
||||
/obj/machinery/holopad/proc/clear_holo(mob/living/user)
|
||||
qdel(masters[user]) // Get rid of user's hologram
|
||||
unset_holo(user)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/holopad/proc/unset_holo(mob/living/silicon/ai/user)
|
||||
if(user.current == src)
|
||||
user.current = null
|
||||
/obj/machinery/holopad/proc/unset_holo(mob/living/user)
|
||||
var/mob/living/silicon/ai/AI = user
|
||||
if(istype(AI) && AI.current == src)
|
||||
AI.current = null
|
||||
masters -= user // Discard AI from the list of those who use holopad
|
||||
use_power = max(HOLOPAD_PASSIVE_POWER_USAGE, use_power - HOLOGRAM_POWER_USAGE)//Reduce power usage
|
||||
if (!masters.len) // If no users left
|
||||
set_light(0) // pad lighting (hologram lighting will be handled automatically since its owner was deleted)
|
||||
icon_state = "holopad0"
|
||||
use_power = HOLOPAD_PASSIVE_POWER_USAGE
|
||||
SetLightsAndPower()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/holopad/proc/move_hologram(mob/living/silicon/ai/user)
|
||||
/obj/machinery/holopad/proc/move_hologram(mob/living/user, turf/new_turf)
|
||||
if(masters[user])
|
||||
step_to(masters[user], user.eyeobj)
|
||||
var/obj/effect/overlay/holo_pad_hologram/H = masters[user]
|
||||
H.loc = get_turf(user.eyeobj)
|
||||
step_to(H, new_turf)
|
||||
H.loc = new_turf
|
||||
var/area/holo_area = get_area(src)
|
||||
var/area/eye_area = new_turf.loc
|
||||
|
||||
if(!(eye_area in holo_area.related))
|
||||
clear_holo(user)
|
||||
return TRUE
|
||||
|
||||
/obj/effect/overlay/holo_pad_hologram
|
||||
var/mob/living/Impersonation
|
||||
var/datum/holocall/HC
|
||||
|
||||
/obj/effect/overlay/holo_pad_hologram/Destroy()
|
||||
Impersonation = null
|
||||
if(HC)
|
||||
HC.Disconnect(HC.calling_holopad)
|
||||
return ..()
|
||||
|
||||
/obj/effect/overlay/holo_pad_hologram/Process_Spacemove(movement_dir = 0)
|
||||
return 1
|
||||
|
||||
/obj/effect/overlay/holo_pad_hologram/examine(mob/user)
|
||||
if(Impersonation)
|
||||
return Impersonation.examine(user)
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/circuitboard/machine/holopad
|
||||
name = "AI Holopad (Machine Board)"
|
||||
build_path = /obj/machinery/holopad
|
||||
origin_tech = "programming=1"
|
||||
req_components = list(/obj/item/weapon/stock_parts/capacitor = 1)
|
||||
|
||||
#undef RANGE_BASED
|
||||
#undef AREA_BASED
|
||||
#undef HOLOPAD_PASSIVE_POWER_USAGE
|
||||
#undef HOLOGRAM_POWER_USAGE
|
||||
#undef HOLOGRAM_POWER_USAGE
|
||||
@@ -0,0 +1,44 @@
|
||||
diff a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm (rejected hunks)
|
||||
@@ -152,7 +152,7 @@ GLOBAL_LIST_EMPTY(holopads)
|
||||
var/datum/holocall/HC = I
|
||||
if(HC.connected_holopad == src)
|
||||
dat += "<a href='?src=\ref[src];disconnectcall=\ref[HC]'>Disconnect call from [HC.user].</a><br>"
|
||||
-
|
||||
+
|
||||
|
||||
var/datum/browser/popup = new(user, "holopad", name, 300, 130)
|
||||
popup.set_content(dat)
|
||||
@@ -192,7 +192,7 @@ GLOBAL_LIST_EMPTY(holopads)
|
||||
if(A)
|
||||
LAZYADD(callnames[A], I)
|
||||
callnames -= get_area(src)
|
||||
-
|
||||
+
|
||||
var/result = input(usr, "Choose an area to call", "Holocall") as null|anything in callnames
|
||||
if(QDELETED(usr) || !result || outgoing_call)
|
||||
return
|
||||
@@ -201,7 +201,7 @@ GLOBAL_LIST_EMPTY(holopads)
|
||||
temp = "Dialing...<br>"
|
||||
temp += "<A href='?src=\ref[src];mainmenu=1'>Main Menu</A>"
|
||||
new /datum/holocall(usr, src, callnames[result])
|
||||
-
|
||||
+
|
||||
else if(href_list["connectcall"])
|
||||
var/datum/holocall/call_to_connect = locate(href_list["connectcall"])
|
||||
if(!QDELETED(call_to_connect))
|
||||
@@ -315,12 +315,12 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
|
||||
for(var/mob/living/silicon/ai/master in masters)
|
||||
if(masters[master] && speaker != master)
|
||||
master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mode)
|
||||
-
|
||||
+
|
||||
for(var/I in holo_calls)
|
||||
var/datum/holocall/HC = I
|
||||
if(HC.connected_holopad == src && speaker != HC.hologram)
|
||||
- HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans)
|
||||
-
|
||||
+ HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mode)
|
||||
+
|
||||
if(outgoing_call && speaker == outgoing_call.user)
|
||||
outgoing_call.hologram.say(raw_message)
|
||||
|
||||
@@ -251,6 +251,8 @@ GLOBAL_LIST_INIT(pipeID2State, list(
|
||||
var/mob/living/carbon/C = user
|
||||
for(var/i=1 to 20)
|
||||
C.vomit(0,1,0,4,0)
|
||||
if(prob(20))
|
||||
C.spew_organ()
|
||||
sleep(5)
|
||||
C.blood_volume = 0
|
||||
return(OXYLOSS|BRUTELOSS)
|
||||
|
||||
@@ -364,6 +364,10 @@
|
||||
var/list/targets = list()
|
||||
var/turretview = view(scan_range, base)
|
||||
for(var/A in turretview)
|
||||
var/atom/AA = A
|
||||
if(AA.invisibility>SEE_INVISIBLE_LIVING)
|
||||
continue
|
||||
|
||||
if(check_anomalies)//if it's set to check for simple animals
|
||||
if(istype(A, /mob/living/simple_animal))
|
||||
var/mob/living/simple_animal/SA = A
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
var/dish_quants = list() //used by the snack machine's custom compartment to count dishes.
|
||||
|
||||
var/obj/item/weapon/vending_refill/refill_canister = null //The type of refill canisters used by this machine.
|
||||
var/refill_count = 3 //The number of canisters the vending machine uses
|
||||
|
||||
/obj/machinery/vending/Initialize()
|
||||
..()
|
||||
@@ -88,7 +89,9 @@
|
||||
/obj/machinery/vending/cola = "Robust Softdrinks",
|
||||
/obj/machinery/vending/cigarette = "ShadyCigs Deluxe",
|
||||
/obj/machinery/vending/autodrobe = "AutoDrobe",
|
||||
/obj/machinery/vending/clothing = "ClothesMate")
|
||||
/obj/machinery/vending/clothing = "ClothesMate",
|
||||
/obj/machinery/vending/medical = "NanoMed Plus",
|
||||
/obj/machinery/vending/wallmed = "NanoMed")
|
||||
|
||||
/obj/item/weapon/circuitboard/machine/vendor/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/weapon/screwdriver))
|
||||
@@ -104,7 +107,7 @@
|
||||
/obj/item/weapon/circuitboard/machine/vendor/proc/set_type(var/obj/machinery/vending/typepath)
|
||||
build_path = typepath
|
||||
name = "[names_paths[build_path]] Vendor (Machine Board)"
|
||||
req_components = list(initial(typepath.refill_canister) = 3)
|
||||
req_components = list(initial(typepath.refill_canister) = initial(typepath.refill_count))
|
||||
|
||||
/obj/item/weapon/circuitboard/machine/vendor/apply_default_parts(obj/machinery/M)
|
||||
for(var/typepath in names_paths)
|
||||
@@ -113,7 +116,6 @@
|
||||
break
|
||||
..()
|
||||
|
||||
|
||||
/obj/machinery/vending/Destroy()
|
||||
qdel(wires)
|
||||
wires = null
|
||||
@@ -307,7 +309,10 @@
|
||||
if(panel_open)
|
||||
attack_hand(user)
|
||||
return
|
||||
else if(istype(W, /obj/item/weapon/coin) && premium.len > 0)
|
||||
else if(istype(W, /obj/item/weapon/coin))
|
||||
if(!premium.len)
|
||||
to_chat(user, "<span class='warning'>[src] doesn't have a coin slot.</span>")
|
||||
return
|
||||
if(!user.drop_item())
|
||||
return
|
||||
W.loc = src
|
||||
@@ -874,6 +879,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
|
||||
premium = list(/obj/item/weapon/storage/box/hug/medical = 1,/obj/item/weapon/reagent_containers/hypospray/medipen = 3, /obj/item/weapon/storage/belt/medical = 3, /obj/item/weapon/wrench/medical = 1)
|
||||
armor = list(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50)
|
||||
resistance_flags = FIRE_PROOF
|
||||
refill_canister = /obj/item/weapon/vending_refill/medical
|
||||
|
||||
//This one's from bay12
|
||||
/obj/machinery/vending/plasmaresearch
|
||||
@@ -896,6 +902,8 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
|
||||
contraband = list(/obj/item/weapon/reagent_containers/pill/tox = 2,/obj/item/weapon/reagent_containers/pill/morphine = 2)
|
||||
armor = list(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50)
|
||||
resistance_flags = FIRE_PROOF
|
||||
refill_canister = /obj/item/weapon/vending_refill/medical
|
||||
refill_count = 1
|
||||
|
||||
/obj/machinery/vending/security
|
||||
name = "\improper SecTech"
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
icon_state = "mecha_ion"
|
||||
origin_tech = "materials=4;engineering=4;combat=6;magnets=6"
|
||||
energy_drain = 500
|
||||
projectile = /obj/item/projectile/energy/tesla_cannon
|
||||
projectile = /obj/item/projectile/energy/tesla/cannon
|
||||
fire_sound = 'sound/magic/lightningbolt.ogg'
|
||||
|
||||
|
||||
|
||||
@@ -323,11 +323,30 @@
|
||||
/obj/effect/overlay/temp/ratvar/grille/broken
|
||||
icon_state = "ratvarbrokengrilleglow"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/mending_mantra
|
||||
layer = ABOVE_MOB_LAYER
|
||||
duration = 20
|
||||
alpha = 200
|
||||
icon_state = "mending_mantra"
|
||||
light_range = 1.5
|
||||
light_color = "#1E8CE1"
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/mending_mantra/Initialize(mapload)
|
||||
. = ..()
|
||||
transform = matrix()*2
|
||||
var/matrix/M = transform
|
||||
M.Turn(90)
|
||||
animate(src, alpha = 20, time = duration, easing = BOUNCE_EASING, flags = ANIMATION_PARALLEL)
|
||||
animate(src, transform = M, time = duration, flags = ANIMATION_PARALLEL)
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/volt_hit
|
||||
name = "volt blast"
|
||||
layer = ABOVE_MOB_LAYER
|
||||
duration = 5
|
||||
icon_state = "volt_hit"
|
||||
light_range = 1.5
|
||||
light_power = 2
|
||||
light_color = LIGHT_COLOR_ORANGE
|
||||
var/mob/user
|
||||
var/damage = 20
|
||||
|
||||
@@ -336,7 +355,6 @@
|
||||
damage *= multiplier
|
||||
duration = max(round(damage * 0.2), 1)
|
||||
. = ..()
|
||||
set_light(1.5, 2, LIGHT_COLOR_ORANGE)
|
||||
|
||||
/obj/effect/overlay/temp/ratvar/volt_hit/true/Initialize(mapload, caster, multiplier)
|
||||
. = ..()
|
||||
|
||||
@@ -9,10 +9,12 @@
|
||||
host = _host
|
||||
last_host_loc = _host.loc
|
||||
ignore_if_not_on_turf = _ignore_if_not_on_turf
|
||||
checkers = list()
|
||||
SetRange(range)
|
||||
|
||||
/datum/proximity_monitor/Destroy()
|
||||
host = null
|
||||
last_host_loc = null
|
||||
QDEL_LIST(checkers)
|
||||
return ..()
|
||||
|
||||
@@ -34,46 +36,47 @@
|
||||
|
||||
current_range = range
|
||||
|
||||
var/list/old_checkers = checkers
|
||||
var/old_checkers_len = LAZYLEN(old_checkers)
|
||||
var/list/checkers_local = checkers
|
||||
var/old_checkers_len = checkers_local.len
|
||||
|
||||
var/atom/host_loc = host.loc
|
||||
var/atom/_host = host
|
||||
|
||||
var/atom/loc_to_use = ignore_if_not_on_turf ? host_loc : get_turf(host)
|
||||
var/atom/loc_to_use = ignore_if_not_on_turf ? _host.loc : get_turf(_host)
|
||||
if(!isturf(loc_to_use)) //only check the host's loc
|
||||
if(range)
|
||||
var/obj/effect/abstract/proximity_checker/pc
|
||||
if(old_checkers_len)
|
||||
pc = old_checkers[old_checkers_len]
|
||||
--old_checkers.len
|
||||
pc = checkers_local[old_checkers_len]
|
||||
--checkers_local.len
|
||||
QDEL_LIST(checkers_local)
|
||||
else
|
||||
pc = new(host_loc, src)
|
||||
pc = new(loc_to_use, src)
|
||||
|
||||
checkers = list(pc) //only check the host's loc
|
||||
checkers_local += pc //only check the host's loc
|
||||
return
|
||||
|
||||
var/list/turfs = RANGE_TURFS(range, loc_to_use)
|
||||
var/old_checkers_used = min(turfs.len, old_checkers_len)
|
||||
var/turfs_len = turfs.len
|
||||
var/old_checkers_used = min(turfs_len, old_checkers_len)
|
||||
|
||||
//reuse what we can
|
||||
for(var/I in 1 to old_checkers_len)
|
||||
if(I <= old_checkers_used)
|
||||
var/obj/effect/abstract/proximity_checker/pc = old_checkers[I]
|
||||
var/obj/effect/abstract/proximity_checker/pc = checkers_local[I]
|
||||
pc.loc = turfs[I]
|
||||
else
|
||||
qdel(old_checkers[I]) //delete the leftovers
|
||||
qdel(checkers_local[I]) //delete the leftovers
|
||||
|
||||
LAZYCLEARLIST(old_checkers)
|
||||
|
||||
//create what we lack
|
||||
var/list/checkers_local = list()
|
||||
for(var/I in (old_checkers_used + 1) to turfs.len)
|
||||
checkers_local += new /obj/effect/abstract/proximity_checker(turfs[I], src)
|
||||
|
||||
checkers = checkers_local
|
||||
if(old_checkers_len < turfs_len)
|
||||
//create what we lack
|
||||
for(var/I in (old_checkers_used + 1) to turfs_len)
|
||||
checkers_local += new /obj/effect/abstract/proximity_checker(turfs[I], src)
|
||||
else
|
||||
checkers_local.Cut(old_checkers_used + 1, old_checkers_len)
|
||||
|
||||
/obj/effect/abstract/proximity_checker
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
anchored = TRUE
|
||||
var/datum/proximity_monitor/monitor
|
||||
|
||||
/obj/effect/abstract/proximity_checker/Initialize(mapload, datum/proximity_monitor/_monitor)
|
||||
@@ -81,8 +84,8 @@
|
||||
if(_monitor)
|
||||
monitor = _monitor
|
||||
else
|
||||
stack_trace("proximity_checker created without proximity_monitor")
|
||||
qdel(src)
|
||||
stack_trace("proximity_checker created without host")
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
/obj/effect/abstract/proximity_checker/Destroy()
|
||||
monitor = null
|
||||
@@ -90,9 +93,6 @@
|
||||
|
||||
/obj/effect/abstract/proximity_checker/Crossed(atom/movable/AM)
|
||||
set waitfor = FALSE
|
||||
var/datum/proximity_monitor/M = monitor
|
||||
if(!M.current_range)
|
||||
return
|
||||
var/atom/H = M.host
|
||||
var/atom/H = monitor.host
|
||||
testing("HasProx: [H] -> [AM]")
|
||||
H.HasProximity(AM)
|
||||
|
||||
@@ -37,9 +37,9 @@
|
||||
return 1
|
||||
|
||||
|
||||
/obj/item/device/flashlight/attack(mob/living/carbon/human/M, mob/living/carbon/human/user)
|
||||
/obj/item/device/flashlight/attack(mob/living/carbon/M, mob/living/carbon/human/user)
|
||||
add_fingerprint(user)
|
||||
if(on && user.zone_selected == "eyes")
|
||||
if(istype(M) && on && user.zone_selected in list("eyes", "mouth"))
|
||||
|
||||
if((user.disabilities & CLUMSY || user.getBrainLoss() >= 60) && prob(50)) //too dumb to use flashlight properly
|
||||
return ..() //just hit them in the head
|
||||
@@ -48,28 +48,101 @@
|
||||
to_chat(user, "<span class='warning'>You don't have the dexterity to do this!</span>")
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/H = M //mob has protective eyewear
|
||||
if(ishuman(M) && ((H.head && H.head.flags_cover & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags_cover & MASKCOVERSEYES) || (H.glasses && H.glasses.flags_cover & GLASSESCOVERSEYES)))
|
||||
to_chat(user, "<span class='notice'>You're going to need to remove that [(H.head && H.head.flags_cover & HEADCOVERSEYES) ? "helmet" : (H.wear_mask && H.wear_mask.flags_cover & MASKCOVERSEYES) ? "mask": "glasses"] first.</span>")
|
||||
if(!M.get_bodypart("head"))
|
||||
to_chat(user, "<span class='warning'>[M] doesn't have a head!</span>")
|
||||
return
|
||||
|
||||
if(M == user) //they're using it on themselves
|
||||
if(M.flash_act(visual = 1))
|
||||
M.visible_message("[M] directs [src] to [M.p_their()] eyes.", "<span class='notice'>You wave the light in front of your eyes! Trippy!</span>")
|
||||
else
|
||||
M.visible_message("[M] directs [src] to [M.p_their()] eyes.", "<span class='notice'>You wave the light in front of your eyes.</span>")
|
||||
else
|
||||
user.visible_message("<span class='warning'>[user] directs [src] to [M]'s eyes.</span>", \
|
||||
"<span class='danger'>You direct [src] to [M]'s eyes.</span>")
|
||||
var/mob/living/carbon/C = M
|
||||
if(istype(C))
|
||||
if(C.stat == DEAD || (C.disabilities & BLIND)) //mob is dead or fully blind
|
||||
to_chat(user, "<span class='warning'>[C] pupils don't react to the light!</span>")
|
||||
else if(C.dna.check_mutation(XRAY)) //mob has X-RAY vision
|
||||
to_chat(user, "<span class='danger'>[C] pupils give an eerie glow!</span>")
|
||||
else //they're okay!
|
||||
if(C.flash_act(visual = 1))
|
||||
to_chat(user, "<span class='notice'>[C]'s pupils narrow.</span>")
|
||||
switch(user.zone_selected)
|
||||
if("eyes")
|
||||
if((M.head && M.head.flags_cover & HEADCOVERSEYES) || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSEYES) || (M.glasses && M.glasses.flags_cover & GLASSESCOVERSEYES))
|
||||
to_chat(user, "<span class='notice'>You're going to need to remove that [(M.head && M.head.flags_cover & HEADCOVERSEYES) ? "helmet" : (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSEYES) ? "mask": "glasses"] first.</span>")
|
||||
return
|
||||
|
||||
var/obj/item/organ/eyes/E = M.getorganslot("eye_sight")
|
||||
if(!E)
|
||||
to_chat(user, "<span class='danger'>[M] doesn't have any eyes!</span>")
|
||||
return
|
||||
|
||||
if(M == user) //they're using it on themselves
|
||||
if(M.flash_act(visual = 1))
|
||||
M.visible_message("[M] directs [src] to [M.p_their()] eyes.", "<span class='notice'>You wave the light in front of your eyes! Trippy!</span>")
|
||||
else
|
||||
M.visible_message("[M] directs [src] to [M.p_their()] eyes.", "<span class='notice'>You wave the light in front of your eyes.</span>")
|
||||
else
|
||||
user.visible_message("<span class='warning'>[user] directs [src] to [M]'s eyes.</span>", \
|
||||
"<span class='danger'>You direct [src] to [M]'s eyes.</span>")
|
||||
if(M.stat == DEAD || (M.disabilities & BLIND) || !M.flash_act(visual = 1)) //mob is dead or fully blind
|
||||
to_chat(user, "<span class='warning'>[M]'s pupils don't react to the light!</span>")
|
||||
else if(M.dna && M.dna.check_mutation(XRAY)) //mob has X-RAY vision
|
||||
to_chat(user, "<span class='danger'>[M]'s pupils give an eerie glow!</span>")
|
||||
else //they're okay!
|
||||
to_chat(user, "<span class='notice'>[M]'s pupils narrow.</span>")
|
||||
|
||||
if("mouth")
|
||||
|
||||
if((M.head && M.head.flags_cover & HEADCOVERSMOUTH) || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSMOUTH))
|
||||
to_chat(user, "<span class='notice'>You're going to need to remove that [(M.head && M.head.flags_cover & HEADCOVERSMOUTH) ? "helmet" : "mask"] first.</span>")
|
||||
return
|
||||
|
||||
var/their = M.p_their()
|
||||
|
||||
var/list/mouth_organs = new
|
||||
for(var/obj/item/organ/O in M.internal_organs)
|
||||
if(O.zone == "mouth")
|
||||
mouth_organs.Add(O)
|
||||
var/organ_list = ""
|
||||
var/organ_count = LAZYLEN(mouth_organs)
|
||||
if(organ_count)
|
||||
for(var/I in 1 to organ_count)
|
||||
if(I > 1)
|
||||
if(I == mouth_organs.len)
|
||||
organ_list += ", and "
|
||||
else
|
||||
organ_list += ", "
|
||||
var/obj/item/organ/O = mouth_organs[I]
|
||||
organ_list += (O.gender == "plural" ? O.name : "\an [O.name]")
|
||||
|
||||
var/pill_count = 0
|
||||
for(var/datum/action/item_action/hands_free/activate_pill/AP in M.actions)
|
||||
pill_count++
|
||||
|
||||
if(M == user)
|
||||
var/can_use_mirror = FALSE
|
||||
if(isturf(user.loc))
|
||||
var/obj/structure/mirror/mirror = locate(/obj/structure/mirror, user.loc)
|
||||
if(mirror)
|
||||
switch(user.dir)
|
||||
if(NORTH)
|
||||
can_use_mirror = mirror.pixel_y > 0
|
||||
if(SOUTH)
|
||||
can_use_mirror = mirror.pixel_y < 0
|
||||
if(EAST)
|
||||
can_use_mirror = mirror.pixel_x > 0
|
||||
if(WEST)
|
||||
can_use_mirror = mirror.pixel_x < 0
|
||||
|
||||
M.visible_message("[M] directs [src] to [their] mouth.", \
|
||||
"<span class='notice'>You point [src] into your mouth.</span>")
|
||||
if(!can_use_mirror)
|
||||
to_chat(user, "<span class='notice'>You can't see anything without a mirror.</span>")
|
||||
return
|
||||
if(organ_count)
|
||||
to_chat(user, "<span class='notice'>Inside your mouth [organ_count > 1 ? "are" : "is"] [organ_list].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>There's nothing inside your mouth.</span>")
|
||||
if(pill_count)
|
||||
to_chat(user, "<span class='notice'>You have [pill_count] implanted pill[pill_count > 1 ? "s" : ""].</span>")
|
||||
|
||||
else
|
||||
user.visible_message("<span class='notice'>[user] directs [src] to [M]'s mouth.</span>",\
|
||||
"<span class='notice'>You direct [src] to [M]'s mouth.</span>")
|
||||
if(organ_count)
|
||||
to_chat(user, "<span class='notice'>Inside [their] mouth [organ_count > 1 ? "are" : "is"] [organ_list].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>[M] doesn't have any organs in [their] mouth.</span>")
|
||||
if(pill_count)
|
||||
to_chat(user, "<span class='notice'>[M] has [pill_count] pill[pill_count > 1 ? "s" : ""] implanted in [their] teeth.")
|
||||
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -280,7 +353,7 @@
|
||||
return TRUE
|
||||
|
||||
/obj/item/device/flashlight/emp/attack(mob/living/M, mob/living/user)
|
||||
if(on && user.zone_selected == "eyes") // call original attack proc only if aiming at the eyes
|
||||
if(on && user.zone_selected in list("eyes", "mouth")) // call original attack when examining organs
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
@@ -237,6 +237,7 @@
|
||||
/obj/item/borg/upgrade/selfrepair/proc/check_dropped()
|
||||
if(loc != cyborg)
|
||||
toggle_action.Remove(cyborg)
|
||||
QDEL_NULL(toggle_action)
|
||||
cyborg = null
|
||||
deactivate()
|
||||
|
||||
@@ -399,4 +400,4 @@
|
||||
return
|
||||
|
||||
R.make_shell(src)
|
||||
return TRUE
|
||||
return TRUE
|
||||
|
||||
@@ -29,6 +29,7 @@ Mineral Sheets
|
||||
GLOBAL_LIST_INIT(sandstone_recipes, list ( \
|
||||
new/datum/stack_recipe("pile of dirt", /obj/machinery/hydroponics/soil, 3, time = 10, one_per_turf = 1, on_floor = 1), \
|
||||
new/datum/stack_recipe("sandstone door", /obj/structure/mineral_door/sandstone, 10, one_per_turf = 1, on_floor = 1), \
|
||||
new/datum/stack_recipe("aesthetic volcanic floor tile", /obj/item/stack/tile/basalt, 2, 2, 4, 20), \
|
||||
new/datum/stack_recipe("Assistant Statue", /obj/structure/statue/sandstone/assistant, 5, one_per_turf = 1, on_floor = 1), \
|
||||
new/datum/stack_recipe("Breakdown into sand", /obj/item/weapon/ore/glass, 1, one_per_turf = 0, on_floor = 1), \
|
||||
/* new/datum/stack_recipe("sandstone wall", ???), \
|
||||
|
||||
@@ -88,6 +88,14 @@
|
||||
turf_type = /turf/open/floor/wood
|
||||
resistance_flags = FLAMMABLE
|
||||
|
||||
//Basalt
|
||||
/obj/item/stack/tile/basalt
|
||||
name = "basalt tile"
|
||||
singular_name = "basalt floor tile"
|
||||
desc = "Artificially made ashy soil themed on a hostile enviroment."
|
||||
icon_state = "tile_basalt"
|
||||
origin_tech = "materials=1"
|
||||
turf_type = /turf/open/floor/grass/fakebasalt
|
||||
|
||||
//Carpets
|
||||
/obj/item/stack/tile/carpet
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/obj/item/weapon/grenade/spawnergrenade
|
||||
desc = "It will unleash unleash an unspecified anomaly into the vicinity."
|
||||
desc = "It will unleash an unspecified anomaly into the vicinity."
|
||||
name = "delivery grenade"
|
||||
icon = 'icons/obj/grenade.dmi'
|
||||
icon_state = "delivery"
|
||||
|
||||
@@ -219,7 +219,8 @@
|
||||
new /obj/item/weapon/reagent_containers/glass/bottle/polonium(src)
|
||||
new /obj/item/weapon/reagent_containers/glass/bottle/venom(src)
|
||||
new /obj/item/weapon/reagent_containers/glass/bottle/neurotoxin2(src)
|
||||
new /obj/item/weapon/reagent_containers/glass/bottle/formaldehyde(src)
|
||||
new /obj/item/weapon/reagent_containers/glass/bottle/formaldehyde(src)
|
||||
new /obj/item/weapon/reagent_containers/glass/bottle/spewium(src)
|
||||
new /obj/item/weapon/reagent_containers/glass/bottle/cyanide(src)
|
||||
new /obj/item/weapon/reagent_containers/glass/bottle/histamine(src)
|
||||
new /obj/item/weapon/reagent_containers/glass/bottle/initropidril(src)
|
||||
|
||||
@@ -71,3 +71,9 @@
|
||||
icon_state = "refill_clothes"
|
||||
charges = list(31, 4, 4)// of 101 standard, 12 contraband, 10 premium(?)
|
||||
init_charges = list(31, 4, 4)
|
||||
|
||||
/obj/item/weapon/vending_refill/medical
|
||||
machine_name = "NanoMed"
|
||||
icon_state = "refill_medical"
|
||||
charges = list(26, 5, 3)// of 76 standard, 13 contraband, 8 premium
|
||||
init_charges = list(26, 5, 3)
|
||||
@@ -298,7 +298,7 @@
|
||||
else
|
||||
for(var/mob/M in range(1,src))
|
||||
if(CanHug(M))
|
||||
child.Attach(M)
|
||||
child.Leap(M)
|
||||
break
|
||||
|
||||
/obj/structure/alien/egg/obj_break(damage_flag)
|
||||
|
||||
@@ -16,27 +16,25 @@
|
||||
var/obj/item/weapon/electronics/airlock/electronics
|
||||
var/start_showpiece_type = null //add type for items on display
|
||||
|
||||
/obj/structure/displaycase/New()
|
||||
..()
|
||||
/obj/structure/displaycase/Initialize()
|
||||
. = ..()
|
||||
if(start_showpiece_type)
|
||||
showpiece = new start_showpiece_type (src)
|
||||
update_icon()
|
||||
|
||||
/obj/structure/displaycase/Destroy()
|
||||
if(electronics)
|
||||
qdel(electronics)
|
||||
electronics = null
|
||||
QDEL_NULL(electronics)
|
||||
if(showpiece)
|
||||
qdel(showpiece)
|
||||
showpiece = null
|
||||
QDEL_NULL(showpiece)
|
||||
return ..()
|
||||
|
||||
/obj/structure/displaycase/examine(mob/user)
|
||||
..()
|
||||
if(showpiece)
|
||||
to_chat(user, "<span class='notice'>There's [showpiece] inside.</span>")
|
||||
if(alert)
|
||||
to_chat(user, "<span class='notice'>Hooked up with an anti-theft system.</span>")
|
||||
if(showpiece)
|
||||
to_chat(user, "<span class='notice'>There's [showpiece] inside.</span>")
|
||||
|
||||
|
||||
/obj/structure/displaycase/proc/dump()
|
||||
@@ -176,8 +174,8 @@
|
||||
/obj/structure/displaycase/attack_hand(mob/user)
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
if (showpiece && (broken || open))
|
||||
dump()
|
||||
to_chat(user, "<span class='notice'>You deactivate the hover field built into the case.</span>")
|
||||
dump()
|
||||
src.add_fingerprint(user)
|
||||
update_icon()
|
||||
return
|
||||
@@ -249,3 +247,96 @@
|
||||
desc = "A glass lab container for storing interesting creatures."
|
||||
start_showpiece_type = /obj/item/clothing/mask/facehugger/lamarr
|
||||
req_access = list(GLOB.access_rd)
|
||||
|
||||
|
||||
|
||||
/obj/structure/displaycase/trophy
|
||||
name = "trophy display case"
|
||||
desc = "Store your trophies of accomplishment in here, and they will stay forever."
|
||||
var/trophy_message = ""
|
||||
var/placer_key = ""
|
||||
var/added_roundstart = TRUE
|
||||
alert = TRUE
|
||||
integrity_failure = 0
|
||||
|
||||
/obj/structure/displaycase/trophy/Initialize()
|
||||
. = ..()
|
||||
GLOB.trophy_cases += src
|
||||
|
||||
/obj/structure/displaycase/trophy/Destroy()
|
||||
GLOB.trophy_cases -= src
|
||||
return ..()
|
||||
|
||||
/obj/structure/displaycase/trophy/examine(mob/user)
|
||||
..()
|
||||
if(trophy_message)
|
||||
to_chat(user, "The plaque reads:")
|
||||
to_chat(user, trophy_message)
|
||||
|
||||
/obj/structure/displaycase/trophy/attackby(obj/item/weapon/W, mob/user, params)
|
||||
|
||||
if(!user.Adjacent(src)) //no TK museology
|
||||
return
|
||||
|
||||
if(!added_roundstart)
|
||||
to_chat(user, "You've already put something new in this case.")
|
||||
return
|
||||
|
||||
if(is_type_in_typecache(W, GLOB.blacklisted_cargo_types))
|
||||
to_chat(user, "<span class='danger'>The case rejects the [W].</span>")
|
||||
return
|
||||
|
||||
for(var/a in W.GetAllContents())
|
||||
if(is_type_in_typecache(a, GLOB.blacklisted_cargo_types))
|
||||
to_chat(user, "<span class='danger'>The case rejects the [W].</span>")
|
||||
return
|
||||
|
||||
if(user.drop_item())
|
||||
|
||||
if(showpiece)
|
||||
to_chat(user, "You press a button, and [showpiece] descends into the floor of the case.")
|
||||
QDEL_NULL(showpiece)
|
||||
|
||||
to_chat(user, "You insert [W] into the case.")
|
||||
W.forceMove(src)
|
||||
showpiece = W
|
||||
added_roundstart = FALSE
|
||||
update_icon()
|
||||
|
||||
placer_key = user.ckey
|
||||
|
||||
trophy_message = W.desc //default value
|
||||
|
||||
var/chosen_plaque = stripped_input(user, "What would you like the plaque to say? Default value is item's description.", "Trophy Plaque")
|
||||
if(chosen_plaque)
|
||||
if(user.Adjacent(src))
|
||||
trophy_message = chosen_plaque
|
||||
to_chat(user, "You set the plaque's text.")
|
||||
else
|
||||
to_chat(user, "You are too far to set the plaque's text.")
|
||||
|
||||
SSpersistence.SaveTrophy(src)
|
||||
|
||||
else
|
||||
to_chat(user, "<span class='warning'>\The [W] is stuck to your hand, you can't put it in the [src.name]!</span>")
|
||||
|
||||
return
|
||||
|
||||
/obj/structure/displaycase/trophy/dump()
|
||||
if (showpiece)
|
||||
if(added_roundstart)
|
||||
visible_message("<span class='danger'>The [showpiece] crumbles to dust!</span>")
|
||||
new /obj/effect/decal/cleanable/ash(loc)
|
||||
QDEL_NULL(showpiece)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/showpiece_dummy
|
||||
name = "Cheap replica"
|
||||
|
||||
/obj/item/showpiece_dummy/Initialize(mapload, path)
|
||||
. = ..()
|
||||
var/obj/item/I = path
|
||||
name = initial(I.name)
|
||||
icon = initial(I.icon)
|
||||
icon_state = initial(I.icon_state)
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
pixel_y = -20
|
||||
|
||||
/obj/structure/flora/tree/jungle/Initialize()
|
||||
icon_state = "[icon_state][rand(1, 3)]"
|
||||
icon_state = "[icon_state][rand(1, 6)]"
|
||||
..()
|
||||
|
||||
//grass
|
||||
|
||||
+3
-3
@@ -35,10 +35,10 @@ GLOBAL_LIST_INIT(freqtospan, list(
|
||||
return 1
|
||||
|
||||
/atom/movable/proc/send_speech(message, range = 7, obj/source = src, bubble_type, list/spans, datum/language/message_language = null, message_mode)
|
||||
var/rendered = compose_message(src, message_language, message, , spans)
|
||||
var/rendered = compose_message(src, message_language, message, , spans, message_mode)
|
||||
for(var/_AM in get_hearers_in_view(range, source))
|
||||
var/atom/movable/AM = _AM
|
||||
AM.Hear(rendered, src, message_language, message, , spans)
|
||||
AM.Hear(rendered, src, message_language, message, , spans, message_mode)
|
||||
|
||||
//To get robot span classes, stuff like that.
|
||||
/atom/movable/proc/get_spans()
|
||||
@@ -58,7 +58,7 @@ GLOBAL_LIST_INIT(freqtospan, list(
|
||||
var/endspanpart = "</span>"
|
||||
|
||||
//Message
|
||||
var/messagepart = " <span class='message'>[lang_treat(speaker, message_language, raw_message, spans)]</span></span>"
|
||||
var/messagepart = " <span class='message'>[lang_treat(speaker, message_language, raw_message, spans, message_mode)]</span></span>"
|
||||
|
||||
var/languageicon = ""
|
||||
var/datum/language/D = get_language_instance(message_language)
|
||||
|
||||
@@ -143,14 +143,14 @@
|
||||
qdel(S.mmi)
|
||||
|
||||
qdel(AM)
|
||||
|
||||
|
||||
if(AM && !QDELETED(AM)) //It's indestructible
|
||||
visible_message("<span class='boldwarning'>[src] spits out the [AM]!</span>")
|
||||
AM.alpha = oldalpha
|
||||
AM.color = oldcolor
|
||||
AM.transform = oldtransform
|
||||
AM.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1, 10),rand(1, 10))
|
||||
|
||||
|
||||
/turf/open/chasm/straight_down/lava_land_surface/normal_air
|
||||
initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
|
||||
|
||||
@@ -158,3 +158,17 @@
|
||||
|
||||
/turf/open/chasm/CanPass(atom/movable/mover, turf/target, height=0)
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
//Jungle
|
||||
|
||||
/turf/open/chasm/jungle
|
||||
icon = 'icons/turf/floors/junglechasm.dmi'
|
||||
planetary_atmos = TRUE
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
|
||||
/turf/open/chasm/straight_down/jungle
|
||||
icon = 'icons/turf/floors/junglechasm.dmi'
|
||||
planetary_atmos = TRUE
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
@@ -1,6 +1,7 @@
|
||||
/* In this file:
|
||||
* Wood floor
|
||||
* Grass floor
|
||||
* Fake Basalt
|
||||
* Carpet floor
|
||||
* Fake pits
|
||||
* Fake space
|
||||
@@ -67,6 +68,7 @@
|
||||
broken_states = list("sand")
|
||||
flags = NONE
|
||||
var/ore_type = /obj/item/weapon/ore/glass
|
||||
var/turfverb = "uproot"
|
||||
|
||||
/turf/open/floor/grass/Initialize()
|
||||
..()
|
||||
@@ -76,7 +78,7 @@
|
||||
if(istype(C, /obj/item/weapon/shovel) && params)
|
||||
new ore_type(src)
|
||||
new ore_type(src) //Make some sand if you shovel grass
|
||||
user.visible_message("<span class='notice'>[user] digs up [src].</span>", "<span class='notice'>You uproot [src].</span>")
|
||||
user.visible_message("<span class='notice'>[user] digs up [src].</span>", "<span class='notice'>You [src.turfverb] [src].</span>")
|
||||
playsound(src, 'sound/effects/shovel_dig.ogg', 50, 1)
|
||||
make_plating()
|
||||
if(..())
|
||||
@@ -93,7 +95,6 @@
|
||||
initial_gas_mix = "o2=22;n2=82;TEMP=180"
|
||||
slowdown = 2
|
||||
|
||||
|
||||
/turf/open/floor/grass/snow/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/weapon/crowbar))//You need to dig this turf out instead of crowbarring it
|
||||
return
|
||||
@@ -113,6 +114,24 @@
|
||||
icon_state = "basalt[rand(0, 12)]"
|
||||
set_basalt_light(src)
|
||||
|
||||
|
||||
/turf/open/floor/grass/fakebasalt //Heart is not a real planeteer power
|
||||
name = "aesthetic volcanic flooring"
|
||||
desc = "Safely recreated turf for your hellplanet-scaping"
|
||||
icon = 'icons/turf/floors.dmi'
|
||||
icon_state = "basalt"
|
||||
floor_tile = /obj/item/stack/tile/basalt
|
||||
ore_type = /obj/item/weapon/ore/glass/basalt
|
||||
turfverb = "dig up"
|
||||
slowdown = 0
|
||||
|
||||
/turf/open/floor/grass/fakebasalt/Initialize()
|
||||
..()
|
||||
if(prob(15))
|
||||
icon_state = "basalt[rand(0, 12)]"
|
||||
set_basalt_light(src)
|
||||
|
||||
|
||||
/turf/open/floor/carpet
|
||||
name = "carpet"
|
||||
desc = "Soft velvet carpeting. Feels good between your toes."
|
||||
|
||||
@@ -3,19 +3,9 @@
|
||||
desc = "Upon closer examination, it's still dirt."
|
||||
icon = 'icons/turf/floors.dmi'
|
||||
icon_state = "dirt"
|
||||
var/smooth_icon = 'icons/turf/floors/dirt.dmi'
|
||||
canSmoothWith = list(/turf/closed, /turf/open/floor/plating/dirt)
|
||||
smooth = SMOOTH_MORE|SMOOTH_BORDER
|
||||
baseturf = /turf/open/chasm/straight_down/lava_land_surface
|
||||
baseturf = /turf/open/chasm/straight_down/jungle
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
planetary_atmos = TRUE
|
||||
|
||||
/turf/open/floor/plating/dirt/Initialize()
|
||||
pixel_y = -2
|
||||
pixel_x = -2
|
||||
icon = smooth_icon
|
||||
..()
|
||||
|
||||
/turf/open/floor/plating/dirt/dark
|
||||
icon_state = "darkdirt"
|
||||
smooth_icon = 'icons/turf/floors/darkdirt.dmi'
|
||||
icon_state = "greenerdirt"
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
diff a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm (rejected hunks)
|
||||
@@ -8,7 +8,7 @@
|
||||
if(href_list["ahelp"])
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
-
|
||||
+
|
||||
var/ahelp_ref = href_list["ahelp"]
|
||||
var/datum/admin_help/AH = locate(ahelp_ref)
|
||||
if(AH)
|
||||
@@ -485,10 +485,6 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
|
||||
current_ticket.AddInteraction("[key_name_admin(usr)] opened a new ticket.")
|
||||
current_ticket.Close()
|
||||
|
||||
if(!(/client/verb/adminhelp in verbs))
|
||||
to_chat(usr, "<span class='warning'>Nice try!</span>")
|
||||
return
|
||||
|
||||
new /datum/admin_help(msg, src, FALSE)
|
||||
|
||||
//admin proc
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
if (!msg)
|
||||
return
|
||||
var/nicknames = world.file2list("config/admin_nicknames.txt")
|
||||
var/static/nicknames = world.file2list("config/admin_nicknames.txt")
|
||||
|
||||
var/rendered = "<span class='game deadsay'><span class='prefix'>DEAD:</span> <span class='name'>ADMIN([src.holder.fakekey ? pick(nicknames) : src.key])</span> says, <span class='message'>\"[msg]\"</span></span>"
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
var/res = alert(usr, "Show the title of this song to the players?",, "No", "Yes", "Cancel")
|
||||
switch(res)
|
||||
if("Yes")
|
||||
to_chat(world, "An admin played: [S]")
|
||||
to_chat(world, "<span class='boldannounce'>An admin played: [S]</span>")
|
||||
if("Cancel")
|
||||
return
|
||||
|
||||
|
||||
@@ -350,7 +350,6 @@ Traitors and the like can also be revived with the previous role mostly intact.
|
||||
|
||||
if(G_found.mind && !G_found.mind.active)
|
||||
G_found.mind.transfer_to(new_character) //be careful when doing stuff like this! I've already checked the mind isn't in use
|
||||
new_character.mind.special_verbs = list()
|
||||
else
|
||||
new_character.mind_initialize()
|
||||
if(!new_character.mind.assigned_role)
|
||||
|
||||
@@ -828,6 +828,14 @@
|
||||
/obj/item/weapon/defibrillator/loaded)
|
||||
crate_name = "defibrillator crate"
|
||||
|
||||
/datum/supply_pack/medical/vending
|
||||
name = "Medical Vending Crate"
|
||||
cost = 2000
|
||||
contains = list(/obj/item/weapon/vending_refill/medical,
|
||||
/obj/item/weapon/vending_refill/medical,
|
||||
/obj/item/weapon/vending_refill/medical)
|
||||
crate_name = "medical vending crate"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////// Science /////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
return
|
||||
if(confirm == "Yes")
|
||||
suiciding = 1
|
||||
log_game("[key_name(src)] (job: [job ? "[job]" : "None"]) commited suicide at [get_area(src)].")
|
||||
message_admins("[key_name(src)] (job: [job ? "[job]" : "None"]) commited suicide at [get_area(src)].")
|
||||
log_game("[key_name(src)] (job: [job ? "[job]" : "None"]) committed suicide at [get_area(src)].")
|
||||
message_admins("[key_name(src)] (job: [job ? "[job]" : "None"]) committed suicide at [get_area(src)].")
|
||||
var/obj/item/held_item = get_active_held_item()
|
||||
if(held_item)
|
||||
var/damagetype = held_item.suicide_act(src)
|
||||
|
||||
@@ -326,9 +326,6 @@
|
||||
disable_flight(1)
|
||||
if(!suit)
|
||||
disable_flight(1)
|
||||
if(!resync)
|
||||
addtimer(CALLBACK(src, .proc/resync), 600)
|
||||
resync = 1
|
||||
if(!wearer) //Oh god our user fell off!
|
||||
disable_flight(1)
|
||||
if(!pressure && brake)
|
||||
@@ -340,12 +337,6 @@
|
||||
stabilizer = FALSE
|
||||
usermessage("Warning: Sensor data is not being recieved from flight shoes. Stabilizers and airbrake modules OFFLINE!", 2)
|
||||
|
||||
//Resync the suit
|
||||
/obj/item/device/flightpack/proc/resync()
|
||||
resync = FALSE
|
||||
suit.resync()
|
||||
|
||||
//How fast should the wearer be?
|
||||
/obj/item/device/flightpack/proc/update_slowdown()
|
||||
if(!flight)
|
||||
suit.slowdown = slowdown_ground
|
||||
@@ -356,20 +347,11 @@
|
||||
/obj/item/device/flightpack/process()
|
||||
if(!suit || (processing_mode == FLIGHTSUIT_PROCESSING_NONE))
|
||||
return FALSE
|
||||
update_slowdown()
|
||||
update_icon()
|
||||
check_conditions()
|
||||
calculate_momentum_speed()
|
||||
momentum_drift()
|
||||
handle_boost()
|
||||
handle_damage()
|
||||
handle_flight()
|
||||
|
||||
/obj/item/device/flightpack/proc/handle_flight()
|
||||
if(!flight)
|
||||
return FALSE
|
||||
if(wearer)
|
||||
wearer.float(TRUE)
|
||||
|
||||
/obj/item/device/flightpack/proc/handle_damage()
|
||||
if(crash_damage)
|
||||
@@ -424,7 +406,6 @@
|
||||
if(boost_charge < boost_maxcharge)
|
||||
boost_charge = Clamp(boost_charge+boost_chargerate, 0, boost_maxcharge)
|
||||
|
||||
|
||||
/obj/item/device/flightpack/proc/cycle_power()
|
||||
if(powersetting < powersetting_high)
|
||||
powersetting++
|
||||
@@ -654,6 +635,8 @@
|
||||
wearer.movement_type |= FLYING
|
||||
wearer.pass_flags |= flight_passflags
|
||||
usermessage("ENGAGING FLIGHT ENGINES.")
|
||||
update_slowdown()
|
||||
wearer.floating = TRUE
|
||||
wearer.visible_message("<font color='blue' size='2'>[wearer]'s flight engines activate as they lift into the air!</font>")
|
||||
//I DONT HAVE SOUND EFFECTS YET playsound(
|
||||
flight = TRUE
|
||||
@@ -670,6 +653,8 @@
|
||||
momentum_x = 0
|
||||
momentum_y = 0
|
||||
usermessage("DISENGAGING FLIGHT ENGINES.")
|
||||
update_slowdown()
|
||||
wearer.floating = FALSE
|
||||
wearer.visible_message("<font color='blue' size='2'>[wearer] drops to the ground as their flight engines cut out!</font>")
|
||||
//NO SOUND YET playsound(
|
||||
ion_trail.stop()
|
||||
@@ -749,11 +734,13 @@
|
||||
wearer.visible_message("<span class='notice'>[wearer.name]'s flightpack engines flare in intensity as they are rocketed forward by the immense thrust!</span>")
|
||||
boost = TRUE
|
||||
update_slowdown()
|
||||
update_icon()
|
||||
|
||||
/obj/item/device/flightpack/proc/deactivate_booster()
|
||||
usermessage("Boosters disengaged!")
|
||||
boost = FALSE
|
||||
update_slowdown()
|
||||
update_icon()
|
||||
|
||||
/obj/item/device/flightpack/proc/enable_airbrake()
|
||||
if(wearer)
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
var/scanning = 0
|
||||
var/list/log = list()
|
||||
origin_tech = "engineering=4;biotech=2;programming=5"
|
||||
var/range = 8
|
||||
var/view_check = TRUE
|
||||
|
||||
/obj/item/device/detective_scanner/attack_self(mob/user)
|
||||
if(log.len && !scanning)
|
||||
@@ -43,7 +45,7 @@
|
||||
log = list()
|
||||
scanning = 0
|
||||
|
||||
/obj/item/device/detective_scanner/pre_attackby(atom/A, mob/user, params)
|
||||
/obj/item/device/detective_scanner/afterattack(atom/A, mob/user, params)
|
||||
scan(A, user)
|
||||
return FALSE
|
||||
|
||||
@@ -51,9 +53,7 @@
|
||||
set waitfor = 0
|
||||
if(!scanning)
|
||||
// Can remotely scan objects and mobs.
|
||||
if(!in_range(A, user) && !(A in view(world.view, user)))
|
||||
return
|
||||
if(loc != user)
|
||||
if((get_dist(A, user) > range) || (!(A in view(range, user)) && view_check) || (loc != user))
|
||||
return
|
||||
|
||||
scanning = 1
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
filling_color = "#D2691E"
|
||||
tastes = list("donut" = 1)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/donut/New()
|
||||
..()
|
||||
/obj/item/weapon/reagent_containers/food/snacks/donut/Initialize()
|
||||
. = ..()
|
||||
if(prob(30))
|
||||
icon_state = "donut2"
|
||||
name = "frosted donut"
|
||||
@@ -28,8 +28,8 @@
|
||||
bitesize = 10
|
||||
tastes = list("donut" = 3, "chaos" = 1)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/donut/chaos/New()
|
||||
..()
|
||||
/obj/item/weapon/reagent_containers/food/snacks/donut/chaos/Initialize()
|
||||
. = ..()
|
||||
extra_reagent = pick("nutriment", "capsaicin", "frostoil", "krokodil", "plasma", "cocoa", "slimejelly", "banana", "berryjuice", "omnizine")
|
||||
reagents.add_reagent("[extra_reagent]", 3)
|
||||
bonus_reagents = list("[extra_reagent]" = 3, "sugar" = 1)
|
||||
@@ -48,8 +48,8 @@
|
||||
extra_reagent = "berryjuice"
|
||||
tastes = list("jelly" = 1, "donut" = 3)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/donut/jelly/New()
|
||||
..()
|
||||
/obj/item/weapon/reagent_containers/food/snacks/donut/jelly/Initialize()
|
||||
. = ..()
|
||||
if(extra_reagent)
|
||||
reagents.add_reagent("[extra_reagent]", 3)
|
||||
if(prob(30))
|
||||
@@ -210,13 +210,13 @@
|
||||
filling_color = "#F0E68C"
|
||||
tastes = list("mushroom" = 1, "biscuit" = 1)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/plumphelmetbiscuit/New()
|
||||
/obj/item/weapon/reagent_containers/food/snacks/plumphelmetbiscuit/Initialize()
|
||||
var/fey = prob(10)
|
||||
if(fey)
|
||||
name = "exceptional plump helmet biscuit"
|
||||
desc = "Microwave is taken by a fey mood! It has cooked an exceptional plump helmet biscuit!"
|
||||
bonus_reagents = list("omnizine" = 5, "nutriment" = 1, "vitamin" = 1)
|
||||
..()
|
||||
. = ..()
|
||||
if(fey)
|
||||
reagents.add_reagent("omnizine", 5)
|
||||
|
||||
|
||||
@@ -128,6 +128,13 @@
|
||||
list_reagents = list("nutriment" = 5, "tomatojuice" = 10, "vitamin" = 3)
|
||||
tastes = list("tomato" = 1)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/soup/tomato/eyeball
|
||||
name = "eyeball soup"
|
||||
desc = "It looks back at you..."
|
||||
icon_state = "eyeballsoup"
|
||||
bonus_reagents = list("nutriment" = 1, "liquidgibs" = 3)
|
||||
tastes = list("tomato" = 1, "squirming" = 1)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/soup/milo
|
||||
name = "milosoup"
|
||||
desc = "The universes best soup! Yum!!!"
|
||||
@@ -196,5 +203,3 @@
|
||||
icon_state = "redbeetsoup"
|
||||
bonus_reagents = list("nutriment" = 4, "vitamin" = 6)
|
||||
tastes = list("beet" = 1)
|
||||
|
||||
|
||||
|
||||
@@ -83,5 +83,5 @@
|
||||
icon = 'icons/obj/food/pizzaspaghetti.dmi'
|
||||
icon_state = "beefnoodle"
|
||||
trash = /obj/item/weapon/reagent_containers/glass/bowl
|
||||
bonus_reagents = list("nutriment" = 5, "vitamin" = 6)
|
||||
bonus_reagents = list("nutriment" = 5, "vitamin" = 6, "liquidgibs" = 3)
|
||||
tastes = list("noodle" = 1, "meat" = 1)
|
||||
|
||||
@@ -264,7 +264,7 @@
|
||||
time = 40
|
||||
reqs = list(
|
||||
/obj/item/weapon/reagent_containers/food/snacks/meat/steak/goliath = 1,
|
||||
/obj/item/weapon/legion_skull = 1,
|
||||
/obj/item/organ/hivelord_core/legion = 1,
|
||||
/datum/reagent/consumable/ketchup = 2,
|
||||
/datum/reagent/consumable/capsaicin = 2
|
||||
)
|
||||
@@ -325,3 +325,5 @@
|
||||
)
|
||||
result = /obj/item/weapon/reagent_containers/food/snacks/branrequests
|
||||
category = CAT_MISCFOOD
|
||||
|
||||
|
||||
|
||||
@@ -91,6 +91,18 @@
|
||||
result = /obj/item/weapon/reagent_containers/food/snacks/soup/tomato
|
||||
category = CAT_SOUP
|
||||
|
||||
/datum/crafting_recipe/food/eyeballsoup
|
||||
name = "Eyeball soup"
|
||||
reqs = list(
|
||||
/datum/reagent/water = 10,
|
||||
/obj/item/weapon/reagent_containers/glass/bowl = 1,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/grown/tomato = 2,
|
||||
/obj/item/organ/eyes = 1
|
||||
)
|
||||
result = /obj/item/weapon/reagent_containers/food/snacks/soup/tomato/eyeball
|
||||
category = CAT_SOUP
|
||||
|
||||
|
||||
/datum/crafting_recipe/food/milosoup
|
||||
name = "Milo soup"
|
||||
reqs = list(
|
||||
|
||||
@@ -111,6 +111,7 @@
|
||||
for(var/datum/plant_gene/trait/trait in seed.genes)
|
||||
trait.on_squash(src, target)
|
||||
|
||||
reagents.reaction(T)
|
||||
for(var/A in T)
|
||||
reagents.reaction(A)
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
if(D.make_reagents.len)
|
||||
return 0
|
||||
|
||||
var/build_amount = 1
|
||||
var/build_amount = 0
|
||||
|
||||
for(var/mat_id in D.materials)
|
||||
var/M = D.materials[mat_id]
|
||||
@@ -93,7 +93,15 @@
|
||||
if(!M || !redemption_mat)
|
||||
return 0
|
||||
|
||||
build_amount = min(build_amount, round(redemption_mat.amount / M))
|
||||
var/smeltable_sheets = round(redemption_mat.amount / M)
|
||||
|
||||
if(!smeltable_sheets)
|
||||
return 0
|
||||
|
||||
if(!build_amount)
|
||||
build_amount = smeltable_sheets
|
||||
|
||||
build_amount = min(build_amount, smeltable_sheets)
|
||||
|
||||
return build_amount
|
||||
|
||||
@@ -152,6 +160,7 @@
|
||||
if(exchange_parts(user, W))
|
||||
return
|
||||
if(default_pry_open(W))
|
||||
materials.retrieve_all()
|
||||
return
|
||||
if(default_unfasten_wrench(user, W))
|
||||
return
|
||||
|
||||
@@ -20,6 +20,6 @@
|
||||
to_follow = V.source
|
||||
var/link = FOLLOW_LINK(src, to_follow)
|
||||
// Recompose the message, because it's scrambled by default
|
||||
message = compose_message(speaker, message_language, raw_message, radio_freq, spans)
|
||||
message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode)
|
||||
to_chat(src, "[link] [message]")
|
||||
|
||||
|
||||
@@ -35,22 +35,21 @@
|
||||
blood_volume += 0.1 // regenerate blood VERY slowly
|
||||
|
||||
//Effects of bloodloss
|
||||
var/word = pick("dizzy","woozy","faint")
|
||||
switch(blood_volume)
|
||||
if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE)
|
||||
if(prob(5))
|
||||
to_chat(src, "<span class='warning'>You feel [pick("dizzy","woozy","faint")].</span>")
|
||||
to_chat(src, "<span class='warning'>You feel [word].</span>")
|
||||
adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.01, 1))
|
||||
if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY)
|
||||
adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.02, 1))
|
||||
if(prob(5))
|
||||
blur_eyes(6)
|
||||
var/word = pick("dizzy","woozy","faint")
|
||||
to_chat(src, "<span class='warning'>You feel very [word].</span>")
|
||||
if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD)
|
||||
adjustOxyLoss(5)
|
||||
if(prob(15))
|
||||
Paralyse(rand(1,3))
|
||||
var/word = pick("dizzy","woozy","faint")
|
||||
to_chat(src, "<span class='warning'>You feel extremely [word].</span>")
|
||||
if(0 to BLOOD_VOLUME_SURVIVE)
|
||||
death()
|
||||
@@ -70,7 +69,7 @@
|
||||
|
||||
bleed_rate = max(bleed_rate - 0.5, temp_bleed)//if no wounds, other bleed effects (heparin) naturally decreases
|
||||
|
||||
if(bleed_rate && !bleedsuppress)
|
||||
if(bleed_rate && !bleedsuppress && !(status_flags & FAKEDEATH))
|
||||
bleed(bleed_rate)
|
||||
|
||||
//Makes a blood drop, leaking amt units of blood from the mob
|
||||
|
||||
@@ -87,6 +87,8 @@
|
||||
owner.adjustFireLoss(-heal_amt)
|
||||
owner.adjustOxyLoss(-heal_amt)
|
||||
owner.adjustCloneLoss(-heal_amt)
|
||||
else
|
||||
owner.adjustPlasma(plasma_rate * 0.1)
|
||||
|
||||
/obj/item/organ/alien/plasmavessel/Insert(mob/living/carbon/M, special = 0)
|
||||
..()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/mob/living/proc/alien_talk(message, shown_name = name)
|
||||
/mob/living/proc/alien_talk(message, shown_name = real_name)
|
||||
log_say("[key_name(src)] : [message]")
|
||||
message = trim(message)
|
||||
if(!message) return
|
||||
|
||||
@@ -484,7 +484,7 @@
|
||||
adjustBruteLoss(3)
|
||||
else
|
||||
if(T)
|
||||
T.add_vomit_floor(src, 0)//toxic barf looks different
|
||||
T.add_vomit_floor(src, toxic)//toxic barf looks different
|
||||
nutrition -= lost_nutrition
|
||||
adjustToxLoss(-3)
|
||||
T = get_step(T, dir)
|
||||
@@ -492,6 +492,16 @@
|
||||
break
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/proc/spew_organ(power = 5)
|
||||
if(!internal_organs.len)
|
||||
return //Guess we're out of organs
|
||||
var/obj/item/organ/guts = pick(internal_organs)
|
||||
var/turf/T = get_turf(src)
|
||||
guts.Remove(src)
|
||||
guts.forceMove(T)
|
||||
var/atom/throw_target = get_edge_target_turf(guts, dir)
|
||||
guts.throw_at(throw_target, power, 4, src)
|
||||
|
||||
|
||||
/mob/living/carbon/fully_replace_character_name(oldname,newname)
|
||||
..()
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
diff a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm (rejected hunks)
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
dna.species.spec_death(gibbed, src)
|
||||
|
||||
- if(SSticker && SSticker.mode)
|
||||
+ if(SSticker.HasRoundStarted())
|
||||
SSblackbox.ReportDeath(src)
|
||||
if(mind && mind.devilinfo)
|
||||
INVOKE_ASYNC(mind.devilinfo, /datum/devilinfo.proc/beginResurrectionCheck, src)
|
||||
@@ -134,7 +134,7 @@
|
||||
if(stat == DEAD || (status_flags & FAKEDEATH))
|
||||
appears_dead = 1
|
||||
if(suiciding)
|
||||
msg += "<span class='warning'>[t_He] appear[p_s()] to have commited suicide... there is no hope of recovery.</span>\n"
|
||||
msg += "<span class='warning'>[t_He] appear[p_s()] to have committed suicide... there is no hope of recovery.</span>\n"
|
||||
if(hellbound)
|
||||
msg += "<span class='warning'>[t_His] soul seems to have been ripped out of [t_his] body. Revival is impossible.</span>\n"
|
||||
msg += "<span class='deadsay'>[t_He] [t_is] limp and unresponsive; there are no signs of life"
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
//Holopad
|
||||
if(istype(ai.current, /obj/machinery/holopad))
|
||||
var/obj/machinery/holopad/H = ai.current
|
||||
H.move_hologram(ai)
|
||||
H.move_hologram(ai, T)
|
||||
|
||||
/mob/camera/aiEye/Move()
|
||||
return 0
|
||||
@@ -106,4 +106,4 @@
|
||||
|
||||
/mob/camera/aiEye/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
|
||||
if(relay_speech && speaker && ai && !radio_freq && speaker != ai && near_camera(speaker))
|
||||
ai.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans)
|
||||
ai.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mode)
|
||||
|
||||
@@ -108,6 +108,7 @@
|
||||
speak_emote = list("clanks", "clinks", "clunks", "clangs")
|
||||
verb_ask = "requests"
|
||||
verb_exclaim = "proclaims"
|
||||
verb_whisper = "imparts"
|
||||
verb_yell = "harangues"
|
||||
bubble_icon = "clock"
|
||||
initial_languages = list(/datum/language/common, /datum/language/ratvar)
|
||||
|
||||
@@ -401,7 +401,7 @@ Difficulty: Very Hard
|
||||
to_chat(user, observer_desc)
|
||||
to_chat(user, "It is activated by [activation_method].")
|
||||
|
||||
/obj/machinery/anomalous_crystal/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans)
|
||||
/obj/machinery/anomalous_crystal/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, message_mode)
|
||||
..()
|
||||
if(isliving(speaker))
|
||||
ActivationReaction(speaker, ACTIVATE_SPEECH)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/mob/living/simple_animal/slime/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans)
|
||||
/mob/living/simple_animal/slime/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, message_mode)
|
||||
if(speaker != src && !radio_freq && !stat)
|
||||
if (speaker in Friends)
|
||||
speech_buffer = list()
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
response_disarm = "shoos"
|
||||
response_harm = "stomps on"
|
||||
emote_see = list("jiggles", "bounces in place")
|
||||
speak_emote = list("telepathically chirps")
|
||||
speak_emote = list("blorbles")
|
||||
bubble_icon = "slime"
|
||||
initial_languages = list(/datum/language/common, /datum/language/slime)
|
||||
|
||||
@@ -31,10 +31,10 @@
|
||||
|
||||
see_in_dark = 8
|
||||
|
||||
verb_say = "telepathically chirps"
|
||||
verb_ask = "telepathically asks"
|
||||
verb_exclaim = "telepathically cries"
|
||||
verb_yell = "telephatically cries"
|
||||
verb_say = "blorbles"
|
||||
verb_ask = "inquisitively blorbles"
|
||||
verb_exclaim = "loudly blorbles"
|
||||
verb_yell = "loudly blorbles"
|
||||
|
||||
// canstun and canweaken don't affect slimes because they ignore stun and weakened variables
|
||||
// for the sake of cleanliness, though, here they are.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user