Merge branch 'master' into upstream-merge-31737

This commit is contained in:
Poojawa
2017-10-21 07:18:14 -05:00
committed by GitHub
591 changed files with 181531 additions and 178280 deletions
+11
View File
@@ -240,6 +240,17 @@ This prevents nesting levels from getting deeper then they need to be.
* Queries must never specify the database, be it in code, or in text files in the repo.
### Mapping Standards
* TGM Format & Map Merge
* All new maps submitted to the repo through a pull request must be in TGM format (unless there is a valid reason present to have it in the default BYOND format.) This is done using the [Map Merge](https://github.com/tgstation/tgstation/wiki/Map-Merger) utility included in the repo to convert the file to TGM format.
* Likewise, you MUST run `Map Merge - TGM.bat` prior to opening your PR when updating existing maps to minimize the change differences (even when using third party mapping programs such as FastDMM.)
* Failure to run Map Merge on a map after using third party mapping programs (such as FastDMM) greatly increases the risk of the map's key dictionary becoming corrupted by future edits after running map merge. Resolving the corruption issue involves rebuilding the map's key dictionary; id est rewriting all the keys contained within the map by reconverting it from BYOND to TGM format - which creates very large differences that ultimately delay the PR process and is extremely likely to cause merge conflicts with other pull requests.
* Variable Editing (Var-edits)
* While var-editing an item within the editor is perfectly fine, it is preferred that when you are changing the base behavior of an item (how it functions) that you make a new subtype of that item within the code, especially if you plan to use the item in multiple locations on the same map, or across multiple maps. This makes it easier to make corrections as needed to all instances of the item at one time as opposed to having to find each instance of it and change them all individually.
* Subtypes only intended to be used on away mission or ruin maps should be contained within an .dm file with a name corresponding to that map within `code\modules\awaymissions` or `code\modules\ruins` respectively. This is so in the event that the map is removed, that subtype will be removed at the same time as well to minimize leftover/unused data within the repo.
* Please attempt to clean out any dirty variables that may be contained within items you alter through var-editing. For example, due to how DM functions, changing the `pixel_x` variable from 23 to 0 will leave a dirty record in the map's code of `pixel_x = 0`. Likewise this can happen when changing an item's icon to something else and then back. This can lead to some issues where an item's icon has changed within the code, but becomes broken on the map due to it still attempting to use the old entry.
* Areas should not be var-edited on a map to change it's name or attributes. All areas of a single type and it's altered instances are considered the same area within the code, and editing their variables on a map can lead to issues with powernets and event subsystems which are difficult to debug.
### Other Notes
+4 -24
View File
@@ -735,30 +735,10 @@
/area/ruin/powered)
"cu" = (
/obj/structure/closet/crate/secure/engineering,
/obj/item/wrench{
color = "#ff0000";
desc = "A prototype of a new wrench design, allegedly the red color scheme makes it go faster.";
name = "experimental wrench";
toolspeed = 3
},
/obj/item/screwdriver{
color = "#ff0000";
desc = "A prototype of a new screwdriver design, allegedly the red color scheme makes it go faster.";
name = "experimental screwdriver";
toolspeed = 3
},
/obj/item/wirecutters{
color = "#ff0000";
desc = "A prototype of a new wirecutter design, allegedly the red color scheme makes it go faster.";
name = "experimental wirecutters";
toolspeed = 3
},
/obj/item/crowbar/red{
color = "#ff0000";
desc = "A prototype of a new crowbar design, allegedly the red color scheme makes it go faster.";
name = "experimental crowbar";
toolspeed = 3
},
/obj/item/wrench/caravan,
/obj/item/screwdriver/caravan,
/obj/item/wirecutters/caravan,
/obj/item/crowbar/red/caravan,
/turf/open/floor/mineral/plastitanium,
/area/ruin/powered)
"cv" = (
File diff suppressed because it is too large Load Diff
+13 -5
View File
@@ -893,7 +893,7 @@
/turf/open/floor/carpet,
/area/crew_quarters/heads/hos)
"aco" = (
/obj/structure/closet/bombcloset,
/obj/structure/closet/bombcloset/security,
/turf/open/floor/plasteel/showroomfloor,
/area/security/main)
"acp" = (
@@ -57018,12 +57018,14 @@
/obj/machinery/atmospherics/pipe/manifold/general/visible{
dir = 8
},
/obj/structure/window/plasma/reinforced/spawner/east,
/obj/machinery/power/rad_collector/anchored,
/obj/structure/cable/yellow{
d2 = 8;
icon_state = "0-8"
},
/obj/structure/window/plasma/reinforced{
dir = 4
},
/turf/open/floor/engine,
/area/engine/supermatter)
"cEw" = (
@@ -57042,12 +57044,14 @@
/obj/machinery/atmospherics/pipe/manifold/general/visible{
dir = 4
},
/obj/structure/window/plasma/reinforced/spawner/west,
/obj/machinery/power/rad_collector/anchored,
/obj/structure/cable/yellow{
d2 = 4;
icon_state = "0-4"
},
/obj/structure/window/plasma/reinforced{
dir = 8
},
/turf/open/floor/engine,
/area/engine/supermatter)
"cEz" = (
@@ -57229,24 +57233,28 @@
/obj/machinery/atmospherics/pipe/simple/general/visible{
dir = 5
},
/obj/structure/window/plasma/reinforced/spawner/east,
/obj/machinery/power/rad_collector/anchored,
/obj/structure/cable/yellow{
d2 = 8;
icon_state = "0-8"
},
/obj/structure/window/plasma/reinforced{
dir = 4
},
/turf/open/floor/engine,
/area/engine/supermatter)
"cFh" = (
/obj/machinery/atmospherics/pipe/simple/general/visible{
dir = 9
},
/obj/structure/window/plasma/reinforced/spawner/west,
/obj/machinery/power/rad_collector/anchored,
/obj/structure/cable/yellow{
d2 = 4;
icon_state = "0-4"
},
/obj/structure/window/plasma/reinforced{
dir = 8
},
/turf/open/floor/engine,
/area/engine/supermatter)
"cFj" = (
File diff suppressed because it is too large Load Diff
+11 -5
View File
@@ -3622,6 +3622,7 @@
min_oxy = 5;
name = "Sergeant Araneus";
real_name = "Sergeant Araneus";
movement_type = 1;
response_help = "pets";
turns_per_move = 10;
voice_name = "unidentifiable voice"
@@ -4763,7 +4764,7 @@
/turf/open/floor/plasteel,
/area/security/warden)
"ajw" = (
/obj/structure/closet/bombcloset,
/obj/structure/closet/bombcloset/security,
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
dir = 4
},
@@ -40810,6 +40811,7 @@
network = list("MiniSat","tcomm");
pixel_y = -29
},
/obj/structure/bed/dogbed/renault,
/mob/living/simple_animal/pet/fox/Renault,
/turf/open/floor/carpet,
/area/crew_quarters/heads/captain/private)
@@ -80883,9 +80885,9 @@
/obj/machinery/atmospherics/pipe/manifold/general/visible{
dir = 1
},
/obj/structure/window/plasma/reinforced/spawner,
/obj/machinery/power/rad_collector/anchored,
/obj/structure/cable,
/obj/structure/window/plasma/reinforced,
/turf/open/floor/engine,
/area/engine/supermatter)
"dbb" = (
@@ -82697,9 +82699,9 @@
/obj/machinery/atmospherics/pipe/simple/general/visible{
dir = 10
},
/obj/structure/window/plasma/reinforced/spawner,
/obj/machinery/power/rad_collector/anchored,
/obj/structure/cable,
/obj/structure/window/plasma/reinforced,
/turf/open/floor/engine,
/area/engine/supermatter)
"deU" = (
@@ -82810,24 +82812,28 @@
/area/engine/supermatter)
"dfk" = (
/obj/machinery/atmospherics/pipe/manifold/general/visible,
/obj/structure/window/plasma/reinforced/spawner/north,
/obj/machinery/power/rad_collector/anchored,
/obj/structure/cable{
icon_state = "0-2";
d2 = 2
},
/obj/structure/window/plasma/reinforced{
dir = 1
},
/turf/open/floor/engine,
/area/engine/supermatter)
"dfm" = (
/obj/machinery/atmospherics/pipe/simple/general/visible{
dir = 9
},
/obj/structure/window/plasma/reinforced/spawner/north,
/obj/machinery/power/rad_collector/anchored,
/obj/structure/cable{
icon_state = "0-2";
d2 = 2
},
/obj/structure/window/plasma/reinforced{
dir = 1
},
/turf/open/floor/engine,
/area/engine/supermatter)
"dfp" = (
+22 -14
View File
@@ -22161,7 +22161,7 @@
network = list("Engine");
pixel_x = 23
},
/obj/structure/cable/yellow{
/obj/structure/cable{
d1 = 4;
d2 = 8;
icon_state = "4-8"
@@ -22172,13 +22172,15 @@
/obj/machinery/atmospherics/pipe/manifold/general/visible{
dir = 8
},
/obj/structure/window/plasma/reinforced/spawner/east,
/obj/machinery/power/rad_collector/anchored,
/obj/structure/cable/yellow{
/obj/structure/cable{
d2 = 8;
icon_state = "0-8"
},
/turf/open/floor/engine,
/obj/structure/window/plasma/reinforced{
dir = 4
},
/turf/open/floor/circuit/green,
/area/engine/supermatter)
"aMT" = (
/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
@@ -22199,16 +22201,18 @@
/obj/machinery/atmospherics/pipe/manifold/general/visible{
dir = 4
},
/obj/structure/window/plasma/reinforced/spawner/west,
/obj/machinery/power/rad_collector/anchored,
/obj/structure/cable/yellow{
/obj/structure/cable{
d2 = 4;
icon_state = "0-4"
},
/turf/open/floor/engine,
/obj/structure/window/plasma/reinforced{
dir = 8
},
/turf/open/floor/circuit/green,
/area/engine/supermatter)
"aMX" = (
/obj/structure/cable/yellow{
/obj/structure/cable{
d1 = 4;
d2 = 8;
icon_state = "4-8"
@@ -23109,25 +23113,29 @@
/obj/machinery/atmospherics/pipe/simple/general/visible{
dir = 5
},
/obj/structure/window/plasma/reinforced/spawner/east,
/obj/machinery/power/rad_collector/anchored,
/obj/structure/cable/yellow{
/obj/structure/cable{
d2 = 8;
icon_state = "0-8"
},
/turf/open/floor/engine,
/obj/structure/window/plasma/reinforced{
dir = 4
},
/turf/open/floor/circuit/green,
/area/engine/supermatter)
"aOD" = (
/obj/machinery/atmospherics/pipe/simple/general/visible{
dir = 9
},
/obj/structure/window/plasma/reinforced/spawner/west,
/obj/machinery/power/rad_collector/anchored,
/obj/structure/cable/yellow{
/obj/structure/cable{
d2 = 4;
icon_state = "0-4"
},
/turf/open/floor/engine,
/obj/structure/window/plasma/reinforced{
dir = 8
},
/turf/open/floor/circuit/green,
/area/engine/supermatter)
"aOE" = (
/obj/structure/cable{
+120 -96
View File
@@ -2788,7 +2788,7 @@
/turf/open/floor/plasteel/showroomfloor,
/area/security/main)
"aip" = (
/obj/structure/closet/bombcloset,
/obj/structure/closet/bombcloset/security,
/obj/effect/turf_decal/delivery,
/turf/open/floor/plasteel/showroomfloor,
/area/security/main)
@@ -46290,11 +46290,6 @@
/turf/open/floor/plasteel,
/area/engine/engineering)
"car" = (
/obj/structure/cable/yellow{
icon_state = "1-4";
d1 = 1;
d2 = 4
},
/obj/structure/cable/yellow{
d1 = 1;
d2 = 8;
@@ -47261,16 +47256,6 @@
/turf/open/floor/plasteel,
/area/engine/engineering)
"ccV" = (
/obj/structure/cable/yellow{
d1 = 4;
d2 = 8;
icon_state = "4-8"
},
/obj/structure/cable/yellow{
d1 = 2;
d2 = 4;
icon_state = "2-4"
},
/obj/effect/turf_decal/stripes/line{
dir = 4
},
@@ -47282,22 +47267,12 @@
id = "Singularity";
name = "radiation shutters"
},
/obj/structure/cable/yellow{
d1 = 4;
d2 = 8;
icon_state = "4-8"
},
/obj/effect/turf_decal/bot{
dir = 2
},
/turf/open/floor/plasteel/black,
/area/engine/engineering)
"ccX" = (
/obj/structure/cable/yellow{
d1 = 4;
d2 = 8;
icon_state = "4-8"
},
/obj/structure/cable/yellow{
d1 = 2;
d2 = 4;
@@ -47326,11 +47301,6 @@
/turf/open/floor/plating,
/area/engine/engineering)
"cda" = (
/obj/structure/cable/yellow{
d1 = 1;
d2 = 4;
icon_state = "1-4"
},
/obj/effect/landmark/event_spawn,
/turf/open/floor/plating,
/area/engine/engineering)
@@ -47346,16 +47316,6 @@
/turf/open/floor/plating,
/area/engine/engineering)
"cdc" = (
/obj/structure/cable/yellow{
d1 = 2;
d2 = 8;
icon_state = "2-8"
},
/obj/structure/cable/yellow{
d1 = 4;
d2 = 8;
icon_state = "4-8"
},
/obj/effect/turf_decal/stripes/line{
dir = 8
},
@@ -47599,19 +47559,9 @@
/turf/open/floor/plasteel,
/area/engine/engineering)
"cdQ" = (
/obj/structure/cable/yellow{
d1 = 1;
d2 = 2;
icon_state = "1-2"
},
/turf/open/floor/plasteel/yellow/side,
/area/engine/engineering)
"cdR" = (
/obj/structure/cable/yellow{
d1 = 1;
d2 = 2;
icon_state = "1-2"
},
/obj/machinery/button/door{
id = "Singularity";
name = "Shutters Control";
@@ -47666,11 +47616,6 @@
/turf/open/floor/plating,
/area/engine/engineering)
"cdX" = (
/obj/structure/cable/yellow{
d1 = 1;
d2 = 2;
icon_state = "1-2"
},
/obj/machinery/button/door{
id = "Singularity";
name = "Shutters Control";
@@ -47850,14 +47795,10 @@
id = "Singularity";
name = "radiation shutters"
},
/obj/structure/cable/yellow{
d1 = 1;
d2 = 2;
icon_state = "1-2"
},
/obj/effect/turf_decal/stripes/line{
dir = 1
},
/obj/effect/spawner/structure/window/reinforced,
/turf/open/floor/plating,
/area/engine/engineering)
"ceu" = (
@@ -48053,9 +47994,6 @@
/turf/open/floor/plating,
/area/engine/engineering)
"ceY" = (
/obj/machinery/power/rad_collector/anchored,
/obj/item/tank/internals/plasma,
/obj/structure/cable/yellow,
/obj/effect/turf_decal/stripes/line{
dir = 1
},
@@ -48872,6 +48810,9 @@
icon_state = "0-8"
},
/obj/machinery/power/tesla_coil,
/obj/structure/window/plasma/reinforced{
dir = 4
},
/turf/open/floor/plating/airless,
/area/engine/engineering)
"chy" = (
@@ -48884,6 +48825,9 @@
d2 = 4
},
/obj/machinery/power/tesla_coil,
/obj/structure/window/plasma/reinforced{
dir = 8
},
/turf/open/floor/plating/airless,
/area/engine/engineering)
"chA" = (
@@ -49000,7 +48944,15 @@
/turf/open/floor/plating/airless,
/area/engine/engineering)
"chQ" = (
/turf/open/space/basic,
/obj/structure/window/plasma/reinforced{
dir = 4
},
/obj/machinery/power/rad_collector/anchored,
/obj/structure/cable/yellow{
d2 = 8;
icon_state = "0-8"
},
/turf/open/floor/plating/airless,
/area/engine/engineering)
"chR" = (
/obj/structure/cable{
@@ -54066,6 +54018,78 @@
/obj/machinery/smoke_machine,
/turf/open/floor/plasteel/white,
/area/medical/chemistry)
"YXI" = (
/obj/machinery/door/firedoor,
/obj/machinery/door/poddoor/shutters/preopen{
id = "Singularity";
name = "radiation shutters"
},
/obj/effect/turf_decal/bot{
dir = 2
},
/turf/open/floor/plasteel/black,
/area/engine/engineering)
"YXJ" = (
/obj/machinery/power/rad_collector/anchored,
/turf/open/floor/plating,
/area/engine/engineering)
"YXK" = (
/obj/machinery/power/rad_collector/anchored,
/turf/open/floor/plating,
/area/engine/engineering)
"YXL" = (
/obj/effect/turf_decal/stripes/line{
dir = 1
},
/turf/open/floor/plating,
/area/engine/engineering)
"YXM" = (
/obj/structure/cable/yellow{
d1 = 1;
d2 = 2;
icon_state = "1-2"
},
/obj/structure/cable/yellow{
icon_state = "1-4";
d1 = 1;
d2 = 4
},
/obj/item/tank/internals/plasma,
/turf/open/floor/plating/airless,
/area/engine/engineering)
"YXN" = (
/obj/structure/window/plasma/reinforced{
dir = 8
},
/obj/machinery/power/rad_collector/anchored,
/obj/structure/cable/yellow{
icon_state = "0-4";
d2 = 4
},
/turf/open/floor/plating/airless,
/area/engine/engineering)
"YXO" = (
/obj/structure/window/plasma/reinforced{
dir = 8
},
/obj/machinery/power/rad_collector/anchored,
/obj/structure/cable/yellow{
icon_state = "0-4";
d2 = 4
},
/turf/open/floor/plating/airless,
/area/engine/engineering)
"YXP" = (
/obj/structure/window/plasma/reinforced{
dir = 8
},
/obj/machinery/power/rad_collector/anchored,
/obj/structure/cable/yellow{
icon_state = "0-4";
d2 = 4
},
/turf/open/floor/plating/airless,
/area/engine/engineering)
(1,1,1) = {"
aaa
@@ -81734,7 +81758,7 @@ bOG
bva
bDi
bXk
cbX
YXJ
cbX
cdK
bXk
@@ -81991,7 +82015,7 @@ bOG
bTE
cae
bXk
cbX
YXK
cbX
cdK
bXk
@@ -83791,20 +83815,20 @@ bZC
cal
cbh
cam
ccT
cam
cdQ
cet
ceY
cfa
cbX
cfU
cgu
cgU
chw
cgU
YXM
chw
chw
chw
cgU
chw
cgU
cjs
cfV
cfV
@@ -84048,18 +84072,18 @@ bZA
cam
cam
cam
ccU
cam
cdQ
cet
ceZ
cfa
ceY
cbX
cfV
cgv
cfV
chx
chQ
chx
cfV
chQ
chx
chQ
chx
@@ -84308,8 +84332,8 @@ ccc
ccV
cdR
cet
ceZ
cfa
ceY
cbX
cfU
cgv
cgV
@@ -85587,9 +85611,9 @@ bXo
bYi
bYV
bZA
cas
cbk
cce
cdN
YXI
YXL
cda
cdV
cex
@@ -85847,7 +85871,7 @@ bZF
cat
bXk
ccg
cdb
cey
cdW
cey
cey
@@ -86364,8 +86388,8 @@ cch
cdc
cdX
cet
ceZ
cfa
ceY
cbX
cfU
cgv
cgV
@@ -86618,20 +86642,20 @@ bZA
cam
cam
cam
cdd
cam
cdQ
cet
ceZ
cfa
ceY
cbX
cfV
cgv
cfV
chz
chQ
YXN
chz
cfV
YXO
chz
chQ
YXP
chz
cfV
cfV
@@ -86875,20 +86899,20 @@ bZC
cal
cbm
cci
cde
cam
cdQ
cet
ceZ
cfa
ceY
cbX
cfU
cgx
cgU
chA
cgU
chA
cgU
chA
cgU
chA
chA
chA
cjt
cfV
cfV
+13
View File
@@ -177,6 +177,19 @@
#define LAVALAND_EQUIPMENT_EFFECT_PRESSURE 50 //what pressure you have to be under to increase the effect of equipment meant for lavaland
#define LAVALAND_DEFAULT_ATMOS "o2=14;n2=23;TEMP=300"
//IF YOU EVER CHANGE THESE CHANGE SPRITES TO MATCH.
#define PIPING_LAYER_MIN 1
#define PIPING_LAYER_MAX 3
#define PIPING_LAYER_DEFAULT 2
#define PIPING_LAYER_P_X 5
#define PIPING_LAYER_P_Y 5
#define PIPING_LAYER_LCHANGE 0.05
#define PIPING_ALL_LAYER 1 //intended to connect with all layers, check for all instead of just one.
#define PIPING_ONE_PER_TURF 2 //can only be built if nothing else with this flag is on the tile already.
#define PIPING_DEFAULT_LAYER_ONLY 4 //can only exist at PIPING_LAYER_DEFAULT
#define PIPING_CARDINAL_AUTONORMALIZE 8 //north/south east/west doesn't matter, auto normalize on build.
#define THERMAL_ENERGY(gas) (gas.temperature * gas.heat_capacity())
#define ADD_GAS(gas_id, out_list)\
+3 -1
View File
@@ -31,6 +31,8 @@
#define islava(A) (istype(A, /turf/open/lava))
#define ischasm(A) (istype(A, /turf/open/chasm))
#define isplatingturf(A) (istype(A, /turf/open/floor/plating))
//Mobs
@@ -181,4 +183,4 @@ GLOBAL_LIST_INIT(glass_sheet_types, typecacheof(list(
/obj/item/stack/sheet/plasmaglass,
/obj/item/stack/sheet/plasmarglass)))
#define is_glass_sheet(O) (is_type_in_typecache(O, GLOB.glass_sheet_types))
#define is_glass_sheet(O) (is_type_in_typecache(O, GLOB.glass_sheet_types))
+19 -1
View File
@@ -93,6 +93,7 @@
//Mob AI Status
//Hostile simple animals
//If you add a new status, be sure to add a list for it to the simple_animals global in _globalvars/lists/mobs.dm
#define AI_ON 1
#define AI_IDLE 2
#define AI_OFF 3
@@ -155,4 +156,21 @@
#define MEGAFAUNA_DEFAULT_RECOVERY_TIME 5
#define SHADOW_SPECIES_LIGHT_THRESHOLD 0.2
#define SHADOW_SPECIES_LIGHT_THRESHOLD 0.2
// Offsets defines
#define OFFSET_UNIFORM "uniform"
#define OFFSET_ID "id"
#define OFFSET_GLOVES "gloves"
#define OFFSET_GLASSES "glasses"
#define OFFSET_EARS "ears"
#define OFFSET_SHOES "shoes"
#define OFFSET_S_STORE "s_store"
#define OFFSET_FACEMASK "mask"
#define OFFSET_HEAD "head"
#define OFFSET_FACE "face"
#define OFFSET_BELT "belt"
#define OFFSET_BACK "back"
#define OFFSET_SUIT "suit"
#define OFFSET_NECK "neck"
+6 -6
View File
@@ -7,24 +7,24 @@ Construction breaks otherwise
//Pipes
#define PIPE_SIMPLE /obj/machinery/atmospherics/pipe/simple
#define PIPE_MANIFOLD /obj/machinery/atmospherics/pipe/manifold
#define PIPE_4WAYMANIFOLD /obj/machinery/atmospherics/pipe/manifold4w
#define PIPE_4WAYMANIFOLD /obj/machinery/atmospherics/pipe/manifold4w
#define PIPE_HE /obj/machinery/atmospherics/pipe/heat_exchanging/simple
#define PIPE_HE_MANIFOLD /obj/machinery/atmospherics/pipe/heat_exchanging/manifold
#define PIPE_HE_4WAYMANIFOLD /obj/machinery/atmospherics/pipe/heat_exchanging/manifold4w
#define PIPE_JUNCTION /obj/machinery/atmospherics/pipe/heat_exchanging/junction
#define PIPE_BLUESPACE /obj/machinery/atmospherics/pipe/bluespace
#define PIPE_LAYER_MANIFOLD /obj/machinery/atmospherics/pipe/layer_manifold
//Unary
#define PIPE_CONNECTOR /obj/machinery/atmospherics/components/unary/portables_connector
#define PIPE_UVENT /obj/machinery/atmospherics/components/unary/vent_pump
#define PIPE_SCRUBBER /obj/machinery/atmospherics/components/unary/vent_scrubber
#define PIPE_INJECTOR /obj/machinery/atmospherics/components/unary/outlet_injector
#define PIPE_HEAT_EXCHANGE /obj/machinery/atmospherics/components/unary/heat_exchanger
#define PIPE_HEAT_EXCHANGE /obj/machinery/atmospherics/components/unary/heat_exchanger
//Binary
#define PIPE_PUMP /obj/machinery/atmospherics/components/binary/pump
#define PIPE_PASSIVE_GATE /obj/machinery/atmospherics/components/binary/passive_gate
#define PIPE_VOLUME_PUMP /obj/machinery/atmospherics/components/binary/volume_pump
#define PIPE_PASSIVE_GATE /obj/machinery/atmospherics/components/binary/passive_gate
#define PIPE_VOLUME_PUMP /obj/machinery/atmospherics/components/binary/volume_pump
#define PIPE_MVALVE /obj/machinery/atmospherics/components/binary/valve
#define PIPE_DVALVE /obj/machinery/atmospherics/components/binary/valve/digital
#define PIPE_DVALVE /obj/machinery/atmospherics/components/binary/valve/digital
//Trinary
#define PIPE_GAS_FILTER /obj/machinery/atmospherics/components/trinary/filter
#define PIPE_GAS_MIXER /obj/machinery/atmospherics/components/trinary/mixer
+9 -6
View File
@@ -18,13 +18,16 @@ Ask ninjanomnom if they're around
#define RAD_TOX_COEFFICIENT 0.05 // Toxin damage per tick coefficient
#define RAD_MOB_SAFE 300 // How much stored radiation in a mob with no ill effects
#define RAD_MOB_KNOCKDOWN 1500 // How much stored radiation to start stunning
// If (mutate*2<knockdown) then monkeys will sometimes turn into gorillas before being knocked down
// otherwise they only turn into gorillas *after* being knocked down
#define RAD_MOB_MUTATE 800 // How much stored radiation to check for mutation
#define RAD_MOB_HAIRLOSS 500 // How much stored radiation to check for hair loss
#define RAD_KNOCKDOWN_TIME 200 // How much knockdown to apply
#define RAD_MOB_KNOCKDOWN 2000 // How much stored radiation to check for stunning
#define RAD_MOB_KNOCKDOWN_PROB 1 // Chance of knockdown per tick when over threshold
#define RAD_MOB_KNOCKDOWN_AMOUNT 3 // Amount of knockdown when it occurs
#define RAD_MOB_VOMIT 1500 // The amount of radiation to check for vomitting
#define RAD_MOB_VOMIT_PROB 1 // Chance per tick of vomitting
#define RAD_MOB_MUTATE 1000 // How much stored radiation to check for mutation
#define RAD_MOB_HAIRLOSS 500 // How much stored radiation to check for hair loss
#define RAD_NO_INSULATION 1.0 // For things that shouldn't become irradiated for whatever reason
#define RAD_VERY_LIGHT_INSULATION 0.9 // What girders have
+5
View File
@@ -34,6 +34,7 @@
#define FLOOR_BOT 4 // Floorbots
#define CLEAN_BOT 8 // Cleanbots
#define MED_BOT 16 // Medibots
#define HONK_BOT 32 // Honkbots & ED-Honks
//AI notification defines
#define NEW_BORG 1
@@ -41,3 +42,7 @@
#define RENAME 3
#define AI_SHELL 4
#define DISCONNECT 5
//Assembly defines
#define ASSEMBLY_FIRST_STEP 0
#define ASSEMBLY_SECOND_STEP 1
+2
View File
@@ -58,6 +58,8 @@
#define DOCKING_BLOCKED 1
#define DOCKING_IMMOBILIZED 2
#define DOCKING_AREA_EMPTY 4
#define DOCKING_NULL_DESTINATION 8
#define DOCKING_NULL_SOURCE 16
//Docking turf movements
+1
View File
@@ -485,6 +485,7 @@
//Picks from the list, with some safeties, and returns the "default" arg if it fails
#define DEFAULTPICK(L, default) ((islist(L) && length(L)) ? pick(L) : default)
#define LAZYINITLIST(L) if (!L) L = list()
#define UNSETEMPTY(L) if (L && !L.len) L = null
#define LAZYREMOVE(L, I) if(L) { L -= I; if(!L.len) { L = null; } }
+5
View File
@@ -129,3 +129,8 @@
return "[A.loc] [COORD(T)] ([A.loc.type])"
else if(A.loc)
return "[A.loc] (0, 0, 0) ([A.loc.type])"
/proc/log_manifest(key,datum/mind/mind,mob/body,latejoin = FALSE)
if (CONFIG_GET(flag/log_manifest))
WRITE_FILE(GLOB.manifest_log, "[key] \\ [body.real_name] \\ [mind.assigned_role] \\ [mind.special_role ? mind.special_role : "NONE"] \\ [latejoin ? "LATEJOIN":"ROUNDSTART"]")
+145 -75
View File
@@ -308,7 +308,8 @@ world
*/
/proc/ReadRGB(rgb)
if(!rgb) return
if(!rgb)
return
// interpret the HSV or HSVA value
var/i=1,start=1
@@ -317,19 +318,27 @@ world
var/digits=0
for(i=start, i<=length(rgb), ++i)
ch = text2ascii(rgb, i)
if(ch < 48 || (ch > 57 && ch < 65) || (ch > 70 && ch < 97) || ch > 102) break
if(ch < 48 || (ch > 57 && ch < 65) || (ch > 70 && ch < 97) || ch > 102)
break
++digits
if(digits == 8) break
if(digits == 8)
break
var/single = digits < 6
if(digits != 3 && digits != 4 && digits != 6 && digits != 8) return
if(digits == 4 || digits == 8) usealpha = 1
if(digits != 3 && digits != 4 && digits != 6 && digits != 8)
return
if(digits == 4 || digits == 8)
usealpha = 1
for(i=start, digits>0, ++i)
ch = text2ascii(rgb, i)
if(ch >= 48 && ch <= 57) ch -= 48
else if(ch >= 65 && ch <= 70) ch -= 55
else if(ch >= 97 && ch <= 102) ch -= 87
else break
if(ch >= 48 && ch <= 57)
ch -= 48
else if(ch >= 65 && ch <= 70)
ch -= 55
else if(ch >= 97 && ch <= 102)
ch -= 87
else
break
--digits
switch(which)
if(0)
@@ -337,69 +346,91 @@ world
if(single)
r |= r << 4
++which
else if(!(digits & 1)) ++which
else if(!(digits & 1))
++which
if(1)
g = (g << 4) | ch
if(single)
g |= g << 4
++which
else if(!(digits & 1)) ++which
else if(!(digits & 1))
++which
if(2)
b = (b << 4) | ch
if(single)
b |= b << 4
++which
else if(!(digits & 1)) ++which
else if(!(digits & 1))
++which
if(3)
alpha = (alpha << 4) | ch
if(single) alpha |= alpha << 4
if(single)
alpha |= alpha << 4
. = list(r, g, b)
if(usealpha) . += alpha
if(usealpha)
. += alpha
/proc/ReadHSV(hsv)
if(!hsv) return
if(!hsv)
return
// interpret the HSV or HSVA value
var/i=1,start=1
if(text2ascii(hsv) == 35) ++start // skip opening #
if(text2ascii(hsv) == 35)
++start // skip opening #
var/ch,which=0,hue=0,sat=0,val=0,alpha=0,usealpha
var/digits=0
for(i=start, i<=length(hsv), ++i)
ch = text2ascii(hsv, i)
if(ch < 48 || (ch > 57 && ch < 65) || (ch > 70 && ch < 97) || ch > 102) break
if(ch < 48 || (ch > 57 && ch < 65) || (ch > 70 && ch < 97) || ch > 102)
break
++digits
if(digits == 9) break
if(digits > 7) usealpha = 1
if(digits <= 4) ++which
if(digits <= 2) ++which
if(digits == 9)
break
if(digits > 7)
usealpha = 1
if(digits <= 4)
++which
if(digits <= 2)
++which
for(i=start, digits>0, ++i)
ch = text2ascii(hsv, i)
if(ch >= 48 && ch <= 57) ch -= 48
else if(ch >= 65 && ch <= 70) ch -= 55
else if(ch >= 97 && ch <= 102) ch -= 87
else break
if(ch >= 48 && ch <= 57)
ch -= 48
else if(ch >= 65 && ch <= 70)
ch -= 55
else if(ch >= 97 && ch <= 102)
ch -= 87
else
break
--digits
switch(which)
if(0)
hue = (hue << 4) | ch
if(digits == (usealpha ? 6 : 4)) ++which
if(digits == (usealpha ? 6 : 4))
++which
if(1)
sat = (sat << 4) | ch
if(digits == (usealpha ? 4 : 2)) ++which
if(digits == (usealpha ? 4 : 2))
++which
if(2)
val = (val << 4) | ch
if(digits == (usealpha ? 2 : 0)) ++which
if(digits == (usealpha ? 2 : 0))
++which
if(3)
alpha = (alpha << 4) | ch
. = list(hue, sat, val)
if(usealpha) . += alpha
if(usealpha)
. += alpha
/proc/HSVtoRGB(hsv)
if(!hsv) return "#000000"
if(!hsv)
return "#000000"
var/list/HSV = ReadHSV(hsv)
if(!HSV) return "#000000"
if(!HSV)
return "#000000"
var/hue = HSV[1]
var/sat = HSV[2]
@@ -407,27 +438,30 @@ world
// Compress hue into easier-to-manage range
hue -= hue >> 8
if(hue >= 0x5fa) hue -= 0x5fa
if(hue >= 0x5fa)
hue -= 0x5fa
var/hi,mid,lo,r,g,b
hi = val
lo = round((255 - sat) * val / 255, 1)
mid = lo + round(abs(round(hue, 510) - hue) * (hi - lo) / 255, 1)
if(hue >= 765)
if(hue >= 1275) {r=hi; g=lo; b=mid}
if(hue >= 1275) {r=hi; g=lo; b=mid}
else if(hue >= 1020) {r=mid; g=lo; b=hi }
else {r=lo; g=mid; b=hi }
else {r=lo; g=mid; b=hi }
else
if(hue >= 510) {r=lo; g=hi; b=mid}
else if(hue >= 255) {r=mid; g=hi; b=lo }
else {r=hi; g=mid; b=lo }
if(hue >= 510) {r=lo; g=hi; b=mid}
else if(hue >= 255) {r=mid; g=hi; b=lo }
else {r=hi; g=mid; b=lo }
return (HSV.len > 3) ? rgb(r,g,b,HSV[4]) : rgb(r,g,b)
/proc/RGBtoHSV(rgb)
if(!rgb) return "#0000000"
if(!rgb)
return "#0000000"
var/list/RGB = ReadRGB(rgb)
if(!RGB) return "#0000000"
if(!RGB)
return "#0000000"
var/r = RGB[1]
var/g = RGB[2]
@@ -456,15 +490,22 @@ world
return hsv(hue, sat, val, (RGB.len>3 ? RGB[4] : null))
/proc/hsv(hue, sat, val, alpha)
if(hue < 0 || hue >= 1536) hue %= 1536
if(hue < 0) hue += 1536
if(hue < 0 || hue >= 1536)
hue %= 1536
if(hue < 0)
hue += 1536
if((hue & 0xFF) == 0xFF)
++hue
if(hue >= 1536) hue = 0
if(sat < 0) sat = 0
if(sat > 255) sat = 255
if(val < 0) val = 0
if(val > 255) val = 255
if(hue >= 1536)
hue = 0
if(sat < 0)
sat = 0
if(sat > 255)
sat = 255
if(val < 0)
val = 0
if(val > 255)
val = 255
. = "#"
. += TO_HEX_DIGIT(hue >> 8)
. += TO_HEX_DIGIT(hue >> 4)
@@ -474,8 +515,10 @@ world
. += TO_HEX_DIGIT(val >> 4)
. += TO_HEX_DIGIT(val)
if(!isnull(alpha))
if(alpha < 0) alpha = 0
if(alpha > 255) alpha = 255
if(alpha < 0)
alpha = 0
if(alpha > 255)
alpha = 255
. += TO_HEX_DIGIT(alpha >> 4)
. += TO_HEX_DIGIT(alpha)
@@ -493,32 +536,44 @@ world
var/list/HSV2 = ReadHSV(hsv2)
// add missing alpha if needed
if(HSV1.len < HSV2.len) HSV1 += 255
else if(HSV2.len < HSV1.len) HSV2 += 255
if(HSV1.len < HSV2.len)
HSV1 += 255
else if(HSV2.len < HSV1.len)
HSV2 += 255
var/usealpha = HSV1.len > 3
// normalize hsv values in case anything is screwy
if(HSV1[1] > 1536) HSV1[1] %= 1536
if(HSV2[1] > 1536) HSV2[1] %= 1536
if(HSV1[1] < 0) HSV1[1] += 1536
if(HSV2[1] < 0) HSV2[1] += 1536
if(HSV1[1] > 1536)
HSV1[1] %= 1536
if(HSV2[1] > 1536)
HSV2[1] %= 1536
if(HSV1[1] < 0)
HSV1[1] += 1536
if(HSV2[1] < 0)
HSV2[1] += 1536
if(!HSV1[3]) {HSV1[1] = 0; HSV1[2] = 0}
if(!HSV2[3]) {HSV2[1] = 0; HSV2[2] = 0}
// no value for one color means don't change saturation
if(!HSV1[3]) HSV1[2] = HSV2[2]
if(!HSV2[3]) HSV2[2] = HSV1[2]
if(!HSV1[3])
HSV1[2] = HSV2[2]
if(!HSV2[3])
HSV2[2] = HSV1[2]
// no saturation for one color means don't change hues
if(!HSV1[2]) HSV1[1] = HSV2[1]
if(!HSV2[2]) HSV2[1] = HSV1[1]
if(!HSV1[2])
HSV1[1] = HSV2[1]
if(!HSV2[2])
HSV2[1] = HSV1[1]
// Compress hues into easier-to-manage range
HSV1[1] -= HSV1[1] >> 8
HSV2[1] -= HSV2[1] >> 8
var/hue_diff = HSV2[1] - HSV1[1]
if(hue_diff > 765) hue_diff -= 1530
else if(hue_diff <= -765) hue_diff += 1530
if(hue_diff > 765)
hue_diff -= 1530
else if(hue_diff <= -765)
hue_diff += 1530
var/hue = round(HSV1[1] + hue_diff * amount, 1)
var/sat = round(HSV1[2] + (HSV2[2] - HSV1[2]) * amount, 1)
@@ -526,8 +581,10 @@ world
var/alpha = usealpha ? round(HSV1[4] + (HSV2[4] - HSV1[4]) * amount, 1) : null
// normalize hue
if(hue < 0 || hue >= 1530) hue %= 1530
if(hue < 0) hue += 1530
if(hue < 0 || hue >= 1530)
hue %= 1530
if(hue < 0)
hue += 1530
// decompress hue
hue += round(hue / 255)
@@ -547,8 +604,10 @@ world
var/list/RGB2 = ReadRGB(rgb2)
// add missing alpha if needed
if(RGB1.len < RGB2.len) RGB1 += 255
else if(RGB2.len < RGB1.len) RGB2 += 255
if(RGB1.len < RGB2.len)
RGB1 += 255
else if(RGB2.len < RGB1.len)
RGB2 += 255
var/usealpha = RGB1.len > 3
var/r = round(RGB1[1] + (RGB2[1] - RGB1[1]) * amount, 1)
@@ -563,15 +622,18 @@ world
/proc/HueToAngle(hue)
// normalize hsv in case anything is screwy
if(hue < 0 || hue >= 1536) hue %= 1536
if(hue < 0) hue += 1536
if(hue < 0 || hue >= 1536)
hue %= 1536
if(hue < 0)
hue += 1536
// Compress hue into easier-to-manage range
hue -= hue >> 8
return hue / (1530/360)
/proc/AngleToHue(angle)
// normalize hsv in case anything is screwy
if(angle < 0 || angle >= 360) angle -= 360 * round(angle / 360)
if(angle < 0 || angle >= 360)
angle -= 360 * round(angle / 360)
var/hue = angle * (1530/360)
// Decompress hue
hue += round(hue / 255)
@@ -583,18 +645,23 @@ world
var/list/HSV = ReadHSV(hsv)
// normalize hsv in case anything is screwy
if(HSV[1] >= 1536) HSV[1] %= 1536
if(HSV[1] < 0) HSV[1] += 1536
if(HSV[1] >= 1536)
HSV[1] %= 1536
if(HSV[1] < 0)
HSV[1] += 1536
// Compress hue into easier-to-manage range
HSV[1] -= HSV[1] >> 8
if(angle < 0 || angle >= 360) angle -= 360 * round(angle / 360)
if(angle < 0 || angle >= 360)
angle -= 360 * round(angle / 360)
HSV[1] = round(HSV[1] + angle * (1530/360), 1)
// normalize hue
if(HSV[1] < 0 || HSV[1] >= 1530) HSV[1] %= 1530
if(HSV[1] < 0) HSV[1] += 1530
if(HSV[1] < 0 || HSV[1] >= 1530)
HSV[1] %= 1530
if(HSV[1] < 0)
HSV[1] += 1530
// decompress hue
HSV[1] += round(HSV[1] / 255)
@@ -614,8 +681,10 @@ world
var/gray = RGB[1]*0.3 + RGB[2]*0.59 + RGB[3]*0.11
var/tone_gray = TONE[1]*0.3 + TONE[2]*0.59 + TONE[3]*0.11
if(gray <= tone_gray) return BlendRGB("#000000", tone, gray/(tone_gray || 1))
else return BlendRGB(tone, "#ffffff", (gray-tone_gray)/((255-tone_gray) || 1))
if(gray <= tone_gray)
return BlendRGB("#000000", tone, gray/(tone_gray || 1))
else
return BlendRGB(tone, "#ffffff", (gray-tone_gray)/((255-tone_gray) || 1))
//Used in the OLD chem colour mixing algorithm
@@ -715,7 +784,8 @@ The _flatIcons list is a cache for generated icon files.
var/image/I = current
currentLayer = I.layer
if(currentLayer<0) // Special case for FLY_LAYER
if(currentLayer <= -1000) return flat
if(currentLayer <= -1000)
return flat
if(pSet == 0) // Underlay
currentLayer = A.layer+currentLayer/1000
else // Overlay
+9 -3
View File
@@ -13,7 +13,8 @@ GLOBAL_LIST_INIT(sqrtTable, list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4,
return x!=0?x/abs(x):0
/proc/Atan2(x, y)
if(!x && !y) return 0
if(!x && !y)
return 0
var/a = arccos(x / sqrt(x*x + y*y))
return y >= 0 ? a : -a
@@ -25,6 +26,9 @@ GLOBAL_LIST_INIT(sqrtTable, list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4,
#define Clamp(CLVALUE,CLMIN,CLMAX) ( max( (CLMIN), min((CLVALUE), (CLMAX)) ) )
/proc/Modulus(x, y) //Byond's modulus doesn't work with decimals.
return x - y * round(x / y)
// cotangent
/proc/Cot(x)
return 1 / Tan(x)
@@ -100,10 +104,12 @@ GLOBAL_LIST_INIT(sqrtTable, list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4,
. = list()
var/d = b*b - 4 * a * c
var/bottom = 2 * a
if(d < 0) return
if(d < 0)
return
var/root = sqrt(d)
. += (-b + root) / bottom
if(!d) return
if(!d)
return
. += (-b - root) / bottom
// tangent
+5 -1
View File
@@ -137,7 +137,8 @@ Turf and target are separate in case you want to teleport some distance from a t
return
if(destination.y>world.maxy || destination.y<1)
return
else return
else
return
return destination
@@ -1221,6 +1222,9 @@ proc/pick_closest_path(value, list/matches = get_fancy_list_of_atom_types())
/proc/stack_trace(msg)
CRASH(msg)
/datum/proc/stack_trace(msg)
CRASH(msg)
//Key thing that stops lag. Cornerstone of performance in ss13, Just sitting here, in unsorted.dm.
//Increases delay as the server gets more overloaded,
+1 -1
View File
@@ -19,7 +19,7 @@ GLOBAL_LIST_EMPTY(silicon_mobs) //all silicon mobs
GLOBAL_LIST_EMPTY(ai_list)
GLOBAL_LIST_EMPTY(pai_list)
GLOBAL_LIST_EMPTY(available_ai_shells)
GLOBAL_LIST_EMPTY(simple_animals)
GLOBAL_LIST_INIT(simple_animals, list(list(),list(),list())) // One for each AI_* status define
GLOBAL_LIST_EMPTY(spidermobs) //all sentient spider mobs
GLOBAL_LIST_EMPTY(language_datum_instances)
+2
View File
@@ -5,5 +5,7 @@
GLOBAL_LIST_INIT(typecache_mob, typecacheof(list(/mob)))
GLOBAL_LIST_INIT(typecache_living, typecacheof(list(/mob/living)))
GLOBAL_LIST_INIT(typecache_machine_or_structure, typecacheof(list(/obj/machinery))|typecacheof(list(/obj/structure)))
+2
View File
@@ -18,6 +18,8 @@ GLOBAL_VAR(sql_error_log)
GLOBAL_PROTECT(sql_error_log)
GLOBAL_VAR(world_pda_log)
GLOBAL_PROTECT(world_pda_log)
GLOBAL_VAR(manifest_log)
GLOBAL_PROTECT(manifest_log)
GLOBAL_LIST_EMPTY(bombers)
GLOBAL_PROTECT(bombers)
+2 -1
View File
@@ -76,7 +76,8 @@
// This is necessary for storage items not on your person.
/obj/item/Adjacent(var/atom/neighbor, var/recurse = 1)
if(neighbor == loc) return 1
if(neighbor == loc)
return 1
if(isitem(loc))
if(recurse > 0)
return loc.Adjacent(neighbor,recurse - 1)
+12 -17
View File
@@ -22,7 +22,6 @@
else
A.move_camera_by_click()
/mob/living/silicon/ai/ClickOn(var/atom/A, params)
if(world.time <= next_click)
return
@@ -36,20 +35,16 @@
return
var/turf/pixel_turf = get_turf_pixel(A)
var/turf_visible
if(pixel_turf)
turf_visible = GLOB.cameranet.checkTurfVis(pixel_turf)
if(!turf_visible)
if(istype(loc, /obj/item/device/aicard) && (pixel_turf in view(client.view, loc)))
turf_visible = TRUE
else
if (pixel_turf.obscured)
log_admin("[key_name_admin(src)] might be running a modified client! (failed checkTurfVis on AI click of [A]([COORD(pixel_turf)])")
message_admins("[key_name_admin(src)] might be running a modified client! (failed checkTurfVis on AI click of [A]([ADMIN_COORDJMP(pixel_turf)]))")
if(REALTIMEOFDAY >= chnotify + 9000)
chnotify = REALTIMEOFDAY
send2irc_adminless_only("NOCHEAT", "[key_name(src)] might be running a modified client! (failed checkTurfVis on AI click of [A]([COORD(pixel_turf)]))")
return
if(isnull(pixel_turf))
return
if(!can_see(A))
message_admins("[key_name_admin(src)] might be running a modified client! (failed can_see on AI click of [A]([ADMIN_COORDJMP(pixel_turf)]))")
var/message = "[key_name(src)] might be running a modified client! (failed can_see on AI click of [A]([COORD(pixel_turf)]))"
log_admin(message)
if(REALTIMEOFDAY >= chnotify + 9000)
chnotify = REALTIMEOFDAY
send2irc_adminless_only("NOCHEAT", message)
return
var/list/modifiers = params2list(params)
if(modifiers["shift"] && modifiers["ctrl"])
@@ -74,7 +69,7 @@
if(world.time <= next_move)
return
if(aicamera.in_camera_mode && pixel_turf && turf_visible)
if(aicamera.in_camera_mode)
aicamera.camera_mode_off()
aicamera.captureimage(pixel_turf, usr)
return
@@ -150,7 +145,7 @@
if(emagged)
return
if(!secondsElectrified)
// permenant shock
// permanent shock
Topic("aiEnable=6", list("aiEnable"="6"), 1) // 1 meaning no window (consistency!)
else
// disable/6 is not in Topic; disable/5 disables both temporary and permenant shock
+3 -8
View File
@@ -385,13 +385,11 @@
Laser Eyes: as the name implies, handles this since nothing else does currently
face_atom: turns the mob towards what you clicked on
*/
/mob/proc/LaserEyes(atom/A)
/mob/proc/LaserEyes(atom/A, params)
return
/mob/living/LaserEyes(atom/A)
/mob/living/LaserEyes(atom/A, params)
changeNext_move(CLICK_CD_RANGE)
var/turf/T = get_turf(src)
var/turf/U = get_turf(A)
var/obj/item/projectile/beam/LE = new /obj/item/projectile/beam( loc )
LE.icon = 'icons/effects/genetics.dmi'
@@ -400,10 +398,7 @@
LE.firer = src
LE.def_zone = get_organ_target()
LE.original = A
LE.current = T
LE.yo = U.y - T.y
LE.xo = U.x - T.x
LE.preparePixelProjectile(A, src, params)
LE.fire()
// Simple helper to face what you clicked on, in case it should be needed in more than one place
+3 -2
View File
@@ -6,11 +6,12 @@
almost anything into a trash can.
*/
/atom/MouseDrop(atom/over, src_location, over_location, src_control, over_control, params)
if(!usr || !over)
if(!usr || !over)
return
if(over == src)
return usr.client.Click(src, src_location, src_control, params)
if(!Adjacent(usr) || !over.Adjacent(usr)) return // should stop you from dragging through windows
if(!Adjacent(usr) || !over.Adjacent(usr))
return // should stop you from dragging through windows
over.MouseDrop_T(src,usr)
return
+16 -10
View File
@@ -173,7 +173,7 @@
/obj/screen/alert/verygross
name = "Very grossed out."
desc = "I'm not feeling very well.."
desc = "You're not feeling very well..."
icon_state = "gross2"
/obj/screen/alert/disgusted
@@ -243,7 +243,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
/obj/screen/alert/fire/Click()
var/mob/living/L = usr
if(!L.can_resist())
if(!istype(L) || !L.can_resist())
return
L.changeNext_move(CLICK_CD_RESIST)
if(L.canmove)
@@ -491,8 +491,10 @@ so as to remain in compliance with the most up-to-date laws."
var/atom/target = null
/obj/screen/alert/hackingapc/Click()
if(!usr || !usr.client) return
if(!target) return
if(!usr || !usr.client)
return
if(!target)
return
var/mob/living/silicon/ai/AI = usr
var/turf/T = get_turf(target)
if(T)
@@ -515,7 +517,8 @@ so as to remain in compliance with the most up-to-date laws."
timeout = 300
/obj/screen/alert/notify_cloning/Click()
if(!usr || !usr.client) return
if(!usr || !usr.client)
return
var/mob/dead/observer/G = usr
G.reenter_corpse()
@@ -528,10 +531,13 @@ so as to remain in compliance with the most up-to-date laws."
var/action = NOTIFY_JUMP
/obj/screen/alert/notify_action/Click()
if(!usr || !usr.client) return
if(!target) return
if(!usr || !usr.client)
return
if(!target)
return
var/mob/dead/observer/G = usr
if(!istype(G)) return
if(!istype(G))
return
switch(action)
if(NOTIFY_ATTACK)
target.attack_ghost(G)
@@ -559,7 +565,7 @@ so as to remain in compliance with the most up-to-date laws."
/obj/screen/alert/restrained/Click()
var/mob/living/L = usr
if(!L.can_resist())
if(!istype(L) || !L.can_resist())
return
L.changeNext_move(CLICK_CD_RESIST)
if((L.canmove) && (L.last_special <= world.time))
@@ -567,7 +573,7 @@ so as to remain in compliance with the most up-to-date laws."
/obj/screen/alert/restrained/buckled/Click()
var/mob/living/L = usr
if(!L.can_resist())
if(!istype(L) || !L.can_resist())
return
L.changeNext_move(CLICK_CD_RESIST)
if(L.last_special <= world.time)
+4 -2
View File
@@ -180,7 +180,8 @@
/datum/hud/proc/toggle_show_robot_modules()
if(!iscyborg(mymob)) return
if(!iscyborg(mymob))
return
var/mob/living/silicon/robot/R = mymob
@@ -188,7 +189,8 @@
update_robot_modules_display()
/datum/hud/proc/update_robot_modules_display(mob/viewer)
if(!iscyborg(mymob)) return
if(!iscyborg(mymob))
return
var/mob/living/silicon/robot/R = mymob
+2 -1
View File
@@ -325,7 +325,8 @@
usr.stop_pulling()
/obj/screen/pull/update_icon(mob/mymob)
if(!mymob) return
if(!mymob)
return
if(mymob.pulling)
icon_state = "pull"
else
+204 -204
View File
@@ -1,206 +1,206 @@
/*
Humans:
Adds an exception for gloves, to allow special glove types like the ninja ones.
Otherwise pretty standard.
*/
/mob/living/carbon/human/UnarmedAttack(atom/A, proximity)
if(!has_active_hand()) //can't attack without a hand.
to_chat(src, "<span class='notice'>You look at your arm and sigh.</span>")
return
// Special glove functions:
// If the gloves do anything, have them return 1 to stop
// normal attack_hand() here.
var/obj/item/clothing/gloves/G = gloves // not typecast specifically enough in defines
if(proximity && istype(G) && G.Touch(A,1))
return
var/override = 0
for(var/datum/mutation/human/HM in dna.mutations)
override += HM.on_attack_hand(src, A, proximity)
if(override)
return
A.attack_hand(src)
/atom/proc/attack_hand(mob/user)
return
/atom/proc/interact(mob/user)
return
/*
/mob/living/carbon/human/RestrainedClickOn(var/atom/A) ---carbons will handle this
return
*/
/mob/living/carbon/RestrainedClickOn(atom/A)
return 0
/mob/living/carbon/human/RangedAttack(atom/A)
if(gloves)
var/obj/item/clothing/gloves/G = gloves
if(istype(G) && G.Touch(A,0)) // for magic gloves
return
for(var/datum/mutation/human/HM in dna.mutations)
HM.on_ranged_attack(src, A)
if(isturf(A) && get_dist(src,A) <= 1)
src.Move_Pulled(A)
/*
Animals & All Unspecified
*/
/mob/living/UnarmedAttack(atom/A)
A.attack_animal(src)
/atom/proc/attack_animal(mob/user)
return
/mob/living/RestrainedClickOn(atom/A)
return
/*
Monkeys
*/
/mob/living/carbon/monkey/UnarmedAttack(atom/A)
A.attack_paw(src)
/atom/proc/attack_paw(mob/user)
return
/*
Monkey RestrainedClickOn() was apparently the
one and only use of all of the restrained click code
(except to stop you from doing things while handcuffed);
moving it here instead of various hand_p's has simplified
things considerably
*/
/mob/living/carbon/monkey/RestrainedClickOn(atom/A)
if(..())
return
if(a_intent != INTENT_HARM || !ismob(A))
return
if(is_muzzled())
return
var/mob/living/carbon/ML = A
if(istype(ML))
var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")
var/obj/item/bodypart/affecting = null
if(ishuman(ML))
var/mob/living/carbon/human/H = ML
affecting = H.get_bodypart(ran_zone(dam_zone))
var/armor = ML.run_armor_check(affecting, "melee")
if(prob(75))
ML.apply_damage(rand(1,3), BRUTE, affecting, armor)
ML.visible_message("<span class='danger'>[name] bites [ML]!</span>", \
"<span class='userdanger'>[name] bites [ML]!</span>")
if(armor >= 2)
return
/*
Humans:
Adds an exception for gloves, to allow special glove types like the ninja ones.
Otherwise pretty standard.
*/
/mob/living/carbon/human/UnarmedAttack(atom/A, proximity)
if(!has_active_hand()) //can't attack without a hand.
to_chat(src, "<span class='notice'>You look at your arm and sigh.</span>")
return
// Special glove functions:
// If the gloves do anything, have them return 1 to stop
// normal attack_hand() here.
var/obj/item/clothing/gloves/G = gloves // not typecast specifically enough in defines
if(proximity && istype(G) && G.Touch(A,1))
return
var/override = 0
for(var/datum/mutation/human/HM in dna.mutations)
override += HM.on_attack_hand(src, A, proximity)
if(override)
return
A.attack_hand(src)
/atom/proc/attack_hand(mob/user)
return
/atom/proc/interact(mob/user)
return
/*
/mob/living/carbon/human/RestrainedClickOn(var/atom/A) ---carbons will handle this
return
*/
/mob/living/carbon/RestrainedClickOn(atom/A)
return 0
/mob/living/carbon/human/RangedAttack(atom/A, mouseparams)
if(gloves)
var/obj/item/clothing/gloves/G = gloves
if(istype(G) && G.Touch(A,0)) // for magic gloves
return
for(var/datum/mutation/human/HM in dna.mutations)
HM.on_ranged_attack(src, A, mouseparams)
if(isturf(A) && get_dist(src,A) <= 1)
src.Move_Pulled(A)
/*
Animals & All Unspecified
*/
/mob/living/UnarmedAttack(atom/A)
A.attack_animal(src)
/atom/proc/attack_animal(mob/user)
return
/mob/living/RestrainedClickOn(atom/A)
return
/*
Monkeys
*/
/mob/living/carbon/monkey/UnarmedAttack(atom/A)
A.attack_paw(src)
/atom/proc/attack_paw(mob/user)
return
/*
Monkey RestrainedClickOn() was apparently the
one and only use of all of the restrained click code
(except to stop you from doing things while handcuffed);
moving it here instead of various hand_p's has simplified
things considerably
*/
/mob/living/carbon/monkey/RestrainedClickOn(atom/A)
if(..())
return
if(a_intent != INTENT_HARM || !ismob(A))
return
if(is_muzzled())
return
var/mob/living/carbon/ML = A
if(istype(ML))
var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")
var/obj/item/bodypart/affecting = null
if(ishuman(ML))
var/mob/living/carbon/human/H = ML
affecting = H.get_bodypart(ran_zone(dam_zone))
var/armor = ML.run_armor_check(affecting, "melee")
if(prob(75))
ML.apply_damage(rand(1,3), BRUTE, affecting, armor)
ML.visible_message("<span class='danger'>[name] bites [ML]!</span>", \
"<span class='userdanger'>[name] bites [ML]!</span>")
if(armor >= 2)
return
for(var/thing in viruses)
var/datum/disease/D = thing
ML.ForceContractDisease(D)
else
ML.visible_message("<span class='danger'>[src] has attempted to bite [ML]!</span>")
/*
Aliens
Defaults to same as monkey in most places
*/
/mob/living/carbon/alien/UnarmedAttack(atom/A)
A.attack_alien(src)
/atom/proc/attack_alien(mob/living/carbon/alien/user)
attack_paw(user)
return
/mob/living/carbon/alien/RestrainedClickOn(atom/A)
return
// Babby aliens
/mob/living/carbon/alien/larva/UnarmedAttack(atom/A)
A.attack_larva(src)
/atom/proc/attack_larva(mob/user)
return
/*
Slimes
Nothing happening here
*/
/mob/living/simple_animal/slime/UnarmedAttack(atom/A)
A.attack_slime(src)
/atom/proc/attack_slime(mob/user)
return
/mob/living/simple_animal/slime/RestrainedClickOn(atom/A)
return
/*
Drones
*/
/mob/living/simple_animal/drone/UnarmedAttack(atom/A)
A.attack_drone(src)
/atom/proc/attack_drone(mob/living/simple_animal/drone/user)
attack_hand(user) //defaults to attack_hand. Override it when you don't want drones to do same stuff as humans.
/mob/living/simple_animal/slime/RestrainedClickOn(atom/A)
return
/*
True Devil
*/
/mob/living/carbon/true_devil/UnarmedAttack(atom/A, proximity)
A.attack_hand(src)
/*
Brain
*/
/mob/living/brain/UnarmedAttack(atom/A)//Stops runtimes due to attack_animal being the default
return
/*
pAI
*/
/mob/living/silicon/pai/UnarmedAttack(atom/A)//Stops runtimes due to attack_animal being the default
return
/*
Simple animals
*/
/mob/living/simple_animal/UnarmedAttack(atom/A, proximity)
if(!dextrous)
return ..()
if(!ismob(A))
A.attack_hand(src)
update_inv_hands()
/*
Hostile animals
*/
/mob/living/simple_animal/hostile/UnarmedAttack(atom/A)
target = A
if(dextrous && !is_type_in_typecache(A, environment_target_typecache) && !ismob(A))
..()
else
AttackingTarget()
/*
New Players:
Have no reason to click on anything at all.
*/
/mob/dead/new_player/ClickOn()
return
ML.ForceContractDisease(D)
else
ML.visible_message("<span class='danger'>[src] has attempted to bite [ML]!</span>")
/*
Aliens
Defaults to same as monkey in most places
*/
/mob/living/carbon/alien/UnarmedAttack(atom/A)
A.attack_alien(src)
/atom/proc/attack_alien(mob/living/carbon/alien/user)
attack_paw(user)
return
/mob/living/carbon/alien/RestrainedClickOn(atom/A)
return
// Babby aliens
/mob/living/carbon/alien/larva/UnarmedAttack(atom/A)
A.attack_larva(src)
/atom/proc/attack_larva(mob/user)
return
/*
Slimes
Nothing happening here
*/
/mob/living/simple_animal/slime/UnarmedAttack(atom/A)
A.attack_slime(src)
/atom/proc/attack_slime(mob/user)
return
/mob/living/simple_animal/slime/RestrainedClickOn(atom/A)
return
/*
Drones
*/
/mob/living/simple_animal/drone/UnarmedAttack(atom/A)
A.attack_drone(src)
/atom/proc/attack_drone(mob/living/simple_animal/drone/user)
attack_hand(user) //defaults to attack_hand. Override it when you don't want drones to do same stuff as humans.
/mob/living/simple_animal/slime/RestrainedClickOn(atom/A)
return
/*
True Devil
*/
/mob/living/carbon/true_devil/UnarmedAttack(atom/A, proximity)
A.attack_hand(src)
/*
Brain
*/
/mob/living/brain/UnarmedAttack(atom/A)//Stops runtimes due to attack_animal being the default
return
/*
pAI
*/
/mob/living/silicon/pai/UnarmedAttack(atom/A)//Stops runtimes due to attack_animal being the default
return
/*
Simple animals
*/
/mob/living/simple_animal/UnarmedAttack(atom/A, proximity)
if(!dextrous)
return ..()
if(!ismob(A))
A.attack_hand(src)
update_inv_hands()
/*
Hostile animals
*/
/mob/living/simple_animal/hostile/UnarmedAttack(atom/A)
target = A
if(dextrous && !is_type_in_typecache(A, environment_target_typecache) && !ismob(A))
..()
else
AttackingTarget()
/*
New Players:
Have no reason to click on anything at all.
*/
/mob/dead/new_player/ClickOn()
return
+28 -25
View File
@@ -99,13 +99,14 @@
color = "#FFADFF"//PINK, rgb(255, 173, 255)
/datum/reagent/drug/aphrodisiac/on_mob_life(mob/living/M)
if(prob(33))
M.adjustArousalLoss(2)
if(prob(5))
M.emote(pick("moan","blush"))
if(prob(5))
var/aroused_message = pick("You feel frisky.", "You're having trouble suppressing your urges.", "You feel in the mood.")
to_chat(M, "<span class='love'>[aroused_message]</span>")
if(M && M.canbearoused)
if(prob(33))
M.adjustArousalLoss(2)
if(prob(5))
M.emote(pick("moan","blush"))
if(prob(5))
var/aroused_message = pick("You feel frisky.", "You're having trouble suppressing your urges.", "You feel in the mood.")
to_chat(M, "<span class='love'>[aroused_message]</span>")
..()
/datum/reagent/drug/aphrodisiacplus
@@ -120,20 +121,22 @@
overdose_threshold = 20
/datum/reagent/drug/aphrodisiacplus/on_mob_life(mob/living/M)
if(prob(33))
M.adjustArousalLoss(6)//not quite six times as powerful, but still considerably more powerful.
if(prob(5))
if(M.getArousalLoss() > 75)
M.say(pick("Hnnnnngghh...", "Ohh...", "Mmnnn..."))
else
M.emote(pick("moan","blush"))
if(prob(5))
var/aroused_message
if(M.getArousalLoss() > 90)
aroused_message = pick("You need to fuck someone!", "You're bursting with sexual tension!", "You can't get sex off your mind!")
else
aroused_message = pick("You feel a bit hot.", "You feel strong sexual urges.", "You feel in the mood.", "You're ready to go down on someone.")
to_chat(M, "<span class='love'>[aroused_message]</span>")
if(M && M.canbearoused)
if(prob(33))
M.adjustArousalLoss(6)//not quite six times as powerful, but still considerably more powerful.
if(prob(5))
if(M.getArousalLoss() > 75)
M.say(pick("Hnnnnngghh...", "Ohh...", "Mmnnn..."))
else
M.emote(pick("moan","blush"))
if(prob(5))
var/aroused_message
if(M.getArousalLoss() > 90)
aroused_message = pick("You need to fuck someone!", "You're bursting with sexual tension!", "You can't get sex off your mind!")
else
aroused_message = pick("You feel a bit hot.", "You feel strong sexual urges.", "You feel in the mood.", "You're ready to go down on someone.")
to_chat(M, "<span class='love'>[aroused_message]</span>")
..()
/datum/reagent/drug/aphrodisiacplus/addiction_act_stage2(mob/living/M)
if(prob(30))
@@ -150,7 +153,7 @@
..()
/datum/reagent/drug/aphrodisiacplus/overdose_process(mob/living/M)
if(prob(33))
if(M && M.canbearoused && prob(33))
if(M.getArousalLoss() >= 100 && ishuman(M) && M.has_dna())
var/mob/living/carbon/human/H = M
if(prob(50)) //Less spam
@@ -174,7 +177,7 @@
reagent_state = SOLID
/datum/reagent/drug/anaphrodisiac/on_mob_life(mob/living/M)
if(prob(33))
if(M && M.canbearoused && prob(33))
M.adjustArousalLoss(-2)
..()
@@ -188,12 +191,12 @@
overdose_threshold = 20
/datum/reagent/drug/anaphrodisiacplus/on_mob_life(mob/living/M)
if(prob(33))
if(M && M.canbearoused && prob(33))
M.adjustArousalLoss(-4)
..()
/datum/reagent/drug/anaphrodisiacplus/overdose_process(mob/living/M)
if(prob(33))
if(M && M.canbearoused && prob(33))
if(M.min_arousal > 0)
M.min_arousal -= 1
if(M.min_arousal > 50)
+29 -1
View File
@@ -163,7 +163,20 @@
item_state = "russianflask"
volume = 60
/obj/item/clothing/mask/gas/stalker
name = "S.T.A.L.K.E.R. mask"
desc = "Smells like reactor four."
icon = 'icons/obj/custom.dmi'
item_state = "stalker"
icon_state = "stalker"
flags_1 = BLOCK_GAS_SMOKE_EFFECT_1 | MASKINTERNALS_1
flags_inv = HIDEEARS|HIDEEYES|HIDEFACE|HIDEFACIALHAIR
w_class = WEIGHT_CLASS_NORMAL
item_state = "gas_alt"
gas_transfer_coefficient = 0.01
permeability_coefficient = 0.01
flags_cover = MASKCOVERSEYES | MASKCOVERSMOUTH
resistance_flags = 0
/*Sylas*/
@@ -174,3 +187,18 @@
icon_state = "petcollar-stripe"
item_color = "petcollar-stripe"
tagname = null
/*PLACEHOLDER*/
/obj/item/clothing/under/singery/custom
name = "bluish performer's outfit"
desc = "Just looking at this makes you want to sing."
icon_state = "ssing"
item_state = "ssing"
item_color = "ssing"
fitted = NO_FEMALE_UNIFORM
alternate_worn_layer = ABOVE_SHOES_LAYER
can_adjust = 0
+208 -244
View File
@@ -111,10 +111,10 @@
var/list/env_gases = environment.gases
environment.assert_gases(arglist(GLOB.hardcoded_gases))
var/o2_concentration = env_gases["o2"][MOLES]/total_moles
var/n2_concentration = env_gases["n2"][MOLES]/total_moles
var/co2_concentration = env_gases["co2"][MOLES]/total_moles
var/plasma_concentration = env_gases["plasma"][MOLES]/total_moles
var/o2_concentration = env_gases[/datum/gas/oxygen][MOLES]/total_moles
var/n2_concentration = env_gases[/datum/gas/nitrogen][MOLES]/total_moles
var/co2_concentration = env_gases[/datum/gas/carbon_dioxide][MOLES]/total_moles
var/plasma_concentration = env_gases[/datum/gas/plasma][MOLES]/total_moles
environment.garbage_collect()
if(abs(n2_concentration - N2STANDARD) < 20)
@@ -321,8 +321,8 @@
//Sleeper
/obj/item/device/dogborg/sleeper
name = "Medbelly"
desc = "Equipment for medical hound. A mounted sleeper that stabilizes patients and can inject reagents in the borg's reserves."
name = "hound sleeper"
desc = "nothing should see this."
icon = 'icons/mob/dogborg.dmi'
icon_state = "sleeper"
w_class = WEIGHT_CLASS_TINY
@@ -330,12 +330,38 @@
var/mob/living/silicon/robot/hound = null
var/inject_amount = 10
var/min_health = -100
var/cleaning = 0
var/cleaning = FALSE
var/cleaning_cycles = 10
var/patient_laststat = null
var/mob_energy = 30000 //Energy gained from digesting mobs (including PCs)
var/list/injection_chems = list("antitoxin", "morphine", "salbutamol", "bicaridine", "kelotane"),
var/list/injection_chems = list("antitoxin", "epinephrine", "morphine", "salbutamol", "bicaridine", "kelotane")
var/eject_port = "ingestion"
var/list/items_preserved = list()
var/escape_in_progress = FALSE
var/message_cooldown
var/breakout_time = 300
var/list/items_preserved = list(
/obj/item/hand_tele,
/obj/item/card/id,
/obj/item/device/pda,
/obj/item/device/aicard,
/obj/item/gun,
/obj/item/pinpointer,
/obj/item/clothing/shoes/magboots,
/obj/item/clothing/head/helmet/space,
/obj/item/clothing/suit/space,
/obj/item/reagent_containers/hypospray/CMO,
/obj/item/tank/jetpack/oxygen/captain,
/obj/item/clothing/accessory/medal/gold/captain,
/obj/item/clothing/suit/armor,
/obj/item/documents,
/obj/item/nuke_core,
/obj/item/nuke_core_container,
/obj/item/areaeditor/blueprints,
/obj/item/documents/syndicate,
/obj/item/disk/nuclear,
/obj/item/bombcore,
/obj/item/grenade
)
var/list/important_items = list(
/obj/item/hand_tele,
/obj/item/card/id/captains_spare,
@@ -356,10 +382,12 @@
/obj/item/documents/syndicate,
/obj/item/disk/nuclear,
/obj/item/bombcore,
/obj/item/grenade)
/obj/item/grenade
)
/obj/item/device/dogborg/sleeper/New()
..()
update_icon()
flags_1 |= NOBLUDGEON_1 //No more attack messages
/obj/item/device/dogborg/sleeper/Exit(atom/movable/O)
@@ -371,16 +399,13 @@
return
if(!ishuman(target))
return
if(!target.devourable)
to_chat(user, "<span class='warning'>This person is incompatible with our equipment.</span>")
return
if(target.buckled)
to_chat(user, "<span class='warning'>The user is buckled and can not be put into your [src.name].</span>")
return
if(patient)
to_chat(user, "<span class='warning'>Your [src.name] is already occupied.</span>")
return
user.visible_message("<span class='warning'>[hound.name] is ingesting [target.name] into their [src.name].</span>", "<span class='notice'>You start ingesting [target] into your [src]...</span>")
user.visible_message("<span class='warning'>[hound.name] is carefully inserting [target.name] into their [src.name].</span>", "<span class='notice'>You start placing [target] into your [src]...</span>")
if(!patient && ishuman(target) && !target.buckled && do_after (user, 50, target = target))
if(!in_range(src, target)) //Proximity is probably old news by now, do a new check.
@@ -389,18 +414,42 @@
if(patient) return //If you try to eat two people at once, you can only eat one.
else //If you don't have someone in you, proceed.
if(!isslimeperson(target) && ("toxin" in injection_chems))
injection_chems -= "toxin"
injection_chems += "antitoxin"
if(isslimeperson(target) && !("toxin" in injection_chems))
injection_chems -= "antitoxin"
injection_chems += "toxin"
target.forceMove(src)
target.reset_perspective(src)
update_patient()
update_gut()
START_PROCESSING(SSobj, src)
user.visible_message("<span class='warning'>[hound.name]'s medical pod lights up as [target.name] slips inside into their [src.name].</span>", "<span class='notice'>Your medical pod lights up as [target] slips into your [src]. Life support functions engaged.</span>")
user.visible_message("<span class='warning'>[hound.name]'s medical pod lights up and expands as [target.name] slips inside into their [src.name].</span>", "<span class='notice'>Your medical pod lights up as [target] slips into your [src]. Life support functions engaged.</span>")
message_admins("[key_name(hound)] has eaten [key_name(patient)] as a dogborg. ([hound ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[hound.x];Y=[hound.y];Z=[hound.z]'>JMP</a>" : "null"])")
playsound(hound, 'sound/effects/bin_close.ogg', 100, 1)
/obj/item/device/dogborg/sleeper/container_resist(mob/living/user)
hound = loc
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
if(user.a_intent == INTENT_HELP)
return
user.visible_message("<span class='notice'>You see [user] kicking against the expanded material of [hound.name]'s gut!</span>", \
"<span class='notice'>You struggle inside [src], kicking the release with your foot... (this will take about [DisplayTimeText(breakout_time)].)</span>", \
"<span class='italics'>You hear a thump from [hound.name].</span>")
if(do_after(user, breakout_time, target = src))
if(!user || user.stat != CONSCIOUS || user.loc != src )
return
user.visible_message("<span class='warning'>[user] successfully broke out of [hound.name]!</span>", \
"<span class='notice'>You successfully break out of [hound.name]!</span>")
go_out()
/obj/item/device/dogborg/sleeper/proc/go_out(var/target)
hound = src.loc
testing("go_out activated")
hound.setClickCooldown(50)
if(length(contents) > 0)
hound.visible_message("<span class='warning'>[hound.name] empties out their contents via their [eject_port] port.</span>", "<span class='notice'>You empty your contents via your [eject_port] port.</span>")
hound.visible_message("<span class='warning'>[hound.name] empties out their contents via their release port.</span>", "<span class='notice'>You empty your contents via your release port.</span>")
if(target)
if(ishuman(target))
var/mob/living/carbon/human/person = target
@@ -419,199 +468,103 @@
var/obj/T = C
T.loc = hound.loc
items_preserved.Cut()
cleaning = 0
update_gut()
cleaning = FALSE
playsound(loc, 'sound/effects/splat.ogg', 50, 1)
update_patient()
else //You clicked eject with nothing in you, let's just reset stuff to be sure.
items_preserved.Cut()
cleaning = 0
update_patient()
/obj/item/device/dogborg/sleeper/proc/drain(var/amt = 3) //Slightly reduced cost (before, it was always injecting inaprov)
if (amt > 0)
hound.cell.give(amt)
else
hound.cell.use(amt)
cleaning = FALSE
hound.visible_message("<span class='warning'>[hound.name] belches, torso flexing.</span>")
update_gut()
/obj/item/device/dogborg/sleeper/attack_self(mob/user)
if(..())
return
sleeperUI(user)
ui_interact(user)
/obj/item/device/dogborg/sleeper/proc/sleeperUI(mob/user)
var/dat
dat += "<h3>Injector</h3>"
/obj/item/device/dogborg/sleeper/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
if(patient && !(patient.stat & DEAD))
dat += "<A href='?src=\ref[src];inject=epinephrine'>Inject Epinephrine</A>"
else
dat += "<span class='linkOff'>Inject Epinephrine</span>"
if(patient && patient.health > min_health)
for(var/re in injection_chems)
var/datum/reagent/C = GLOB.chemical_reagents_list[re]
if(C)
dat += "<BR><A href='?src=\ref[src];inject=[C.id]'>Inject [C.name]</A>"
else
for(var/re in injection_chems)
var/datum/reagent/C = GLOB.chemical_reagents_list[re]
if(C)
dat += "<BR><span class='linkOff'>Inject [C.name]</span>"
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "dogborg_sleeper", name, 375, 550, master_ui, state)
ui.open()
dat += "<h3>Sleeper Status</h3>"
dat += "<A id='refbutton' href='?src=\ref[src];refresh=1'>Refresh</A>"
dat += "<A href='?src=\ref[src];eject=1'>Eject All</A>"
dat += "<A href='?src=\ref[src];port=1'>Eject port: [eject_port]</A>"
if(!cleaning)
dat += "<A href='?src=\ref[src];clean=1'>Self-Clean</A>"
else
dat += "<span class='linkOff'>Self-Clean</span>"
/obj/item/device/dogborg/sleeper/ui_data()
var/list/data = list()
data["occupied"] = patient ? 1 : 0
dat += "<div class='statusDisplay'>"
//Cleaning and there are still un-preserved items
if(cleaning && length(contents - items_preserved))
dat += "<font color='red'><B>Self-cleaning mode.</B> [length(contents - items_preserved)] object(s) remaining.</font><BR>"
data["items"] = "Self-cleaning mode active: [length(contents - items_preserved)] object(s) remaining."
data["cleaning"] = cleaning
if(injection_chems != null)
data["chem"] = list()
for(var/chem in injection_chems)
var/datum/reagent/R = GLOB.chemical_reagents_list[chem]
data["chem"] += list(list("name" = R.name, "id" = R.id))
//There are no items to be processed other than un-preserved items
else if(cleaning && length(items_preserved))
dat += "<font color='red'><B>Self-cleaning done. Eject remaining objects now.</B></font><BR>"
data["occupant"] = list()
var/mob/living/mob_occupant = patient
if(mob_occupant)
data["occupant"]["name"] = mob_occupant.name
switch(mob_occupant.stat)
if(CONSCIOUS)
data["occupant"]["stat"] = "Conscious"
data["occupant"]["statstate"] = "good"
if(SOFT_CRIT)
data["occupant"]["stat"] = "Conscious"
data["occupant"]["statstate"] = "average"
if(UNCONSCIOUS)
data["occupant"]["stat"] = "Unconscious"
data["occupant"]["statstate"] = "average"
if(DEAD)
data["occupant"]["stat"] = "Dead"
data["occupant"]["statstate"] = "bad"
data["occupant"]["health"] = mob_occupant.health
data["occupant"]["maxHealth"] = mob_occupant.maxHealth
data["occupant"]["minHealth"] = HEALTH_THRESHOLD_DEAD
data["occupant"]["bruteLoss"] = mob_occupant.getBruteLoss()
data["occupant"]["oxyLoss"] = mob_occupant.getOxyLoss()
data["occupant"]["toxLoss"] = mob_occupant.getToxLoss()
data["occupant"]["fireLoss"] = mob_occupant.getFireLoss()
data["occupant"]["cloneLoss"] = mob_occupant.getCloneLoss()
data["occupant"]["brainLoss"] = mob_occupant.getBrainLoss()
data["occupant"]["reagents"] = list()
if(mob_occupant.reagents.reagent_list.len)
for(var/datum/reagent/R in mob_occupant.reagents.reagent_list)
data["occupant"]["reagents"] += list(list("name" = R.name, "volume" = R.volume))
return data
//Preserved items count when the list is populated
if(length(items_preserved))
dat += "<font color='red'>[length(items_preserved)] uncleanable object(s).</font><BR>"
if(!patient)
dat += "Sleeper Unoccupied"
else
dat += "[patient.name] => "
switch(patient.stat)
if(0)
dat += "<span class='good'>Conscious</span>"
if(1)
dat += "<span class='average'>Unconscious</span>"
else
dat += "<span class='bad'>DEAD</span>"
var/healthcolor = (patient.health > 0 ? "color:white;" : "color:red;")
var/brutecolor = (patient.getBruteLoss() < 60 ? "color:gray;" : "color:red;")
var/o2color = (patient.getOxyLoss() < 60 ? "color:gray;" : "color:red;")
var/toxcolor = (patient.getToxLoss() < 60 ? "color:gray;" : "color:red;")
var/burncolor = (patient.getFireLoss() < 60 ? "color:gray;" : "color:red;")
dat += "<span style='[healthcolor]'>\t-Overall Health %: [round(patient.health)]</span><BR>"
dat += "<span style='[brutecolor]'>\t-Brute Damage %: [patient.getBruteLoss()]</span><BR>"
dat += "<span style='[o2color]'>\t-Respiratory Damage %: [patient.getOxyLoss()]</span><BR>"
dat += "<span style='[toxcolor]'>\t-Toxin Content %: [patient.getToxLoss()]</span><BR>"
dat += "<span style='[burncolor]'>\t-Burn Severity %: [patient.getFireLoss()]</span><BR>"
if(patient.getBrainLoss())
dat += "<div class='line'><span class='average'>Significant brain damage detected.</span></div><br>"
if(patient.getCloneLoss())
dat += "<div class='line'><span class='average'>Patient may be improperly cloned.</span></div><br>"
if(patient.reagents.reagent_list.len)
for(var/datum/reagent/R in patient.reagents.reagent_list)
dat += "<div class='line'><div style='width: 170px;' class='statusLabel'>[R.name]:</div><div class='statusValue'>[round(R.volume, 0.1)] units</div></div><br>"
dat += "</div>"
var/datum/browser/popup = new(user, "sleeper", "Sleeper Console", 520, 540) //Set up the popup browser window
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
popup.set_content(dat)
popup.open()
return
/obj/item/device/dogborg/sleeper/Topic(href, href_list)
if(..() || usr == patient)
return
usr.set_machine(src)
if(href_list["refresh"])
update_patient()
src.updateUsrDialog()
sleeperUI(usr)
return
if(href_list["eject"])
go_out()
sleeperUI(usr)
return
if(href_list["clean"])
if(!cleaning)
var/confirm = alert(usr, "You are about to engage self-cleaning mode. This will fill your [src] with caustic enzymes to remove any objects or biomatter, and convert them into energy. Are you sure?", "Confirmation", "Self-Clean", "Cancel")
if(confirm == "Self-Clean")
if(cleaning)
return
else
cleaning = 1
drain(500)
START_PROCESSING(SSobj, src)
sleeperUI(usr)
if(patient)
to_chat(patient, "<span class='danger'>[hound.name]'s [src.name] fills with caustic enzymes around you!</span>")
return
if(cleaning)
sleeperUI(usr)
return
if(href_list["port"])
switch(eject_port)
if("ingestion")
eject_port = "disposal"
if("disposal")
eject_port = "ingestion"
sleeperUI(usr)
/obj/item/device/dogborg/sleeper/ui_act(action, params)
if(..())
return
if(patient && !(patient.stat & DEAD))
if(href_list["inject"] == "epinephrine" || patient.health > min_health)
inject_chem(usr, href_list["inject"])
else
to_chat(usr, "<span class='notice'>ERROR: Subject is not in stable condition for injections.</span>")
else
to_chat(usr,"<span class='notice'>ERROR: Subject cannot metabolise chemicals.</span>")
src.updateUsrDialog()
sleeperUI(usr) //Needs a callback to boop the page to refresh.
return
/obj/item/device/dogborg/sleeper/proc/inject_chem(mob/user, chem)
if(patient && patient.reagents)
if(chem in injection_chems + "epinephrine")
if(hound.cell.charge < 800) //This is so borgs don't kill themselves with it.
to_chat(hound, "<span class='notice'>You don't have enough power to synthesize fluids.</span>")
switch(action)
if("eject")
go_out()
. = TRUE
if("inject")
var/chem = params["chem"]
if(!patient)
return
else if(patient.reagents.get_reagent_amount(chem) + 10 >= 20) //Preventing people from accidentally killing themselves by trying to inject too many chemicals!
to_chat(hound, "<span class='notice'>Your stomach is currently too full of fluids to secrete more fluids of this kind.</span>")
else if(patient.reagents.get_reagent_amount(chem) + 10 <= 20) //No overdoses for you
patient.reagents.add_reagent(chem, inject_amount)
drain(750) //-750 charge per injection
var/units = round(patient.reagents.get_reagent_amount(chem))
to_chat(hound, "<span class='notice'>Injecting [units] unit\s of [injection_chems[chem]] into occupant.</span>") //If they were immersed, the reagents wouldn't leave with them.
/obj/item/device/dogborg/sleeper/process()
if(cleaning) //We're cleaning, return early after calling this as we don't care about the patient.
src.clean_cycle()
return
if(patient) //We're caring for the patient. Medical emergency! Or endo scene.
update_patient()
if(patient.health < 0)
patient.adjustOxyLoss(-1) //Heal some oxygen damage if they're in critical condition
patient.updatehealth()
patient.AdjustStun(-80)
patient.AdjustKnockdown(-80)
patient.AdjustUnconscious(-80)
src.drain()
if((patient.reagents.get_reagent_amount("epinephrine") < 5) && (patient.health < patient.maxHealth)) //Stop pumping full HP people full of drugs. Don't heal people you're digesting, meanie.
patient.reagents.add_reagent("epinephrine", 5)
return
if(!patient && !cleaning) //We think we're done working.
if(!update_patient()) //One last try to find someone
STOP_PROCESSING(SSobj, src)
return
/obj/item/device/dogborg/sleeper/proc/update_patient()
inject_chem(chem)
. = TRUE
if("cleaning")
testing("cleaning attempted")
if(!contents)
testing("cleaning has no contents")
to_chat(src, "Your [src] is already cleaned.")
return
if(patient)
to_chat(patient, "<span class='danger'>[hound.name]'s [src.name] fills with caustic enzymes around you!</span>")
testing("clean_cycle activated")
to_chat(src, "<span class='danger'>Cleaning process enabled.</span>")
clean_cycle()
. = TRUE
/obj/item/device/dogborg/sleeper/proc/update_gut()
testing("update_gut proc fired")
//Well, we HAD one, what happened to them?
if(patient in contents)
if(patient_laststat != patient.stat)
@@ -661,7 +614,7 @@
//Gurgleborg process
/obj/item/device/dogborg/sleeper/proc/clean_cycle()
testing("clean_cycle activated")
//Sanity? Maybe not required. More like if indigestible person OOC escapes.
for(var/I in items_preserved)
if(!(I in contents))
@@ -669,24 +622,10 @@
var/list/touchable_items = contents - items_preserved
//Belly is entirely empty
if(!length(contents))
to_chat(hound, "<span class='notice'>Your [src.name] is now clean. Ending self-cleaning cycle.</span>")
cleaning = 0
update_patient()
return
//sound effects
for(var/mob/living/M in contents)
if(prob(20))
M.stop_sound_channel(CHANNEL_PRED)
playsound(get_turf(hound),"digest_pred",75,0,-6,0,channel=CHANNEL_PRED)
M.stop_sound_channel(CHANNEL_PRED)
M.playsound_local("digest_prey",60)
//If the timing is right, and there are items to be touched
if(SSmobs.times_fired%6==1 && length(touchable_items))
if(cleaning_cycles)
testing("clean_cycle being used")
cleaning_cycles--
cleaning = TRUE
//Burn all the mobs or add them to the exclusion list
for(var/mob/living/carbon/human/T in (touchable_items))
if((T.status_flags & GODMODE) || !T.digestable)
@@ -694,7 +633,29 @@
else
T.adjustBruteLoss(2)
T.adjustFireLoss(3)
src.update_patient()
update_gut()
addtimer(CALLBACK(src, .proc/clean_cycle), 50)
else
testing("clean_cycle resetted")
cleaning_cycles = initial(cleaning_cycles)
cleaning = FALSE
update_gut()
to_chat(hound, "<span class='notice'>Your [src.name] chimes it ends its self-cleaning cycle.</span>")//Belly is entirely empty
if(!length(contents))
to_chat(hound, "<span class='notice'>Your [src.name] is now clean. Ending self-cleaning cycle.</span>")
cleaning = FALSE
update_gut()
return
//sound effects
for(var/mob/living/M in contents)
if(prob(50))
M.stop_sound_channel(CHANNEL_PRED)
playsound(get_turf(hound),"digest_pred",75,0,-6,0,channel=CHANNEL_PRED)
M.stop_sound_channel(CHANNEL_PRED)
M.playsound_local("digest_prey",60)
//Pick a random item to deal with (if there are any)
var/atom/target = pick(touchable_items)
@@ -704,17 +665,17 @@
var/mob/living/carbon/human/T = target
//Mob is now dead
if(T.stat & DEAD && T.digestable)
if(T.stat == DEAD && T.digestable)
message_admins("[key_name(hound)] has digested [key_name(T)] as a dogborg. ([hound ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[hound.x];Y=[hound.y];Z=[hound.z]'>JMP</a>" : "null"])")
to_chat(hound,"<span class='notice'>You feel your belly slowly churn around [T], breaking them down into a soft slurry to be used as power for your systems.</span>")
to_chat(T,"<span class='notice'>You feel [hound]'s belly slowly churn around your form, breaking you down into a soft slurry to be used as power for [hound]'s systems.</span>")
src.drain(-30000) //Fueeeeellll
src.hound.cell.give(30000) //Fueeeeellll
T.stop_sound_channel(CHANNEL_PRED)
playsound(get_turf(hound),"death_pred",50,0,-6,0,channel=CHANNEL_PRED)
T.stop_sound_channel(CHANNEL_PRED)
T.playsound_local("death_prey",60)
qdel(T)
src.update_patient()
src.update_gut()
//Handle the target being anything but a /mob/living/carbon/human
else
@@ -727,38 +688,40 @@
//If the object is not one to preserve
else
//Special case for PDAs as they are dumb. TODO fix Del on PDAs to be less dumb.
if (istype(T, /obj/item/device/pda))
var/obj/item/device/pda/PDA = T
if (PDA.id)
PDA.id.forceMove(src)
PDA.id = null
qdel(T)
qdel(T)
src.update_gut()
src.hound.cell.give(10)
return
//Special case for IDs to make them digested
//else if (istype(T, /obj/item/card/id))
//var/obj/item/card/id/ID = T
//ID.digest() //Need the digest proc, first.
//Anything not perserved, PDA, or ID
else
//Spill(T) //Needs the spill proc to be added
qdel(T)
src.update_patient()
src.hound.cell.give(30) //10 charge? that was such a practically nonexistent number it hardly gave any purpose for this bit :v *cranks up*
/obj/item/device/dogborg/sleeper/proc/inject_chem(chem)
testing("inject chem triggered, checking power")
if(hound.cell.charge <= 800) //This is so borgs don't kill themselves with it. Remember, 750 charge used every injection.
to_chat(hound, "<span class='notice'>You don't have enough power to synthesize fluids.</span>")
return
testing("Has power, checking for overdose")
if(patient.reagents.get_reagent_amount(chem) + 10 >= 20) //Preventing people from accidentally killing themselves by trying to inject too many chemicals!
to_chat(hound, "<span class='notice'>Your stomach is currently too full of fluids to secrete more fluids of this kind.</span>")
return
testing("isn't overdosing, attempting to add_reagent")
patient.reagents.add_reagent(chem, 10)
testing("add_reagent")
src.hound.cell.use(750) //-750 charge per injection
testing("draining power")
var/units = round(patient.reagents.get_reagent_amount(chem))
to_chat(hound, "<span class='notice'>Injecting [units] unit\s of [chem] into occupant.</span>") //If they were immersed, the reagents wouldn't leave with them.
/obj/item/device/dogborg/sleeper/container_resist()
if(prob(8))
go_out()
/obj/item/device/dogborg/sleeper/medihound //Medihound sleeper
name = "Mobile Sleeper"
desc = "Equipment for medical hound. A mounted sleeper that stabilizes patients and can inject reagents in the borg's reserves."
icon = 'icons/mob/dogborg.dmi'
icon_state = "sleeper"
/obj/item/device/dogborg/sleeper/K9 //The K9 portabrig
name = "Mobile Brig"
desc = "Equipment for a K9 unit. A mounted portable-brig that holds criminals."
icon = 'icons/mob/dogborg.dmi'
icon_state = "sleeperb"
inject_amount = 10
inject_amount = 0
min_health = -100
injection_chems = null //So they don't have all the same chems as the medihound!
@@ -791,7 +754,7 @@
return //If they moved away, you can't eat them.
brigman.forceMove(src)
brigman.reset_perspective(src)
update_patient()
update_gut()
START_PROCESSING(SSobj, src)
user.visible_message("<span class='warning'>[hound.name]'s mobile brig clunks in series as [brigman] slips inside.</span>", "<span class='notice'>Your mobile brig groans lightly as [brigman] slips inside.</span>")
playsound(hound, 'sound/effects/bin_close.ogg', 80, 1) // Really don't need ERP sound effects for robots
@@ -803,9 +766,9 @@
desc = "A mounted garbage compactor unit with fuel processor."
icon = 'icons/mob/dogborg.dmi'
icon_state = "compactor"
inject_amount = 10
inject_amount = 0
min_health = -100
injection_chems = null //So they don't have all the same chems as the medihound!
injection_chems = null
var/max_item_count = 48
/obj/item/storage/attackby(obj/item/device/dogborg/sleeper/compactor, mob/user, proximity) //GIT CIRCUMVENTED YO!
@@ -828,7 +791,7 @@
if(target_obj.type in important_items)
to_chat(user,"<span class='warning'>\The [target] registers an error code to your [src.name]</span>")
return
if(target_obj.w_class > WEIGHT_CLASS_SMALL)
if(target_obj.w_class > WEIGHT_CLASS_NORMAL)
to_chat(user,"<span class='warning'>\The [target] is too large to fit into your [src.name]</span>")
return
user.visible_message("<span class='warning'>[hound.name] is ingesting [target.name] into their [src.name].</span>", "<span class='notice'>You start ingesting [target] into your [src.name]...</span>")
@@ -860,7 +823,7 @@
return //If they moved away, you can't eat them.
trashman.forceMove(src)
trashman.reset_perspective(src)
update_patient()
update_gut()
START_PROCESSING(SSobj, src)
user.visible_message("<span class='warning'>[hound.name]'s garbage processor groans lightly as [trashman] slips inside.</span>", "<span class='notice'>Your garbage compactor groans lightly as [trashman] slips inside.</span>")
playsound(hound, 'sound/effects/bin_close.ogg', 80, 1)
@@ -917,6 +880,7 @@
return
if(cell.charge <= 500)
to_chat(src,"<span class='danger'>Insufficent reserves for jump actuators!</span>")
return
else
@@ -55,6 +55,8 @@ CONFIG_DEF(flag/log_twitter) // log certain expliotable parrots and other such f
CONFIG_DEF(flag/log_world_topic) // log all world.Topic() calls
CONFIG_DEF(flag/log_manifest) // log crew manifest to seperate file
CONFIG_DEF(flag/allow_admin_ooccolor) // Allows admins with relevant permissions to have their own ooc colour
CONFIG_DEF(flag/allow_vote_restart) // allow votes to restart
@@ -199,9 +201,6 @@ CONFIG_DEF(flag/load_jobs_from_txt)
CONFIG_DEF(flag/forbid_singulo_possession)
CONFIG_DEF(flag/useircbot) //tgs2 support
protection = CONFIG_ENTRY_LOCKED
CONFIG_DEF(flag/automute_on) //enables automuting/spam prevention
CONFIG_DEF(string/panic_server_name)
+26 -13
View File
@@ -276,16 +276,29 @@ Delayed insert mode was removed in mysql 7 and only works with MyISAM type table
/datum/DBColumn/proc/SqlTypeName(type_handler = sql_type)
switch(type_handler)
if(TINYINT) return "TINYINT"
if(SMALLINT) return "SMALLINT"
if(MEDIUMINT) return "MEDIUMINT"
if(INTEGER) return "INTEGER"
if(BIGINT) return "BIGINT"
if(FLOAT) return "FLOAT"
if(DOUBLE) return "DOUBLE"
if(DATE) return "DATE"
if(DATETIME) return "DATETIME"
if(TIMESTAMP) return "TIMESTAMP"
if(TIME) return "TIME"
if(STRING) return "STRING"
if(BLOB) return "BLOB"
if(TINYINT)
return "TINYINT"
if(SMALLINT)
return "SMALLINT"
if(MEDIUMINT)
return "MEDIUMINT"
if(INTEGER)
return "INTEGER"
if(BIGINT)
return "BIGINT"
if(FLOAT)
return "FLOAT"
if(DOUBLE)
return "DOUBLE"
if(DATE)
return "DATE"
if(DATETIME)
return "DATETIME"
if(TIMESTAMP)
return "TIMESTAMP"
if(TIME)
return "TIME"
if(STRING)
return "STRING"
if(BLOB)
return "BLOB"
+2 -1
View File
@@ -385,7 +385,8 @@ SUBSYSTEM_DEF(garbage)
find_references(TRUE)
/datum/proc/DoSearchVar(X, Xname)
if(usr && usr.client && !usr.client.running_find_references) return
if(usr && usr.client && !usr.client.running_find_references)
return
if(istype(X, /datum))
var/datum/D = X
if(D.last_find_references == last_find_references)
+34
View File
@@ -0,0 +1,34 @@
SUBSYSTEM_DEF(idlenpcpool)
name = "Idling NPC Pool"
flags = SS_POST_FIRE_TIMING|SS_NO_INIT|SS_BACKGROUND
priority = 10
wait = 60
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
var/list/currentrun = list()
/datum/controller/subsystem/idlenpcpool/stat_entry()
var/list/idlelist = GLOB.simple_animals[AI_IDLE]
..("IdleNPCS:[idlelist.len]")
/datum/controller/subsystem/idlenpcpool/fire(resumed = FALSE)
if (!resumed)
var/list/idlelist = GLOB.simple_animals[AI_IDLE]
src.currentrun = idlelist.Copy()
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
while(currentrun.len)
var/mob/living/simple_animal/SA = currentrun[currentrun.len]
--currentrun.len
if(!SA.ckey)
if(SA.stat != DEAD)
SA.handle_automated_movement()
if(SA.stat != DEAD)
SA.consider_wakeup()
if (MC_TICK_CHECK)
return
+38
View File
@@ -567,3 +567,41 @@ SUBSYSTEM_DEF(job)
var/msg = "Unable to send mob [M] to late join!"
message_admins(msg)
CRASH(msg)
///////////////////////////////////
//Keeps track of all living heads//
///////////////////////////////////
/datum/controller/subsystem/job/proc/get_living_heads()
. = list()
for(var/mob/living/carbon/human/player in GLOB.mob_list)
if(player.stat != DEAD && player.mind && (player.mind.assigned_role in GLOB.command_positions))
. |= player.mind
////////////////////////////
//Keeps track of all heads//
////////////////////////////
/datum/controller/subsystem/job/proc/get_all_heads()
. = list()
for(var/mob/player in GLOB.mob_list)
if(player.mind && (player.mind.assigned_role in GLOB.command_positions))
. |= player.mind
//////////////////////////////////////////////
//Keeps track of all living security members//
//////////////////////////////////////////////
/datum/controller/subsystem/job/proc/get_living_sec()
. = list()
for(var/mob/living/carbon/human/player in GLOB.mob_list)
if(player.stat != DEAD && player.mind && (player.mind.assigned_role in GLOB.security_positions))
. |= player.mind
////////////////////////////////////////
//Keeps track of all security members//
////////////////////////////////////////
/datum/controller/subsystem/job/proc/get_all_sec()
. = list()
for(var/mob/living/carbon/human/player in GLOB.mob_list)
if(player.mind && (player.mind.assigned_role in GLOB.security_positions))
. |= player.mind
+2 -1
View File
@@ -37,7 +37,8 @@ SUBSYSTEM_DEF(npcpool)
// 5. Do all assignments: goes through the delegated/coordianted bots and assigns the right variables/tasks to them.
if (!resumed)
src.currentrun = GLOB.simple_animals.Copy()
var/list/activelist = GLOB.simple_animals[AI_ON]
src.currentrun = activelist.Copy()
stage = PROCESSING_SIMPLES
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
-1
View File
@@ -28,7 +28,6 @@ SUBSYSTEM_DEF(pai)
card.setPersonality(pai)
SSticker.mode.update_cult_icons_removed(card.pai.mind)
SSticker.mode.update_rev_icons_removed(card.pai.mind)
candidates -= candidate
usr << browse(null, "window=findPai")
+2 -2
View File
@@ -59,14 +59,14 @@ SUBSYSTEM_DEF(persistence)
path = text2path(old_secret_satchels[pos]["saved_obj"])
if(F)
if(isfloorturf(F.loc) && !istype(F.loc, /turf/open/floor/plating/))
if(isfloorturf(F.loc) && !isplatingturf(F.loc))
F.hide(1)
if(ispath(path))
new path(F)
placed_satchel++
var/free_satchels = 0
for(var/turf/T in shuffle(block(locate(TRANSITIONEDGE,TRANSITIONEDGE,ZLEVEL_STATION_PRIMARY), locate(world.maxx-TRANSITIONEDGE,world.maxy-TRANSITIONEDGE,ZLEVEL_STATION_PRIMARY)))) //Nontrivially expensive but it's roundstart only
if(isfloorturf(T) && !istype(T, /turf/open/floor/plating/))
if(isfloorturf(T) && !isplatingturf(T))
new /obj/item/storage/backpack/satchel/flat/secret(T)
free_satchels++
if((free_satchels + placed_satchel) == 10) //ten tiles, more than enough to kill anything that moves
@@ -0,0 +1,7 @@
PROCESSING_SUBSYSTEM_DEF(projectiles)
name = "Projectiles"
priority = 25
wait = 1
stat_tag = "PP"
flags = SS_NO_INIT|SS_TICKER|SS_KEEP_TIMING
var/global_max_tick_moves = 10
+2
View File
@@ -12,6 +12,7 @@ SUBSYSTEM_DEF(ticker)
var/force_ending = 0 //Round was ended by admin intervention
// If true, there is no lobby phase, the game starts immediately.
var/start_immediately = FALSE
var/setup_done = FALSE //All game setup done including mode post setup and
var/hide_mode = 0
var/datum/game_mode/mode = null
@@ -331,6 +332,7 @@ SUBSYSTEM_DEF(ticker)
var/list/adm = get_admin_counts()
var/list/allmins = adm["present"]
send2irc("Server", "Round [GLOB.round_id ? "#[GLOB.round_id]:" : "of"] [hide_mode ? "secret":"[mode.name]"] has started[allmins.len ? ".":" with no active admins online!"]")
setup_done = TRUE
/datum/controller/subsystem/ticker/proc/OnRoundstart(datum/callback/cb)
if(!HasRoundStarted())
@@ -1,5 +1,6 @@
/datum/antagonist/abductor
name = "Abductor"
job_rank = ROLE_ABDUCTOR
var/datum/objective_team/abductor_team/team
var/sub_role
var/outfit
@@ -18,9 +19,15 @@
landmark_type = /obj/effect/landmark/abductor/scientist
greet_text = "Use your stealth technology and equipment to incapacitate humans for your scientist to retrieve."
/datum/antagonist/abductor/New(datum/mind/new_owner, datum/objective_team/abductor_team/T)
team = T
return ..()
/datum/antagonist/abductor/create_team(datum/objective_team/abductor_team/new_team)
if(!new_team)
return
if(!istype(new_team))
stack_trace("Wrong team type passed to [type] initialization.")
team = new_team
/datum/antagonist/abductor/get_team()
return team
/datum/antagonist/abductor/on_gain()
SSticker.mode.abductors += owner
@@ -31,7 +38,6 @@
/datum/antagonist/abductor/on_removal()
SSticker.mode.abductors -= owner
team.members -= owner
owner.objectives -= team.objectives
if(owner.current)
to_chat(owner.current,"<span class='userdanger'>You are no longer the [owner.special_role]!</span>")
+42 -2
View File
@@ -7,6 +7,8 @@ GLOBAL_LIST_EMPTY(antagonists)
var/can_coexist_with_others = TRUE //Whether or not the person will be able to have more than one datum
var/list/typecache_datum_blacklist = list() //List of datums this type can't coexist with
var/delete_on_mind_deletion = TRUE
var/job_rank
var/replace_banned = TRUE //Should replace jobbaned player with ghosts if granted.
/datum/antagonist/New(datum/mind/new_owner)
GLOB.antagonists += src
@@ -23,9 +25,10 @@ GLOBAL_LIST_EMPTY(antagonists)
/datum/antagonist/proc/can_be_owned(datum/mind/new_owner)
. = TRUE
if(owner.has_antag_datum(type))
var/datum/mind/tested = new_owner || owner
if(tested.has_antag_datum(type))
return FALSE
for(var/i in owner.antag_datums)
for(var/i in tested.antag_datums)
var/datum/antagonist/A = i
if(is_type_in_typecache(src, A.typecache_datum_blacklist))
return FALSE
@@ -42,12 +45,35 @@ GLOBAL_LIST_EMPTY(antagonists)
/datum/antagonist/proc/remove_innate_effects(mob/living/mob_override)
return
//Assign default team and creates one for one of a kind team antagonists
/datum/antagonist/proc/create_team(datum/objective_team/team)
return
//Proc called when the datum is given to a mind.
/datum/antagonist/proc/on_gain()
if(owner && owner.current)
if(!silent)
greet()
apply_innate_effects()
if(is_banned(owner.current) && replace_banned)
replace_banned_player()
/datum/antagonist/proc/is_banned(mob/M)
if(!M)
return FALSE
. = (jobban_isbanned(M,"Syndicate") || (job_rank && jobban_isbanned(M,job_rank)))
/datum/antagonist/proc/replace_banned_player()
set waitfor = FALSE
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [name]?", "[name]", null, job_rank, 50, owner.current)
var/mob/dead/observer/theghost = null
if(candidates.len)
theghost = pick(candidates)
to_chat(owner, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!")
message_admins("[key_name_admin(theghost)] has taken control of ([key_name_admin(owner.current)]) to replace a jobbaned player.")
owner.current.ghostize(0)
owner.current.key = theghost.key
/datum/antagonist/proc/on_removal()
remove_innate_effects()
@@ -55,6 +81,9 @@ GLOBAL_LIST_EMPTY(antagonists)
LAZYREMOVE(owner.antag_datums, src)
if(!silent && owner.current)
farewell()
var/datum/objective_team/team = get_team()
if(team)
team.remove_member(owner)
qdel(src)
/datum/antagonist/proc/greet()
@@ -62,3 +91,14 @@ GLOBAL_LIST_EMPTY(antagonists)
/datum/antagonist/proc/farewell()
return
//Returns the team antagonist belongs to if any.
/datum/antagonist/proc/get_team()
return
//Should probably be on ticker or job ss ?
/proc/get_antagonists(antag_type,specific = FALSE)
. = list()
for(var/datum/antagonist/A in GLOB.antagonists)
if(!specific && istype(A,antag_type) || specific && A.type == antag_type)
. += A.owner
@@ -1,22 +1,30 @@
/datum/antagonist/brother
name = "Brother"
job_rank = ROLE_BROTHER
var/special_role = "blood brother"
var/datum/objective_team/brother_team/team
/datum/antagonist/brother/New(datum/mind/new_owner, datum/objective_team/brother_team/T)
team = T
/datum/antagonist/brother/New(datum/mind/new_owner)
return ..()
/datum/antagonist/brother/create_team(datum/objective_team/brother_team/new_team)
if(!new_team)
return
if(!istype(new_team))
stack_trace("Wrong team type passed to [type] initialization.")
team = new_team
/datum/antagonist/brother/get_team()
return team
/datum/antagonist/brother/on_gain()
SSticker.mode.brothers += owner
owner.special_role = special_role
owner.objectives += team.objectives
finalize_brother()
return ..()
/datum/antagonist/brother/on_removal()
SSticker.mode.brothers -= owner
team.members -= owner
owner.objectives -= team.objectives
if(owner.current)
to_chat(owner.current,"<span class='userdanger'>You are no longer the [special_role]!</span>")
@@ -1,6 +1,8 @@
//CLOCKCULT PROOF OF CONCEPT
/datum/antagonist/clockcult
name = "Clock Cultist"
var/datum/action/innate/hierophant/hierophant_network = new()
job_rank = ROLE_SERVANT_OF_RATVAR
/datum/antagonist/clockcult/silent
silent = TRUE
@@ -47,8 +49,6 @@
var/mob/living/current = owner.current
SSticker.mode.servants_of_ratvar += owner
SSticker.mode.update_servant_icons_added(owner)
if(jobban_isbanned(current, ROLE_SERVANT_OF_RATVAR))
addtimer(CALLBACK(SSticker.mode, /datum/game_mode.proc/replace_jobbaned_player, current, ROLE_SERVANT_OF_RATVAR, ROLE_SERVANT_OF_RATVAR), 0)
owner.special_role = "Servant of Ratvar"
owner.current.log_message("<font color=#BE8700>Has been converted to the cult of Ratvar!</font>", INDIVIDUAL_ATTACK_LOG)
if(issilicon(current))
@@ -1,8 +1,10 @@
#define SUMMON_POSSIBILITIES 3
/datum/antagonist/cult
name = "Cultist"
var/datum/action/innate/cult/comm/communion = new
var/datum/action/innate/cult/mastervote/vote = new
job_rank = ROLE_CULTIST
/datum/antagonist/cult/Destroy()
QDEL_NULL(communion)
@@ -73,8 +75,6 @@
add_objectives()
SSticker.mode.cult += owner // Only add after they've been given objectives
cult_memorization(owner)
if(jobban_isbanned(current, ROLE_CULTIST))
addtimer(CALLBACK(SSticker.mode, /datum/game_mode.proc/replace_jobbaned_player, current, ROLE_CULTIST, ROLE_CULTIST), 0)
SSticker.mode.update_cult_icons_added(owner)
current.log_message("<font color=#960000>Has been converted to the cult of Nar'Sie!</font>", INDIVIDUAL_ATTACK_LOG)
if(GLOB.blood_target && GLOB.blood_target_image && current.client)
+1
View File
@@ -1,5 +1,6 @@
/datum/antagonist/traitor
name = "Traitor"
job_rank = ROLE_TRAITOR
var/should_specialise = TRUE //do we split into AI and human
var/base_datum_custom = ANTAG_DATUM_TRAITOR_CUSTOM //used for body transfer
var/ai_datum = ANTAG_DATUM_TRAITOR_AI
+2 -1
View File
@@ -85,6 +85,8 @@ GLOBAL_LIST_INIT(devil_title, list("Lord ", "Prelate ", "Count ", "Viscount ", "
GLOBAL_LIST_INIT(devil_syllable, list("hal", "ve", "odr", "neit", "ci", "quon", "mya", "folth", "wren", "geyr", "hil", "niet", "twou", "phi", "coa"))
GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master", ", the Lord of all things", ", Jr."))
/datum/antagonist/devil
name = "Devil"
job_rank = ROLE_DEVIL
//Don't delete upon mind destruction, otherwise soul re-selling will break.
delete_on_mind_deletion = FALSE
var/obligation
@@ -107,7 +109,6 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
/obj/effect/proc_holder/spell/targeted/conjure_item/violin,
/obj/effect/proc_holder/spell/targeted/summon_dancefloor))
var/ascendable = FALSE
name = "Devil"
/datum/antagonist/devil/New()
+1
View File
@@ -1,5 +1,6 @@
/datum/antagonist/ninja
name = "Ninja"
job_rank = ROLE_NINJA
var/helping_station = 0
var/give_objectives = TRUE
+229
View File
@@ -0,0 +1,229 @@
//How often to check for promotion possibility
#define HEAD_UPDATE_PERIOD 300
/datum/antagonist/rev
name = "Revolutionary"
job_rank = ROLE_REV
var/hud_type = "rev"
var/datum/objective_team/revolution/rev_team
/datum/antagonist/rev/can_be_owned(datum/mind/new_owner)
. = ..()
if(new_owner.assigned_role in GLOB.command_positions)
return FALSE
if(new_owner.unconvertable)
return FALSE
/datum/antagonist/rev/apply_innate_effects(mob/living/mob_override)
var/mob/living/M = mob_override || owner.current
update_rev_icons_added(M)
/datum/antagonist/rev/remove_innate_effects(mob/living/mob_override)
var/mob/living/M = mob_override || owner.current
update_rev_icons_removed(M)
/datum/antagonist/rev/proc/equip_rev()
return
/datum/antagonist/rev/New()
. = ..()
/datum/antagonist/rev/on_gain()
. = ..()
create_objectives()
equip_rev()
owner.current.log_message("<font color='red'>Has been converted to the revolution!</font>", INDIVIDUAL_ATTACK_LOG)
/datum/antagonist/rev/on_removal()
remove_objectives()
. = ..()
/datum/antagonist/rev/greet()
to_chat(owner, "<span class='danger'><FONT size = 3> You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill the heads to win the revolution!</FONT></span>")
owner.announce_objectives()
/datum/antagonist/rev/create_team(datum/objective_team/revolution/new_team)
if(!new_team)
//For now only one revolution at a time
for(var/datum/antagonist/rev/head/H in GLOB.antagonists)
if(H.rev_team)
rev_team = H.rev_team
return
rev_team = new /datum/objective_team/revolution
rev_team.update_objectives()
rev_team.update_heads()
return
if(!istype(new_team))
stack_trace("Wrong team type passed to [type] initialization.")
rev_team = new_team
/datum/antagonist/rev/get_team()
return rev_team
/datum/antagonist/rev/proc/create_objectives()
owner.objectives |= rev_team.objectives
/datum/antagonist/rev/proc/remove_objectives()
owner.objectives -= rev_team.objectives
//Bump up to head_rev
/datum/antagonist/rev/proc/promote()
var/old_team = rev_team
var/datum/mind/old_owner = owner
silent = TRUE
owner.remove_antag_datum(/datum/antagonist/rev)
var/datum/antagonist/rev/head/new_revhead = new(old_owner)
new_revhead.silent = TRUE
old_owner.add_antag_datum(new_revhead,old_team)
new_revhead.silent = FALSE
to_chat(old_owner, "<span class='userdanger'>You have proved your devotion to revolution! You are a head revolutionary now!</span>")
/datum/antagonist/rev/head
name = "Head Revolutionary"
hud_type = "rev_head"
var/remove_clumsy = FALSE
var/give_flash = FALSE
var/give_hud = FALSE
/datum/antagonist/rev/proc/update_rev_icons_added(mob/living/M)
var/datum/atom_hud/antag/revhud = GLOB.huds[ANTAG_HUD_REV]
revhud.join_hud(M)
set_antag_hud(M,hud_type)
/datum/antagonist/rev/proc/update_rev_icons_removed(mob/living/M)
var/datum/atom_hud/antag/revhud = GLOB.huds[ANTAG_HUD_REV]
revhud.leave_hud(M)
set_antag_hud(M, null)
/datum/antagonist/rev/proc/can_be_converted(mob/living/candidate)
if(!candidate.mind)
return FALSE
if(!can_be_owned(candidate.mind))
return FALSE
var/mob/living/carbon/C = candidate //Check to see if the potential rev is implanted
if(!istype(C)) //Can't convert simple animals
return FALSE
if(C.isloyal())
return FALSE
return TRUE
/datum/antagonist/rev/proc/add_revolutionary(datum/mind/rev_mind,stun = TRUE)
if(!can_be_converted(rev_mind.current))
return FALSE
if(stun)
if(iscarbon(rev_mind.current))
var/mob/living/carbon/carbon_mob = rev_mind.current
carbon_mob.silent = max(carbon_mob.silent, 5)
carbon_mob.flash_act(1, 1)
rev_mind.current.Stun(100)
rev_mind.add_antag_datum(/datum/antagonist/rev,rev_team)
rev_mind.special_role = "Revolutionary"
return TRUE
/datum/antagonist/rev/head/proc/demote()
var/datum/mind/old_owner = owner
var/old_team = rev_team
silent = TRUE
owner.remove_antag_datum(/datum/antagonist/rev/head)
var/datum/antagonist/rev/new_rev = new /datum/antagonist/rev(old_owner)
new_rev.silent = TRUE
old_owner.add_antag_datum(new_rev,old_team)
new_rev.silent = FALSE
to_chat(old_owner, "<span class='userdanger'>Revolution has been disappointed of your leader traits! You are a regular revolutionary now!</span>")
/datum/antagonist/rev/farewell()
if(ishuman(owner.current))
owner.current.visible_message("[owner.current] looks like they just remembered their real allegiance!", \
"<span class='userdanger'><FONT size = 3>You are no longer a brainwashed revolutionary! Your memory is hazy from the time you were a rebel...the only thing you remember is the name of the one who brainwashed you...</FONT></span>")
else if(issilicon(owner.current))
owner.current.visible_message("The frame beeps contentedly, purging the hostile memory engram from the MMI before initalizing it.", \
"<span class='userdanger'><FONT size = 3>The frame's firmware detects and deletes your neural reprogramming! You remember nothing but the name of the one who flashed you.</FONT></span>")
/datum/antagonist/rev/proc/remove_revolutionary(borged, deconverter)
log_attack("[owner.current] (Key: [key_name(owner.current)]) has been deconverted from the revolution by [deconverter] (Key: [key_name(deconverter)])!")
if(borged)
message_admins("[ADMIN_LOOKUPFLW(owner.current)] has been borged while being a [name]")
owner.special_role = null
if(iscarbon(owner.current))
var/mob/living/carbon/C = owner.current
C.Unconscious(100)
owner.remove_antag_datum(type)
/datum/antagonist/rev/head/remove_revolutionary(borged,deconverter)
if(!borged)
return
. = ..()
/datum/antagonist/rev/head/equip_rev()
var/mob/living/carbon/human/H = owner.current
if(!istype(H))
return
if(remove_clumsy && owner.assigned_role == "Clown")
to_chat(owner, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.")
H.dna.remove_mutation(CLOWNMUT)
if(give_flash)
var/obj/item/device/assembly/flash/T = new(H)
var/list/slots = list (
"backpack" = slot_in_backpack,
"left pocket" = slot_l_store,
"right pocket" = slot_r_store
)
var/where = H.equip_in_one_of_slots(T, slots)
if (!where)
to_chat(H, "The Syndicate were unfortunately unable to get you a flash.")
else
to_chat(H, "The flash in your [where] will help you to persuade the crew to join your cause.")
if(give_hud)
var/obj/item/organ/cyberimp/eyes/hud/security/syndicate/S = new(H)
S.Insert(H, special = FALSE, drop_if_replaced = FALSE)
to_chat(H, "Your eyes have been implanted with a cybernetic security HUD which will help you keep track of who is mindshield-implanted, and therefore unable to be recruited.")
/datum/objective_team/revolution
name = "Revolution"
var/list/objectives = list()
var/max_headrevs = 3
/datum/objective_team/revolution/proc/update_objectives(initial = FALSE)
var/untracked_heads = SSjob.get_all_heads()
for(var/datum/objective/mutiny/O in objectives)
untracked_heads -= O.target
for(var/datum/mind/M in untracked_heads)
var/datum/objective/mutiny/new_target = new()
new_target.team = src
new_target.target = M
new_target.update_explanation_text()
objectives += new_target
for(var/datum/mind/M in members)
M.objectives |= objectives
addtimer(CALLBACK(src,.proc/update_objectives),HEAD_UPDATE_PERIOD,TIMER_UNIQUE)
/datum/objective_team/revolution/proc/head_revolutionaries()
. = list()
for(var/datum/mind/M in members)
if(M.has_antag_datum(/datum/antagonist/rev/head))
. += M
/datum/objective_team/revolution/proc/update_heads()
if(SSticker.HasRoundStarted())
var/list/datum/mind/head_revolutionaries = head_revolutionaries()
var/list/datum/mind/heads = SSjob.get_all_heads()
var/list/sec = SSjob.get_all_sec()
if(head_revolutionaries.len < max_headrevs && head_revolutionaries.len < round(heads.len - ((8 - sec.len) / 3)))
var/list/datum/mind/non_heads = members - head_revolutionaries
var/list/datum/mind/promotable = list()
for(var/datum/mind/khrushchev in non_heads)
if(khrushchev.current && !khrushchev.current.incapacitated() && !khrushchev.current.restrained() && khrushchev.current.client && khrushchev.current.stat != DEAD)
if(ROLE_REV in khrushchev.current.client.prefs.be_special)
promotable += khrushchev
if(promotable.len)
var/datum/mind/new_leader = pick(promotable)
var/datum/antagonist/rev/rev = new_leader.has_antag_datum(/datum/antagonist/rev)
rev.promote()
addtimer(CALLBACK(src,.proc/update_heads),HEAD_UPDATE_PERIOD,TIMER_UNIQUE)
+17 -5
View File
@@ -5,6 +5,7 @@
/datum/antagonist/wizard
name = "Space Wizard"
job_rank = ROLE_WIZARD
var/give_objectives = TRUE
var/strip = TRUE //strip before equipping
var/allow_rename = TRUE
@@ -32,6 +33,16 @@
/datum/antagonist/wizard/proc/unregister()
SSticker.mode.wizards -= src
/datum/antagonist/wizard/create_team(datum/objective_team/wizard/new_team)
if(!new_team)
return
if(!istype(new_team))
stack_trace("Wrong team type passed to [type] initialization.")
wiz_team = new_team
/datum/antagonist/wizard/get_team()
return wiz_team
/datum/objective_team/wizard
name = "wizard team"
@@ -99,6 +110,8 @@
/datum/antagonist/wizard/on_removal()
unregister()
for(var/objective in objectives)
owner.objectives -= objective
owner.RemoveAllSpells() // TODO keep track which spells are wizard spells which innate stuff
return ..()
@@ -144,8 +157,7 @@
/datum/antagonist/wizard/apply_innate_effects(mob/living/mob_override)
var/mob/living/M = mob_override || owner.current
if(wiz_team) //Don't bother with the icon if you're solo wizard
update_wiz_icons_added(M)
update_wiz_icons_added(M, wiz_team ? TRUE : FALSE) //Don't bother showing the icon if you're solo wizard
M.faction |= "wizard"
/datum/antagonist/wizard/remove_innate_effects(mob/living/mob_override)
@@ -166,10 +178,10 @@
owner.announce_objectives()
/datum/antagonist/wizard/apprentice/register()
SSticker.mode.apprentices |= src
SSticker.mode.apprentices |= owner
/datum/antagonist/wizard/apprentice/unregister()
SSticker.mode.apprentices -= src
SSticker.mode.apprentices -= owner
/datum/antagonist/wizard/apprentice/equip_wizard()
. = ..()
@@ -237,7 +249,7 @@
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/turf_teleport/blink(null))
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(null))
/datum/antagonist/wizard/proc/update_wiz_icons_added(mob/living/wiz)
/datum/antagonist/wizard/proc/update_wiz_icons_added(mob/living/wiz,join = TRUE)
var/datum/atom_hud/antag/wizhud = GLOB.huds[ANTAG_HUD_WIZ]
wizhud.join_hud(wiz)
set_antag_hud(wiz, hud_version)
+2 -1
View File
@@ -249,7 +249,8 @@
// Otherwise, the user mob's machine var will be reset directly.
//
/proc/onclose(mob/user, windowid, atom/ref=null)
if(!user.client) return
if(!user.client)
return
var/param = "null"
if(ref)
param = "\ref[ref]"
+2
View File
@@ -77,6 +77,8 @@
/datum/datacore/proc/manifest()
for(var/mob/dead/new_player/N in GLOB.player_list)
if(N.new_character)
log_manifest(N.ckey,N.new_character.mind,N.new_character)
if(ishuman(N.new_character))
manifest_inject(N.new_character, N.client)
CHECK_TICK
+3 -2
View File
@@ -18,10 +18,11 @@
if(!parrot || parrot.loc != affected_mob)
cure()
else if(prob(parrot.speak_chance))
affected_mob.say(pick(parrot.speech_buffer))
if(parrot.speech_buffer.len)
affected_mob.say(pick(parrot.speech_buffer))
/datum/disease/parrot_possession/cure()
if(parrot && parrot.loc == affected_mob)
parrot.forceMove(affected_mob.drop_location())
affected_mob.visible_message("<span class='danger'>[parrot] is violently driven out of [affected_mob]!</span>", "<span class='userdanger'>[parrot] bursts out of your chest!</span>")
..()
..()
+4 -2
View File
@@ -95,8 +95,10 @@ STI KALY - blind
var/list/L = list()
for(var/turf/T in get_area_turfs(thearea.type))
if(T.z != affected_mob.z) continue
if(T.name == "space") continue
if(T.z != affected_mob.z)
continue
if(T.name == "space")
continue
if(!T.density)
var/clear = 1
for(var/obj/O in T)
+1 -1
View File
@@ -50,7 +50,7 @@
for(var/mob/M in GLOB.dead_mob_list)
if(!M.client || isnewplayer(M))
continue
var/T = get_turf(src)
var/T = get_turf(user)
if(M.stat == DEAD && M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTSIGHT) && !(M in viewers(T, null)))
M.show_message(msg)
+10
View File
@@ -1,4 +1,5 @@
#define EXPLOSION_THROW_SPEED 4
#define REEBE_HUGBOX_COEFFICIENT 0.5
GLOBAL_LIST_EMPTY(explosions)
//Against my better judgement, I will return the explosion datum
@@ -60,6 +61,13 @@ GLOBAL_LIST_EMPTY(explosions)
light_impact_range = min(GLOB.MAX_EX_LIGHT_RANGE, light_impact_range)
flash_range = min(GLOB.MAX_EX_FLASH_RANGE, flash_range)
flame_range = min(GLOB.MAX_EX_FLAME_RANGE, flame_range)
if(!ignorecap && epicenter.z == ZLEVEL_CITYOFCOGS)
devastation_range = min(GLOB.MAX_EX_DEVESTATION_RANGE * REEBE_HUGBOX_COEFFICIENT, devastation_range)
heavy_impact_range = min(GLOB.MAX_EX_HEAVY_RANGE * REEBE_HUGBOX_COEFFICIENT, heavy_impact_range)
light_impact_range = min(GLOB.MAX_EX_LIGHT_RANGE * REEBE_HUGBOX_COEFFICIENT, light_impact_range)
flash_range = min(GLOB.MAX_EX_FLASH_RANGE * REEBE_HUGBOX_COEFFICIENT, flash_range)
flame_range = min(GLOB.MAX_EX_FLAME_RANGE * REEBE_HUGBOX_COEFFICIENT, flame_range)
//DO NOT REMOVE THIS STOPLAG, IT BREAKS THINGS
//not sleeping causes us to ex_act() the thing that triggered the explosion
@@ -388,3 +396,5 @@ GLOBAL_LIST_EMPTY(explosions)
// 10 explosion power is a (1, 3, 6) explosion.
// 5 explosion power is a (0, 1, 3) explosion.
// 1 explosion power is a (0, 0, 1) explosion.
#undef REEBE_HUGBOX_COEFFICIENT
+1 -1
View File
@@ -206,7 +206,7 @@
continue
if(extended_safety_checks)
if(istype(F, /turf/open/lava)) //chasms aren't /floor, and so are pre-filtered
if(islava(F)) //chasms aren't /floor, and so are pre-filtered
var/turf/open/lava/L = F
if(!L.is_safe())
continue
@@ -0,0 +1,89 @@
/*
list/atom/output_atoms
mid_sounds (list or soundfile) Since this can be either a list or a single soundfile you can have random sounds. May contain further lists but must contain a soundfile at the end.
mid_length (num) The length to wait between playing mid_sounds
start_sound (soundfile) Played before starting the mid_sounds loop
start_length (num) How long to wait before starting the main loop after playing start_sound
end_sound (soundfile) The sound played after the main loop has concluded
chance (num) Chance per loop to play a mid_sound
volume (num) Sound output volume
muted (bool) Private. Used to stop the sound loop.
max_loops (num) The max amount of loops to run for.
*/
/datum/looping_sound
var/list/atom/output_atoms
var/mid_sounds
var/mid_length
var/start_sound
var/start_length
var/end_sound
var/chance
var/volume
var/muted = TRUE
var/max_loops
/datum/looping_sound/New(list/_output_atoms, start_immediately=FALSE)
if(!mid_sounds)
WARNING("A looping sound datum was created without sounds to play.")
return
if(_output_atoms)
output_atoms = _output_atoms
else
output_atoms = list()
if(start_immediately)
start()
/datum/looping_sound/Destroy()
stop()
output_atoms = null
return ..()
/datum/looping_sound/proc/start()
if(!muted)
return
muted = FALSE
on_start()
/datum/looping_sound/proc/stop()
if(muted)
return
muted = TRUE
/datum/looping_sound/proc/sound_loop(looped=0)
if(muted || (max_loops && looped > max_loops))
on_stop(looped)
return
if(!chance || prob(chance))
play(get_sound(looped))
addtimer(CALLBACK(src, .proc/sound_loop, ++looped), mid_length)
/datum/looping_sound/proc/play(soundfile)
var/list/atoms_cache = output_atoms
for(var/i in 1 to atoms_cache.len)
var/atom/thing = atoms_cache[i]
playsound(thing, soundfile, volume)
/datum/looping_sound/proc/get_sound(looped, _mid_sounds)
if(!_mid_sounds)
. = mid_sounds
else
. = _mid_sounds
while(!isfile(.) && !isnull(.))
. = pickweight(.)
/datum/looping_sound/proc/on_start()
var/start_wait = 0
if(start_sound)
play(start_sound)
start_wait = start_length
addtimer(CALLBACK(src, .proc/sound_loop), start_wait)
/datum/looping_sound/proc/on_stop(looped)
if(end_sound)
play(end_sound)
@@ -0,0 +1,9 @@
/datum/looping_sound/showering
start_sound = 'sound/machines/shower/shower_start.ogg'
start_length = 2
mid_sounds = list('sound/machines/shower/shower_mid1.ogg'=1,'sound/machines/shower/shower_mid2.ogg'=1,'sound/machines/shower/shower_mid3.ogg'=1)
mid_length = 10
end_sound = 'sound/machines/shower/shower_end.ogg'
volume = 25
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+6 -3
View File
@@ -358,9 +358,12 @@
for (var/obj/O in oview(1, A))
if (O.density == 1)
if (O == A) continue
if (O == D) continue
if (O.opacity) continue
if (O == A)
continue
if (O == D)
continue
if (O.opacity)
continue
else
surface = O
ST = get_turf(O)
+47 -80
View File
@@ -147,6 +147,10 @@
qdel(A)
return
LAZYADD(antag_datums, A)
A.create_team(team)
var/datum/objective_team/antag_team = A.get_team()
if(antag_team)
antag_team.add_member(src)
A.on_gain()
return A
@@ -227,15 +231,9 @@
remove_antag_equip()
/datum/mind/proc/remove_rev()
if(src in SSticker.mode.revolutionaries)
SSticker.mode.revolutionaries -= src
SSticker.mode.update_rev_icons_removed(src)
if(src in SSticker.mode.head_revolutionaries)
SSticker.mode.head_revolutionaries -= src
SSticker.mode.update_rev_icons_removed(src)
var/datum/antagonist/rev/rev = has_antag_datum(/datum/antagonist/rev)
remove_antag_datum(rev.type)
special_role = null
remove_objectives()
remove_antag_equip()
/datum/mind/proc/remove_antag_equip()
var/list/Mob_Contents = current.get_contents()
@@ -258,7 +256,6 @@
SSticker.mode.update_changeling_icons_removed(src)
SSticker.mode.update_traitor_icons_removed(src)
SSticker.mode.update_cult_icons_removed(src)
SSticker.mode.update_rev_icons_removed(src)
/datum/mind/proc/equip_traitor(var/employer = "The Syndicate", var/silent = FALSE)
if(!current)
@@ -302,7 +299,8 @@
uplink_loc = R
if (!uplink_loc)
if(!silent) to_chat(traitor_mob, "Unfortunately, [employer] wasn't able to get you an Uplink.")
if(!silent)
to_chat(traitor_mob, "Unfortunately, [employer] wasn't able to get you an Uplink.")
. = 0
else
var/obj/item/device/uplink/U = new(uplink_loc)
@@ -312,19 +310,22 @@
if(uplink_loc == R)
R.traitor_frequency = sanitize_frequency(rand(MIN_FREQ, MAX_FREQ))
if(!silent) to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [R.name]. Simply dial the frequency [format_frequency(R.traitor_frequency)] to unlock its hidden features.")
if(!silent)
to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [R.name]. Simply dial the frequency [format_frequency(R.traitor_frequency)] to unlock its hidden features.")
traitor_mob.mind.store_memory("<B>Radio Frequency:</B> [format_frequency(R.traitor_frequency)] ([R.name]).")
else if(uplink_loc == PDA)
PDA.lock_code = "[rand(100,999)] [pick(GLOB.phonetic_alphabet)]"
if(!silent) to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [PDA.name]. Simply enter the code \"[PDA.lock_code]\" into the ringtone select to unlock its hidden features.")
if(!silent)
to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [PDA.name]. Simply enter the code \"[PDA.lock_code]\" into the ringtone select to unlock its hidden features.")
traitor_mob.mind.store_memory("<B>Uplink Passcode:</B> [PDA.lock_code] ([PDA.name]).")
else if(uplink_loc == P)
P.traitor_unlock_degrees = rand(1, 360)
if(!silent) to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [P.name]. Simply twist the top of the pen [P.traitor_unlock_degrees] from its starting position to unlock its hidden features.")
if(!silent)
to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [P.name]. Simply twist the top of the pen [P.traitor_unlock_degrees] from its starting position to unlock its hidden features.")
traitor_mob.mind.store_memory("<B>Uplink Degrees:</B> [P.traitor_unlock_degrees] ([P.name]).")
//Link a new mobs mind to the creator of said mob. They will join any team they are currently on, and will only switch teams when their creator does.
@@ -333,8 +334,9 @@
if(iscultist(creator))
SSticker.mode.add_cultist(src)
else if(is_revolutionary_in_general(creator))
SSticker.mode.add_revolutionary(src)
else if(is_revolutionary(creator))
var/datum/antagonist/rev/converter = creator.mind.has_antag_datum(/datum/antagonist/rev)
converter.add_revolutionary(src,FALSE)
else if(is_servant_of_ratvar(creator))
add_servant_of_ratvar(current)
@@ -549,9 +551,10 @@
text = "<i><b>[text]</b></i>: "
if (assigned_role in GLOB.command_positions)
text += "<b>HEAD</b> | not mindshielded | employee | headrev | rev"
else if (src in SSticker.mode.head_revolutionaries)
else if (has_antag_datum(/datum/antagonist/rev/head))
var/datum/antagonist/rev/head = has_antag_datum(/datum/antagonist/rev/head)
var/last_healthy_headrev = TRUE
for(var/datum/mind/I in SSticker.mode.head_revolutionaries)
for(var/datum/mind/I in head.rev_team.head_revolutionaries())
if(I == src)
continue
var/mob/M = I.current
@@ -576,7 +579,7 @@
text += "<br>Objectives are empty! <a href='?src=\ref[src];revolution=autoobjectives'>Set to kill all heads</a>."
else if(current.isloyal())
text += "head | <b>MINDSHIELDED</b> | employee | <a href='?src=\ref[src];revolution=headrev'>headrev</a> | rev"
else if (src in SSticker.mode.revolutionaries)
else if (has_antag_datum(/datum/antagonist/rev))
text += "head | not mindshielded | <a href='?src=\ref[src];revolution=clear'>employee</a> | <a href='?src=\ref[src];revolution=headrev'>headrev</a> | <b>REV</b>"
else
text += "head | not mindshielded | <b>EMPLOYEE</b> | <a href='?src=\ref[src];revolution=headrev'>headrev</a> | <a href='?src=\ref[src];revolution=rev'>rev</a>"
@@ -721,8 +724,7 @@
out += sections[i]+"<br>"
if(((src in SSticker.mode.head_revolutionaries) || (src in SSticker.mode.traitors) || (src in SSticker.mode.syndicates)) && ishuman(current))
if(((src in SSticker.mode.traitors) || (src in SSticker.mode.syndicates)) && ishuman(current))
text = "Uplink: <a href='?src=\ref[src];common=uplink'>give</a>"
var/obj/item/device/uplink/U = find_syndicate_uplink()
if(U)
@@ -938,57 +940,41 @@
switch(href_list["revolution"])
if("clear")
remove_rev()
to_chat(current, "<span class='userdanger'>You have been brainwashed! You are no longer a revolutionary!</span>")
message_admins("[key_name_admin(usr)] has de-rev'ed [current].")
log_admin("[key_name(usr)] has de-rev'ed [current].")
if("rev")
if(src in SSticker.mode.head_revolutionaries)
SSticker.mode.head_revolutionaries -= src
SSticker.mode.update_rev_icons_removed(src)
to_chat(current, "<span class='userdanger'>Revolution has been disappointed of your leader traits! You are a regular revolutionary now!</span>")
else if(!(src in SSticker.mode.revolutionaries))
to_chat(current, "<span class='danger'><FONT size = 3> You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill the heads to win the revolution!</FONT></span>")
if(has_antag_datum(/datum/antagonist/rev/head))
var/datum/antagonist/rev/head/head = has_antag_datum(/datum/antagonist/rev/head)
head.demote()
else if(!has_antag_datum(/datum/antagonist/rev))
add_antag_datum(/datum/antagonist/rev)
special_role = "Revolutionary"
message_admins("[key_name_admin(usr)] has rev'ed [current].")
log_admin("[key_name(usr)] has rev'ed [current].")
else
return
SSticker.mode.revolutionaries += src
SSticker.mode.update_rev_icons_added(src)
special_role = "Revolutionary"
message_admins("[key_name_admin(usr)] has rev'ed [current].")
log_admin("[key_name(usr)] has rev'ed [current].")
if("headrev")
if(src in SSticker.mode.revolutionaries)
SSticker.mode.revolutionaries -= src
SSticker.mode.update_rev_icons_removed(src)
to_chat(current, "<span class='userdanger'>You have proved your devotion to revoltion! Yea are a head revolutionary now!</span>")
else if(!(src in SSticker.mode.head_revolutionaries))
if(has_antag_datum(/datum/antagonist/rev))
var/datum/antagonist/rev/rev = has_antag_datum(/datum/antagonist/rev)
rev.promote()
else if(!has_antag_datum(/datum/antagonist/rev/head))
//what about the team here.
var/datum/antagonist/rev/head/new_head = new /datum/antagonist/rev/head(src)
new_head.give_flash = TRUE
new_head.give_hud = TRUE
new_head.remove_clumsy = TRUE
add_antag_datum(new_head)
to_chat(current, "<span class='userdanger'>You are a member of the revolutionaries' leadership now!</span>")
else
return
if (SSticker.mode.head_revolutionaries.len>0)
// copy targets
var/datum/mind/valid_head = locate() in SSticker.mode.head_revolutionaries
if (valid_head)
for (var/datum/objective/mutiny/O in valid_head.objectives)
var/datum/objective/mutiny/rev_obj = new
rev_obj.owner = src
rev_obj.target = O.target
rev_obj.explanation_text = "Assassinate [O.target.name], the [O.target.assigned_role]."
objectives += rev_obj
SSticker.mode.greet_revolutionary(src,0)
SSticker.mode.head_revolutionaries += src
SSticker.mode.update_rev_icons_added(src)
special_role = "Head Revolutionary"
message_admins("[key_name_admin(usr)] has head-rev'ed [current].")
log_admin("[key_name(usr)] has head-rev'ed [current].")
if("autoobjectives")
SSticker.mode.forge_revolutionary_objectives(src)
SSticker.mode.greet_revolutionary(src,0)
to_chat(usr, "<span class='notice'>The objectives for revolution have been generated and shown to [key]</span>")
if("flash")
if (!SSticker.mode.equip_revolutionary(current))
var/datum/antagonist/rev/head/head = has_antag_datum(/datum/antagonist/rev/head)
if(!head.equip_rev())
to_chat(usr, "<span class='danger'>Spawning flash failed!</span>")
if("takeflash")
@@ -1447,31 +1433,12 @@
to_chat(H, "Spawning an amulet from your Master failed.")
/datum/mind/proc/make_Rev()
if (SSticker.mode.head_revolutionaries.len>0)
// copy targets
var/datum/mind/valid_head = locate() in SSticker.mode.head_revolutionaries
if (valid_head)
for (var/datum/objective/mutiny/O in valid_head.objectives)
var/datum/objective/mutiny/rev_obj = new
rev_obj.owner = src
rev_obj.target = O.target
rev_obj.explanation_text = "Assassinate [O.target.current.real_name], the [O.target.assigned_role]."
objectives += rev_obj
SSticker.mode.greet_revolutionary(src,0)
SSticker.mode.head_revolutionaries += src
SSticker.mode.update_rev_icons_added(src)
var/datum/antagonist/rev/head/head = new(src)
head.give_flash = TRUE
head.give_hud = TRUE
add_antag_datum(head)
special_role = "Head Revolutionary"
SSticker.mode.forge_revolutionary_objectives(src)
SSticker.mode.greet_revolutionary(src,0)
var/list/L = current.get_contents()
var/obj/item/device/assembly/flash/flash = locate() in L
qdel(flash)
take_uplink()
var/fail = 0
fail |= !SSticker.mode.equip_revolutionary(current)
/datum/mind/proc/AddSpell(obj/effect/proc_holder/spell/S)
spell_list += S
S.action.Grant(current)
+2 -2
View File
@@ -645,9 +645,9 @@ GLOBAL_LIST_EMPTY(mutations_list)
/datum/mutation/human/laser_eyes/get_visual_indicator(mob/living/carbon/human/owner)
return visual_indicators[1]
/datum/mutation/human/laser_eyes/on_ranged_attack(mob/living/carbon/human/owner, atom/target)
/datum/mutation/human/laser_eyes/on_ranged_attack(mob/living/carbon/human/owner, atom/target, mouseparams)
if(owner.a_intent == INTENT_HARM)
owner.LaserEyes(target)
owner.LaserEyes(target, mouseparams)
/mob/living/carbon/proc/update_mutations_overlay()
+1 -1
View File
@@ -89,7 +89,7 @@
continue
thing.rad_act(strength)
var/static/list/blacklisted = typecacheof(list(/turf, /obj/structure/cable, /obj/machinery/atmospherics))
var/static/list/blacklisted = typecacheof(list(/turf, /mob, /obj/structure/cable, /obj/machinery/atmospherics))
if(!can_contaminate || blacklisted[thing.type])
continue
if(prob((strength-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_CHANCE_COEFFICIENT * min(1/(steps*range_modifier), 1))) // Only stronk rads get to have little baby rads
+1 -1
View File
@@ -261,7 +261,7 @@
var/turf/next = get_step(ridden, direction)
var/turf/current = get_turf(ridden)
if(istype(next, /turf/open/lava) || istype(current, /turf/open/lava)) //We can move from land to lava, or lava to land, but not from land to land
if(islava(next) || islava(current)) //We can move from land to lava, or lava to land, but not from land to land
..()
else
to_chat(user, "Boats don't go on land!")
+7
View File
@@ -255,3 +255,10 @@
suffix = "gondolaasteroid.dmm"
name = "Gondoland"
description = "Just an ordinary rock- wait, what's that thing?"
/datum/map_template/ruin/space/whiteshipruin_box
id = "whiteshipruin_box"
suffix = "whiteshipruin_box.dmm"
name = "NT Medical Ship"
description = "An ancient ship, said to be among the first discovered derelicts near Space Station 13 that was still in working order. \
Aged and deprecated by time, this relic of a vessel is now broken beyond repair."
+1 -5
View File
@@ -433,11 +433,7 @@
playsound(spawn_turf, 'sound/effects/curse2.ogg', 80, 1, -1)
var/turf/ownerloc = get_turf(owner)
var/obj/item/projectile/curse_hand/C = new (spawn_turf)
C.current = spawn_turf
C.starting = spawn_turf
C.yo = ownerloc.y - spawn_turf.y
C.xo = ownerloc.x - spawn_turf.x
C.original = owner
C.preparePixelProjectile(ownerloc, spawn_turf)
C.fire()
/obj/effect/temp_visual/curse
+159 -158
View File
@@ -1,158 +1,159 @@
/datum/wires/airlock
holder_type = /obj/machinery/door/airlock
proper_name = "Airlock"
/datum/wires/airlock/secure
randomize = TRUE
/datum/wires/airlock/New(atom/holder)
wires = list(
WIRE_POWER1, WIRE_POWER2,
WIRE_BACKUP1, WIRE_BACKUP2,
WIRE_OPEN, WIRE_BOLTS, WIRE_IDSCAN, WIRE_AI,
WIRE_SHOCK, WIRE_SAFETY, WIRE_TIMING, WIRE_LIGHT,
WIRE_ZAP1, WIRE_ZAP2
)
add_duds(2)
..()
/datum/wires/airlock/interactable(mob/user)
var/obj/machinery/door/airlock/A = holder
if(!issilicon(user) && A.isElectrified() && A.shock(user, 100))
return FALSE
if(A.panel_open)
return TRUE
/datum/wires/airlock/get_status()
var/obj/machinery/door/airlock/A = holder
var/list/status = list()
status += "The door bolts [A.locked ? "have fallen!" : "look up."]"
status += "The test light is [A.hasPower() ? "on" : "off"]."
status += "The AI connection light is [A.aiControlDisabled || A.emagged ? "off" : "on"]."
status += "The check wiring light is [A.safe ? "off" : "on"]."
status += "The timer is powered [A.autoclose ? "on" : "off"]."
status += "The speed light is [A.normalspeed ? "on" : "off"]."
status += "The emergency light is [A.emergency ? "on" : "off"]."
return status
/datum/wires/airlock/on_pulse(wire)
set waitfor = FALSE
var/obj/machinery/door/airlock/A = holder
switch(wire)
if(WIRE_POWER1, WIRE_POWER2) // Pulse to loose power.
A.loseMainPower()
if(WIRE_BACKUP1, WIRE_BACKUP2) // Pulse to loose backup power.
A.loseBackupPower()
if(WIRE_OPEN) // Pulse to open door (only works not emagged and ID wire is cut or no access is required).
if(A.emagged)
return
if(!A.requiresID() || A.check_access(null))
if(A.density)
A.open()
else
A.close()
if(WIRE_BOLTS) // Pulse to toggle bolts (but only raise if power is on).
if(!A.locked)
A.bolt()
A.audible_message("<span class='italics'>You hear a click from the bottom of the door.</span>", null, 1)
else
if(A.hasPower())
A.unbolt()
A.audible_message("<span class='italics'>You hear a click from the bottom of the door.</span>", null, 1)
A.update_icon()
if(WIRE_IDSCAN) // Pulse to disable emergency access and flash red lights.
if(A.hasPower() && A.density)
A.do_animate("deny")
if(A.emergency)
A.emergency = FALSE
A.update_icon()
if(WIRE_AI) // Pulse to disable WIRE_AI control for 10 ticks (follows same rules as cutting).
if(A.aiControlDisabled == 0)
A.aiControlDisabled = 1
else if(A.aiControlDisabled == -1)
A.aiControlDisabled = 2
sleep(10)
if(A)
if(A.aiControlDisabled == 1)
A.aiControlDisabled = 0
else if(A.aiControlDisabled == 2)
A.aiControlDisabled = -1
if(WIRE_SHOCK) // Pulse to shock the door for 10 ticks.
if(!A.secondsElectrified)
A.set_electrified(30)
if(usr)
A.shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])")
add_logs(usr, A, "electrified")
sleep(10)
if(A)
while (A.secondsElectrified > 0)
A.secondsElectrified -= 1
if(A.secondsElectrified < 0)
A.set_electrified(0)
sleep(10)
if(WIRE_SAFETY)
A.safe = !A.safe
if(!A.density)
A.close()
if(WIRE_TIMING)
A.normalspeed = !A.normalspeed
if(WIRE_LIGHT)
A.lights = !A.lights
A.update_icon()
/datum/wires/airlock/on_cut(wire, mend)
var/obj/machinery/door/airlock/A = holder
switch(wire)
if(WIRE_POWER1, WIRE_POWER2) // Cut to loose power, repair all to gain power.
if(mend && !is_cut(WIRE_POWER1) && !is_cut(WIRE_POWER2))
A.regainMainPower()
if(usr)
A.shock(usr, 50)
else
A.loseMainPower()
if(usr)
A.shock(usr, 50)
if(WIRE_BACKUP1, WIRE_BACKUP2) // Cut to loose backup power, repair all to gain backup power.
if(mend && !is_cut(WIRE_BACKUP1) && !is_cut(WIRE_BACKUP2))
A.regainBackupPower()
if(usr)
A.shock(usr, 50)
else
A.loseBackupPower()
if(usr)
A.shock(usr, 50)
if(WIRE_BOLTS) // Cut to drop bolts, mend does nothing.
if(!mend)
A.bolt()
if(WIRE_AI) // Cut to disable WIRE_AI control, mend to re-enable.
if(mend)
if(A.aiControlDisabled == 1) // 0 = normal, 1 = locked out, 2 = overridden by WIRE_AI, -1 = previously overridden by WIRE_AI
A.aiControlDisabled = 0
else if(A.aiControlDisabled == 2)
A.aiControlDisabled = -1
else
if(A.aiControlDisabled == 0)
A.aiControlDisabled = 1
else if(A.aiControlDisabled == -1)
A.aiControlDisabled = 2
if(WIRE_SHOCK) // Cut to shock the door, mend to unshock.
if(mend)
if(A.secondsElectrified)
A.set_electrified(0)
else
if(A.secondsElectrified != -1)
A.set_electrified(-1)
if(usr)
A.shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])")
add_logs(usr, A, "electrified")
if(WIRE_SAFETY) // Cut to disable safeties, mend to re-enable.
A.safe = mend
if(WIRE_TIMING) // Cut to disable auto-close, mend to re-enable.
A.autoclose = mend
if(A.autoclose && !A.density)
A.close()
if(WIRE_LIGHT) // Cut to disable lights, mend to re-enable.
A.lights = mend
A.update_icon()
if(WIRE_ZAP1, WIRE_ZAP2) // Ouch.
A.shock(usr, 50)
/datum/wires/airlock
holder_type = /obj/machinery/door/airlock
proper_name = "Airlock"
/datum/wires/airlock/secure
randomize = TRUE
/datum/wires/airlock/New(atom/holder)
wires = list(
WIRE_POWER1, WIRE_POWER2,
WIRE_BACKUP1, WIRE_BACKUP2,
WIRE_OPEN, WIRE_BOLTS, WIRE_IDSCAN, WIRE_AI,
WIRE_SHOCK, WIRE_SAFETY, WIRE_TIMING, WIRE_LIGHT,
WIRE_ZAP1, WIRE_ZAP2
)
add_duds(2)
..()
/datum/wires/airlock/interactable(mob/user)
var/obj/machinery/door/airlock/A = holder
if(!issilicon(user) && A.isElectrified() && A.shock(user, 100))
return FALSE
if(A.panel_open)
return TRUE
/datum/wires/airlock/get_status()
var/obj/machinery/door/airlock/A = holder
var/list/status = list()
status += "The door bolts [A.locked ? "have fallen!" : "look up."]"
status += "The test light is [A.hasPower() ? "on" : "off"]."
status += "The AI connection light is [A.aiControlDisabled || A.emagged ? "off" : "on"]."
status += "The check wiring light is [A.safe ? "off" : "on"]."
status += "The timer is powered [A.autoclose ? "on" : "off"]."
status += "The speed light is [A.normalspeed ? "on" : "off"]."
status += "The emergency light is [A.emergency ? "on" : "off"]."
return status
/datum/wires/airlock/on_pulse(wire)
set waitfor = FALSE
var/obj/machinery/door/airlock/A = holder
switch(wire)
if(WIRE_POWER1, WIRE_POWER2) // Pulse to loose power.
A.loseMainPower()
if(WIRE_BACKUP1, WIRE_BACKUP2) // Pulse to loose backup power.
A.loseBackupPower()
if(WIRE_OPEN) // Pulse to open door (only works not emagged and ID wire is cut or no access is required).
if(A.emagged)
return
if(!A.requiresID() || A.check_access(null))
if(A.density)
A.open()
else
A.close()
if(WIRE_BOLTS) // Pulse to toggle bolts (but only raise if power is on).
if(!A.locked)
A.bolt()
A.audible_message("<span class='italics'>You hear a click from the bottom of the door.</span>", null, 1)
else
if(A.hasPower())
A.unbolt()
A.audible_message("<span class='italics'>You hear a click from the bottom of the door.</span>", null, 1)
A.update_icon()
if(WIRE_IDSCAN) // Pulse to disable emergency access and flash red lights.
if(A.hasPower() && A.density)
A.do_animate("deny")
if(A.emergency)
A.emergency = FALSE
A.update_icon()
if(WIRE_AI) // Pulse to disable WIRE_AI control for 10 ticks (follows same rules as cutting).
if(A.aiControlDisabled == 0)
A.aiControlDisabled = 1
else if(A.aiControlDisabled == -1)
A.aiControlDisabled = 2
sleep(10)
if(A)
if(A.aiControlDisabled == 1)
A.aiControlDisabled = 0
else if(A.aiControlDisabled == 2)
A.aiControlDisabled = -1
if(WIRE_SHOCK) // Pulse to shock the door for 10 ticks.
if(!A.secondsElectrified)
A.set_electrified(30)
if(usr)
A.shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])")
add_logs(usr, A, "electrified")
sleep(10)
if(A)
while (A.secondsElectrified > 0)
A.secondsElectrified -= 1
if(A.secondsElectrified < 0)
A.set_electrified(0)
sleep(10)
if(WIRE_SAFETY)
A.safe = !A.safe
if(!A.density)
A.close()
if(WIRE_TIMING)
A.normalspeed = !A.normalspeed
if(WIRE_LIGHT)
A.lights = !A.lights
A.update_icon()
/datum/wires/airlock/on_cut(wire, mend)
var/obj/machinery/door/airlock/A = holder
switch(wire)
if(WIRE_POWER1, WIRE_POWER2) // Cut to loose power, repair all to gain power.
if(mend && !is_cut(WIRE_POWER1) && !is_cut(WIRE_POWER2))
A.regainMainPower()
if(usr)
A.shock(usr, 50)
else
A.loseMainPower()
if(usr)
A.shock(usr, 50)
if(WIRE_BACKUP1, WIRE_BACKUP2) // Cut to loose backup power, repair all to gain backup power.
if(mend && !is_cut(WIRE_BACKUP1) && !is_cut(WIRE_BACKUP2))
A.regainBackupPower()
if(usr)
A.shock(usr, 50)
else
A.loseBackupPower()
if(usr)
A.shock(usr, 50)
if(WIRE_BOLTS) // Cut to drop bolts, mend does nothing.
if(!mend)
A.bolt()
if(WIRE_AI) // Cut to disable WIRE_AI control, mend to re-enable.
if(mend)
if(A.aiControlDisabled == 1) // 0 = normal, 1 = locked out, 2 = overridden by WIRE_AI, -1 = previously overridden by WIRE_AI
A.aiControlDisabled = 0
else if(A.aiControlDisabled == 2)
A.aiControlDisabled = -1
else
if(A.aiControlDisabled == 0)
A.aiControlDisabled = 1
else if(A.aiControlDisabled == -1)
A.aiControlDisabled = 2
if(WIRE_SHOCK) // Cut to shock the door, mend to unshock.
if(mend)
if(A.secondsElectrified)
A.set_electrified(0)
else
if(A.secondsElectrified != -1)
A.set_electrified(-1)
if(usr)
A.shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])")
add_logs(usr, A, "electrified")
if(WIRE_SAFETY) // Cut to disable safeties, mend to re-enable.
A.safe = mend
if(WIRE_TIMING) // Cut to disable auto-close, mend to re-enable.
A.autoclose = mend
if(A.autoclose && !A.density)
A.close()
if(WIRE_LIGHT) // Cut to disable lights, mend to re-enable.
A.lights = mend
A.update_icon()
if(WIRE_ZAP1, WIRE_ZAP2) // Ouch.
if(usr)
A.shock(usr, 50)
+2 -1
View File
@@ -89,7 +89,8 @@ GLOBAL_LIST_EMPTY(teleportlocs)
// want to find machines, mobs, etc, in the same logical area, you will need to check all the
// related areas. This returns a master contents list to assist in that.
/proc/area_contents(area/A)
if(!istype(A)) return null
if(!istype(A))
return null
var/list/contents = list()
for(var/area/LSA in A.related)
contents += LSA.contents
+9 -1
View File
@@ -426,4 +426,12 @@
/area/ruin/space/old_ai_sat/bridge
name = "Bridge"
icon_state = "bridge"
icon_state = "bridge"
//ABANDONED BOX WHITESHIP
/area/ruin/space/has_grav/whiteship/box
name = "Abandoned Ship"
icon_state = "red"
+2 -1
View File
@@ -451,7 +451,8 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
return 1
/atom/proc/get_global_map_pos()
if(!islist(GLOB.global_map) || isemptylist(GLOB.global_map)) return
if(!islist(GLOB.global_map) || isemptylist(GLOB.global_map))
return
var/cur_x = null
var/cur_y = null
var/list/y_arr = null
+2 -1
View File
@@ -61,7 +61,8 @@
return ..()
/atom/movable/Move(atom/newloc, direct = 0)
if(!loc || !newloc) return 0
if(!loc || !newloc)
return 0
var/atom/oldloc = loc
if(loc != newloc)
+14 -7
View File
@@ -8,10 +8,12 @@
/* DATA HUD DATUMS */
/atom/proc/add_to_all_human_data_huds()
for(var/datum/atom_hud/data/human/hud in GLOB.huds) hud.add_to_hud(src)
for(var/datum/atom_hud/data/human/hud in GLOB.huds)
hud.add_to_hud(src)
/atom/proc/remove_from_all_data_huds()
for(var/datum/atom_hud/data/hud in GLOB.huds) hud.remove_from_hud(src)
for(var/datum/atom_hud/data/hud in GLOB.huds)
hud.remove_from_hud(src)
/datum/atom_hud/data
@@ -21,10 +23,13 @@
/datum/atom_hud/data/human/medical/basic
/datum/atom_hud/data/human/medical/basic/proc/check_sensors(mob/living/carbon/human/H)
if(!istype(H)) return 0
if(!istype(H))
return 0
var/obj/item/clothing/under/U = H.w_uniform
if(!istype(U)) return 0
if(U.sensor_mode <= SENSOR_VITALS) return 0
if(!istype(U))
return 0
if(U.sensor_mode <= SENSOR_VITALS)
return 0
return 1
/datum/atom_hud/data/human/medical/basic/add_to_single_hud(mob/M, mob/living/carbon/H)
@@ -128,7 +133,8 @@
B.update_suit_sensors(src)
var/turf/T = get_turf(src)
if (T) GLOB.crewmonitor.queueUpdate(T.z)
if (T)
GLOB.crewmonitor.queueUpdate(T.z)
//called when a living mob changes health
/mob/living/proc/med_hud_set_health()
@@ -200,7 +206,8 @@
sec_hud_set_security_status()
var/turf/T = get_turf(src)
if (T) GLOB.crewmonitor.queueUpdate(T.z)
if (T)
GLOB.crewmonitor.queueUpdate(T.z)
/mob/living/carbon/human/proc/sec_hud_set_implants()
var/image/holder
+12 -7
View File
@@ -67,20 +67,25 @@
else
to_chat(H, "Unable to reach your apprentice! You can either attack the spellbook with the contract to refund your points, or wait and try again later.")
/obj/item/antag_spawner/contract/spawn_antag(client/C, turf/T, school,datum/mind/wizard)
/obj/item/antag_spawner/contract/spawn_antag(client/C, turf/T, school,datum/mind/user)
new /obj/effect/particle_effect/smoke(T)
var/mob/living/carbon/human/M = new/mob/living/carbon/human(T)
C.prefs.copy_to(M)
M.key = C.key
var/datum/mind/app_mind = M.mind
var/datum/antagonist/wizard/master_antag = wizard.has_antag_datum(/datum/antagonist/wizard)
if(!master_antag.wiz_team)
master_antag.create_wiz_team()
var/datum/antagonist/wizard/apprentice/app = new(app_mind)
app.wiz_team = master_antag.wiz_team
app.master = wizard
app.master = user
app.school = school
master_antag.wiz_team.members += app_mind
var/datum/antagonist/wizard/master_wizard = user.has_antag_datum(/datum/antagonist/wizard)
if(master_wizard)
if(!master_wizard.wiz_team)
master_wizard.create_wiz_team()
app.wiz_team = master_wizard.wiz_team
master_wizard.wiz_team.add_member(app_mind)
app_mind.add_antag_datum(app)
//TODO Kill these if possible
app_mind.assigned_role = "Apprentice"
+1 -1
View File
@@ -79,7 +79,7 @@
var/datum/mind/bro = pick(possible_brothers)
possible_brothers -= bro
antag_candidates -= bro
team.members += bro
team.add_member(bro)
bro.restricted_roles = restricted_jobs
log_game("[bro.key] (ckey) has been selected as a Brother")
pre_brother_teams += team
+2 -1
View File
@@ -68,7 +68,8 @@ GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "w
if(antag_candidates.len>0)
for(var/i = 0, i < num_changelings, i++)
if(!antag_candidates.len) break
if(!antag_candidates.len)
break
var/datum/mind/changeling = pick(antag_candidates)
antag_candidates -= changeling
changelings += changeling
@@ -54,17 +54,20 @@
/obj/effect/proc_holder/changeling/biodegrade/proc/dissolve_handcuffs(mob/living/carbon/human/user, obj/O)
if(O && user.handcuffed == O)
visible_message("<span class='warning'>[O] dissolves into a puddle of sizzling goop.</span>")
user.visible_message("<span class='warning'>[O] dissolve[O.gender==PLURAL?"":"s"] into a puddle of sizzling goop.</span>")
new /obj/effect/decal/cleanable/greenglow(O.drop_location())
qdel(O)
/obj/effect/proc_holder/changeling/biodegrade/proc/dissolve_straightjacket(mob/living/carbon/human/user, obj/S)
if(S && user.wear_suit == S)
visible_message("<span class='warning'>[S] dissolves into a puddle of sizzling goop.</span>")
user.visible_message("<span class='warning'>[S] dissolves into a puddle of sizzling goop.</span>")
new /obj/effect/decal/cleanable/greenglow(S.drop_location())
qdel(S)
/obj/effect/proc_holder/changeling/biodegrade/proc/open_closet(mob/living/carbon/human/user, obj/structure/closet/C)
if(C && user.loc == C)
C.visible_message("<span class='warning'>[C]'s door breaks and opens!</span>")
new /obj/effect/decal/cleanable/greenglow(C.drop_location())
C.welded = FALSE
C.locked = FALSE
C.broken = TRUE
@@ -73,5 +76,6 @@
/obj/effect/proc_holder/changeling/biodegrade/proc/dissolve_cocoon(mob/living/carbon/human/user, obj/structure/spider/cocoon/C)
if(C && user.loc == C)
new /obj/effect/decal/cleanable/greenglow(C.drop_location())
qdel(C) //The cocoon's destroy will move the changeling outside of it without interference
to_chat(user, "<span class='warning'>We dissolve the cocoon!</span>")
@@ -1,6 +1,6 @@
/obj/effect/proc_holder/changeling/linglink
name = "Hivemind Link"
desc = "Link your victim's mind into the hivemind for personal interrogation"
desc = "Link your victim's mind into the hivemind for personal interrogation."
chemical_cost = 0
dna_cost = 0
req_human = 1
@@ -257,7 +257,7 @@
/obj/item/ammo_casing/magic/tentacle
name = "tentacle"
desc = "a tentacle."
desc = "A tentacle."
projectile_type = /obj/item/projectile/tentacle
caliber = "tentacle"
icon_state = "tentacle_end"
@@ -1,6 +1,6 @@
/obj/effect/proc_holder/changeling/resonant_shriek
name = "Resonant Shriek"
desc = "Our lungs and vocal chords shift, allowing us to briefly emit a noise that deafens and confuses the weak-minded."
desc = "Our lungs and vocal cords shift, allowing us to briefly emit a noise that deafens and confuses the weak-minded."
helptext = "Emits a high-frequency sound that confuses and deafens humans, blows out nearby lights and overloads cyborg sensors."
chemical_cost = 20
dna_cost = 1
@@ -1,6 +1,6 @@
/obj/effect/proc_holder/changeling/sting
name = "Tiny Prick"
desc = "Stabby stabby"
desc = "Stabby stabby."
var/sting_icon = null
/obj/effect/proc_holder/changeling/sting/Click()
@@ -43,7 +43,8 @@
if(possible_changelings.len>0)
for(var/j = 0, j < num_changelings, j++)
if(!possible_changelings.len) break
if(!possible_changelings.len)
break
var/datum/mind/changeling = pick(possible_changelings)
antag_candidates -= changeling
possible_changelings -= changeling
@@ -38,7 +38,7 @@
beckon(AM)
/obj/effect/clockwork/city_of_cogs_rift/proc/beckon(atom/movable/AM)
AM.visible_message("<span class='danger'>[AM] passes through [src]!</span>", ignore_mob = AM)
AM.visible_message("<span class='danger'>[AM] passes through [src]!</span>", ignored_mob = AM)
AM.forceMove(pick(!is_servant_of_ratvar(AM) ? GLOB.city_of_cogs_spawns : GLOB.servant_spawns))
AM.visible_message("<span class='danger'>[AM] materializes from the air!</span>", \
"<span class='boldannounce'>You pass through [src] and appear [is_servant_of_ratvar(AM) ? "back at the City of Cogs" : "somewhere unfamiliar. Looks like it was a one-way trip.."].</span>")
@@ -48,3 +48,6 @@
var/mob/living/L = AM
L.overlay_fullscreen("flash", /obj/screen/fullscreen/flash/static)
L.clear_fullscreen("flash", 5)
var/obj/item/device/transfer_valve/TTV = locate() in L.GetAllContents()
if(TTV)
to_chat(L, "<span class='userdanger'>The air resonates with the Ark's presence; your explosives will be significantly dampened here!</span>")
@@ -156,11 +156,7 @@
add_logs(ranged_ability_user, U, "fired at with Kindle")
playsound(ranged_ability_user, 'sound/magic/blink.ogg', 50, TRUE, frequency = 0.5)
var/obj/item/projectile/kindle/A = new(T)
A.original = target
A.starting = T
A.current = T
A.yo = U.y - T.y
A.xo = U.x - T.x
A.preparePixelProjectile(target, caller, params)
A.fire()
remove_ranged_ability()
@@ -398,15 +398,15 @@
switch(selected_scripture) //display info based on selected scripture tier
if(SCRIPTURE_DRIVER)
data["tier_info"] = "<font color=#B18B25><b>These scriptures are permenantly unlocked.</b></font>"
data["tier_info"] = "<font color=#B18B25><b>These scriptures are permanently unlocked.</b></font>"
if(SCRIPTURE_SCRIPT)
if(SSticker.scripture_states[SCRIPTURE_SCRIPT])
data["tier_info"] = "<font color=#B18B25><b>These scriptures are permenantly unlocked.</b></font>"
data["tier_info"] = "<font color=#B18B25><b>These scriptures are permanently unlocked.</b></font>"
else
data["tier_info"] = "<font color=#B18B25><i>These scriptures will automatically unlock when the Ark is halfway ready or if [DisplayPower(SCRIPT_UNLOCK_THRESHOLD)] of power is reached.</i></font>"
if(SCRIPTURE_APPLICATION)
if(SSticker.scripture_states[SCRIPTURE_APPLICATION])
data["tier_info"] = "<font color=#B18B25><b>These scriptures are permenantly unlocked.</b></font>"
data["tier_info"] = "<font color=#B18B25><b>These scriptures are permanently unlocked.</b></font>"
else
data["tier_info"] = "<font color=#B18B25><i>Unlock these optional scriptures by converting another servant or if [DisplayPower(APPLICATION_UNLOCK_THRESHOLD)] of power is reached..</i></font>"
@@ -116,9 +116,9 @@
continue
if(ishostile(L))
var/mob/living/simple_animal/hostile/H = L
if(ismegafauna(H) || (!H.mind && H.AIStatus == AI_OFF))
if(("ratvar" in H.faction) || (!H.mind && "neutral" in H.faction))
continue
if(("ratvar" in H.faction) || ("neutral" in H.faction))
if(ismegafauna(H) || (!H.mind && H.AIStatus == AI_OFF))
continue
else if(isrevenant(L))
var/mob/living/simple_animal/revenant/R = L
@@ -127,10 +127,15 @@
else if(!L.mind)
continue
. += L
var/list/viewcache = list()
for(var/N in GLOB.mechas_list)
var/obj/mecha/M = N
if(get_dist(M, src) <= sight_range && M.occupant && !is_servant_of_ratvar(M.occupant) && (M in view(sight_range, src)))
. += M
if(get_dist(M, src) <= sight_range && M.occupant && !is_servant_of_ratvar(M.occupant))
if(!length(viewcache))
for (var/obj/Z in view(sight_range, src))
viewcache += Z
if (M in viewcache)
. += M
/obj/structure/destructible/clockwork/ocular_warden/proc/lose_target()
if(!target)
+1 -1
View File
@@ -302,7 +302,7 @@
/obj/item/clothing/suit/magusred
name = "magus robes"
desc = "A set of armored robes worn by the followers of Nar-Sie"
desc = "A set of armored robes worn by the followers of Nar-Sie."
icon_state = "magusred"
item_state = "magusred"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
+4 -2
View File
@@ -25,7 +25,8 @@
if(!(AT.z in GLOB.station_z_levels)) //Only check one, it's enough.
skip = 1
break
if(skip) continue
if(skip)
continue
A.power_light = FALSE
A.power_equip = FALSE
A.power_environ = FALSE
@@ -40,7 +41,8 @@
if(istype(A,area_type))
skip = 1
break
if(skip) continue
if(skip)
continue
C.cell.charge = 0
+7 -50
View File
@@ -184,6 +184,8 @@
/datum/game_mode/proc/check_finished(force_ending) //to be called by SSticker
if(!SSticker.setup_done)
return FALSE
if(replacementmode && round_converted == 2)
return replacementmode.check_finished()
if(SSshuttle.emergency && (SSshuttle.emergency.mode == SHUTTLE_ENDGAME))
@@ -196,7 +198,7 @@
if(!continuous_sanity_checked) //make sure we have antags to be checking in the first place
for(var/mob/Player in GLOB.mob_list)
if(Player.mind)
if(Player.mind.special_role)
if(Player.mind.special_role || LAZYLEN(Player.mind.antag_datums))
continuous_sanity_checked = 1
return 0
if(!continuous_sanity_checked)
@@ -212,7 +214,7 @@
for(var/mob/Player in GLOB.living_mob_list)
if(Player.mind && Player.stat != DEAD && !isnewplayer(Player) &&!isbrain(Player) && Player.client)
if(Player.mind.special_role) //Someone's still antaging!
if(Player.mind.special_role || LAZYLEN(Player.mind.antag_datums)) //Someone's still antaging!
living_antag_player = Player
return 0
@@ -392,43 +394,6 @@
if(P.client && P.ready == PLAYER_READY_TO_PLAY)
. ++
///////////////////////////////////
//Keeps track of all living heads//
///////////////////////////////////
/datum/game_mode/proc/get_living_heads()
. = list()
for(var/mob/living/carbon/human/player in GLOB.mob_list)
if(player.stat != DEAD && player.mind && (player.mind.assigned_role in GLOB.command_positions))
. |= player.mind
////////////////////////////
//Keeps track of all heads//
////////////////////////////
/datum/game_mode/proc/get_all_heads()
. = list()
for(var/mob/player in GLOB.mob_list)
if(player.mind && (player.mind.assigned_role in GLOB.command_positions))
. |= player.mind
//////////////////////////////////////////////
//Keeps track of all living security members//
//////////////////////////////////////////////
/datum/game_mode/proc/get_living_sec()
. = list()
for(var/mob/living/carbon/human/player in GLOB.mob_list)
if(player.stat != DEAD && player.mind && (player.mind.assigned_role in GLOB.security_positions))
. |= player.mind
////////////////////////////////////////
//Keeps track of all security members//
////////////////////////////////////////
/datum/game_mode/proc/get_all_sec()
. = list()
for(var/mob/living/carbon/human/player in GLOB.mob_list)
if(player.mind && (player.mind.assigned_role in GLOB.security_positions))
. |= player.mind
//////////////////////////
//Reports player logouts//
//////////////////////////
@@ -529,19 +494,11 @@
return max(0, enemy_minimum_age - C.player_age)
/datum/game_mode/proc/replace_jobbaned_player(mob/living/M, role_type, pref)
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [role_type]?", "[role_type]", null, pref, 50, M)
var/mob/dead/observer/theghost = null
if(candidates.len)
theghost = pick(candidates)
to_chat(M, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!")
message_admins("[key_name_admin(theghost)] has taken control of ([key_name_admin(M)]) to replace a jobbaned player.")
M.ghostize(0)
M.key = theghost.key
/datum/game_mode/proc/remove_antag_for_borging(datum/mind/newborgie)
SSticker.mode.remove_cultist(newborgie, 0, 0)
SSticker.mode.remove_revolutionary(newborgie, 0)
var/datum/antagonist/rev/rev = newborgie.has_antag_datum(/datum/antagonist/rev)
if(rev)
rev.remove_revolutionary(TRUE)
/datum/game_mode/proc/generate_station_goals()
var/list/possible = list()
@@ -426,7 +426,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
for(var/obj/machinery/door/D in GLOB.airlocks)
if(!(D.z in GLOB.station_z_levels))
continue
INVOKE_ASYNC(D, /obj/machinery/door.proc/hostile_lockdown, src)
INVOKE_ASYNC(D, /obj/machinery/door.proc/hostile_lockdown, owner)
addtimer(CALLBACK(D, /obj/machinery/door.proc/disable_lockdown), 900)
var/obj/machinery/computer/communications/C = locate() in GLOB.machines
@@ -498,7 +498,6 @@ Congratulations! You are now trained for invasive xenobiology research!"}
origin_tech = "materials=4;magnets=5;abductor=2"
/obj/item/restraints/handcuffs/energy/used
desc = "energy discharge"
flags_1 = DROPDEL_1
/obj/item/restraints/handcuffs/energy/used/dropped(mob/user)
@@ -597,7 +596,7 @@ Congratulations! You are now trained for invasive xenobiology research!"}
/obj/structure/bed/abductor
name = "resting contraption"
desc = "This looks similar to contraptions from earth. Could aliens be stealing our technology?"
desc = "This looks similar to contraptions from Earth. Could aliens be stealing our technology?"
icon = 'icons/obj/abductor.dmi'
buildstacktype = /obj/item/stack/sheet/mineral/abductor
icon_state = "bed"
@@ -241,10 +241,11 @@
/obj/item/organ/heart/gland/plasma/activate()
to_chat(owner, "<span class='warning'>You feel bloated.</span>")
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, owner, "<span class='userdanger'>A massive stomachache overcomes you.</span>"), 150)
addtimer(CALLBACK(src, .proc/vomit_plasma), 200)
/obj/item/organ/heart/gland/plasma/proc/vomit_plasma()
sleep(150)
if(!owner)
return
to_chat(owner, "<span class='userdanger'>A massive stomachache overcomes you.</span>")
sleep(50)
if(!owner)
return
owner.visible_message("<span class='danger'>[owner] vomits a cloud of plasma!</span>")
@@ -42,8 +42,7 @@
/datum/game_mode/monkey/announce()
to_chat(world, "<B>The current game mode is - Monkey!</B>")
to_chat(world, "<B>One or more crewmembers have been infected with Jungle Fever! Crew: Contain the outbreak. None of the infected monkeys may escape alive to CentCom. \
Monkeys: Ensure that your kind lives on! Rise up against your captors!</B>")
to_chat(world, "<B>One or more crewmembers have been infected with Jungle Fever! Crew: Contain the outbreak. None of the infected monkeys may escape alive to CentCom. Monkeys: Ensure that your kind lives on! Rise up against your captors!</B>")
/datum/game_mode/monkey/proc/greet_carrier(datum/mind/carrier)
@@ -115,5 +114,4 @@
to_chat(world, "<span class='userdanger'>The staff managed to contain the monkey infestation!</span>")
/datum/game_mode/monkey/generate_report()
return "Reports of an ancient [pick("retrovirus", "flesh eating bacteria", "disease", "magical curse blamed on viruses", "bananna blight")] outbreak that turn humans into monkies has been \
reported in your quadrant. Any such infections may be treated with bananna juice. If an outbreak occurs, ensure the station is quarantined to prevent a largescale outbreak at Centcom."
return "Reports of an ancient [pick("retrovirus", "flesh eating bacteria", "disease", "magical curse blamed on viruses", "banana blight")] outbreak that turn humans into monkeys has been reported in your quadrant. Any such infections may be treated with banana juice. If an outbreak occurs, ensure the station is quarantined to prevent a largescale outbreak at CentCom."
@@ -241,7 +241,7 @@
if(T.flags_1 & NOJAUNT_1)
T.flags_1 &= ~NOJAUNT_1
new /obj/effect/temp_visual/revenant(T)
if(!istype(T, /turf/open/floor/plating) && !istype(T, /turf/open/floor/engine/cult) && isfloorturf(T) && prob(15))
if(!isplatingturf(T) && !istype(T, /turf/open/floor/engine/cult) && isfloorturf(T) && prob(15))
var/turf/open/floor/floor = T
if(floor.intact && floor.floor_tile)
new floor.floor_tile(floor)
+7 -4
View File
@@ -407,14 +407,17 @@ GLOBAL_LIST_EMPTY(possible_items)
/datum/objective/steal/proc/select_target() //For admins setting objectives manually.
var/list/possible_items_all = GLOB.possible_items+"custom"
var/new_target = input("Select target:", "Objective target", steal_target) as null|anything in possible_items_all
if (!new_target) return
if (!new_target)
return
if (new_target == "custom") //Can set custom items.
var/obj/item/custom_target = input("Select type:","Type") as null|anything in typesof(/obj/item)
if (!custom_target) return
if (!custom_target)
return
var/custom_name = initial(custom_target.name)
custom_name = stripped_input("Enter target name:", "Objective target", custom_name)
if (!custom_name) return
if (!custom_name)
return
steal_target = custom_target
explanation_text = "Steal [custom_name]."
@@ -711,7 +714,7 @@ GLOBAL_LIST_EMPTY(possible_items_special)
var/needed_heads = rand(min_lings,GLOB.command_positions.len)
needed_heads = min(SSticker.mode.changelings.len,needed_heads)
var/list/heads = SSticker.mode.get_living_heads()
var/list/heads = SSjob.get_living_heads()
for(var/datum/mind/head in heads)
if(head in SSticker.mode.changelings) //Looking at you HoP.
continue
+11
View File
@@ -7,7 +7,18 @@
/datum/objective_team/New(starting_members)
. = ..()
if(starting_members)
if(islist(starting_members))
for(var/datum/mind/M in starting_members)
add_member(M)
else
add_member(starting_members)
members += starting_members
/datum/objective_team/proc/is_solo()
return members.len == 1
/datum/objective_team/proc/add_member(datum/mind/new_member)
members |= new_member
/datum/objective_team/proc/remove_member(datum/mind/member)
members -= member

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