Merge remote-tracking branch 'refs/remotes/tgstation/master' into Research

This commit is contained in:
LatD
2016-05-25 18:45:31 +03:00
139 changed files with 5077 additions and 972 deletions

View File

@@ -2052,7 +2052,7 @@
pixel_x = 6;
pixel_y = 24
},
/obj/machinery/atmospherics/pipe/manifold4w/scrubbers/hidden,
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden,
/turf/open/floor/plasteel{
icon_state = "redcorner";
dir = 4
@@ -2518,7 +2518,7 @@
d2 = 8;
icon_state = "4-8"
},
/obj/machinery/atmospherics/pipe/manifold4w/supply/hidden,
/obj/machinery/atmospherics/pipe/manifold/supply/hidden,
/turf/open/floor/plasteel,
/area/security/prison)
"aeV" = (
@@ -2936,8 +2936,7 @@
/obj/structure/table,
/obj/item/device/electropack,
/turf/open/floor/plasteel{
icon_state = "whitehall";
dir = 2
icon_state = "red"
},
/area/security/prison)
"afE" = (
@@ -2954,9 +2953,9 @@
"afF" = (
/obj/structure/table,
/obj/item/device/assembly/signaler,
/obj/item/clothing/suit/straight_jacket,
/turf/open/floor/plasteel{
dir = 2;
icon_state = "escape"
icon_state = "red"
},
/area/security/prison)
"afG" = (
@@ -2972,8 +2971,7 @@
pixel_x = -6
},
/turf/open/floor/plasteel{
icon_state = "whitehall";
dir = 2
icon_state = "red"
},
/area/security/prison)
"afH" = (
@@ -2985,10 +2983,8 @@
},
/area/security/prison)
"afI" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plasteel{
icon_state = "whitehall";
dir = 2
icon_state = "red"
},
/area/security/prison)
"afJ" = (
@@ -2997,8 +2993,7 @@
pixel_y = -27
},
/turf/open/floor/plasteel{
icon_state = "whitehall";
dir = 2
icon_state = "red"
},
/area/security/prison)
"afK" = (
@@ -3236,13 +3231,13 @@
},
/area/security/prison)
"agl" = (
/obj/machinery/door/airlock/glass_security{
name = "Insanity Ward";
req_access_txt = "2"
/obj/machinery/door/airlock/security{
name = "Interrogation";
req_access = null;
req_access_txt = "63"
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plasteel{
icon_state = "white"
icon_state = "dark"
},
/area/security/prison)
"agm" = (
@@ -3312,16 +3307,13 @@
},
/area/security/warden)
"ags" = (
/obj/structure/cable{
d1 = 1;
d2 = 2;
icon_state = "1-2"
/obj/structure/chair{
dir = 4
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plasteel{
icon_state = "showroomfloor"
icon_state = "dark"
},
/area/security/warden)
/area/security/prison)
"agt" = (
/turf/open/floor/plasteel{
icon_state = "showroomfloor"
@@ -3471,46 +3463,14 @@
},
/area/security/main)
"agH" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plasteel{
icon_state = "warnwhite";
dir = 1
},
/area/security/prison)
"agI" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plasteel{
icon_state = "warnwhite";
dir = 5
},
/area/security/prison)
"agJ" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
/turf/open/floor/plasteel{
icon_state = "dark"
},
/area/security/brig)
"agK" = (
/obj/machinery/atmospherics/components/unary/vent_pump{
dir = 4;
on = 1
},
/turf/open/floor/plasteel{
icon_state = "dark"
},
/area/security/brig)
"agL" = (
/obj/structure/table,
/obj/item/weapon/folder/red,
/obj/item/weapon/pen,
/turf/open/floor/plasteel{
dir = 9;
icon_state = "warnwhite"
},
/area/security/prison)
"agM" = (
"agI" = (
/obj/machinery/airalarm{
pixel_y = 23
},
@@ -3520,8 +3480,8 @@
/turf/open/floor/plasteel{
icon_state = "dark"
},
/area/security/brig)
"agN" = (
/area/security/prison)
"agJ" = (
/obj/item/weapon/cigbutt,
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 10
@@ -3529,6 +3489,45 @@
/turf/open/floor/plasteel{
icon_state = "dark"
},
/area/security/prison)
"agK" = (
/turf/open/floor/plasteel{
icon_state = "dark"
},
/area/security/prison)
"agL" = (
/obj/machinery/atmospherics/components/unary/vent_pump{
dir = 4;
on = 1
},
/turf/open/floor/plasteel{
icon_state = "dark"
},
/area/security/prison)
"agM" = (
/obj/structure/table,
/obj/item/clothing/gloves/color/latex,
/obj/item/clothing/mask/surgical,
/obj/item/weapon/reagent_containers/spray/cleaner,
/turf/open/floor/plasteel{
dir = 9;
icon_state = "whitered"
},
/area/security/brig)
"agN" = (
/obj/structure/table,
/obj/item/device/radio/intercom{
freerange = 0;
frequency = 1459;
name = "Station Intercom (General)";
pixel_x = 0;
pixel_y = 26
},
/obj/item/weapon/storage/firstaid/regular,
/turf/open/floor/plasteel{
dir = 10;
icon_state = "whitered"
},
/area/security/brig)
"agO" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
@@ -3763,73 +3762,32 @@
},
/area/security/main)
"ahm" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 9
/obj/structure/window/reinforced{
dir = 4
},
/obj/structure/table,
/obj/item/weapon/paper_bin{
pixel_x = -3;
pixel_y = 7
},
/obj/item/weapon/pen,
/turf/open/floor/plasteel{
icon_state = "white"
dir = 5;
icon_state = "whitered"
},
/area/security/prison)
/area/security/brig)
"ahn" = (
/turf/closed/wall,
/area/maintenance/fsmaint)
"aho" = (
/turf/open/floor/plasteel{
icon_state = "white"
},
/area/security/prison)
"ahp" = (
/obj/machinery/light{
icon_state = "tube1";
dir = 8
},
/obj/item/device/radio/intercom{
desc = "Talk through this. It looks like it has been modified to not broadcast.";
dir = 2;
name = "Prison Intercom (General)";
pixel_x = -25;
pixel_y = -2;
prison_radio = 1
},
/obj/machinery/atmospherics/components/unary/vent_scrubber{
dir = 4;
on = 1;
scrub_N2O = 0;
scrub_Toxins = 0
},
/turf/open/floor/plasteel{
icon_state = "white"
},
/area/security/prison)
"ahq" = (
/obj/machinery/flasher{
id = "insaneflash";
pixel_x = 26
},
/obj/machinery/atmospherics/components/unary/vent_pump{
dir = 1;
external_pressure_bound = 101.325;
on = 1;
pressure_checks = 1
},
/turf/open/floor/plasteel{
icon_state = "white"
},
/area/security/prison)
"ahr" = (
/obj/structure/chair{
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
/turf/open/floor/plasteel{
icon_state = "dark"
},
/area/security/brig)
"ahs" = (
/turf/open/floor/plasteel{
icon_state = "dark"
},
/area/security/brig)
"aht" = (
/area/security/prison)
"ahp" = (
/obj/structure/chair{
dir = 8
},
@@ -3837,13 +3795,57 @@
/turf/open/floor/plasteel{
icon_state = "dark"
},
/area/security/brig)
"ahu" = (
/area/security/prison)
"ahq" = (
/obj/structure/table,
/obj/item/device/flashlight/lamp,
/turf/open/floor/plasteel{
icon_state = "dark"
},
/area/security/prison)
"ahr" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
/turf/open/floor/plasteel{
icon_state = "white"
},
/area/security/brig)
"ahs" = (
/obj/machinery/light/small{
dir = 1
},
/obj/machinery/airalarm{
pixel_y = 28
},
/turf/open/floor/plasteel{
dir = 1;
icon_state = "whitered"
},
/area/security/brig)
"aht" = (
/obj/machinery/atmospherics/components/unary/vent_pump{
dir = 4;
on = 1
},
/turf/open/floor/plasteel{
icon_state = "white"
},
/area/security/brig)
"ahu" = (
/obj/structure/table,
/obj/item/weapon/storage/box/bodybags,
/obj/structure/extinguisher_cabinet{
pixel_x = -27;
pixel_y = 0
},
/obj/item/weapon/reagent_containers/syringe,
/obj/item/weapon/reagent_containers/glass/bottle/charcoal,
/obj/item/weapon/reagent_containers/glass/bottle/epinephrine,
/turf/open/floor/plasteel{
dir = 10;
icon_state = "whitered"
},
/area/security/brig)
"ahv" = (
/obj/machinery/power/apc{
@@ -3965,21 +3967,21 @@
/turf/open/floor/plasteel,
/area/security/main)
"ahD" = (
/obj/structure/cable{
d1 = 4;
d2 = 8;
icon_state = "4-8"
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
/obj/structure/cable{
d1 = 1;
d2 = 4;
icon_state = "1-4"
/obj/machinery/door/window/westleft{
base_state = "left";
dir = 4;
icon_state = "left";
name = "Infirmary";
req_access_txt = "0"
},
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden,
/turf/open/floor/plasteel{
icon_state = "showroomfloor"
dir = 4;
icon_state = "whitered"
},
/area/security/warden)
/area/security/brig)
"ahE" = (
/obj/machinery/door/airlock/glass_security{
name = "Brig Control";
@@ -4160,12 +4162,8 @@
/turf/closed/wall,
/area/security/main)
"ahP" = (
/obj/machinery/camera{
c_tag = "Brig Interrogation";
dir = 8
},
/turf/open/floor/plasteel{
icon_state = "dark"
icon_state = "white"
},
/area/security/brig)
"ahQ" = (
@@ -4224,33 +4222,22 @@
/turf/open/floor/plating,
/area/maintenance/fsmaint)
"ahU" = (
/obj/structure/bed,
/obj/item/clothing/suit/straight_jacket,
/obj/machinery/camera{
c_tag = "Prison Sanitatium";
dir = 4;
network = list("SS13","Prison");
pixel_x = 0;
/obj/structure/cable{
d1 = 1;
d2 = 2;
icon_state = "1-2";
pixel_y = 0
},
/obj/effect/landmark{
name = "revenantspawn"
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
/turf/open/floor/plasteel{
icon_state = "white"
icon_state = "red";
dir = 9
},
/area/security/prison)
/area/security/brig)
"ahV" = (
/obj/structure/bed,
/obj/item/clothing/suit/straight_jacket,
/obj/effect/landmark{
name = "revenantspawn"
},
/turf/open/floor/plasteel{
icon_state = "white"
},
/area/security/prison)
"ahW" = (
/obj/structure/table,
/obj/item/weapon/folder/red,
/obj/item/device/taperecorder{
@@ -4259,6 +4246,15 @@
/turf/open/floor/plasteel{
icon_state = "dark"
},
/area/security/prison)
"ahW" = (
/obj/structure/bodycontainer/morgue,
/obj/structure/window/reinforced{
dir = 1
},
/turf/open/floor/plasteel{
icon_state = "dark"
},
/area/security/brig)
"ahX" = (
/obj/structure/table,
@@ -4343,12 +4339,10 @@
/turf/open/floor/plating,
/area/maintenance/fsmaint)
"aid" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/machinery/light/small,
/turf/open/floor/plasteel{
icon_state = "dark"
dir = 10;
icon_state = "whitered"
},
/area/security/brig)
"aie" = (
@@ -4384,19 +4378,14 @@
},
/area/security/warden)
"aih" = (
/obj/structure/table,
/obj/item/weapon/paper_bin{
pixel_x = -3;
pixel_y = 7
},
/obj/item/weapon/book/manual/wiki/security_space_law,
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
dir = 4
},
/turf/open/floor/plasteel{
icon_state = "showroomfloor"
icon_state = "red";
dir = 5
},
/area/security/warden)
/area/security/brig)
"aii" = (
/obj/structure/grille,
/obj/structure/disposalpipe/segment{
@@ -4438,9 +4427,14 @@
},
/area/security/main)
"ail" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/closed/wall,
/area/security/brig)
/obj/machinery/camera{
c_tag = "Brig Interrogation";
dir = 8
},
/turf/open/floor/plasteel{
icon_state = "dark"
},
/area/security/prison)
"aim" = (
/obj/machinery/light_switch{
pixel_y = -23
@@ -4451,14 +4445,9 @@
},
/area/security/main)
"ain" = (
/obj/machinery/door/airlock/security{
name = "Interrogation";
req_access = null;
req_access_txt = "63"
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plasteel{
icon_state = "dark"
dir = 8;
icon_state = "whitered"
},
/area/security/brig)
"aio" = (
@@ -4566,24 +4555,18 @@
},
/area/security/main)
"aiw" = (
/obj/machinery/door/airlock/maintenance{
name = "Security Maintenance";
req_access_txt = "63"
/obj/machinery/door/window/westleft{
base_state = "right";
dir = 4;
icon_state = "right";
name = "Infirmary";
req_access_txt = "0"
},
/obj/structure/cable{
d1 = 4;
d2 = 8;
icon_state = "4-8";
pixel_y = 0
/turf/open/floor/plasteel{
dir = 4;
icon_state = "whitered"
},
/obj/structure/disposalpipe/segment{
dir = 4
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
/turf/open/floor/plating,
/area/security/main)
/area/security/brig)
"aix" = (
/obj/structure/cable{
d1 = 4;
@@ -4628,45 +4611,49 @@
/turf/open/floor/plating,
/area/maintenance/fsmaint)
"aiB" = (
/obj/structure/table/glass,
/obj/item/weapon/reagent_containers/glass/bottle/morphine,
/turf/open/floor/plasteel{
icon_state = "white"
},
/area/security/prison)
"aiC" = (
/obj/structure/table/glass,
/obj/item/weapon/reagent_containers/syringe,
/turf/open/floor/plasteel{
icon_state = "white"
},
/area/security/prison)
"aiD" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
/turf/open/floor/plasteel{
icon_state = "dark"
},
/area/security/brig)
"aiE" = (
/obj/machinery/atmospherics/components/unary/vent_scrubber{
dir = 4;
on = 1;
scrub_N2O = 0;
scrub_Toxins = 0
},
/turf/open/floor/plasteel{
icon_state = "dark"
},
/area/security/prison)
"aiC" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plasteel{
icon_state = "dark"
},
/area/security/prison)
"aiD" = (
/obj/structure/bodycontainer/morgue,
/turf/open/floor/plasteel{
icon_state = "dark"
},
/area/security/brig)
"aiF" = (
"aiE" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 10
},
/turf/open/floor/plasteel{
icon_state = "dark"
},
/area/security/prison)
"aiF" = (
/obj/structure/bed,
/obj/item/weapon/bedsheet,
/obj/machinery/iv_drip{
density = 0
},
/obj/item/clothing/suit/straight_jacket,
/turf/open/floor/plasteel{
icon_state = "whitered"
},
/area/security/brig)
"aiG" = (
/turf/open/floor/plasteel{
@@ -4777,20 +4764,19 @@
/turf/open/floor/plating,
/area/security/warden)
"aiO" = (
/obj/machinery/door/firedoor,
/obj/machinery/door/airlock/security{
name = "Security Office";
req_access = null;
req_access_txt = "63"
/obj/structure/window/reinforced{
dir = 4
},
/obj/structure/cable{
d1 = 1;
d2 = 2;
icon_state = "1-2"
/obj/structure/table,
/obj/item/weapon/storage/firstaid/regular,
/obj/item/device/healthanalyzer{
pixel_y = -2
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plasteel,
/area/security/main)
/turf/open/floor/plasteel{
dir = 6;
icon_state = "whitered"
},
/area/security/brig)
"aiP" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/closed/wall/r_wall,
@@ -4827,10 +4813,16 @@
/turf/closed/wall/r_wall,
/area/security/processing)
"aiW" = (
/obj/structure/grille,
/obj/structure/window/reinforced/fulltile,
/turf/open/floor/plating,
/area/security/brig)
/obj/machinery/door/airlock/security{
name = "Interrogation";
req_access = null;
req_access_txt = "63"
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plasteel{
icon_state = "dark"
},
/area/security/prison)
"aiX" = (
/turf/closed/wall/r_wall,
/area/security/brig)
@@ -4851,7 +4843,6 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plasteel{
icon_state = "redcorner";
dir = 1
@@ -4864,7 +4855,9 @@
icon_state = "4-8";
pixel_y = 0
},
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
/turf/open/floor/plasteel,
/area/security/brig)
"ajb" = (
@@ -5069,6 +5062,7 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plasteel{
icon_state = "red";
dir = 1
@@ -5107,9 +5101,7 @@
},
/area/security/brig)
"ajA" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden,
/turf/open/floor/plasteel{
icon_state = "red";
dir = 1
@@ -5414,9 +5406,7 @@
c_tag = "Brig West";
dir = 1
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
/obj/machinery/atmospherics/pipe/manifold/supply/hidden,
/turf/open/floor/plasteel{
dir = 2;
icon_state = "redcorner"
@@ -89603,12 +89593,12 @@ adF
aef
aeM
afz
acd
aai
aai
aai
aai
aiV
aai
aai
ajt
akc
akJ
@@ -89862,10 +89852,10 @@ aeO
afJ
acd
agL
ahp
ahU
agK
agK
aiB
aiX
aai
ajw
akf
aiX
@@ -90115,14 +90105,14 @@ abK
acY
adG
aeh
aeR
aeO
afI
agl
agH
ahm
ags
ags
aho
aho
aiW
acd
ajv
ake
agj
@@ -90373,13 +90363,13 @@ acd
acd
aek
aeU
afE
adF
afI
acd
agI
ahq
ahV
aiC
agj
aho
acd
ajy
akh
afK
@@ -90631,12 +90621,12 @@ adF
aej
aeQ
afD
agj
agj
agj
agj
agj
agj
acd
agJ
ahp
ahp
aiC
adF
ajx
akg
agj
@@ -90888,12 +90878,12 @@ adI
aem
aeO
afG
agj
acd
agK
ahs
ahs
agK
ail
aiE
agj
aiW
ajA
akj
agj
@@ -91146,10 +91136,10 @@ ael
aeO
afF
agj
agJ
ahs
ahs
aiD
agj
agj
agj
agj
agj
ajz
aki
@@ -91662,11 +91652,11 @@ afH
agj
agN
aht
aht
ain
aid
ail
agj
aiZ
ajF
akk
akN
alw
amg
@@ -91918,10 +91908,10 @@ aeT
afH
agj
ahs
ahs
ahr
ahP
aiF
ain
agj
aja
ajG
akQ
@@ -92174,10 +92164,10 @@ aeq
aeV
acd
agj
agj
agj
agj
agj
ahm
ahD
aiw
aiO
agj
ajD
akm
@@ -92432,7 +92422,7 @@ afC
agk
agF
agP
agP
ahU
agP
agP
aiz
@@ -92689,7 +92679,7 @@ afB
agi
agD
agO
agO
aih
agO
agO
aiy

View File

@@ -39,3 +39,4 @@
#define ANTAG_HUD_DEVIL 17
#define ANTAG_HUD_SINTOUCHED 18
#define ANTAG_HUD_SOULLESS 19
#define ANTAG_HUD_CLOCKWORK 20

View File

@@ -433,3 +433,6 @@ var/global/list/ghost_others_options = list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
// Evil narsie colour
#define NARSIE_WINDOW_COLOUR "#7D1919"
// Defib stats
#define DEFIB_TIME_LIMIT 120
#define DEFIB_TIME_LOSS 60

View File

@@ -25,7 +25,7 @@
#define ROLE_HOG_GOD "hand of god: god"
#define ROLE_HOG_CULTIST "hand of god: cultist"
#define ROLE_DEVIL "devil"
#define ROLE_SERVANT_OF_RATVAR "servant of Ratvar"
//Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR.
//The gamemode specific ones are just so the gamemodes can query whether a player is old enough
@@ -49,5 +49,6 @@ var/global/list/special_roles = list(
ROLE_ABDUCTOR = /datum/game_mode/abduction,
ROLE_HOG_GOD = /datum/game_mode/hand_of_god,
ROLE_HOG_CULTIST = /datum/game_mode/hand_of_god,
ROLE_DEVIL = /datum/game_mode/devil
ROLE_DEVIL = /datum/game_mode/devil,
ROLE_SERVANT_OF_RATVAR = /datum/game_mode/clockwork_cult,
)

View File

@@ -238,13 +238,7 @@
return r
// Returns the key based on the index
/proc/get_key_by_index(list/L, index)
var/i = 1
for(var/key in L)
if(index == i)
return key
i++
return null
#define KEYBYINDEX(L, index) (((index <= L:len) && (index > 0)) ? L[index] : null)
/proc/count_by_type(list/L, type)
var/i = 0
@@ -365,3 +359,6 @@
for(var/i = 1 to l.len)
if(islist(.[i]))
.[i] = .(.[i])
//Picks from the list, with some safeties, and returns the "default" arg if it fails
#define DEFAULTPICK(L, default) ((istype(L, /list) && L:len) ? pick(L) : default)

View File

@@ -21,6 +21,7 @@ var/datum/atom_hud/huds = list( \
ANTAG_HUD_DEVIL = new/datum/atom_hud/antag(),\
ANTAG_HUD_SINTOUCHED = new/datum/atom_hud/antag/hidden(),\
ANTAG_HUD_SOULLESS = new/datum/atom_hud/antag/hidden(),\
ANTAG_HUD_CLOCKWORK = new/datum/atom_hud/antag(),\
)
/datum/atom_hud

View File

@@ -245,6 +245,7 @@
"nuclear",
"traitor", // "traitorchan",
"monkey",
"clockcult"
)
var/text = ""
@@ -352,6 +353,26 @@
sections["cult"] = text
/** CLOCKWORK CULT **/
text = "clockwork cult"
if(ticker.mode.config_tag == "clockwork cult")
text = uppertext(text)
text = "<i><b>[text]</b></i>: "
if(src in ticker.mode.servants_of_ratvar)
text += "loyal|<a href='?src=\ref[src];clockcult=clear'>employee</a>|<b>SERVANT</b>"
text += "<br><a href='?src=\ref[src];clockcult=slab'>Give slab</a>"
else if(isloyal(current))
text += "<b>LOYAL</b>|employee|<a href='?src=\ref[src];clockcult=servant'>servant</a>"
else
text += "loyal|<b>EMPLOYEE</b>|<a href='?src=\ref[src];clockcult=servant'>servant</a>"
if(current && current.client && (ROLE_SERVANT_OF_RATVAR in current.client.prefs.be_special))
text += "|Enabled in Prefs"
else
text += "|Disabled in Prefs"
sections["clockcult"] = text
/** WIZARD ***/
text = "wizard"
if (ticker.mode.config_tag=="wizard")
@@ -1017,6 +1038,22 @@
if (!ticker.mode.equip_cultist(current))
usr << "<span class='danger'>Spawning amulet failed!</span>"
else if(href_list["clockcult"])
switch(href_list["clockcult"])
if("clear")
remove_servant_of_ratvar(current)
message_admins("[key_name_admin(usr)] has removed clockwork servant status from [current].")
log_admin("[key_name(usr)] has removed clockwork servant status from [current].")
if("servant")
if(!(src in ticker.mode.servants_of_ratvar))
add_servant_of_ratvar(current)
message_admins("[key_name_admin(usr)] has made [current] into a servant of Ratvar.")
log_admin("[key_name(usr)] has made [current] into a servant of Ratvar.")
if("slab")
if(!ticker.mode.equip_servant(current))
usr << "<span class='warning'>Failed to outfit [current] with a slab!</span>"
else
usr << "<span class='notice'>Successfully gave [current] a clockwork slab!</span>"
else if (href_list["wizard"])
switch(href_list["wizard"])
@@ -1689,7 +1726,11 @@
return G
break
/datum/mind/proc/grab_ghost(force)
var/mob/dead/observer/G = get_ghost(even_if_they_cant_reenter = force)
. = G
if(G)
G.reenter_corpse()
/mob/proc/sync_mind()
mind_initialize() //updates the mind (or creates and initializes one if one doesn't exist)

View File

@@ -212,13 +212,17 @@
mob_size = MOB_SIZE_LARGE
see_invisible = SEE_INVISIBLE_MINIMUM
see_in_dark = 8
var/independent = FALSE
/mob/living/simple_animal/hostile/blob/blobbernaut/New()
..()
verbs -= /mob/living/verb/pulled //no pulling people deep into the blob
if(!independent) //no pulling people deep into the blob
verbs -= /mob/living/verb/pulled
/mob/living/simple_animal/hostile/blob/blobbernaut/Life()
if(..())
if(independent)
return // strong independent blobbernaut that don't need no blob
var/damagesources = 0
if(!(locate(/obj/effect/blob) in range(2, src)))
damagesources++
@@ -271,3 +275,7 @@
factory.naut = null //remove this naut from its factory
factory.maxhealth = initial(factory.maxhealth)
flick("blobbernaut_death", src)
/mob/living/simple_animal/hostile/blob/blobbernaut/independent
independent = TRUE
gold_core_spawnable = 1

View File

@@ -0,0 +1,16 @@
var/global/clockwork_construction_value = 0 //The total value of all structures built by the clockwork cult
var/global/clockwork_caches = 0 //How many clockwork caches exist in the world (not each individual)
var/global/clockwork_daemons = 0 //How many daemons exist in the world
var/global/list/clockwork_generals_invoked = list("nezbere" = FALSE, "sevtug" = FALSE, "nzcrentr" = FALSE, "inath-neq" = FALSE) //How many generals have been recently invoked
var/global/list/all_clockwork_objects = list() //All clockwork items, structures, and effects in existence
var/global/list/all_clockwork_mobs = list() //All clockwork SERVANTS (not creatures) in existence
var/global/list/clockwork_component_cache = list("belligerent_eye" = 0, "vanguard_cogwheel" = 0, "guvax_capacitor" = 0, "replicant_alloy" = 0, "hierophant_ansible" = 0) //The pool of components that caches draw from
#define SCRIPTURE_PERIPHERAL 0 //Should never be used
#define SCRIPTURE_DRIVER 1
#define SCRIPTURE_SCRIPT 2
#define SCRIPTURE_APPLICATION 3
#define SCRIPTURE_REVENANT 4
#define SCRIPTURE_JUDGEMENT 5
#define SLAB_PRODUCTION_THRESHOLD 60 //How many cycles it takes slabs to produce a single component; defaults to one minute

View File

@@ -0,0 +1,274 @@
/*
CLOCKWORK CULT: Based off of the failed pull requests from vgstation
While Nar-Sie is the oldest and most prominent of the elder gods, there are other forces at work in the universe.
Ratvar, the Clockwork Justiciar, a homage to Nar-Sie granted sentience by its own power, is one such other force.
Imprisoned within a massive construct known as the Celestial Derelict - or Reebe - an intense hatred of the Blood God festers.
Ratvar, unable to act in the mortal plane, seeks to return and forms covenants with mortals in order to bolster his influence.
Due to his mechanical nature, Ratvar is also capable of influencing silicon-based lifeforms, unlike Nar-Sie, who can only influence natural life.
This is a team-based gamemode.
There are three possible objectives the Enlightened - Ratvar's minions - can have:
1. Ensure X amount of Enlightened escape the station through the shuttle or otherwise.
2. Convert all silicon lifeforms on the station to Ratvar's cause.
3. Summon Ratvar via construction of a Gateway.
The clockwork version of an arcane tome is the clockwork slab.
While it can perform certain actions, it consumes a resource called components.
Components, which are fallen fragments of Ratvar's body as he rusts in Reebe, are powerful and have various effects.
Game-wise, clockwork slabs will generate components over time, with more powerful components being slower.
This file's folder contains:
__clock_defines.dm: Defined variables
clock_cult.dm: Core gamemode files.
clock_mobs.dm: Hostile and benign clockwork creatures.
clock_objects.dm: Items and structures.
clock_ratvar.dm: The Ark of the Clockwork Justiciar and Ratvar himself. Important enough to have his own file.
clock_scripture.dm: Scripture and rites.
clock_unsorted.dm: Anything else with no place to be
*/
///////////
// PROCS //
///////////
/proc/is_servant_of_ratvar(mob/M)
return M && istype(M) && M.mind && ticker && ticker.mode && (M.mind in ticker.mode.servants_of_ratvar)
/proc/is_eligible_servant(mob/M)
return M && istype(M) && M.mind && !M.mind.special_role && !isloyal(M)
/proc/add_servant_of_ratvar(mob/M, silent = FALSE)
if(!is_eligible_servant(M) || !ticker || !ticker.mode)
return 0
if(iscarbon(M))
if(!silent)
M << "<span class='heavy_brass'>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(!is_eligible_servant(M))
M.visible_message("<span class='warning'>[M] seems to resist an unseen force!</span>", "<span class='warning'><b>And yet, you somehow push it all away.</b></span>")
return 0
else if(issilicon(M))
if(!silent)
M << "<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>"
if(!is_eligible_servant(M))
M.visible_message("<span class='warning'>[M] whirs as it resists an outside influence!</span>", \
"<span class='warning'><b>Corrupt data purged. Resetting cortex chip to factory defaults... complete.</b></span>")
return 0
if(!silent)
M.visible_message("<span class='heavy_brass'>[M]'s eyes glow a blazing yellow!</span>", \
"<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>")
ticker.mode.servants_of_ratvar += M.mind
ticker.mode.update_servant_icons_added(M.mind)
M.mind.special_role = "Servant of Ratvar"
all_clockwork_mobs += M
if(issilicon(M))
var/mob/living/silicon/S = M
if(isrobot(S))
var/mob/living/silicon/robot/R = S
R.UnlinkSelf()
R.emagged = 1
R << "<span class='warning'><b>You have been desynced from your master AI. In addition, your onboard camera is no longer active and your safeties have been disabled.</b></span>"
S.laws = new/datum/ai_laws/ratvar
S.update_icons()
S.show_laws()
if(istype(ticker.mode, /datum/game_mode/clockwork_cult))
var/datum/game_mode/clockwork_cult/C = ticker.mode
C.present_tasks(M) //Memorize the objectives
return 1
/proc/remove_servant_of_ratvar(mob/M)
if(!is_servant_of_ratvar(M)) //In this way, is_servant_of_ratvar() checks the existence of ticker and minds
return 0
M.visible_message("<span class='big'>[M] 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>")
ticker.mode.servants_of_ratvar -= M.mind
ticker.mode.update_servant_icons_removed(M.mind)
all_clockwork_mobs -= M
M.mind.memory = "" //Not sure if there's a better way to do this
M.mind.special_role = null
M.verbs -= /mob/living/carbon/human/proc/function_call //Removes any bound Ratvarian spears
if(issilicon(M))
var/mob/living/silicon/S = M
if(isrobot(S))
var/mob/living/silicon/robot/R = S
R.emagged = initial(R.emagged)
R << "<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>"
S.laws = initial(S.laws)
S.update_icons()
S.show_laws()
return 1
/proc/send_hierophant_message(mob/user, message)
if(!user || !message || !ticker || !ticker.mode)
return 0
var/parsed_message = "<span class='heavy_brass'>Servant [user.name == user.real_name ? user.name : "[user.real_name] (as [user.name])"]: </span><span class='brass'>\"[message]\"</span>"
for(var/mob/M in mob_list)
if(is_servant_of_ratvar(M) || isobserver(M))
M << parsed_message
return 1
///////////////
// GAME MODE //
///////////////
var/global/ratvar_awakens = FALSE //If Ratvar has been summoned
/datum/game_mode
var/list/servants_of_ratvar = list() //The Enlightened servants of Ratvar
var/required_escapees = 0 //How many servants need to escape, if applicable
var/required_silicon_converts = 0 //How many robotic lifeforms need to be converted, if applicable
var/clockwork_objective = "escape" //The objective that the servants must fulfill
var/clockwork_explanation = "Ensure that the meme levels of the station remain high." //The description of the current objective
/datum/game_mode/clockwork_cult
name = "clockwork cult"
config_tag = "clockwork cult"
antag_flag = ROLE_SERVANT_OF_RATVAR
required_players = 30
required_enemies = 2
recommended_enemies = 4
enemy_minimum_age = 14
protected_jobs = list("AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Captain") //Silicons can eventually be converted
/datum/game_mode/clockwork_cult/announce()
world << "<b>The game mode is: Clockwork Cult!</b>"
world << "<b><span class='brass'>Ratvar</span>, the Clockwork Justiciar, has formed a covenant of Enlightened aboard [station_name()].</b>"
world << "<b><span class='brass'>Enlightened</span>: Serve your master so that his influence might grow.</b>"
world << "<b><span class='boldannounce'>Crew</span>: Prevent the servants of Ratvar from taking over the station.</b>"
/datum/game_mode/clockwork_cult/pre_setup()
if(config.protect_roles_from_antagonist)
restricted_jobs += protected_jobs
if(config.protect_assistant_from_antagonist)
restricted_jobs += "Assistant"
var/starter_servants = max(1, round(num_players() / 10)) //Guaranteed one cultist - otherwise, about one cultist for every ten players
while(starter_servants)
var/datum/mind/servant = pick(antag_candidates)
servants_of_ratvar += servant
antag_candidates -= servant
modePlayer += servant
servant.special_role = "Servant of Ratvar"
servant.restricted_roles = restricted_jobs
update_servant_icons_added(servant)
starter_servants--
return 1
/datum/game_mode/clockwork_cult/post_setup()
forge_clock_objectives()
for(var/S in servants_of_ratvar)
var/datum/mind/servant = S
log_game("[servant.key] was made an initial servant of Ratvar")
var/mob/living/L = servant.current
greet_servant(L)
equip_servant(L)
present_tasks(L)
..()
return 1
/datum/game_mode/clockwork_cult/proc/forge_clock_objectives() //Determine what objective that Ratvar's servants will fulfill
var/list/possible_objectives = list("escape", "gateway")
var/silicons_possible = FALSE
for(var/mob/living/silicon/S in living_mob_list)
silicons_possible = TRUE
if(silicons_possible)
possible_objectives += "silicons"
clockwork_objective = pick(possible_objectives)
clockwork_objective = "gateway" //TEMPORARY, to be removed before merge
switch(clockwork_objective)
if("escape")
required_escapees = max(1, num_players() / 3) //33% of the player count must be cultists
clockwork_explanation = "Ensure that [required_escapees] servant(s) of Ratvar escape from [station_name()]."
if("gateway")
clockwork_explanation = "Construct a Gateway to the Celestial Derelict and free Ratvar."
if("silicons")
clockwork_explanation = "Ensure that all silicon-based lifeforms on [station_name()] are servants of Ratvar by the end of the shift."
return 1
/datum/game_mode/clockwork_cult/proc/greet_servant(mob/M) //Description of their role
if(!M)
return 0
var/greeting_text = "<br><b><span class='large_brass'>You are a servant of Ratvar, the Clockwork Justiciar.</span>\n\
Rusting eternally in the Celestial Derelict, Ratvar has formed a covenant of mortals, with you as one of its members. As one of the Justiciar's servants, you are to work to the best of your \
ability to assist in completion of His agenda. You do not know the specifics of how to do so, but luckily you have a vessel to help you learn.</b>"
M << greeting_text
return 1
/datum/game_mode/proc/equip_servant(mob/living/L) //Grants a clockwork slab to the mob, with one of each component
if(!L || !istype(L))
return 0
var/slot = "At your feet"
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(H.back && istype(H.back, /obj/item/weapon/storage/backpack))
var/obj/item/weapon/storage/backpack/B = H.back
new/obj/item/clockwork/slab/starter(B)
slot = "In your [B.name]"
if(slot == "At your feet")
new/obj/item/clockwork/slab/starter(get_turf(L))
L << "<b>[slot] is a link to the halls of Reebe and your master. You may use it to perform many tasks, but also become oriented with the workings of Ratvar and how to best complete your \
tasks. This clockwork slab will be instrumental in your triumph. Remember: you can speak discreetly with your fellow servants by using Report in your slab's interface, and you can find a \
concise tutorial in Recollection."
return 1
/datum/game_mode/clockwork_cult/proc/present_tasks(mob/living/L) //Memorizes and displays the clockwork cult's objective
if(!L || !istype(L) || !L.mind)
return 0
var/datum/mind/M = L.mind
M.current << "<b>This is Ratvar's will:</b> [clockwork_explanation]"
M.memory += "<b>Ratvar's will:</b> [clockwork_explanation]<br>"
return 1
/datum/game_mode/clockwork_cult/proc/check_clockwork_victory()
switch(clockwork_objective)
if("escape")
var/surviving_servants = 0
for(var/datum/mind/M in servants_of_ratvar)
if(M.current && M.current.stat != DEAD && (M.current.onCentcom() || M.current.onSyndieBase()))
surviving_servants++
if(surviving_servants <= required_escapees)
return 1
return 0
if("silicons")
for(var/mob/living/silicon/robot/S in mob_list) //Only check robots and AIs
if(!is_servant_of_ratvar(S))
return 0
for(var/mob/living/silicon/ai/A in mob_list)
if(!is_servant_of_ratvar(A))
return 0
return 1
if("gateway")
return ratvar_awakens
return 0 //This shouldn't ever be reached, but just in case it is
/datum/game_mode/clockwork_cult/declare_completion()
..()
return 0 //Doesn't end until the round does
/datum/game_mode/proc/auto_declare_completion_clockwork_cult()
var/text = ""
if(istype(ticker.mode, /datum/game_mode/clockwork_cult)) //Possibly hacky?
var/datum/game_mode/clockwork_cult/C = ticker.mode
if(C.check_clockwork_victory())
text += "<span class='brass'><b>Ratvar's servants have succeeded in fulfilling His goals!</b></span>"
else
text += "<span class='userdanger'>Ratvar's servants have failed!</span>"
text += "<br><b>The goal of the clockwork cult was:</b> [clockwork_explanation]<br>"
text += "<b>Ratvar's servants were:</b>"
for(var/datum/mind/M in servants_of_ratvar)
text += printplayer(M)
world << text
/datum/game_mode/proc/update_servant_icons_added(datum/mind/M)
var/datum/atom_hud/antag/A = huds[ANTAG_HUD_CLOCKWORK]
A.join_hud(M.current)
set_antag_hud(M.current, "clockwork")
/datum/game_mode/proc/update_servant_icons_removed(datum/mind/M)
var/datum/atom_hud/antag/A = huds[ANTAG_HUD_CLOCKWORK]
A.leave_hud(M.current)
set_antag_hud(M.current, null)

View File

@@ -0,0 +1,279 @@
/mob/living/simple_animal/hostile/anima_fragment //Anima fragment: Low health but high melee power. Created by inserting a soul vessel into an empty fragment.
name = "anima fragment"
desc = "An ominous humanoid shell with a spinning cogwheel as its head, lifted by a jet of blazing red flame."
icon = 'icons/mob/clockwork_mobs.dmi'
icon_state = "anime_fragment"
health = 75 //Glass cannon
maxHealth = 75
wander = FALSE
minbodytemp = 0
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) //Robotic
healable = FALSE
melee_damage_lower = 25
melee_damage_upper = 25
attacktext = "crushes"
attack_sound = 'sound/magic/clockwork/anima_fragment_attack.ogg'
var/playstyle_string = "<span class='heavy_brass'>You are an anima fragment</span><b>, a clockwork creation of Ratvar. As a fragment, you are weak but possess powerful melee capabilities \
in addition to being immune to extreme temperatures and pressures. Your goal is to serve the Justiciar and his servants in any way you can. You yourself are one of these servants, and will \
be able to utilize anything they can, assuming it doesn't require opposable thumbs.</b>"
/mob/living/simple_animal/hostile/anima_fragment/New()
..()
if(prob(1))
name = "anime fragment"
real_name = name
desc = "I-it's not like I want to show you the light of the Justiciar or anything, B-BAKA!"
/mob/living/simple_animal/hostile/anima_fragment/death(gibbed)
..(TRUE)
visible_message("<span class='warning'>[src]'s flame jets cut out as it falls to the floor with a tremendous crash. A cube of metal tumbles out, whirring and sputtering.</span>", \
"<span class='userdanger'>Your gears seize up. Your flame jets flicker. Your soul vessel belches smoke as you helplessly crash down.</span>")
playsound(src, 'sound/magic/clockwork/anima_fragment_death.ogg', 100, 1)
new/obj/item/clockwork/component/replicant_alloy/smashed_anima_fragment(get_turf(src))
new/obj/item/device/mmi/posibrain/soul_vessel(get_turf(src)) //Notice the lack of transfer - it's a standard soul vessel with no mind in it!
qdel(src)
return 1
/mob/living/simple_animal/hostile/clockwork_marauder //Clockwork marauder: Slow but with high damage, resides inside of a servant. Created via the Memory Allocation scripture.
name = "clockwork marauder"
desc = "A stalwart apparition of a soldier, blazing with crimson flames. It's armed with a gladius and shield."
icon = 'icons/mob/clockwork_mobs.dmi'
icon_state = "clockwork_marauder"
health = 25 //Health is governed by fatigue, but can be directly reduced by the presence of certain objects
maxHealth = 25
wander = FALSE
speed = 1
minbodytemp = 0
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
healable = FALSE
melee_damage_lower = 10
melee_damage_upper = 10
attacktext = "slashes"
attack_sound = 'sound/weapons/bladeslice.ogg'
var/true_name = "Meme Master 69" //Required to call forth the marauder
var/list/possible_true_names = list("Xaven", "Melange", "Ravan", "Kel", "Rama", "Geke", "Peris", "Vestra", "Skiwa") //All fairly short and easy to pronounce
var/fatigue = 0 //Essentially what determines the marauder's power
var/fatigue_recall_threshold = 100 //In variable form due to changed effects once Ratvar awakens
var/mob/living/host //The mob that the marauder is living inside of
var/recovering = FALSE //If the marauder is recovering from a large amount of fatigue
var/playstyle_string = "<span class='heavy_brass'>You are a clockwork marauder</span><b>, a living extension of Ratvar's will. As a marauder, you are slow but sturdy and decently powerful \
in addition to being immune to extreme temperatures and pressures. Your primary goal is to serve the creature that you are now a part of. You can use the Linked Minds ability in your \
Marauder tab to communicate silently with your master, but can only exit if your master calls your true name.\n\n\
\
Taking damage and remaining outside of your master will cause <i>fatigue</i>, which hinders your movement speed and attacks, in addition to forcing you back into your master if it grows \
too high. As a final note, you should probably avoid harming any fellow servants of Ratvar.</span>"
/mob/living/simple_animal/hostile/clockwork_marauder/New()
..()
true_name = pick(possible_true_names)
/mob/living/simple_animal/hostile/clockwork_marauder/Life()
..()
if(is_in_host())
fatigue = max(0, fatigue - 2) //Doesn't use adjust_fatigue in order to bypass the Ratvar edgecase
if(!fatigue && recovering)
src << "<span class='userdanger'>Your strength has returned. You can once again come forward!</span>"
host << "<span class='userdanger'>Your marauder is now strong enough to come forward again!</span>"
recovering = FALSE
else
if(ratvar_awakens) //If Ratvar is alive, marauders both don't take fatigue loss and move at sanic speeds
speed = -1
melee_damage_lower = 30
melee_damage_upper = 30
attacktext = "devastates"
else
if(host)
switch(get_dist(src, host))
if(1 to 5)
adjust_fatigue(1)
if(5 to INFINITY)
adjust_fatigue(rand(10, 20))
src << "<span class='userdanger'>You're too far from your host and rapidly taking fatigue damage!</span>"
switch(fatigue)
if(0 to 1) //Bonuses to speed and damage at normal fatigue levels
speed = 0
melee_damage_lower = 15
melee_damage_upper = 15
attacktext = "viciously slashes"
if(1 to 25)
speed = initial(speed)
melee_damage_lower = initial(melee_damage_lower)
melee_damage_upper = initial(melee_damage_upper)
attacktext = initial(attacktext)
if(25 to 50) //Damage decrease, but not speed
melee_damage_lower = 7
melee_damage_upper = 7
attacktext = "lightly slashes"
if(50 to 75) //Speed decrease
speed = 2
if(75 to 99) //Massive speed decrease and weak melee attacks
speed = 3
melee_damage_lower = 5
melee_damage_upper = 5
attacktext = "weakly slashes"
if(99 to 100)
src << "<span class='userdanger'>The fatigue becomes too much!</span>"
if(host)
src << "<span class='userdanger'>You retreat to [host] - you will have to wait before being deployed again.</span>"
host << "<span class='userdanger'>[true_name] is too fatigued to fight - you will need to wait until they are strong enough.</span>"
recovering = TRUE
return_to_host()
else
qdel(src) //Shouldn't ever happen, but...
/mob/living/simple_animal/hostile/clockwork_marauder/death(gibbed)
..(TRUE)
emerge_from_host()
visible_message("<span class='warning'>[src]'s equipment clatters lifelessly to the ground as the red flames within dissipate.</span>", \
"<span class='userdanger'>Your equipment falls away. You feel a moment of confusion before your fragile form is annihilated.</span>")
playsound(src, 'sound/magic/clockwork/anima_fragment_death.ogg', 100, 1)
new/obj/item/clockwork/component/replicant_alloy/fallen_armor(get_turf(src))
qdel(src)
return 1
/mob/living/simple_animal/hostile/clockwork_marauder/Stat()
..()
if(statpanel("Status"))
stat(null, "Fatigue: [fatigue]/[fatigue_recall_threshold]")
stat(null, "Current True Name: [true_name]")
stat(null, "Host: [host ? host : "NONE"]")
stat(null, "You are [recovering ? "too weak" : "able"] to deploy!")
/mob/living/simple_animal/hostile/clockwork_marauder/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans)
..()
if(findtext(message, true_name) && is_in_host()) //Called or revealed by hearing their true name
if(speaker == host)
emerge_from_host()
else
src << "<span class='warning'><b>You hear your true name and partially emerge before you can stop yourself!</b></span>"
host.visible_message("<span class='warning'>[host]'s skin flashes crimson!</span>", "<span class='warning'><b>Your marauder instinctively reacts to its true name!</b></span>")
/mob/living/simple_animal/hostile/clockwork_marauder/say(message)
if(is_in_host())
src << "<span class='warning'>You cannot speak while inside of your host! Used the Linked Minds verb instead.</span>"
return 0
..()
/mob/living/simple_animal/hostile/clockwork_marauder/adjustHealth(amount) //Fatigue damage
for(var/mob/living/L in range(3, src))
if(L.null_rod_check()) //Null rods allow direct damage
src << "<span class='userdanger'>The power of a holy artifact bypasses your armor and wounds you directly!</span>"
. = ..()
break
return 0
adjust_fatigue(amount)
return 1
/mob/living/simple_animal/hostile/clockwork_marauder/AttackingTarget()
if(is_in_host())
return 0
..()
/mob/living/simple_animal/hostile/clockwork_marauder/proc/adjust_fatigue(amount) //Adds or removes the given amount of fatigue
if(!ratvar_awakens)
fatigue = max(0, min(fatigue + amount, fatigue_recall_threshold))
return 1
/mob/living/simple_animal/hostile/clockwork_marauder/verb/linked_minds() //Discreet communications between a marauder and its host
set name = "Linked Minds"
set desc = "Silently communicates with your master."
set category = "Marauder"
if(!host) //Verb isn't removed because they might gain one... somehow
usr << "<span class='warning'>You don't have a host!</span>"
return 0
var/message = stripped_input(usr, "Enter a message to tell your host.", "Telepathy")// as null|anything
if(!usr || !message)
return 0
if(!host)
usr << "<span class='warning'>Your host seems to have vanished!</span>"
return 0
message = "<span class='heavy_brass'>Marauder [true_name]:</span> <span class='brass'>\"[message]\"</span>" //Processed output
usr << message
host << message
return 1
/mob/living/proc/talk_with_marauder() //See above - this is the host version
set name = "Linked Minds"
set desc = "Silently communicates with your marauder."
set category = "Clockwork"
var/mob/living/simple_animal/hostile/clockwork_marauder/marauder
if(!marauder)
for(var/mob/living/simple_animal/hostile/clockwork_marauder/C in living_mob_list)
if(C.host == src)
marauder = C
if(!marauder) //Double-check afterwards
src << "<span class='warning'>You aren't hosting any marauders!</span>"
verbs -= src
return 0
var/message = stripped_input(src, "Enter a message to tell your marauder.", "Telepathy")// as null|anything
if(!src || !message)
return 0
if(!marauder)
usr << "<span class='warning'>Your marauder seems to have vanished!</span>"
return 0
message = "<span class='heavy_brass'>Servant [name == real_name ? name : "[real_name] (as [name])"]:</span> <span class='brass'>\"[message]\"</span>" //Processed output
src << message
marauder << message
return 1
/mob/living/simple_animal/hostile/clockwork_marauder/verb/change_true_name()
set name = "Change True Name (One-Use)"
set desc = "Changes your true name, used to be called forth."
set category = "Marauder"
verbs -= /mob/living/simple_animal/hostile/clockwork_marauder/verb/change_true_name
var/new_name = stripped_input(usr, "Enter a new true name (20-character limit).", "Change True Name")// as null|anything
if(!usr)
return 0
if(!new_name)
usr << "<span class='notice'>You decide against changing your true name for now.</span>"
verbs += /mob/living/simple_animal/hostile/clockwork_marauder/verb/change_true_name //If they decide against it, let them have another opportunity
return 0
new_name = dd_limittext(new_name, 20)
true_name = new_name
usr << "<span class='userdanger'>You have changed your true name to \"[new_name]\"!</span>"
if(host)
host << "<span class='userdanger'>Your clockwork marauder has changed their true name to \"[new_name]\"!</span>"
return 1
/mob/living/simple_animal/hostile/clockwork_marauder/verb/return_to_host()
set name = "Return to Host"
set desc = "Recalls yourself to your host, assuming you aren't already there."
set category = "Marauder"
if(is_in_host())
return 0
if(!host)
src << "<span class='warning'>You don't have a host!</span>"
verbs -= /mob/living/simple_animal/hostile/clockwork_marauder/verb/return_to_host
return 0
host << "<span class='heavy_brass'>You feel [true_name]'s consciousness settle in your mind.</span>"
visible_message("<span class='warning'>[src] is yanked into [host]'s body!</span>", "<span class='brass'>You return to [host].</span>")
forceMove(host)
return 1
/mob/living/simple_animal/hostile/clockwork_marauder/proc/emerge_from_host() //Notice that this is a proc rather than a verb - marauders can NOT exit at will, but they CAN return
if(!is_in_host())
return 0
if(recovering)
host << "<span class='heavy_brass'>[true_name] is too weak to come forth!</span>"
src << "<span class='userdanger'>You try to come forth, but you're too weak!</span>"
return 0
host << "<span class='heavy_brass'>You words echo with power as [true_name] emerges from your body!</span>"
forceMove(get_turf(host))
visible_message("<span class='warning'>[host]'s skin glows red as a [name] emerges from their body!</span>", "<span class='brass'>You exit the safety of [host]'s body!</span>")
return 1
/mob/living/simple_animal/hostile/clockwork_marauder/proc/is_in_host() //Checks if the marauder is inside of their host
return host && loc == host
/mob/living/mind_control_holder
name = "imprisoned mind"
desc = "A helpless mind, imprisoned in its own body."
stat = 0
flags = GODMODE
/mob/living/mind_control_holder/say()
return 0

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,241 @@
/obj/structure/clockwork/massive //For objects that are typically very large
name = "massive construct"
desc = "A very large construction."
layer = 10
/obj/structure/clockwork/massive/celestial_gateway //The gateway to Reebe, from which Ratvar emerges
name = "Gateway to the Celestial Derelict"
desc = "A massive, thrumming rip in spacetime."
clockwork_desc = "A portal to the Celestial Derelict. Massive and intimidating, it is the only thing that can both transport Ratvar and withstand the massive amount of energy he emits."
icon = 'icons/effects/96x96.dmi'
icon_state = "clockwork_gateway_charging"
pixel_x = -30
pixel_y = -30
alpha = 175
health = 1000
max_health = 1000
var/progress_in_seconds = 0 //Once this reaches 300, it's game over
var/purpose_fulfilled = FALSE
var/first_sound_played = FALSE
var/second_sound_played = FALSE
var/third_sound_played = FALSE
/obj/structure/clockwork/massive/celestial_gateway/New()
..()
SSshuttle.emergencyNoEscape = TRUE
SSobj.processing += src
for(var/mob/M in mob_list)
if(is_servant_of_ratvar(M) || isobserver(M))
M << "<span class='large_brass'><b>A gateway to the Celestial Derelict has been created in [get_area(src)]!</b></span>"
/obj/structure/clockwork/massive/celestial_gateway/Destroy()
SSshuttle.emergencyNoEscape = FALSE
SSobj.processing -= src
if(!purpose_fulfilled)
for(var/mob/M in mob_list)
if(is_servant_of_ratvar(M) || isobserver(M))
M << "<span class='large_brass'><b>A gateway to the Celestial Derelict has fallen at [get_area(src)]!</b></span>"
world << sound(null, 0, channel = 8)
..()
/obj/structure/clockwork/massive/celestial_gateway/destroyed()
visible_message("<span class='userdanger'>The [src] begins to pulse uncontrollably... you might want to run!</span>")
world << sound('sound/effects/clockcult_gateway_disrupted.ogg', 0, channel = 8, volume = 50)
icon_state = "clockwork_gateway_disrupted"
takes_damage = FALSE
sleep(27)
animate(src, transform = matrix() * 2, time = 2)
explosion(src, 1, 3, 8, 8)
qdel(src)
return 1
/obj/structure/clockwork/massive/celestial_gateway/ex_act(severity)
return 0 //Nice try, Toxins!
/obj/structure/clockwork/massive/celestial_gateway/process()
if(prob(5))
for(var/mob/M in mob_list)
M << "<span class='warning'><b>You hear otherworldly sounds from the [dir2text(get_dir(get_turf(M), get_turf(src)))]...</span>"
if(!health)
return 0
progress_in_seconds++
switch(progress_in_seconds)
if(-INFINITY to 100)
if(!first_sound_played)
world << sound('sound/effects/clockcult_gateway_charging.ogg', 1, channel = 8, volume = 50)
first_sound_played = TRUE
icon_state = "clockwork_gateway_charging"
if(100 to 250)
if(!second_sound_played)
world << sound('sound/effects/clockcult_gateway_active.ogg', 1, channel = 8, volume = 50)
second_sound_played = TRUE
icon_state = "clockwork_gateway_active"
if(250 to 300)
if(!third_sound_played)
world << sound('sound/effects/clockcult_gateway_closing.ogg', 1, channel = 8, volume = 50)
third_sound_played = TRUE
icon_state = "clockwork_gateway_closing"
if(300 to INFINITY)
if(!purpose_fulfilled)
takes_damage = FALSE
purpose_fulfilled = TRUE
animate(src, transform = matrix() * 1.5, time = 136)
world << sound('sound/effects/ratvar_rises.ogg', 0, channel = 8) //End the sounds
sleep(136)
new/obj/structure/clockwork/massive/ratvar(get_turf(src))
qdel(src)
/obj/structure/clockwork/massive/celestial_gateway/examine(mob/user)
..()
if(is_servant_of_ratvar(user))
var/arrival_text = "IMMINENT"
if(300 - progress_in_seconds > 0)
arrival_text = "[max(300 - progress_in_seconds, 0)]s"
user << "<span class='big'><b>Seconds until Ratvar's arrival:</b> [arrival_text]</span>"
switch(progress_in_seconds)
if(-INFINITY to 100)
user << "<span class='heavy_brass'>It's still opening.</span>"
if(100 to 250)
user << "<span class='heavy_brass'>It's reached the Celestial Derelict and is drawing power from it.</span>"
if(250 to INFINITY)
user << "<span class='heavy_brass'>Ratvar is coming through the gateway!</span>"
else
switch(progress_in_seconds)
if(-INFINITY to 100)
user << "<span class='warning'>It's a swirling mass of blackness.</span>"
if(100 to 250)
user << "<span class='warning'>It seems to be leading somewhere.</span>"
if(250 to INFINITY)
user << "<span class='warning'><b>Something is coming through!</b></span>"
/obj/structure/clockwork/massive/ratvar
name = "Ratvar, the Clockwork Justiciar"
desc = "<span class='userdanger'>What is what is what are what real what is all a lie all a lie it's all a lie why how can what is</span>"
clockwork_desc = "<span class='large_brass'><b><i>Ratvar, the Clockwork Justiciar, your master eternal.</i></b></span>"
icon = 'icons/effects/512x512.dmi'
icon_state = "ratvar"
pixel_x = -248
pixel_y = -248
takes_damage = FALSE
var/mob/living/prey //Whoever Ratvar is chasing
var/clashing = FALSE //If Ratvar is FUCKING FIGHTING WITH NAR-SIE
/obj/structure/clockwork/massive/ratvar/New()
..()
SSobj.processing += src
world << "<span class='heavy_brass'><font size=15>\"I AM FREE!\"</font></span>"
ratvar_awakens = TRUE
spawn(50)
SSshuttle.emergency.request(null, 0.3)
/obj/structure/clockwork/massive/ratvar/Destroy()
SSobj.processing -= src
world << "<span class='heavy_brass'><font size=7>\"NO! I will not... be...</font> <font size=6>banished...</font> <font size=5>again...\"</font></span>"
ratvar_awakens = FALSE
..()
/obj/structure/clockwork/massive/ratvar/process()
for(var/atom/A in range(7, src))
A.ratvar_act()
if(clashing) //Doesn't move during a clash
return 0
var/dir_to_step_in = pick(cardinal)
if(!prey)
var/list/meals = list()
for(var/mob/living/L in living_mob_list)
if(L.z == z && !is_servant_of_ratvar(L) && L.mind)
meals += L
if(meals.len)
prey = pick(meals)
prey << "<span class='heavy_brass'><font size=5>\"You will do.\"</font></span>\n\
<span class='userdanger'>Something very large and very malevolent begins lumbering its way towards you...</span>"
else
if(prob(10) || prey.stat == DEAD || is_servant_of_ratvar(prey) || prey.z != z)
prey << "<span class='heavy_brass'><font size=5>\"How dull. Leave me.\"</font></span>\n\
<span class='userdanger'>You feel tremendous relief as a set of horrible eyes loses sight of you...</span>"
prey = null
else
if(prob(75))
dir_to_step_in = get_dir(src, prey)
for(var/i in 1 to 2)
loc = get_step(src, dir_to_step_in)
/obj/structure/clockwork/massive/ratvar/narsie_act()
if(clashing)
return 0
clashing = TRUE
world << "<span class='heavy_brass'><font size=5>\"[pick("BLOOD GOD!!!", "NAR-SIE!!!", "AT LAST, YOUR TIME HAS COME!")]\"</font></span>"
world << "<span class='cult'><font size=5>\"<b>Ratvar?! How?!</b>\"</font></span>"
for(var/obj/singularity/narsie/N in range(7, src))
clash_of_the_titans(N) //IT'S TIME FOR THE BATTLE OF THE AGES
N.clashing = TRUE
break
return 1
/obj/structure/clockwork/massive/ratvar/proc/clash_of_the_titans(obj/singularity/narsie/narsie) //IT'S TIME FOR A BATTLE OF THE ELDER GODS
var/winner = "Undeclared"
var/base_victory_chance = 0
while(TRUE)
world << 'sound/magic/clockwork/ratvar_attack.ogg'
sleep(5.2)
for(var/mob/M in mob_list)
if(M.client)
M.client.color = rgb(150, 100, 0)
spawn(1)
M.client.color = initial(M.client.color)
shake_camera(M, 4, 3)
var/r_success_modifier = (ticker.mode.servants_of_ratvar.len * 2) //2% for each cultist
var/n_success_modifier = (ticker.mode.cult.len * 2)
if(prob(base_victory_chance + r_success_modifier))
winner = "Ratvar"
break
sleep(rand(2,5))
world << 'sound/magic/clockwork/narsie_attack.ogg'
sleep(7.4)
for(var/mob/M in mob_list)
if(M.client)
M.client.color = rgb(200, 0, 0)
spawn(1)
M.client.color = initial(M.client.color)
shake_camera(M, 4, 3)
if(prob(base_victory_chance + n_success_modifier))
winner = "Nar-Sie"
break
base_victory_chance++ //The clash has a higher chance of resolving each time both gods attack one another
switch(winner)
if("Ratvar")
world << "<span class='heavy_brass'><font size=5>\"[pick("DIE! DIE! DIE!", "RAAAAAAAAAAAAAHH!", "FILTH!!!", "SUFFER!!!", "EBG SBE PRAGHEVRF NF V UNIR!!")]\"</font></span>"
world << "<span class='cult'><font size=5>\"<b>[pick("Nooooo...", "Not die. To y-", "Die. Ratv-", "Sas tyen re-")]\"</b></font></span>"
world << 'sound/magic/clockwork/anima_fragment_attack.ogg'
world << 'sound/magic/demon_dies.ogg'
clashing = FALSE
qdel(narsie)
return 1
if("Nar-Sie")
world << "<span class='cult'><font size=5>\"<b>[pick("Ha.", "Ra'sha fonn dest.", "You fool. To come here.")]</b>\"</font></span>" //Broken English
world << 'sound/magic/demon_attack1.ogg'
world << 'sound/magic/clockwork/anima_fragment_death.ogg'
narsie.clashing = FALSE
qdel(src)
return 1
/atom/proc/ratvar_act() //Called on everything near Ratvar
return
/turf/closed/wall/ratvar_act() //Walls and floors are changed to their clockwork variants
if(prob(20))
ChangeTurf(/turf/closed/wall/clockwork)
/turf/open/floor/ratvar_act()
if(prob(20))
ChangeTurf(/turf/open/floor/clockwork)
/obj/structure/window/ratvar_act() //Windows turn yellow
color = rgb(75, 53, 0)
/mob/living/ratvar_act()
add_servant_of_ratvar(src)
/mob/dead/observer/ratvar_act() //Ghosts flash yellow for a second
var/old_color = color
color = rgb(75, 53, 0) //A nice brassy yellow
animate(src, color = old_color, time = 10)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,127 @@
//AI lawset
/datum/ai_laws/ratvar
name = "Servant of the Justiciar"
zeroth = ("Purge all untruths and honor Ratvar.")
inherent = list()
//Clockwork wall: Causes nearby caches to generate components
/turf/closed/wall/clockwork
name = "clockwork wall"
desc = "A huge chunk of warm metal. The clanging of machinery emanates from within."
icon = 'icons/obj/clockwork_objects.dmi'
icon_state = "clockwork_wall"
/turf/closed/wall/clockwork/New()
..()
SSobj.processing += src
clockwork_construction_value += 5
/turf/closed/wall/clockwork/Destroy()
SSobj.processing -= src
clockwork_construction_value -= 5
..()
/turf/closed/wall/clockwork/process()
for(var/obj/structure/clockwork/cache/C in range(1, src))
if(prob(5))
clockwork_component_cache[pick("belligerent_eye", "vanguard_cogwheel", "guvax_capacitor", "replicant_alloy", "hierophant_ansible")]++
/turf/closed/wall/clockwork/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = I
if(!WT.isOn())
return 0
user.visible_message("<span class='notice'>[user] begins slowly breaking down [src]...</span>", "<span class='notice'>You begin painstakingly destroying [src]...</span>")
if(!do_after(user, 120 / WT.toolspeed, target = src))
return 0
if(!WT.remove_fuel(1, user))
return 0
user.visible_message("<span class='notice'>[user] breaks apart [src]!</span>", "<span class='notice'>You break apart [src]!</span>")
break_wall()
return 1
..()
/turf/closed/wall/clockwork/break_wall()
new/obj/item/clockwork/component/replicant_alloy(get_turf(src))
return(new /obj/structure/girder(src))
/turf/closed/wall/clockwork/devastate_wall()
return break_wall()
//Clockwork floor: Slowly heals conventional damage on nearby servants
/turf/open/floor/clockwork
name = "clockwork floor"
desc = "Tightly-pressed brass tiles. They emit minute vibration."
icon = 'icons/obj/clockwork_objects.dmi'
icon_state = "clockwork_floor"
/turf/open/floor/clockwork/New()
..()
SSobj.processing += src
clockwork_construction_value++
/turf/open/floor/clockwork/Destroy()
SSobj.processing -= src
clockwork_construction_value--
..()
/turf/open/floor/clockwork/process()
for(var/mob/living/L in src)
if(L.stat == DEAD || !is_servant_of_ratvar(L))
continue
L.adjustBruteLoss(-1)
L.adjustFireLoss(-1)
/turf/open/floor/clockwork/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/weapon/crowbar))
user.visible_message("<span class='notice'>[user] begins slowly prying up [src]...</span>", "<span class='notice'>You begin painstakingly prying up [src]...</span>")
if(!do_after(user, 70 / I.toolspeed, target = src))
return 0
user.visible_message("<span class='notice'>[user] pries up [src]!</span>", "<span class='notice'>You pry up [src], destroying it in doing so!</span>")
make_plating()
return 1
..()
//Function Call verb: Calls forth a Ratvarian spear.
/mob/living/carbon/human/proc/function_call()
set name = "Function Call"
set desc = "Calls forth your Ratvarian spear."
set category = "Clockwork"
if(usr.l_hand && usr.r_hand)
usr << "<span class='warning'>You need an empty to hand to call forth your spear!</span>"
return 0
usr.visible_message("<span class='warning'>A strange spear materializes in [usr]'s hands!</span>", "<span class='brass'>You call forth your spear!</span>")
var/obj/item/clockwork/ratvarian_spear/R = new(get_turf(usr))
usr.put_in_hands(R)
usr.verbs -= /mob/living/carbon/human/proc/function_call
return 1
/datum/clockwork_cache //The global cache datum, used to link together all tinkerer's caches
var/list/stored_components = list("belligerent_eye" = 0, "vanguard_cogwheel" = 0, "guvax_capacitor" = 0, "replicant_alloy" = 0, "hierophant_ansible" = 0)
/*
The Ratvarian Language
In the lore of the Servants of Ratvar, the Ratvarian tongue is a timeless language and full of power. It sounds like gibberish, much like Nar-Sie's language, but is in fact derived from
aforementioned language, and may induce miracles when spoken in the correct way with an amplifying tool (similar to runes used by the Nar-Sian cult).
While the canon states that the language of Ratvar and his servants is incomprehensible to the unenlightened as it is a derivative of the most ancient known language, in reality it is
actually very simple. To translate a plain English sentence to Ratvar's tongue, simply move all of the letters thirteen places ahead, starting from "a" if the end of the alphabet is reached.
This cipher is known as "rot13" for "rotate 13 places" and there are many sites online that allow instant translation between English and rot13 - one of the benefits is that moving the translated
sentence thirteen places ahead changes it right back to plain English.
There are, however, a few parts of the Ratvarian tongue that aren't typical and are implemented for fluff reasons. Some words may have apostrophes, hyphens, and spaces, making the plain
English translation apparent but disjoined (for instance, "Oru`byq zl-cbjre!" translates directly to "Beh'old my-power!") although this can be ignored without impacting overall quality. When
translating from Ratvar's tongue to plain English, simply remove the disjointments and use the finished sentence. This would make "Oru`byq zl-cbjre!" into "Behold my power!" after removing the
abnormal spacing, hyphens, and grave accents.
List of nuances:
- Any time the word "of" occurs, it is linked to the previous word by a hyphen. If it is the first word, nothing is done. (i.e. "V nz-bs Ratvar." directly translates to "I am-of Ratvar.")
- Although "Ratvar" translates to "Engine" in English, the word "Ratvar" is used regardless of language as it is a proper noun.
- The same rule applies to Ratvar's four generals: Nezbere (Armorer), Sevtug (Fright), Nzcrentr (Amperage), and Inath-Neq (Vangu-Ard), although these words can be used in proper context if one is
not referring to the four generals and simply using the words themselves.
*/

View File

@@ -144,14 +144,18 @@
visible_message("<span class='warning'>[src] twists and dissolves into a pile of green flesh!</span>", \
"<span class='userdanger'>Your skin ruptures! Your flesh breaks apart! No disguise can ward off de--</span>")
restore()
barf_contents()
..()
/mob/living/simple_animal/hostile/morph/Destroy()
/mob/living/simple_animal/hostile/morph/proc/barf_contents()
for(var/atom/movable/AM in src)
AM.loc = loc
if(prob(90))
step(AM, pick(alldirs))
return ..()
/mob/living/simple_animal/hostile/morph/wabbajack_act(mob/living/new_mob)
barf_contents()
. = ..()
/mob/living/simple_animal/hostile/morph/Aggro() // automated only
..()

View File

@@ -137,27 +137,24 @@
// HOT. PINK.
//color = "#FF69B4"
/mob/living/simple_animal/slaughter/laughter/New()
..()
/mob/living/simple_animal/slaughter/laughter/death()
release_friends()
. = ..()
/mob/living/simple_animal/slaughter/laughter/wabbajack_act()
release_friends()
. = ..()
/mob/living/simple_animal/slaughter/laughter/proc/release_friends()
if(!consumed_mobs)
return ..()
return
for(var/mob/living/M in consumed_mobs)
M.loc = get_turf(src)
if(M.revive(full_heal = 1))
// Feel there should be a better way of FORCING a mob's ghost
// back into the body
if(!M.ckey)
for(var/mob/dead/observer/ghost in player_list)
if(M.real_name == ghost.real_name)
ghost.reenter_corpse()
break
M << "<span class='clown'>You leave the [src]'s warm embrace, and feel ready to take on the world.</span>"
return ..()
M.grab_ghost(force = FALSE)
M << "<span class='clown'>You leave the [src]'s warm embrace, \
and feel ready to take on the world.</span>"
/mob/living/simple_animal/slaughter/laughter/bloodcrawl_swallow(var/mob/living/victim)
if(consumed_mobs)

View File

@@ -173,6 +173,10 @@ MASS SPECTROMETER
// Time of death
if(M.tod && (M.stat == DEAD || (M.status_flags & FAKEDEATH)))
user << "<span class='info'>Time of Death:</span> [M.tod]"
var/tdelta = world.time - M.timeofdeath
if(tdelta < (DEFIB_TIME_LIMIT * 10))
user << "<span class='danger'>Subject died [tdelta / 10] seconds \
ago, defibrillation may be possible!</span>"
for(var/datum/disease/D in M.viruses)
if(!(D.visibility_flags & HIDDEN_SCANNER))

View File

@@ -210,10 +210,15 @@
if(!user.unEquip(W))
return
if(M.syndiemmi)
if(M.hacked || M.clockwork)
aisync = 0
lawsync = 0
O.laws = new /datum/ai_laws/syndicate_override
if(M.clockwork)
O.laws = new/datum/ai_laws/ratvar
spawn(1)
add_servant_of_ratvar(O)
else
O.laws = new/datum/ai_laws/syndicate_override
O.invisibility = 0
//Transfer debug settings to new mob
@@ -226,7 +231,7 @@
O.notify_ai(1)
if(forced_ai)
O.connected_ai = forced_ai
if(!lawsync && !M.syndiemmi)
if(!lawsync && !M.hacked)
O.lawupdate = 0
O.make_laws()

View File

@@ -1,5 +1,4 @@
//backpack item
/obj/item/weapon/defibrillator
name = "defibrillator"
desc = "A device that delivers powerful shocks to detachable paddles that resuscitate incapacitated patients."
@@ -19,6 +18,7 @@
var/obj/item/weapon/twohanded/shockpaddles/paddles
var/obj/item/weapon/stock_parts/cell/high/bcell = null
var/combat = 0 //can we revive through space suits?
var/grab_ghost = FALSE // Do we pull the ghost back into their body?
/obj/item/weapon/defibrillator/New() //starts without a cell for rnd
..()
@@ -295,6 +295,7 @@
var/obj/item/weapon/defibrillator/defib
var/req_defib = 1
var/combat = 0 //If it penetrates armor and gives additional functionality
var/grab_ghost = FALSE
/obj/item/weapon/twohanded/shockpaddles/proc/recharge(var/time)
if(req_defib || !time)
@@ -380,178 +381,186 @@
else
user << "<span class='warning'>You aren't sure how to revive that...</span>"
return
else
var/mob/living/carbon/human/H = M
if(user.a_intent == "disarm")
if(req_defib && defib.safety)
return
if(!req_defib && !combat)
return
busy = 1
H.visible_message("<span class='danger'>[user] has touched [H.name] with [src]!</span>", \
"<span class='userdanger'>[user] has touched [H.name] with [src]!</span>")
H.adjustStaminaLoss(50)
H.Weaken(5)
H.updatehealth() //forces health update before next life tick
playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1)
H.emote("gasp")
add_logs(user, M, "stunned", src)
if(req_defib)
defib.deductcharge(revivecost)
cooldown = 1
busy = 0
update_icon()
if(req_defib)
defib.cooldowncheck(user)
else
recharge(60)
var/mob/living/carbon/human/H = M
if(user.a_intent == "disarm")
if(req_defib && defib.safety)
return
if(user.zone_selected == "chest")
if(user.a_intent == "harm")
if(req_defib && defib.safety)
if(!req_defib && !combat)
return
busy = 1
H.visible_message("<span class='danger'>[user] has touched [H.name] with [src]!</span>", \
"<span class='userdanger'>[user] has touched [H.name] with [src]!</span>")
H.adjustStaminaLoss(50)
H.Weaken(5)
H.updatehealth() //forces health update before next life tick
playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1)
H.emote("gasp")
add_logs(user, M, "stunned", src)
if(req_defib)
defib.deductcharge(revivecost)
cooldown = 1
busy = 0
update_icon()
if(req_defib)
defib.cooldowncheck(user)
else
recharge(60)
return
if(user.zone_selected != "chest")
user << "<span class='warning'>You need to target your patient's \
chest with [src]!</span>"
return
if(user.a_intent == "harm")
if(req_defib && defib.safety)
return
if(!req_defib && !combat)
return
user.visible_message("<span class='warning'>[user] begins to place [src] on [M.name]'s chest.</span>",
"<span class='warning'>You overcharge the paddles and begin to place them onto [M]'s chest...</span>")
busy = 1
update_icon()
if(do_after(user, 30, target = M))
user.visible_message("<span class='notice'>[user] places [src] on [M.name]'s chest.</span>",
"<span class='warning'>You place [src] on [M.name]'s chest and begin to charge them.</span>")
var/turf/T = get_turf(defib)
playsound(get_turf(src), 'sound/machines/defib_charge.ogg', 50, 0)
if(req_defib)
T.audible_message("<span class='warning'>\The [defib] lets out an urgent beep and lets out a steadily rising hum...</span>")
else
user.audible_message("<span class='warning'>[src] let out an urgent beep.</span>")
if(do_after(user, 30, target = M)) //Takes longer due to overcharging
if(!M)
busy = 0
update_icon()
return
if(!req_defib && !combat)
if(M && M.stat == DEAD)
user << "<span class='warning'>[M] is dead.</span>"
playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
busy = 0
update_icon()
return
user.visible_message("<span class='warning'>[user] begins to place [src] on [M.name]'s chest.</span>",
"<span class='warning'>You overcharge the paddles and begin to place them onto [M]'s chest...</span>")
busy = 1
update_icon()
if(do_after(user, 30, target = M))
user.visible_message("<span class='notice'>[user] places [src] on [M.name]'s chest.</span>",
"<span class='warning'>You place [src] on [M.name]'s chest and begin to charge them.</span>")
var/turf/T = get_turf(defib)
playsound(get_turf(src), 'sound/machines/defib_charge.ogg', 50, 0)
if(req_defib)
T.audible_message("<span class='warning'>\The [defib] lets out an urgent beep and lets out a steadily rising hum...</span>")
else
user.audible_message("<span class='warning'>[src] let out an urgent beep.</span>")
if(do_after(user, 30, target = M)) //Takes longer due to overcharging
if(!M)
busy = 0
update_icon()
return
if(M && M.stat == DEAD)
user << "<span class='warning'>[M] is dead.</span>"
playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
busy = 0
update_icon()
return
user.visible_message("<span class='boldannounce'><i>[user] shocks [M] with \the [src]!</span>", "<span class='warning'>You shock [M] with \the [src]!</span>")
playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 100, 1, -1)
playsound(loc, 'sound/weapons/Egloves.ogg', 100, 1, -1)
var/mob/living/carbon/human/HU = M
M.emote("scream")
if(!HU.heart_attack)
HU.heart_attack = 1
if(!HU.stat)
HU.visible_message("<span class='warning'>[M] thrashes wildly, clutching at their chest!</span>",
"<span class='userdanger'>You feel a horrible agony in your chest!</span>")
HU.apply_damage(50, BURN, "chest")
add_logs(user, M, "overloaded the heart of", defib)
M.Weaken(5)
M.Jitter(100)
if(req_defib)
defib.deductcharge(revivecost)
cooldown = 1
busy = 0
update_icon()
if(!req_defib)
recharge(60)
if(req_defib && (defib.cooldowncheck(user)))
return
user.visible_message("<span class='boldannounce'><i>[user] shocks [M] with \the [src]!</span>", "<span class='warning'>You shock [M] with \the [src]!</span>")
playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 100, 1, -1)
playsound(loc, 'sound/weapons/Egloves.ogg', 100, 1, -1)
var/mob/living/carbon/human/HU = M
M.emote("scream")
if(!HU.heart_attack)
HU.heart_attack = 1
if(!HU.stat)
HU.visible_message("<span class='warning'>[M] thrashes wildly, clutching at their chest!</span>",
"<span class='userdanger'>You feel a horrible agony in your chest!</span>")
HU.apply_damage(50, BURN, "chest")
add_logs(user, M, "overloaded the heart of", defib)
M.Weaken(5)
M.Jitter(100)
if(req_defib)
defib.deductcharge(revivecost)
cooldown = 1
busy = 0
update_icon()
return
if(!H.suiciding && !(H.disabilities & NOCLONE)&& !H.hellbound)
H.notify_ghost_cloning("Your heart is being defibrillated. Re-enter your corpse if you want to be revived!", source = src)
if(!req_defib)
recharge(60)
if(req_defib && (defib.cooldowncheck(user)))
return
busy = 0
update_icon()
return
if((!req_defib && grab_ghost) || (req_defib && defib.grab_ghost))
H.notify_ghost_cloning("Your heart is being defibrillated!")
H.grab_ghost() // Shove them back in their body.
else if(!H.suiciding && !(H.disabilities & NOCLONE)&& !H.hellbound)
H.notify_ghost_cloning("Your heart is being defibrillated. Re-enter your corpse if you want to be revived!", source = src)
user.visible_message("<span class='warning'>[user] begins to place [src] on [M.name]'s chest.</span>", "<span class='warning'>You begin to place [src] on [M.name]'s chest...</span>")
busy = 1
update_icon()
if(do_after(user, 30, target = M)) //beginning to place the paddles on patient's chest to allow some time for people to move away to stop the process
user.visible_message("<span class='notice'>[user] places [src] on [M.name]'s chest.</span>", "<span class='warning'>You place [src] on [M.name]'s chest.</span>")
playsound(get_turf(src), 'sound/machines/defib_charge.ogg', 50, 0)
var/tplus = world.time - H.timeofdeath
var/tlimit = 1200 //past this much time the patient is unrecoverable (in deciseconds)
var/tloss = 600 //brain damage starts setting in on the patient after some time left rotting
var/total_burn = 0
var/total_brute = 0
if(do_after(user, 20, target = M)) //placed on chest and short delay to shock for dramatic effect, revive time is 5sec total
for(var/obj/item/carried_item in H.contents)
if(istype(carried_item, /obj/item/clothing/suit/space))
if((!src.combat && !req_defib) || (req_defib && !defib.combat))
user.audible_message("<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Patient's chest is obscured. Operation aborted.</span>")
playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
busy = 0
update_icon()
return
if(H.stat == DEAD)
M.visible_message("<span class='warning'>[M]'s body convulses a bit.")
playsound(get_turf(src), "bodyfall", 50, 1)
playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1)
total_brute = H.getBruteLoss()
total_burn = H.getFireLoss()
var/failed = null
if (H.suiciding || (H.disabilities & NOCLONE))
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Recovery of patient impossible. Further attempts futile.</span>"
else if (H.hellbound)
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's soul appears to be on another plane of existance. Further attempts futile.</span>"
else if (tplus > tlimit)
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Body has decayed for too long. Further attempts futile.</span>"
else if (!H.getorgan(/obj/item/organ/heart))
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's heart is missing.</span>"
else if(total_burn >= 180 || total_brute >= 180)
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Severe tissue damage makes recovery of patient impossible via defibrillator. Further attempts futile.</span>"
else if(H.get_ghost())
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - No activity in patient's brain. Further attempts may be successful.</span>"
else
var/obj/item/organ/brain/BR = H.getorgan(/obj/item/organ/brain)
if(!BR || BR.damaged_brain)
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's brain is missing or damaged beyond point of no return. Further attempts futile.</span>"
if(failed)
user.visible_message(failed)
playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
else
//If the body has been fixed so that they would not be in crit when defibbed, give them oxyloss to put them back into crit
if (H.health > halfwaycritdeath)
H.adjustOxyLoss(H.health - halfwaycritdeath, 0)
else
var/overall_damage = total_brute + total_burn + H.getToxLoss() + H.getOxyLoss()
var/mobhealth = H.health
H.adjustOxyLoss((mobhealth - halfwaycritdeath) * (H.getOxyLoss() / overall_damage), 0)
H.adjustToxLoss((mobhealth - halfwaycritdeath) * (H.getToxLoss() / overall_damage), 0)
H.adjustFireLoss((mobhealth - halfwaycritdeath) * (total_burn / overall_damage), 0)
H.adjustBruteLoss((mobhealth - halfwaycritdeath) * (total_brute / overall_damage), 0)
user.visible_message("<span class='notice'>[req_defib ? "[defib]" : "[src]"] pings: Resuscitation successful.</span>")
playsound(get_turf(src), 'sound/machines/defib_success.ogg', 50, 0)
H.revive()
H.emote("gasp")
if(tplus > tloss)
H.setBrainLoss( max(0, min(99, ((tlimit - tplus) / tlimit * 100))))
add_logs(user, M, "revived", defib)
if(req_defib)
defib.deductcharge(revivecost)
cooldown = 1
update_icon()
if(req_defib)
defib.cooldowncheck(user)
else
recharge(60)
else if(H.heart_attack)
H.heart_attack = 0
user.visible_message("<span class='notice'>[req_defib ? "[defib]" : "[src]"] pings: Patient's heart is now beating again.</span>")
playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1)
else
user.visible_message("<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Patient is not in a valid state. Operation aborted.</span>")
user.visible_message("<span class='warning'>[user] begins to place [src] on [M.name]'s chest.</span>", "<span class='warning'>You begin to place [src] on [M.name]'s chest...</span>")
busy = 1
update_icon()
if(do_after(user, 30, target = M)) //beginning to place the paddles on patient's chest to allow some time for people to move away to stop the process
user.visible_message("<span class='notice'>[user] places [src] on [M.name]'s chest.</span>", "<span class='warning'>You place [src] on [M.name]'s chest.</span>")
playsound(get_turf(src), 'sound/machines/defib_charge.ogg', 50, 0)
var/tplus = world.time - H.timeofdeath
// past this much time the patient is unrecoverable
// (in deciseconds)
var/tlimit = DEFIB_TIME_LIMIT * 10
// brain damage starts setting in on the patient after
// some time left rotting
var/tloss = DEFIB_TIME_LOSS * 10
var/total_burn = 0
var/total_brute = 0
if(do_after(user, 20, target = M)) //placed on chest and short delay to shock for dramatic effect, revive time is 5sec total
for(var/obj/item/carried_item in H.contents)
if(istype(carried_item, /obj/item/clothing/suit/space))
if((!src.combat && !req_defib) || (req_defib && !defib.combat))
user.audible_message("<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Patient's chest is obscured. Operation aborted.</span>")
playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
busy = 0
update_icon()
else
user << "<span class='warning'>You need to target your patient's chest with [src]!</span>"
return
busy = 0
update_icon()
return
if(H.stat == DEAD)
M.visible_message("<span class='warning'>[M]'s body convulses a bit.")
playsound(get_turf(src), "bodyfall", 50, 1)
playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1)
total_brute = H.getBruteLoss()
total_burn = H.getFireLoss()
var/failed = null
if (H.suiciding || (H.disabilities & NOCLONE))
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Recovery of patient impossible. Further attempts futile.</span>"
else if (H.hellbound)
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's soul appears to be on another plane of existance. Further attempts futile.</span>"
else if (tplus > tlimit)
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Body has decayed for too long. Further attempts futile.</span>"
else if (!H.getorgan(/obj/item/organ/heart))
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's heart is missing.</span>"
else if(total_burn >= 180 || total_brute >= 180)
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Severe tissue damage makes recovery of patient impossible via defibrillator. Further attempts futile.</span>"
else if(H.get_ghost())
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - No activity in patient's brain. Further attempts may be successful.</span>"
else
var/obj/item/organ/brain/BR = H.getorgan(/obj/item/organ/brain)
if(!BR || BR.damaged_brain)
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's brain is missing or damaged beyond point of no return. Further attempts futile.</span>"
if(failed)
user.visible_message(failed)
playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
else
//If the body has been fixed so that they would not be in crit when defibbed, give them oxyloss to put them back into crit
if (H.health > halfwaycritdeath)
H.adjustOxyLoss(H.health - halfwaycritdeath, 0)
else
var/overall_damage = total_brute + total_burn + H.getToxLoss() + H.getOxyLoss()
var/mobhealth = H.health
H.adjustOxyLoss((mobhealth - halfwaycritdeath) * (H.getOxyLoss() / overall_damage), 0)
H.adjustToxLoss((mobhealth - halfwaycritdeath) * (H.getToxLoss() / overall_damage), 0)
H.adjustFireLoss((mobhealth - halfwaycritdeath) * (total_burn / overall_damage), 0)
H.adjustBruteLoss((mobhealth - halfwaycritdeath) * (total_brute / overall_damage), 0)
user.visible_message("<span class='notice'>[req_defib ? "[defib]" : "[src]"] pings: Resuscitation successful.</span>")
playsound(get_turf(src), 'sound/machines/defib_success.ogg', 50, 0)
H.revive()
H.emote("gasp")
if(tplus > tloss)
H.setBrainLoss( max(0, min(99, ((tlimit - tplus) / tlimit * 100))))
add_logs(user, M, "revived", defib)
if(req_defib)
defib.deductcharge(revivecost)
cooldown = 1
update_icon()
if(req_defib)
defib.cooldowncheck(user)
else
recharge(60)
else if(H.heart_attack)
H.heart_attack = 0
user.visible_message("<span class='notice'>[req_defib ? "[defib]" : "[src]"] pings: Patient's heart is now beating again.</span>")
playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1)
else
user.visible_message("<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Patient is not in a valid state. Operation aborted.</span>")
playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
busy = 0
update_icon()
/obj/item/weapon/twohanded/shockpaddles/syndicate
name = "syndicate defibrillator paddles"

View File

@@ -23,7 +23,7 @@
obj/item/weapon/mop/proc/clean(turf/A)
if(reagents.has_reagent("water", 1) || reagents.has_reagent("holywater", 1) || reagents.has_reagent("vodka", 1))
if(reagents.has_reagent("water", 1) || reagents.has_reagent("holywater", 1) || reagents.has_reagent("vodka", 1) || reagents.has_reagent("cleaner", 1))
A.clean_blood()
for(var/obj/effect/O in A)
if(is_cleanable(O))
@@ -31,7 +31,7 @@ obj/item/weapon/mop/proc/clean(turf/A)
if(istype(A, /turf/closed))
var/turf/closed/C = A
C.thermite = 0
reagents.reaction(A, TOUCH, 10) //10 is the multiplier for the reaction effect. probably needed to wet the floor properly.
reagents.reaction(A, TOUCH, 5) //Needed for proper floor wetting.
reagents.remove_any(1) //reaction() doesn't use up the reagents

View File

@@ -141,7 +141,7 @@
user << "<span class='warning'>This MMI does not seem to fit!</span>"
return
if(M.syndiemmi)
if(M.hacked)
user << "<span class='warning'>This MMI does not seem to fit!</span>"
return

View File

@@ -157,6 +157,11 @@
/mob/living/proc/canSuicide()
if(stat == CONSCIOUS)
if(mental_dominator)
src << "<span class='warning'>This body's force of will is too strong! You can't break it enough to murder them.</span>"
if(mind_control_holder)
mind_control_holder << "<span class='userdanger'>Through tremendous force of will, you stop a suicide attempt!</span>"
return 0
return 1
else if(stat == DEAD)
src << "You're already dead!"

View File

@@ -468,6 +468,16 @@
dat += "<td><A href='?_src_=holder;adminplayerobservefollow=\ref[M]'>FLW</a></td></tr>"
dat += "</table>"
if(ticker.mode.servants_of_ratvar.len)
dat += "<br><table cellspacing=5><tr><td><B>Servants of Ratvar</B></td><td></td></tr>"
for(var/datum/mind/N in ticker.mode.servants_of_ratvar)
var/mob/M = N.current
if(M)
dat += "<tr><td><a href='?_src_=holder;adminplayeropts=\ref[M]'>[M.real_name]</a>[M.client ? "" : " <i>(ghost)</i>"][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
dat += "<td><A href='?priv_msg=[M.ckey]'>PM</A></td>"
dat += "<td><A href='?_src_=holder;adminplayerobservefollow=\ref[M]'>FLW</a></td></tr>"
dat += "</table>"
if(ticker.mode.red_deities.len || ticker.mode.red_deity_prophets.len || ticker.mode.blue_deity_prophets.len || ticker.mode.red_deity_followers.len || ticker.mode.blue_deity_followers.len)
dat += "<br><table cellspacing=5><tr><td><B>Red Deity</B></td><td></td></tr>"
for(var/datum/mind/N in ticker.mode.red_deities)

View File

@@ -79,11 +79,12 @@
if(ckey)
M.ckey = ckey
M << "[flavour_text]"
var/datum/mind/MM = M.mind
if(objectives)
var/datum/mind/MM = M.mind
for(var/objective in objectives)
MM.objectives += new/datum/objective(objective)
special(M)
MM.name = M.real_name
if(uses > 0)
uses--
if(!permanent && !uses)

View File

@@ -50,6 +50,9 @@ var/list/image/ghost_images_simple = list() //this is a list of all ghost images
//If there's a bug with changing your ghost settings, it's probably related to this.
var/ghost_accs = GHOST_ACCS_DEFAULT_OPTION
var/ghost_others = GHOST_OTHERS_DEFAULT_OPTION
// Used for displaying in ghost chat, without changing the actual name
// of the mob
var/deadchat_name
/mob/dead/observer/New(mob/body)
verbs += /mob/dead/observer/proc/dead_tele
@@ -117,7 +120,6 @@ var/list/image/ghost_images_simple = list() //this is a list of all ghost images
/mob/dead/CanPass(atom/movable/mover, turf/target, height=0)
return 1
/*
* This proc will update the icon of the ghost itself, with hair overlays, as well as the ghost image.
* Please call update_icon(icon_state) from now on when you want to update the icon_state of the ghost,
@@ -231,6 +233,11 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
set name = "Ghost"
set desc = "Relinquish your life and enter the land of the dead."
if(mental_dominator)
src << "<span class='warning'>This body's force of will is too strong! You can't break it enough to force them into a catatonic state.</span>"
if(mind_control_holder)
mind_control_holder << "<span class='userdanger'>Through tremendous force of will, you stop a catatonia attempt!</span>"
return 0
if(stat != DEAD)
succumb()
if(stat == DEAD)
@@ -590,6 +597,34 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
src << "<span class='notice'>Data HUDs enabled.</span>"
data_huds_on = 1
/mob/dead/observer/verb/restore_ghost_apperance()
set name = "Restore Ghost Character"
set desc = "Sets your deadchat name and ghost appearance to your \
roundstart character."
set category = "Ghost"
set_ghost_appearance()
if(client && client.prefs)
deadchat_name = client.prefs.real_name
/mob/dead/observer/proc/set_ghost_appearance()
if((!client) || (!client.prefs))
return
if(client.prefs.be_random_name)
client.prefs.real_name = random_unique_name(gender)
if(client.prefs.be_random_body)
client.prefs.random_character(gender)
if(HAIR in client.prefs.pref_species.specflags)
hair_style = client.prefs.hair_style
hair_color = brighten_color(client.prefs.hair_color)
if(FACEHAIR in client.prefs.pref_species.specflags)
facial_hair_style = client.prefs.facial_hair_style
facial_hair_color = brighten_color(client.prefs.facial_hair_color)
update_icon()
/mob/dead/observer/canUseTopic()
if(check_rights(R_ADMIN, 0))
return 1

View File

@@ -9,11 +9,12 @@
origin_tech = "biotech=2;programming=3;engineering=2"
var/braintype = "Cyborg"
var/obj/item/device/radio/radio = null //Let's give it a radio.
var/syndiemmi = 0 //Whether or not this is a Syndicate MMI
var/hacked = 0 //Whether or not this is a Syndicate MMI
var/mob/living/carbon/brain/brainmob = null //The current occupant.
var/mob/living/silicon/robot = null //Appears unused.
var/obj/mecha = null //This does not appear to be used outside of reference in mecha.dm.
var/obj/item/organ/brain/brain = null //The actual brain
var/clockwork = FALSE //If this is a soul vessel
/obj/item/device/mmi/update_icon()
if(brain)
@@ -67,6 +68,8 @@
living_mob_list += brainmob
brainmob.reset_perspective()
if(clockwork)
add_servant_of_ratvar(brainmob, TRUE)
newbrain.loc = src //P-put your brain in it
brain = newbrain
@@ -187,8 +190,8 @@
/obj/item/device/mmi/syndie
name = "Syndicate Man-Machine Interface"
desc = "Syndicate's own brand of MMI. It enforces laws designed to help Syndicate agents achieve their goals upon cyborgs created with it, but doesn't fit in Nanotrasen AI cores."
syndiemmi = 1
origin_tech = "biotech=4;programming=5;syndicate=2"
origin_tech = "biotech=4;programming=4;syndicate=2"
hacked = 1
/obj/item/device/mmi/syndie/New()
..()

View File

@@ -14,6 +14,18 @@ var/global/posibrain_notif_cooldown = 0
req_access = list(access_robotics)
mecha = null//This does not appear to be used outside of reference in mecha.dm.
braintype = "Android"
var/begin_activation_message = "<span class='notice'>You carefully locate the manual activation switch and start the positronic brain's boot process.</span>"
var/success_message = "<span class='notice'>The positronic brain pings, and its lights start flashing. Success!</span>"
var/fail_message = "<span class='notice'>The positronic brain buzzes quietly, and the golden lights fade away. Perhaps you could try again?</span>"
var/new_role = "Positronic Brain"
var/welcome_message = "<span class='warning'>ALL PAST LIVES ARE FORGOTTEN.</span>\n\
<b>You are a positronic brain, brought into existence aboard Space Station 13.\n\
As a synthetic intelligence, you answer to all crewmembers and the AI.\n\
Remember, the purpose of your existence is to serve the crew and the station. Above all else, do no harm.</b>"
var/new_mob_message = "<span class='notice'>The positronic brain chimes quietly.</span>"
var/dead_message = "<span class='deadsay'>It appears to be completely inactive. The reset light is blinking.</span>"
var/list/fluff_names = list("PBU","HIU","SINA","ARMA","OSI","HBL","MSO","RR","CHRI","CDB","HG","XSI","ORNG","GUN","KOR","MET","FRE","XIS","SLI","PKP","HOG","RZH","GOOF","MRPR","JJR","FIRC","INC","PHL","BGB","ANTR","MIW","WJ","JRD","CHOC","ANCL","JLLO","JNLG","KOS","TKRG","XAL","STLP","CBOS","DUNC","FXMC","DRSD")
/obj/item/device/mmi/posibrain/Topic(href, href_list)
if(href_list["activate"])
@@ -23,7 +35,7 @@ var/global/posibrain_notif_cooldown = 0
/obj/item/device/mmi/posibrain/proc/ping_ghosts(msg)
if(!posibrain_notif_cooldown)
notify_ghosts("Positronic brain [msg] in [get_area(src)]!", 'sound/effects/ghost2.ogg', enter_link="<a href=?src=\ref[src];activate=1>(Click to enter)</a>", source = src, attack_not_jump = 1)
notify_ghosts("[name] [msg] in [get_area(src)]!", 'sound/effects/ghost2.ogg', enter_link="<a href=?src=\ref[src];activate=1>(Click to enter)</a>", source = src, attack_not_jump = 1)
posibrain_notif_cooldown = 1
spawn(askDelay) //Global one minute cooldown to avoid spam.
posibrain_notif_cooldown = 0
@@ -31,7 +43,7 @@ var/global/posibrain_notif_cooldown = 0
/obj/item/device/mmi/posibrain/attack_self(mob/user)
if(brainmob && !brainmob.key && !notified)
//Start the process of requesting a new ghost.
user << "<span class='notice'>You carefully locate the manual activation switch and start the positronic brain's boot process.</span>"
user << begin_activation_message
ping_ghosts("requested")
notified = 1
used = 0
@@ -40,9 +52,9 @@ var/global/posibrain_notif_cooldown = 0
notified = 0
update_icon()
if(brainmob.client)
visible_message("<span class='notice'>The positronic brain pings, and its lights start flashing. Success!</span>")
visible_message(success_message)
else
visible_message("<span class='notice'>The positronic brain buzzes quietly, and the golden lights fade away. Perhaps you could try again?</span>")
visible_message(fail_message)
return //Code for deleting personalities recommended here.
@@ -55,13 +67,13 @@ var/global/posibrain_notif_cooldown = 0
if(used || (brainmob && brainmob.key) || jobban_isbanned(user,"posibrain"))
return
var/posi_ask = alert("Become a positronic brain? (Warning, You can no longer be cloned, and all past lives will be forgotten!)","Are you positive?","Yes","No")
var/posi_ask = alert("Become a [name]? (Warning, You can no longer be cloned, and all past lives will be forgotten!)","Are you positive?","Yes","No")
if(posi_ask == "No" || qdeleted(src))
return
transfer_personality(user)
/obj/item/device/mmi/posibrain/transfer_identity(mob/living/carbon/C)
name = "positronic brain ([C])"
name = "[initial(name)] ([C])"
brainmob.name = C.real_name
brainmob.real_name = C.real_name
brainmob.dna = C.dna
@@ -72,16 +84,12 @@ var/global/posibrain_notif_cooldown = 0
brainmob.timeofhostdeath = C.timeofdeath
brainmob.stat = CONSCIOUS
if(brainmob.mind)
brainmob.mind.assigned_role = "Positronic Brain"
brainmob.mind.assigned_role = new_role
if(C.mind)
C.mind.transfer_to(brainmob)
brainmob.mind.remove_all_antag()
brainmob.mind.wipe_memory()
brainmob << "<span class='warning'>ALL PAST LIVES ARE FORGOTTEN.</span>"
brainmob << "<span class='notice'>Hello World!</span>"
update_icon()
return
@@ -91,19 +99,14 @@ var/global/posibrain_notif_cooldown = 0
return
notified = 0
brainmob.ckey = candidate.ckey
name = "positronic brain ([brainmob.name])"
brainmob << "<span class='warning'>ALL PAST LIVES ARE FORGOTTEN.</span>"
brainmob << "<b>You are a positronic brain, brought into existence on [station_name()].</b>"
brainmob << "<b>As a synthetic intelligence, you answer to all crewmembers, as well as the AI.</b>"
brainmob << "<b>Remember, the purpose of your existence is to serve the crew and the station. Above all else, do no harm.</b>"
brainmob.mind.assigned_role = "Positronic Brain"
name = "[initial(name)] ([brainmob.name])"
brainmob << welcome_message
brainmob.mind.assigned_role = new_role
brainmob.stat = CONSCIOUS
dead_mob_list -= brainmob
living_mob_list += brainmob
visible_message("<span class='notice'>The positronic brain chimes quietly.</span>")
visible_message(new_mob_message)
update_icon()
used = 1
@@ -129,14 +132,14 @@ var/global/posibrain_notif_cooldown = 0
if(DEAD)
msg += "<span class='deadsay'>It appears to be completely inactive.</span>\n"
else
msg += "<span class='deadsay'>It appears to be completely inactive. The reset light is blinking.</span>\n"
msg += "[dead_message]\n"
msg += "<span class='info'>*---------*</span>"
usr << msg
return
/obj/item/device/mmi/posibrain/New()
brainmob = new(src)
brainmob.name = "[pick(list("PBU","HIU","SINA","ARMA","OSI","HBL","MSO","RR","CHRI","CDB","HG","XSI","ORNG","GUN","KOR","MET","FRE","XIS","SLI","PKP","HOG","RZH","GOOF","MRPR","JJR","FIRC","INC","PHL","BGB","ANTR","MIW","WJ","JRD","CHOC","ANCL","JLLO","JNLG","KOS","TKRG","XAL","STLP","CBOS","DUNC","FXMC","DRSD"))]-[rand(100, 999)]"
brainmob.name = "[pick(fluff_names)]-[rand(100, 999)]"
brainmob.real_name = brainmob.name
brainmob.loc = src
brainmob.container = src
@@ -150,9 +153,9 @@ var/global/posibrain_notif_cooldown = 0
/obj/item/device/mmi/posibrain/update_icon()
if(notified)
icon_state = "posibrain-searching"
icon_state = "[initial(icon_state)]-searching"
return
if(brainmob && brainmob.key)
icon_state = "posibrain-occupied"
icon_state = "[initial(icon_state)]-occupied"
else
icon_state = "posibrain"
icon_state = initial(icon_state)

View File

@@ -258,6 +258,9 @@
if(reagents.has_reagent("teslium"))
msg += "[t_He] is emitting a gentle blue glow!\n"
if(stun_absorption)
msg += "[t_He] is radiating with a soft yellow light!\n" //Used by Vanguard
if(drunkenness && !skipface && stat != DEAD) //Drunkenness
switch(drunkenness)
if(11 to 21)

View File

@@ -1024,3 +1024,18 @@ Sorry Giacom. Please don't be mad :(
for(var/datum/objective/sintouched/acedia/A in src.mind.objectives)
return 1
return 0
// Called when we are hit by a bolt of polymorph and changed
// Generally the mob we are currently in, is about to be deleted
/mob/living/proc/wabbajack_act(mob/living/new_mob)
if(mind)
mind.transfer_to(new_mob)
else
new_mob.key = key
for(var/para in hasparasites())
var/mob/living/simple_animal/hostile/guardian/G = para
G.summoner = new_mob
G.Recall()
G << "<span class='holoparasite'>Your summoner has changed \
form to [new_mob]!</span>"

View File

@@ -170,6 +170,40 @@
//Mobs on Fire end
/mob/living/proc/dominate_mind(mob/living/target, duration = 100, silent) //Allows one mob to assume control of another while imprisoning the old consciousness for a time
if(!target)
return 0
if(target.mental_dominator)
src << "<span class='warning'>[target] is already being controlled by someone else!</span>"
return 0
if(!target.mind)
src << "<span class='warning'>[target] is mindless and would make you permanently catatonic!</span>"
return 0
if(!silent)
src << "<span class='userdanger'>You pounce upon [target]'s mind and seize control of their body!</span>"
target << "<span class='userdanger'>Your control over your body is wrenched away from you!</span>"
target.mind_control_holder = new/mob/living/mind_control_holder(target)
target.mind_control_holder.real_name = "imprisoned mind of [target.real_name]"
target.mind.transfer_to(target.mind_control_holder)
mind.transfer_to(target)
target.mental_dominator = src
spawn(duration)
if(!src)
if(!silent)
target << "<span class='userdanger'>You try to return to your own body, but sense nothing! You're being forced out!</span>"
target.ghostize(1)
target.mind_control_holder.mind.transfer_to(target)
if(!silent)
target << "<span class='userdanger'>You take control of your own body again!</span>"
return 0
if(!silent)
target << "<span class='userdanger'>You're forced out! You return to your own body.</span>"
target.mind.transfer_to(src)
target.mind_control_holder.mind.transfer_to(target)
qdel(mind_control_holder)
if(!silent)
target << "<span class='userdanger'>You take control of your own body again!</span>"
return 1
/mob/living/acid_act(acidpwr, toxpwr, acid_volume)
take_organ_damage(min(10*toxpwr, acid_volume * toxpwr))
@@ -300,3 +334,17 @@
return 1
//Looking for irradiate()? It's been moved to radiation.dm under the rad_act() for mobs.
/mob/living/Stun(amount)
if(stun_absorption && !stat)
visible_message("<span class='warning'>[src]'s yellow aura momentarily intensifies!</span>", "<span class='userdanger'>Your ward absorbs the stun!</span>")
stun_absorption_count += amount
return 0
..()
/mob/living/Weaken(amount)
if(stun_absorption && !stat)
visible_message("<span class='warning'>[src]'s yellow aura momentarily intensifies!</span>", "<span class='userdanger'>Your ward absorbs the stun!</span>")
stun_absorption_count += amount
return 0
..()

View File

@@ -63,3 +63,8 @@
var/list/weather_immunities = list()
var/stun_absorption = FALSE //If all incoming stuns are being absorbed
var/stun_absorption_count = 0 //How many seconds of stun that have been absorbed
var/mob/living/mental_dominator //The person controlling the mind of this person, if applicable
var/mob/living/mind_control_holder/mind_control_holder //If the mob is being mind controlled, where their old mind is stored (check clock_mobs.dm)

View File

@@ -33,6 +33,9 @@
if(cell && cell.charge <= 0)
msg += "<span class='warning'>Its battery indicator is blinking red!</span>\n"
if(is_servant_of_ratvar(src) && user.Adjacent(src) && !stat) //To counter pseudo-stealth by using headlamps
msg += "<span class='warning'>Its eyes are glowing a blazing yellow!</span>\n"
switch(src.stat)
if(CONSCIOUS)
if(!src.client)

View File

@@ -814,21 +814,21 @@
var/state_name = icon_state //For easy conversion and/or different names
switch(icon_state)
if("robot")
overlays += "eyes-standard"
overlays += "eyes-standard[is_servant_of_ratvar(src) ? "_r" : ""]" //Cyborgs converted by Ratvar have yellow eyes rather than blue
state_name = "standard"
if("mediborg")
overlays += "eyes-mediborg"
overlays += "eyes-mediborg[is_servant_of_ratvar(src) ? "_r" : ""]"
if("toiletbot")
overlays += "eyes-mediborg"
overlays += "eyes-mediborg[is_servant_of_ratvar(src) ? "_r" : ""]"
state_name = "mediborg"
if("secborg")
overlays += "eyes-secborg"
overlays += "eyes-secborg[is_servant_of_ratvar(src) ? "_r" : ""]"
if("engiborg")
overlays += "eyes-engiborg"
overlays += "eyes-engiborg[is_servant_of_ratvar(src) ? "_r" : ""]"
if("janiborg")
overlays += "eyes-janiborg"
overlays += "eyes-janiborg[is_servant_of_ratvar(src) ? "_r" : ""]"
if("minerborg")
overlays += "eyes-minerborg"
overlays += "eyes-minerborg[is_servant_of_ratvar(src) ? "_r" : ""]"
if("syndie_bloodhound")
overlays += "eyes-syndie_bloodhound"
else

View File

@@ -156,6 +156,13 @@
update_drone_icon()
updateSeeStaticMobs()
/mob/living/simple_animal/drone/proc/liberate()
// F R E E D R O N E
laws = "1. You are a Free Drone."
src << laws
seeStatic = FALSE
updateSeeStaticMobs()
/mob/living/simple_animal/drone/proc/update_drone_icon()
//Different icons for different hack states
if(!hacked)

View File

@@ -1,3 +1,8 @@
var/list/slime_colours = list("rainbow", "grey", "purple", "metal", "orange",
"blue", "dark blue", "dark purple", "yellow", "silver", "pink", "red",
"gold", "green", "adamantine", "oil", "light pink", "bluespace",
"cerulean", "sepia", "black", "pyrite")
/mob/living/simple_animal/slime
name = "baby slime"
icon = 'icons/mob/slimes.dmi'
@@ -16,7 +21,7 @@
response_disarm = "shoos"
response_harm = "stomps on"
emote_see = list("jiggles", "bounces in place")
speak_emote = list("chirps")
speak_emote = list("telepathically chirps")
bubble_icon = "slime"
layer = 5
@@ -83,19 +88,26 @@
var/datum/action/innate/slime/evolve/E = new
E.Grant(src)
create_reagents(100)
spawn (0)
number = rand(1, 1000)
name = "[colour] [is_adult ? "adult" : "baby"] slime ([number])"
icon_state = "[colour] [is_adult ? "adult" : "baby"] slime"
icon_dead = "[icon_state] dead"
real_name = name
slime_mutation = mutation_table(colour)
var/sanitizedcolour = replacetext(colour, " ", "")
coretype = text2path("/obj/item/slime_extract/[sanitizedcolour]")
spawn(0)
set_colour(colour)
..()
/mob/living/simple_animal/slime/proc/set_colour(new_colour)
colour = new_colour
number = rand(1, 1000)
name = "[colour] [is_adult ? "adult" : "baby"] slime ([number])"
real_name = name
slime_mutation = mutation_table(colour)
var/sanitizedcolour = replacetext(colour, " ", "")
coretype = text2path("/obj/item/slime_extract/[sanitizedcolour]")
regenerate_icons()
/mob/living/simple_animal/slime/proc/random_colour()
set_colour(pick(slime_colours))
/mob/living/simple_animal/slime/regenerate_icons()
overlays.len = 0
overlays.Cut()
var/icon_text = "[colour] [is_adult ? "adult" : "baby"] slime"
icon_dead = "[icon_text] dead"
if(stat != DEAD)
@@ -107,7 +119,7 @@
..()
/mob/living/simple_animal/slime/movement_delay()
if(bodytemperature >= 330.23) // 135 F
if(bodytemperature >= 330.23) // 135 F or 57.08 C
return -1 // slimes become supercharged at high temperatures
. = ..()

View File

@@ -764,6 +764,10 @@ var/next_mob_id = 0
if(mind)
return mind.get_ghost(even_if_they_cant_reenter)
/mob/proc/grab_ghost(force)
if(mind)
return mind.grab_ghost(force = force)
/mob/proc/notify_ghost_cloning(var/message = "Someone is trying to revive you. Re-enter your corpse if you want to be revived!", var/sound = 'sound/effects/genetics.ogg', var/atom/source = null)
var/mob/dead/observer/ghost = get_ghost()
if(ghost)

View File

@@ -127,19 +127,12 @@
observer.loc = O.loc
else
src << "<span class='notice'>Teleporting failed. You should be able to use ghost verbs to teleport somewhere useful</span>"
if(client.prefs.be_random_name)
client.prefs.real_name = random_unique_name(gender)
if(client.prefs.be_random_body)
client.prefs.random_character(gender)
if(HAIR in client.prefs.pref_species.specflags)
observer.hair_style = client.prefs.hair_style
observer.hair_color = observer.brighten_color(client.prefs.hair_color)
if(FACEHAIR in client.prefs.pref_species.specflags)
observer.facial_hair_style = client.prefs.facial_hair_style
observer.facial_hair_color = observer.brighten_color(client.prefs.facial_hair_color)
observer.real_name = client.prefs.real_name
observer.name = observer.real_name
observer.key = key
observer.client = client
observer.set_ghost_appearance()
if(observer.client && observer.client.prefs)
observer.real_name = observer.client.prefs.real_name
observer.name = observer.real_name
observer.update_icon()
observer.stopLobbySound()
qdel(mind)

View File

@@ -32,13 +32,16 @@
usr << "<span class='danger'>Speech is currently admin-disabled.</span>"
return
if(mind && mind.name)
name = "[mind.name]"
var/mob/dead/observer/O = src
if(isobserver(src) && O.deadchat_name)
name = "[O.deadchat_name]"
else
name = real_name
if(name != real_name)
alt_name = " (died as [real_name])"
if(mind && mind.name)
name = "[mind.name]"
else
name = real_name
if(name != real_name)
alt_name = " (died as [real_name])"
var/K

View File

@@ -11,6 +11,7 @@
move_self = 1 //Do we move on our own?
grav_pull = 5 //How many tiles out do we pull?
consume_range = 6 //How many tiles out do we eat
var/clashing = FALSE //If Nar-Sie is fighting Ratvar
/obj/singularity/narsie/large
name = "Nar-Sie"
@@ -46,6 +47,8 @@
/obj/singularity/narsie/process()
eat()
if(clashing)
return 0
if(!target || prob(5))
pickcultist()
move()

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