diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 27cc7d4835a..368181ea2fd 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -17,7 +17,7 @@ If you want to contribute the first thing you'll need to do is [set up Git](http
We have a [list of guides on the wiki](http://www.tgstation13.org/wiki/index.php/Guides#Development_and_Contribution_Guides) which will help you get started contributing to /tg/station with git and Dream Maker. For beginners, it is recommended you work on small projects, at first. If you need help learning to program in BYOND check out this [repository of resources](http://www.byond.com/developer/articles/resources).
-There is an open list of approachable issues for [your inspiration here](https://github.com/tgstation/-tg-station/issues?q=is%3Aopen+is%3Aissue+label%3A%22Easy+Fix%22).
+There is an open list of approachable issues for [your inspiration here](https://github.com/tgstation/-tg-station/issues?q=is%3Aopen+is%3Aissue+label%3A%22Easy+Task%22).
You can of course, as always, ask for help at [#coderbus](irc://irc.rizon.net/coderbus) on irc.rizon.net. We are just here to have fun and help so do not expect professional support please.
diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_fountain_hall.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_fountain_hall.dmm
index b367a068f15..918b0e894b7 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_surface_fountain_hall.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_fountain_hall.dmm
@@ -8,19 +8,19 @@
},
/area/ruin/unpowered)
"c" = (
-/obj/structure/divine/healingfountain/anyone,
+/obj/structure/healingfountain,
/turf/open/floor/engine/cult{
baseturf = /turf/open/floor/plating/lava/smooth
},
/area/ruin/unpowered)
"d" = (
-/obj/structure/divine/conduit,
+/obj/structure/fluff/divine/conduit,
/turf/open/floor/engine/cult{
baseturf = /turf/open/floor/plating/lava/smooth
},
/area/ruin/unpowered)
"e" = (
-/obj/structure/divine/sacrificealtar,
+/obj/structure/sacrificealtar,
/turf/open/floor/engine/cult{
baseturf = /turf/open/floor/plating/lava/smooth
},
diff --git a/_maps/RandomZLevels/Academy.dmm b/_maps/RandomZLevels/Academy.dmm
index 4577417fc7b..260a66f8642 100644
--- a/_maps/RandomZLevels/Academy.dmm
+++ b/_maps/RandomZLevels/Academy.dmm
@@ -852,7 +852,7 @@
/turf/closed/wall,
/area/awaymission/academy/headmaster)
"cI" = (
-/obj/structure/divine/trap/damage,
+/obj/structure/trap/damage,
/turf/open/floor/carpet,
/area/awaymission/academy/headmaster)
"cJ" = (
@@ -3881,11 +3881,11 @@
d2 = 4;
icon_state = "2-4"
},
-/obj/structure/divine/trap/chill,
+/obj/structure/trap/chill,
/turf/open/floor/plating,
/area/awaymission/academy/academyaft)
"kN" = (
-/obj/structure/divine/trap/fire,
+/obj/structure/trap/fire,
/turf/open/floor/engine,
/area/awaymission/academy/academyaft)
"kO" = (
@@ -3946,7 +3946,7 @@
/turf/open/floor/engine/cult,
/area/awaymission/academy/academycellar)
"la" = (
-/obj/structure/divine/trap/damage,
+/obj/structure/trap/damage,
/turf/open/floor/engine/cult,
/area/awaymission/academy/academycellar)
"lb" = (
diff --git a/_maps/RandomZLevels/caves.dmm b/_maps/RandomZLevels/caves.dmm
index 839dee842a4..dea105695ea 100644
--- a/_maps/RandomZLevels/caves.dmm
+++ b/_maps/RandomZLevels/caves.dmm
@@ -167,7 +167,7 @@
name = "\improper BMP Asteroid Level 4"
})
"av" = (
-/obj/structure/divine/trap/stun{
+/obj/structure/trap/stun{
desc = "A rune inscribed in the floor, the air feeling electrified around it.";
name = "shock rune"
},
@@ -474,7 +474,7 @@
name = "\improper BMP Asteroid Level 3"
})
"aY" = (
-/obj/structure/divine/trap/fire{
+/obj/structure/trap/fire{
desc = "An old rune inscribed on the floor, giving off an intense amount of heat.";
name = "flame rune"
},
@@ -485,7 +485,7 @@
name = "\improper BMP Asteroid Level 4"
})
"aZ" = (
-/obj/structure/divine/trap/fire{
+/obj/structure/trap/fire{
desc = "An old rune inscribed on the floor, giving off an intense amount of heat.";
name = "flame rune"
},
@@ -672,7 +672,7 @@
name = "\improper BMP Asteroid Level 4"
})
"bs" = (
-/obj/structure/divine/trap/stun{
+/obj/structure/trap/stun{
desc = "A rune inscribed in the floor, the air feeling electrified around it.";
name = "shock rune"
},
diff --git a/_maps/RandomZLevels/research.dmm b/_maps/RandomZLevels/research.dmm
index d66f49ddb40..3f56227c366 100644
--- a/_maps/RandomZLevels/research.dmm
+++ b/_maps/RandomZLevels/research.dmm
@@ -4907,7 +4907,7 @@
/turf/open/floor/mineral/plasma,
/area/space)
"nd" = (
-/obj/structure/divine/healingfountain/anyone,
+/obj/structure/healingfountain,
/turf/open/floor/mineral/plasma,
/area/space)
"ne" = (
diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm
index ad6d1b744c1..7f6836d2ebf 100644
--- a/_maps/map_files/MetaStation/MetaStation.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.dmm
@@ -3923,7 +3923,7 @@
pixel_y = 0
},
/obj/structure/rack,
-/obj/item/weapon/storage/fancy,
+/obj/item/weapon/storage/fancy/donut_box,
/turf/open/floor/plasteel/vault{
dir = 1
},
@@ -47246,7 +47246,6 @@
/turf/open/floor/wood,
/area/library)
"bDx" = (
-/obj/machinery/portable_atmospherics/canister/bz,
/turf/open/floor/plasteel/bot,
/area/atmos)
"bDy" = (
@@ -49975,6 +49974,7 @@
dir = 4
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/obj/machinery/portable_atmospherics/canister/freon,
/turf/open/floor/plasteel,
/area/atmos)
"bHQ" = (
@@ -49985,6 +49985,7 @@
dir = 2;
on = 1
},
+/obj/machinery/portable_atmospherics/canister/freon,
/turf/open/floor/plasteel/black/corner{
dir = 2
},
@@ -62702,6 +62703,8 @@
network = list("SS13","Medbay")
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/obj/machinery/limbgrower,
+/obj/item/weapon/reagent_containers/glass/beaker/synthflesh,
/turf/open/floor/plasteel/whiteblue/side{
dir = 4
},
@@ -73092,7 +73095,6 @@
/obj/structure/sign/nosmoking_2{
pixel_y = 32
},
-/obj/machinery/portable_atmospherics/canister/bz,
/turf/open/floor/plasteel/warning{
dir = 5
},
@@ -73555,6 +73557,7 @@
dir = 2;
icon_state = "pipe-c"
},
+/obj/machinery/portable_atmospherics/canister/freon,
/turf/open/floor/plasteel/warning{
dir = 4
},
@@ -74082,6 +74085,7 @@
/turf/open/floor/plasteel/bot,
/area/toxins/storage)
"cxf" = (
+/obj/machinery/portable_atmospherics/canister/freon,
/turf/open/floor/plasteel/warning{
dir = 8
},
@@ -74089,6 +74093,7 @@
"cxg" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/obj/structure/disposalpipe/segment,
+/obj/machinery/portable_atmospherics/canister/freon,
/turf/open/floor/plasteel/warning{
dir = 4
},
diff --git a/_maps/map_files/MiniStation/cargopacks.dm b/_maps/map_files/MiniStation/cargopacks.dm
index a6a1db75df3..097711e7f43 100644
--- a/_maps/map_files/MiniStation/cargopacks.dm
+++ b/_maps/map_files/MiniStation/cargopacks.dm
@@ -1,31 +1,3 @@
-/datum/supply_pack/engineering/oxygen
- name = "Oxygen Canister"
- cost = 15
- contains = list(/obj/machinery/portable_atmospherics/canister/oxygen)
- crate_name = "oxygen canister crate"
- crate_type = /obj/structure/closet/crate/large
-
-/datum/supply_pack/engineering/toxins
- name = "Plasma Canister"
- cost = 30
- contains = list(/obj/machinery/portable_atmospherics/canister/toxins)
- crate_name = "plasma canister crate"
- crate_type = /obj/structure/closet/crate/large
-
-/datum/supply_pack/engineering/nitrogen
- name = "Nitrogen Canister"
- cost = 20
- contains = list(/obj/machinery/portable_atmospherics/canister/nitrogen)
- crate_name = "nitrogen canister crate"
- crate_type = /obj/structure/closet/crate/large
-
-/datum/supply_pack/engineering/carbon_dio
- name = "Carbon Dioxide Canister"
- cost = 35
- contains = list(/obj/machinery/portable_atmospherics/canister/carbon_dioxide)
- crate_name = "carbon dioxide canister crate"
- crate_type = /obj/structure/closet/crate/large
-
/obj/machinery/hydroponics/constructable/unattached
anchored = 0
diff --git a/_maps/map_files/TgStation/tgstation.2.1.3.dmm b/_maps/map_files/TgStation/tgstation.2.1.3.dmm
index cc62442653f..ec77a16dc25 100644
--- a/_maps/map_files/TgStation/tgstation.2.1.3.dmm
+++ b/_maps/map_files/TgStation/tgstation.2.1.3.dmm
@@ -7384,6 +7384,7 @@
/turf/open/floor/plating,
/area/shuttle/pod_1)
"apI" = (
+/obj/machinery/portable_atmospherics/canister/freon,
/turf/open/floor/plasteel/floorgrime,
/area/toxins/storage)
"apJ" = (
@@ -36590,6 +36591,7 @@
scrub_N2O = 0;
scrub_Toxins = 0
},
+/obj/machinery/portable_atmospherics/canister/freon,
/turf/open/floor/plasteel/floorgrime,
/area/toxins/storage)
"bCY" = (
@@ -37039,6 +37041,7 @@
icon_state = "4-8";
pixel_y = 0
},
+/obj/machinery/portable_atmospherics/canister/freon,
/mob/living/simple_animal/mouse,
/turf/open/floor/plasteel/floorgrime,
/area/toxins/storage)
@@ -37088,6 +37091,7 @@
icon_state = "4-8";
pixel_y = 0
},
+/obj/machinery/portable_atmospherics/canister/freon,
/turf/open/floor/plasteel/floorgrime,
/area/toxins/storage)
"bEd" = (
@@ -37871,7 +37875,6 @@
/obj/machinery/light/small{
dir = 8
},
-/obj/machinery/portable_atmospherics/canister/bz,
/turf/open/floor/plasteel/floorgrime,
/area/toxins/storage)
"bFJ" = (
@@ -38435,13 +38438,8 @@
/turf/open/floor/plasteel/white,
/area/medical/sleeper)
"bGS" = (
-/obj/structure/table,
-/obj/item/weapon/reagent_containers/glass/bottle/epinephrine{
- pixel_x = 7;
- pixel_y = -3
- },
-/obj/item/weapon/reagent_containers/glass/bottle/morphine,
-/obj/item/weapon/reagent_containers/syringe,
+/obj/machinery/limbgrower,
+/obj/item/weapon/reagent_containers/glass/beaker/synthflesh,
/turf/open/floor/plasteel/white,
/area/medical/sleeper)
"bGT" = (
@@ -38550,7 +38548,6 @@
dir = 4;
network = list("SS13","RD")
},
-/obj/machinery/portable_atmospherics/canister/bz,
/turf/open/floor/plasteel/floorgrime,
/area/toxins/storage)
"bHf" = (
@@ -39185,6 +39182,18 @@
pixel_y = 2
},
/obj/item/weapon/storage/box/syringes,
+/obj/item/weapon/reagent_containers/glass/bottle/epinephrine{
+ pixel_x = 7;
+ pixel_y = -3
+ },
+/obj/item/weapon/reagent_containers/glass/bottle/morphine{
+ pixel_x = 8;
+ pixel_y = -3
+ },
+/obj/item/weapon/reagent_containers/syringe{
+ pixel_x = 6;
+ pixel_y = -3
+ },
/turf/open/floor/plasteel/white,
/area/medical/sleeper)
"bIn" = (
@@ -41814,13 +41823,13 @@
name = "Station Intercom (General)";
pixel_x = -30
},
-/obj/machinery/portable_atmospherics/canister/bz,
/turf/open/floor/plasteel,
/area/atmos)
"bNQ" = (
/obj/structure/disposalpipe/segment{
dir = 4
},
+/obj/machinery/portable_atmospherics/canister/freon,
/turf/open/floor/plasteel,
/area/atmos)
"bNR" = (
@@ -41853,6 +41862,7 @@
scrub_N2O = 0;
scrub_Toxins = 0
},
+/obj/machinery/portable_atmospherics/canister/freon,
/turf/open/floor/plasteel,
/area/atmos)
"bNT" = (
@@ -90902,7 +90912,7 @@ bJs
bKy
bLM
bLM
-alX
+bNQ
bOV
bQk
bRt
@@ -106060,7 +106070,7 @@ bDc
bEo
bDf
bEb
-bIC
+apI
bGY
bJN
bMp
diff --git a/_maps/map_files/generic/z2.dmm b/_maps/map_files/generic/z2.dmm
index b9586bc48b5..723bcc61f73 100644
--- a/_maps/map_files/generic/z2.dmm
+++ b/_maps/map_files/generic/z2.dmm
@@ -5307,7 +5307,7 @@
/turf/open/floor/plating,
/area/ctf)
"qD" = (
-/obj/structure/divine/trap/ctf/blue,
+/obj/structure/trap/ctf/blue,
/turf/open/floor/plasteel/blue,
/area/ctf)
"qE" = (
@@ -5335,7 +5335,7 @@
/turf/open/floor/plasteel/darkred,
/area/ctf)
"qI" = (
-/obj/structure/divine/trap/ctf/red,
+/obj/structure/trap/ctf/red,
/turf/open/floor/plasteel/darkred,
/area/ctf)
"qJ" = (
@@ -5379,7 +5379,7 @@
/turf/open/floor/plasteel/circuit/gcircuit/off,
/area/ctf)
"qQ" = (
-/obj/structure/divine/trap/ctf/red,
+/obj/structure/trap/ctf/red,
/turf/open/floor/plasteel/red,
/area/ctf)
"qR" = (
diff --git a/code/__DEFINES/clockcult.dm b/code/__DEFINES/clockcult.dm
index 3bc8ff23a82..8102b0c48e6 100644
--- a/code/__DEFINES/clockcult.dm
+++ b/code/__DEFINES/clockcult.dm
@@ -38,8 +38,12 @@ var/global/clockwork_gateway_activated = FALSE //if a gateway to the celestial d
#define REPLICANT_WALL_MINUS_FLOOR REPLICANT_ALLOY_UNIT*0.4 //amount of alloy in a clockwork wall, determines the cost of clockwork wall production
+#define REPLICANT_GEAR REPLICANT_ALLOY_UNIT*0.3 //amount of alloy in a wall gear, minus the brass from the wall
+
#define REPLICANT_WALL_TOTAL REPLICANT_WALL_MINUS_FLOOR+REPLICANT_FLOOR //how much alloy is in a clockwork wall and the floor under it
+#define RATVAR_ALLOY_CHECK "ratvar?" //when passed into can_use_alloy(), converts it into a check for if ratvar has woken/the proselytizer is debug
+
//Ark defines
#define GATEWAY_SUMMON_RATE 2 //the time amount the Gateway to the Celestial Derelict gets each process tick; defaults to 2 per tick
diff --git a/code/__DEFINES/hud.dm b/code/__DEFINES/hud.dm
index 57e6573bc73..6bbc2fe1b59 100644
--- a/code/__DEFINES/hud.dm
+++ b/code/__DEFINES/hud.dm
@@ -30,16 +30,14 @@
#define ANTAG_HUD_OPS 8
#define ANTAG_HUD_WIZ 9
#define ANTAG_HUD_SHADOW 10
-#define ANTAG_HUD_HOG_BLUE 11
-#define ANTAG_HUD_HOG_RED 12
-#define ANTAG_HUD_TRAITOR 13
-#define ANTAG_HUD_NINJA 14
-#define ANTAG_HUD_CHANGELING 15
-#define ANTAG_HUD_ABDUCTOR 16
-#define ANTAG_HUD_DEVIL 17
-#define ANTAG_HUD_SINTOUCHED 18
-#define ANTAG_HUD_SOULLESS 19
-#define ANTAG_HUD_CLOCKWORK 20
+#define ANTAG_HUD_TRAITOR 11
+#define ANTAG_HUD_NINJA 12
+#define ANTAG_HUD_CHANGELING 13
+#define ANTAG_HUD_ABDUCTOR 14
+#define ANTAG_HUD_DEVIL 15
+#define ANTAG_HUD_SINTOUCHED 16
+#define ANTAG_HUD_SOULLESS 17
+#define ANTAG_HUD_CLOCKWORK 18
// Notification action types
#define NOTIFY_JUMP "jump"
diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index fa2ad08b30b..ad3d3d6027b 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -4,6 +4,8 @@
#define in_range(source, user) (get_dist(source, user) <= 1)
+#define is_cleanable(A) (istype(A, /obj/effect/decal/cleanable) || istype(A, /obj/effect/rune)) //if something is cleanable
+
// MOB HELPERS
#define ishuman(A) (istype(A, /mob/living/carbon/human))
diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers.dm
index 27a5a3f1034..0d0b54b8ee0 100644
--- a/code/__DEFINES/layers.dm
+++ b/code/__DEFINES/layers.dm
@@ -50,6 +50,7 @@
#define LIGHTING_LAYER 15
//HUD layer defines
+#define COLORED_VISION_LAYER 17.8
#define FLASH_LAYER 17.9
#define FULLSCREEN_LAYER 18
#define UI_DAMAGE_LAYER 18.1
diff --git a/code/__DEFINES/machines.dm b/code/__DEFINES/machines.dm
index 27280edfd79..0ff00ff276f 100644
--- a/code/__DEFINES/machines.dm
+++ b/code/__DEFINES/machines.dm
@@ -22,4 +22,14 @@
#define CRAFTLATHE 8 //Uses fuck if I know. For use eventually.
#define MECHFAB 16 //Remember, objects utilising this flag should have construction_time and construction_cost vars.
#define BIOGENERATOR 32 //Uses biomass
-//Note: More then one of these can be added to a design but imprinter and lathe designs are incompatable.
\ No newline at end of file
+#define LIMBGROWER 64 //Uses synthetic flesh
+//Note: More then one of these can be added to a design but imprinter and lathe designs are incompatable.
+
+#define MC_CPU "CPU"
+#define MC_HDD "HDD"
+#define MC_SDD "SDD"
+#define MC_CARD "CARD"
+#define MC_NET "NET"
+#define MC_PRINT "PRINT"
+#define MC_CELL "CELL"
+#define MC_CHARGE "CHARGE"
\ No newline at end of file
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 906a3b3498d..1ec6a0ed426 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -482,7 +482,6 @@ var/global/list/ghost_others_options = list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
#define STORAGE_VIEW_DEPTH 2
-
// Medal names
#define BOSS_KILL_MEDAL "Killer"
@@ -528,3 +527,8 @@ var/global/list/ghost_others_options = list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
#define MIN_NTNET_LOGS 10
//TODO Move to a pref
#define STATION_GOAL_BUDGET 1
+
+//Luma coefficients suggested for HDTVs. If you change these, make sure they add up to 1.
+#define LUMA_R 0.213
+#define LUMA_G 0.715
+#define LUMA_B 0.072
\ No newline at end of file
diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm
index aff4dea38c8..51502947f6b 100644
--- a/code/__DEFINES/role_preferences.dm
+++ b/code/__DEFINES/role_preferences.dm
@@ -21,8 +21,6 @@
#define ROLE_GANG "gangster"
#define ROLE_ABDUCTOR "abductor"
#define ROLE_REVENANT "revenant"
-#define ROLE_HOG_GOD "hand of god: god"
-#define ROLE_HOG_CULTIST "hand of god: cultist"
#define ROLE_DEVIL "devil"
#define ROLE_SERVANT_OF_RATVAR "servant of Ratvar"
@@ -45,8 +43,6 @@ var/global/list/special_roles = list(
ROLE_GANG = /datum/game_mode/gang,
ROLE_REVENANT,
ROLE_ABDUCTOR = /datum/game_mode/abduction,
- ROLE_HOG_GOD = /datum/game_mode/hand_of_god,
- ROLE_HOG_CULTIST = /datum/game_mode/hand_of_god,
ROLE_DEVIL = /datum/game_mode/devil,
ROLE_SERVANT_OF_RATVAR = /datum/game_mode/clockwork_cult,
)
diff --git a/code/__DEFINES/say.dm b/code/__DEFINES/say.dm
index 226bfee6310..070837bee97 100644
--- a/code/__DEFINES/say.dm
+++ b/code/__DEFINES/say.dm
@@ -24,6 +24,7 @@
#define SPAN_PAPYRUS "papyrus"
#define SPAN_REALLYBIG "reallybig"
#define SPAN_COMMAND "command_headset"
+#define SPAN_CLOWN "clown"
//bitflag #defines for return value of the radio() proc.
#define ITALICS 1
diff --git a/code/__HELPERS/cmp.dm b/code/__HELPERS/cmp.dm
index 54cdc9bb8ca..1cad2a5e5e4 100644
--- a/code/__HELPERS/cmp.dm
+++ b/code/__HELPERS/cmp.dm
@@ -41,4 +41,7 @@ var/cmp_field = "name"
return a.priority - b.priority
/proc/cmp_clientcolour_priority(datum/client_colour/A, datum/client_colour/B)
- return B.priority - A.priority
\ No newline at end of file
+ return B.priority - A.priority
+
+/proc/cmp_clockscripture_priority(datum/clockwork_scripture/A, datum/clockwork_scripture/B)
+ return initial(A.sort_priority) - initial(B.sort_priority)
\ No newline at end of file
diff --git a/code/__HELPERS/icon_smoothing.dm b/code/__HELPERS/icon_smoothing.dm
index 7f76e50e434..22b6e15808e 100644
--- a/code/__HELPERS/icon_smoothing.dm
+++ b/code/__HELPERS/icon_smoothing.dm
@@ -386,6 +386,5 @@
name = "smooth wall"
icon = 'icons/turf/smooth_wall.dmi'
icon_state = "smooth"
- walltype = "shuttle"
smooth = SMOOTH_TRUE|SMOOTH_DIAGONAL|SMOOTH_BORDER
canSmoothWith = null
diff --git a/code/__HELPERS/matrices.dm b/code/__HELPERS/matrices.dm
index ff1c86cec1d..6f1ea32d2a3 100644
--- a/code/__HELPERS/matrices.dm
+++ b/code/__HELPERS/matrices.dm
@@ -63,91 +63,96 @@
// Color matrices:
-//Luma coefficients suggested for HDTVs. If you change these, make sure they add up to 1.
-#define LUMR 0.2126
-#define LUMG 0.7152
-#define LUMB 0.0722
+/* Documenting a couple of potentially useful color matrices here to inspire ideas
+// Greyscale - indentical to saturation @ 0
+list(LUMA_R,LUMA_R,LUMA_R,0, LUMA_G,LUMA_G,LUMA_G,0, LUMA_B,LUMA_B,LUMA_B,0, 0,0,0,1, 0,0,0,0)
-//Still need color matrix addition, negation, and multiplication.
+// Color inversion
+list(-1,0,0,0, 0,-1,0,0, 0,0,-1,0, 0,0,0,1, 1,1,1,0)
-//Returns an identity color matrix which does nothing
-/proc/color_identity()
- return list(1,0,0, 0,1,0, 0,0,1)
+// Sepiatone
+list(0.393,0.349,0.272,0, 0.769,0.686,0.534,0, 0.189,0.168,0.131,0, 0,0,0,1, 0,0,0,0)
+*/
-//Moves all colors angle degrees around the color wheel while maintaining intensity of the color and not affecting whites
-//TODO: Need a version that only affects one color (ie shift red to blue but leave greens and blues alone)
-/proc/color_rotation(angle)
- if(angle == 0)
- return color_identity()
- angle = Clamp(angle, -180, 180)
- var/cos = cos(angle)
+//Does nothing
+/proc/color_matrix_identity()
+ return list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, 0,0,0,0)
+
+//Adds/subtracts overall lightness
+//0 is identity, 1 makes everything white, -1 makes everything black
+/proc/color_matrix_lightness(power)
+ return list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, power,power,power,0)
+
+//Changes distance hues have from grey while maintaining the overall lightness. Greys are unaffected.
+//1 is identity, 0 is greyscale, >1 oversaturates colors
+/proc/color_matrix_saturation(value)
+ var/inv = 1 - value
+ var/R = round(LUMA_R * inv, 0.001)
+ var/G = round(LUMA_G * inv, 0.001)
+ var/B = round(LUMA_B * inv, 0.001)
+
+ return list(R + value,R,R,0, G,G + value,G,0, B,B,B + value,0, 0,0,0,1, 0,0,0,0)
+
+//Changes distance colors have from rgb(127,127,127) grey
+//1 is identity. 0 makes everything grey >1 blows out colors and greys
+/proc/color_matrix_contrast(value)
+ var/add = (1 - value) / 2
+ return list(value,0,0,0, 0,value,0,0, 0,0,value,0, 0,0,0,1, add,add,add,0)
+
+//Moves all colors angle degrees around the color wheel while maintaining intensity of the color and not affecting greys
+//0 is identity, 120 moves reds to greens, 240 moves reds to blues
+/proc/color_matrix_rotate_hue(angle)
var/sin = sin(angle)
-
- var/constA = 0.143
- var/constB = 0.140
- var/constC = -0.283
+ var/cos = cos(angle)
+ var/cos_inv_third = 0.333*(1-cos)
+ var/sqrt3_sin = sqrt(3)*sin
return list(
- LUMR + cos * (1-LUMR) + sin * -LUMR, LUMR + cos * -LUMR + sin * constA, LUMR + cos * -LUMR + sin * -(1-LUMR),
- LUMG + cos * -LUMG + sin * -LUMG, LUMG + cos * (1-LUMG) + sin * constB, LUMG + cos * -LUMG + sin * LUMG,
- LUMB + cos * -LUMB + sin * (1-LUMB), LUMB + cos * -LUMB + sin * constC, LUMB + cos * (1-LUMB) + sin * LUMB
- )
+round(cos+cos_inv_third, 0.001), round(cos_inv_third+sqrt3_sin, 0.001), round(cos_inv_third-sqrt3_sin, 0.001), 0,
+round(cos_inv_third-sqrt3_sin, 0.001), round(cos+cos_inv_third, 0.001), round(cos_inv_third+sqrt3_sin, 0.001), 0,
+round(cos_inv_third+sqrt3_sin, 0.001), round(cos_inv_third-sqrt3_sin, 0.001), round(cos+cos_inv_third, 0.001), 0,
+0,0,0,1,
+0,0,0,0)
-//Makes everything brighter or darker without regard to existing color or brightness
-/proc/color_brightness(power)
- power = Clamp(power, -255, 255)
- power = power/255
+//These next three rotate values about one axis only
+//x is the red axis, y is the green axis, z is the blue axis.
+/proc/color_matrix_rotate_x(angle)
+ var/sinval = round(sin(angle), 0.001); var/cosval = round(cos(angle), 0.001)
+ return list(1,0,0,0, 0,cosval,sinval,0, 0,-sinval,cosval,0, 0,0,0,1, 0,0,0,0)
- return list(1,0,0, 0,1,0, 0,0,1, power,power,power)
+/proc/color_matrix_rotate_y(angle)
+ var/sinval = round(sin(angle), 0.001); var/cosval = round(cos(angle), 0.001)
+ return list(cosval,0,-sinval,0, 0,1,0,0, sinval,0,cosval,0, 0,0,0,1, 0,0,0,0)
-/var/list/delta_index = list(
- 0, 0.01, 0.02, 0.04, 0.05, 0.06, 0.07, 0.08, 0.1, 0.11,
- 0.12, 0.14, 0.15, 0.16, 0.17, 0.18, 0.20, 0.21, 0.22, 0.24,
- 0.25, 0.27, 0.28, 0.30, 0.32, 0.34, 0.36, 0.38, 0.40, 0.42,
- 0.44, 0.46, 0.48, 0.5, 0.53, 0.56, 0.59, 0.62, 0.65, 0.68,
- 0.71, 0.74, 0.77, 0.80, 0.83, 0.86, 0.89, 0.92, 0.95, 0.98,
- 1.0, 1.06, 1.12, 1.18, 1.24, 1.30, 1.36, 1.42, 1.48, 1.54,
- 1.60, 1.66, 1.72, 1.78, 1.84, 1.90, 1.96, 2.0, 2.12, 2.25,
- 2.37, 2.50, 2.62, 2.75, 2.87, 3.0, 3.2, 3.4, 3.6, 3.8,
- 4.0, 4.3, 4.7, 4.9, 5.0, 5.5, 6.0, 6.5, 6.8, 7.0,
- 7.3, 7.5, 7.8, 8.0, 8.4, 8.7, 9.0, 9.4, 9.6, 9.8,
- 10.0)
+/proc/color_matrix_rotate_z(angle)
+ var/sinval = round(sin(angle), 0.001); var/cosval = round(cos(angle), 0.001)
+ return list(cosval,sinval,0,0, -sinval,cosval,0,0, 0,0,1,0, 0,0,0,1, 0,0,0,0)
-//Exxagerates or removes brightness
-/proc/color_contrast(value)
- value = Clamp(value, -100, 100)
- if(value == 0)
- return color_identity()
- var/x = 0
- if (value < 0)
- x = 127 + value / 100 * 127;
- else
- x = value % 1
- if(x == 0)
- x = delta_index[value]
- else
- x = delta_index[value] * (1-x) + delta_index[value+1] * x//use linear interpolation for more granularity.
- x = x * 127 + 127
+//Returns a matrix addition of A with B
+/proc/color_matrix_add(list/A, list/B)
+ if(!istype(A) || !istype(B))
+ return color_matrix_identity()
+ if(A.len != 20 || B.len != 20)
+ return color_matrix_identity()
+ var/list/output = list()
+ output.len = 20
+ for(var/value in 1 to 20)
+ output[value] = A[value] + B[value]
+ return output
- var/mult = x / 127
- var/add = 0.5 * (127-x) / 255
- return list(mult,0,0, 0,mult,0, 0,0,mult, add,add,add)
-
-//Exxagerates or removes colors
-/proc/color_saturation(value as num)
- if(value == 0)
- return color_identity()
- value = Clamp(value, -100, 100)
- if(value > 0)
- value *= 3
- var/x = 1 + value / 100
- var/inv = 1 - x
- var/R = LUMR * inv
- var/G = LUMG * inv
- var/B = LUMB * inv
-
- return list(R + x,R,R, G,G + x,G, B,B,B + x)
-
-#undef LUMR
-#undef LUMG
-#undef LUMB
+//Returns a matrix multiplication of A with B
+/proc/color_matrix_multiply(list/A, list/B)
+ if(!istype(A) || !istype(B))
+ return color_matrix_identity()
+ if(A.len != 20 || B.len != 20)
+ return color_matrix_identity()
+ var/list/output = list()
+ output.len = 20
+ var/x = 1
+ var/y = 1
+ var/offset = 0
+ for(y in 1 to 5)
+ offset = (y-1)*4
+ for(x in 1 to 4)
+ output[offset+x] = round(A[offset+1]*B[x] + A[offset+2]*B[x+4] + A[offset+3]*B[x+8] + A[offset+4]*B[x+12]+(y==5?B[x+16]:0), 0.001)
+ return output
\ No newline at end of file
diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm
index 0a58fff019a..cdd827a3895 100644
--- a/code/__HELPERS/type2type.dm
+++ b/code/__HELPERS/type2type.dm
@@ -572,4 +572,25 @@ for(var/t in test_times)
var/R = hex2num(copytext(A,2,4))
var/G = hex2num(copytext(A,4,6))
var/B = hex2num(copytext(A,6,0))
- return R+G+B
\ No newline at end of file
+ return R+G+B
+
+//word of warning: using a matrix like this as a color value will simplify it back to a string after being set
+/proc/color_hex2color_matrix(string)
+ var/length = length(string)
+ if(length != 7 && length != 9)
+ return color_matrix_identity()
+ var/r = hex2num(copytext(string, 2, 4))/255
+ var/g = hex2num(copytext(string, 4, 6))/255
+ var/b = hex2num(copytext(string, 6, 8))/255
+ var/a = 1
+ if(length == 9)
+ a = hex2num(copytext(string, 8, 10))/255
+ if(!isnum(r) || !isnum(g) || !isnum(b) || !isnum(a))
+ return color_matrix_identity()
+ return list(r,0,0,0, 0,g,0,0, 0,0,b,0, 0,0,0,a, 0,0,0,0)
+
+//will drop all values not on the diagonal
+/proc/color_matrix2color_hex(list/the_matrix)
+ if(!istype(the_matrix) || the_matrix.len != 20)
+ return "#ffffffff"
+ return rgb(the_matrix[1]*255, the_matrix[6]*255, the_matrix[11]*255, the_matrix[16]*255)
\ No newline at end of file
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index a8f3703f2f7..8f9f98e82fe 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -496,25 +496,6 @@ Turf and target are seperate in case you want to teleport some distance from a t
var/y=arcsin(x/sqrt(1+x*x))
return y
-
-/proc/anim(turf/location,target as mob|obj,a_icon,a_icon_state as text,flick_anim as text,sleeptime = 0,direction as num)
-//This proc throws up either an icon or an animation for a specified amount of time.
-//The variables should be apparent enough.
- var/atom/movable/overlay/animation = new(location)
- if(direction)
- animation.setDir(direction)
- animation.icon = a_icon
- animation.layer = target:layer+1
- if(a_icon_state)
- animation.icon_state = a_icon_state
- else
- animation.icon_state = "blank"
- animation.master = target
- flick(flick_anim, animation)
- sleep(max(sleeptime, 15))
- qdel(animation)
-
-
/atom/proc/GetAllContents()
var/list/processing_list = list(src)
var/list/assembled = list()
@@ -1348,17 +1329,23 @@ proc/pick_closest_path(value)
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,
+//as sleeps aren't cheap and sleeping only to wake up and sleep again is wasteful
+#define DELTA_CALC max(((max(world.tick_usage, world.cpu) / 100) * max(Master.sleep_delta,1)), 1)
+
/proc/stoplag()
- . = 1
+ . = round(1*DELTA_CALC)
sleep(world.tick_lag)
if (world.tick_usage > TICK_LIMIT_TO_RUN) //woke up, still not enough tick, sleep for more.
- . += 2
- sleep(world.tick_lag*2)
+ . += round(2*DELTA_CALC)
+ sleep(world.tick_lag*2*DELTA_CALC)
if (world.tick_usage > TICK_LIMIT_TO_RUN) //woke up, STILL not enough tick, sleep for more.
- . += 4
- sleep(world.tick_lag*4)
+ . += round(4*DELTA_CALC)
+ sleep(world.tick_lag*4*DELTA_CALC)
//you might be thinking of adding more steps to this, or making it use a loop and a counter var
// not worth it.
+#undef DELTA_CALC
/proc/flash_color(mob_or_client, flash_color="#960000", flash_time=20)
var/client/C
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index dc21aa4185a..3300602476c 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -104,6 +104,7 @@
if(W == A)
W.attack_self(src)
update_inv_hands()
+ return
// operate three levels deep here (item in backpack in src; item in box in backpack in src, not any deeper)
if(A.ClickAccessible(src, depth=INVENTORY_DEPTH))
diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm
index ad0ea23e9da..0902579bac8 100644
--- a/code/_onclick/hud/_defines.dm
+++ b/code/_onclick/hud/_defines.dm
@@ -51,17 +51,17 @@
#define ui_storage1 "CENTER+1:18,SOUTH:5"
#define ui_storage2 "CENTER+2:20,SOUTH:5"
-#define ui_borg_sensor "CENTER-3:16, SOUTH:5" //borgs
-#define ui_borg_lamp "CENTER-4:16, SOUTH:5" //borgies
-#define ui_borg_thrusters "CENTER-5:16, SOUTH:5"//borgies
-#define ui_inv1 "CENTER-2:16,SOUTH:5" //borgs
-#define ui_inv2 "CENTER-1 :16,SOUTH:5" //borgs
-#define ui_inv3 "CENTER :16,SOUTH:5" //borgs
-#define ui_borg_module "CENTER+1:16,SOUTH:5"
-#define ui_borg_store "CENTER+2:16,SOUTH:5" //borgs
-
-#define ui_borg_camera "CENTER+3:21,SOUTH:5" //borgs
-#define ui_borg_album "CENTER+4:21,SOUTH:5" //borgs
+#define ui_borg_sensor "CENTER-3:16, SOUTH:5" //borgs
+#define ui_borg_lamp "CENTER-4:16, SOUTH:5" //borgs
+#define ui_borg_thrusters "CENTER-5:16, SOUTH:5" //borgs
+#define ui_inv1 "CENTER-2:16,SOUTH:5" //borgs
+#define ui_inv2 "CENTER-1 :16,SOUTH:5" //borgs
+#define ui_inv3 "CENTER :16,SOUTH:5" //borgs
+#define ui_borg_module "CENTER+1:16,SOUTH:5" //borgs
+#define ui_borg_store "CENTER+2:16,SOUTH:5" //borgs
+#define ui_borg_camera "CENTER+3:21,SOUTH:5" //borgs
+#define ui_borg_album "CENTER+4:21,SOUTH:5" //borgs
+#define ui_borg_talk_wheel "CENTER+4:21,SOUTH+1:5" //borgs
#define ui_monkey_head "CENTER-4:13,SOUTH:5" //monkey
#define ui_monkey_mask "CENTER-3:14,SOUTH:5" //monkey
@@ -69,6 +69,7 @@
#define ui_alien_storage_l "CENTER-2:14,SOUTH:5"//alien
#define ui_alien_storage_r "CENTER+1:18,SOUTH:5"//alien
+#define ui_alien_talk_wheel "EAST-3:26,SOUTH:5" //alien
#define ui_drone_drop "CENTER+1:18,SOUTH:5" //maintenance drones
#define ui_drone_pull "CENTER+2:2,SOUTH:5" //maintenance drones
diff --git a/code/_onclick/hud/alien.dm b/code/_onclick/hud/alien.dm
index 2cd637f9653..305d7719b68 100644
--- a/code/_onclick/hud/alien.dm
+++ b/code/_onclick/hud/alien.dm
@@ -70,6 +70,11 @@
H.leap_icon.screen_loc = ui_alien_storage_r
static_inventory += H.leap_icon
+ using = new/obj/screen/wheel/talk
+ using.screen_loc = ui_alien_talk_wheel
+ wheels += using
+ static_inventory += using
+
using = new /obj/screen/drop()
using.icon = 'icons/mob/screen_alien.dmi'
using.screen_loc = ui_drop_throw
diff --git a/code/_onclick/hud/alien_larva.dm b/code/_onclick/hud/alien_larva.dm
index 9594fe08e61..4c04cc363ac 100644
--- a/code/_onclick/hud/alien_larva.dm
+++ b/code/_onclick/hud/alien_larva.dm
@@ -21,6 +21,11 @@
pull_icon.screen_loc = ui_pull_resist
hotkeybuttons += pull_icon
+ using = new/obj/screen/wheel/talk
+ using.screen_loc = ui_alien_talk_wheel
+ wheels += using
+ static_inventory += using
+
zone_select = new /obj/screen/zone_sel/alien()
zone_select.update_icon(mymob)
static_inventory += zone_select
diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/fullscreen.dm
index 4c6b79fdbb2..9ceaa67bf6a 100644
--- a/code/_onclick/hud/fullscreen.dm
+++ b/code/_onclick/hud/fullscreen.dm
@@ -106,3 +106,18 @@
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "druggy"
+
+/obj/screen/fullscreen/color_vision
+ icon = 'icons/mob/screen_gen.dmi'
+ screen_loc = "WEST,SOUTH to EAST,NORTH"
+ icon_state = "flash"
+ alpha = 80
+
+/obj/screen/fullscreen/color_vision/green
+ color = "#00ff00"
+
+/obj/screen/fullscreen/color_vision/red
+ color = "#ff0000"
+
+/obj/screen/fullscreen/color_vision/blue
+ color = "#0000ff"
\ No newline at end of file
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index 623b49723ae..0dfb1dbb14a 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -33,6 +33,8 @@
var/obj/screen/throw_icon
var/obj/screen/module_store_icon
+ var/list/wheels = list() //list of the wheel screen objects
+
var/list/static_inventory = list() //the screen objects which are static
var/list/toggleable_inventory = list() //the screen objects which can be hidden
var/list/obj/screen/hotkeybuttons = list() //the buttons that can be used via hotkeys
@@ -64,6 +66,8 @@
qdel(module_store_icon)
module_store_icon = null
+ wheels = null //all wheels are also in static_inventory
+
if(static_inventory.len)
for(var/thing in static_inventory)
qdel(thing)
@@ -199,7 +203,18 @@
return
/datum/hud/proc/persistant_inventory_update(mob/viewer)
- return
+ if(!mymob)
+ return
+ var/mob/living/L = mymob
+
+ var/mob/screenmob = viewer || L
+
+ for(var/X in wheels)
+ var/obj/screen/wheel/W = X
+ if(W.toggled)
+ screenmob.client.screen |= W.buttons_list
+ else
+ screenmob.client.screen -= W.buttons_list
//Triggered when F12 is pressed (Unless someone changed something in the DMF)
/mob/verb/button_pressed_F12()
diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm
index 93f36820fd8..b52d23375ab 100644
--- a/code/_onclick/hud/human.dm
+++ b/code/_onclick/hud/human.dm
@@ -95,6 +95,11 @@
using.icon = ui_style
static_inventory += using
+ using = new/obj/screen/wheel/talk
+ using.icon = ui_style
+ wheels += using
+ static_inventory += using
+
using = new /obj/screen/inventory/area_creator
using.icon = ui_style
static_inventory += using
@@ -352,53 +357,59 @@
if(H.wear_mask) screenmob.client.screen -= H.wear_mask
if(H.head) screenmob.client.screen -= H.head
+
+
/datum/hud/human/persistant_inventory_update(mob/viewer)
if(!mymob)
return
+ ..()
var/mob/living/carbon/human/H = mymob
var/mob/screenmob = viewer || H
- if(screenmob.hud_used.hud_shown)
- if(H.s_store)
- H.s_store.screen_loc = ui_sstore1
- screenmob.client.screen += H.s_store
- if(H.wear_id)
- H.wear_id.screen_loc = ui_id
- screenmob.client.screen += H.wear_id
- if(H.belt)
- H.belt.screen_loc = ui_belt
- screenmob.client.screen += H.belt
- if(H.back)
- H.back.screen_loc = ui_back
- screenmob.client.screen += H.back
- if(H.l_store)
- H.l_store.screen_loc = ui_storage1
- screenmob.client.screen += H.l_store
- if(H.r_store)
- H.r_store.screen_loc = ui_storage2
- screenmob.client.screen += H.r_store
- else
- if(H.s_store)
- screenmob.client.screen -= H.s_store
- if(H.wear_id)
- screenmob.client.screen -= H.wear_id
- if(H.belt)
- screenmob.client.screen -= H.belt
- if(H.back)
- screenmob.client.screen -= H.back
- if(H.l_store)
- screenmob.client.screen -= H.l_store
- if(H.r_store)
- screenmob.client.screen -= H.r_store
+
+ if(screenmob.hud_used)
+ if(screenmob.hud_used.hud_shown)
+ if(H.s_store)
+ H.s_store.screen_loc = ui_sstore1
+ screenmob.client.screen += H.s_store
+ if(H.wear_id)
+ H.wear_id.screen_loc = ui_id
+ screenmob.client.screen += H.wear_id
+ if(H.belt)
+ H.belt.screen_loc = ui_belt
+ screenmob.client.screen += H.belt
+ if(H.back)
+ H.back.screen_loc = ui_back
+ screenmob.client.screen += H.back
+ if(H.l_store)
+ H.l_store.screen_loc = ui_storage1
+ screenmob.client.screen += H.l_store
+ if(H.r_store)
+ H.r_store.screen_loc = ui_storage2
+ screenmob.client.screen += H.r_store
+ else
+ if(H.s_store)
+ screenmob.client.screen -= H.s_store
+ if(H.wear_id)
+ screenmob.client.screen -= H.wear_id
+ if(H.belt)
+ screenmob.client.screen -= H.belt
+ if(H.back)
+ screenmob.client.screen -= H.back
+ if(H.l_store)
+ screenmob.client.screen -= H.l_store
+ if(H.r_store)
+ screenmob.client.screen -= H.r_store
if(hud_version != HUD_STYLE_NOHUD)
for(var/obj/item/I in H.held_items)
I.screen_loc = ui_hand_position(H.get_held_index_of_item(I))
- H.client.screen += I
+ screenmob.client.screen += I
else
for(var/obj/item/I in H.held_items)
I.screen_loc = null
- H.client.screen -= I
+ screenmob.client.screen -= I
+
/mob/living/carbon/human/verb/toggle_hotkey_verbs()
set category = "OOC"
diff --git a/code/_onclick/hud/monkey.dm b/code/_onclick/hud/monkey.dm
index dd6ec4bef44..588d212375a 100644
--- a/code/_onclick/hud/monkey.dm
+++ b/code/_onclick/hud/monkey.dm
@@ -16,6 +16,11 @@
using.screen_loc = ui_movi
static_inventory += using
+ using = new/obj/screen/wheel/talk
+ using.icon = ui_style
+ wheels += using
+ static_inventory += using
+
using = new /obj/screen/drop()
using.icon = ui_style
using.screen_loc = ui_drop_throw
diff --git a/code/_onclick/hud/other_mobs.dm b/code/_onclick/hud/other_mobs.dm
index ac42696bc56..af7eabd8e9a 100644
--- a/code/_onclick/hud/other_mobs.dm
+++ b/code/_onclick/hud/other_mobs.dm
@@ -11,31 +11,3 @@
if(client && !hud_used)
hud_used = new /datum/hud/brain(src)
-/datum/hud/hog_god/New(mob/owner)
- ..()
- healths = new /obj/screen/healths/deity()
- infodisplay += healths
-
- deity_power_display = new /obj/screen/deity_power_display()
- infodisplay += deity_power_display
-
- deity_follower_display = new /obj/screen/deity_follower_display()
- infodisplay += deity_follower_display
-
-
-/mob/camera/god/create_mob_hud()
- if(client && !hud_used)
- hud_used = new /datum/hud/hog_god(src)
-
-/obj/screen/deity_power_display
- name = "Faith"
- icon_state = "deity_power"
- screen_loc = ui_deitypower
- layer = HUD_LAYER
-
-/obj/screen/deity_follower_display
- name = "Followers"
- icon_state = "deity_followers"
- screen_loc = ui_deityfollowers
- layer = HUD_LAYER
-
diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm
index aaf740f479e..0e8129962ec 100644
--- a/code/_onclick/hud/robot.dm
+++ b/code/_onclick/hud/robot.dm
@@ -93,6 +93,11 @@
var/mob/living/silicon/robot/mymobR = mymob
var/obj/screen/using
+ using = new/obj/screen/wheel/talk
+ using.screen_loc = ui_borg_talk_wheel
+ wheels += using
+ static_inventory += using
+
//Radio
using = new /obj/screen/robot/radio()
using.screen_loc = ui_borg_radio
@@ -245,20 +250,21 @@
var/mob/screenmob = viewer || R
- if(screenmob.hud_used.hud_shown)
- if(R.module_state_1)
- R.module_state_1.screen_loc = ui_inv1
- screenmob.client.screen += R.module_state_1
- if(R.module_state_2)
- R.module_state_2.screen_loc = ui_inv2
- screenmob.client.screen += R.module_state_2
- if(R.module_state_3)
- R.module_state_3.screen_loc = ui_inv3
- screenmob.client.screen += R.module_state_3
- else
- if(R.module_state_1)
- screenmob.client.screen -= R.module_state_1
- if(R.module_state_2)
- screenmob.client.screen -= R.module_state_2
- if(R.module_state_3)
- screenmob.client.screen -= R.module_state_3
\ No newline at end of file
+ if(screenmob.hud_used)
+ if(screenmob.hud_used.hud_shown)
+ if(R.module_state_1)
+ R.module_state_1.screen_loc = ui_inv1
+ screenmob.client.screen += R.module_state_1
+ if(R.module_state_2)
+ R.module_state_2.screen_loc = ui_inv2
+ screenmob.client.screen += R.module_state_2
+ if(R.module_state_3)
+ R.module_state_3.screen_loc = ui_inv3
+ screenmob.client.screen += R.module_state_3
+ else
+ if(R.module_state_1)
+ screenmob.client.screen -= R.module_state_1
+ if(R.module_state_2)
+ screenmob.client.screen -= R.module_state_2
+ if(R.module_state_3)
+ screenmob.client.screen -= R.module_state_3
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index cb9c698efaf..8dedf4b91b7 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -480,3 +480,139 @@
/obj/screen/healthdoll
name = "health doll"
screen_loc = ui_healthdoll
+
+
+
+/obj/screen/wheel
+ name = "wheel"
+ layer = HUD_LAYER
+ icon_state = ""
+ screen_loc = null //if you make a new wheel, remember to give it a screen_loc
+ var/list/buttons_names = list() //list of the names for each button, its length is the amount of buttons.
+ var/toggled = 0 //wheel is hidden/shown
+ var/wheel_buttons_type //the type of buttons used with this wheel.
+ var/list/buttons_list = list()
+
+/obj/screen/wheel/New()
+ ..()
+ build_options()
+
+
+//we create the buttons for the wheel and place them in a square spiral fashion.
+/obj/screen/wheel/proc/build_options()
+ var/obj/screen/wheel_button/close_wheel/CW = new ()
+ buttons_list += CW //the close option
+ CW.wheel = src
+
+ var/list/offset_x_list = list()
+ var/list/offset_y_list = list()
+ var/num = 1
+ var/N = 1
+ var/M = 0
+ var/sign = -1
+ my_loop:
+ while(offset_y_list.len < buttons_names.len)
+ for(var/i=1, i<=num, i++)
+ offset_y_list += N
+ offset_x_list += M
+ if(offset_y_list.len == buttons_names.len)
+ break my_loop
+ if(N != 0)
+ N = 0
+ M = -sign
+ else
+ N = sign
+ M = 0
+ sign = -sign
+ num++
+
+ var/screenx = 8
+ var/screeny = 8
+ for(var/i = 1, i <= buttons_names.len, i++)
+ var/obj/screen/wheel_button/WB = new wheel_buttons_type()
+ WB.wheel = src
+ buttons_list += WB
+ screenx += offset_x_list[i]
+ screeny += offset_y_list[i]
+ WB.screen_loc = "[screenx], [screeny]"
+ set_button(WB, i)
+
+/obj/screen/wheel/proc/set_button(obj/screen/wheel_button/WB, button_number)
+ WB.name = buttons_names[button_number]
+ return
+
+/obj/screen/wheel/Destroy()
+ for(var/obj/screen/S in buttons_list)
+ qdel(S)
+ return ..()
+
+/obj/screen/wheel/Click()
+ if(world.time <= usr.next_move)
+ return
+ if(usr.stat)
+ return
+ if(isliving(usr))
+ var/mob/living/L = usr
+ if(toggled)
+ L.client.screen -= buttons_list
+ else
+ L.client.screen |= buttons_list
+ toggled = !toggled
+
+
+/obj/screen/wheel/talk
+ name = "talk wheel"
+ icon_state = "talk_wheel"
+ screen_loc = "11:6,2:-11"
+ wheel_buttons_type = /obj/screen/wheel_button/talk
+ buttons_names = list("help","hello","bye","stop","thanks","come","out", "yes", "no")
+ var/list/word_messages = list(list("Help!","Help me!"), list("Hello.", "Hi."), list("Bye.", "Goodbye."),\
+ list("Stop!", "Halt!"), list("Thanks.", "Thanks!", "Thank you."), \
+ list("Come.", "Follow me."), list("Out!", "Go away!", "Get out!"), \
+ list("Yes.", "Affirmative."), list("No.", "Negative"))
+
+/obj/screen/wheel/talk/set_button(obj/screen/wheel_button/WB, button_number)
+ ..()
+ var/obj/screen/wheel_button/talk/T = WB //we already know what type the button is exactly.
+ T.icon_state = "talk_[T.name]"
+ T.word_messages = word_messages[button_number]
+
+
+/obj/screen/wheel_button
+ name = "default wheel button"
+ screen_loc = "8,8"
+ layer = HUD_LAYER
+ mouse_opacity = 2
+ var/obj/screen/wheel/wheel
+
+/obj/screen/wheel_button/Destroy()
+ wheel = null
+ return ..()
+
+/obj/screen/wheel_button/close_wheel
+ name = "close wheel"
+ icon_state = "x3"
+
+/obj/screen/wheel_button/close_wheel/Click()
+ if(isliving(usr))
+ var/mob/living/L = usr
+ L.client.screen -= wheel.buttons_list
+ wheel.toggled = !wheel.toggled
+
+
+/obj/screen/wheel_button/talk
+ name = "talk option"
+ icon_state = "talk_help"
+ var/talk_cooldown = 0
+ var/list/word_messages = list()
+
+/obj/screen/wheel_button/talk/Click(location, control,params)
+ if(isliving(usr))
+ var/mob/living/L = usr
+ if(L.stat)
+ return
+
+ if(word_messages.len && talk_cooldown < world.time)
+ talk_cooldown = world.time + 10
+ L.say(pick(word_messages))
+
diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index bce1a852783..333d7447396 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -184,6 +184,7 @@
var/grey_assistants = 0
var/lavaland_budget = 60
+ var/space_budget = 16
var/aggressive_changelog = 0
@@ -620,6 +621,8 @@
config.grey_assistants = 1
if("lavaland_budget")
config.lavaland_budget = text2num(value)
+ if("space_budget")
+ config.space_budget = text2num(value)
if("no_summon_guns")
config.no_summon_guns = 1
if("no_summon_magic")
diff --git a/code/controllers/master.dm b/code/controllers/master.dm
index 6c0658aa2e7..43155df2247 100644
--- a/code/controllers/master.dm
+++ b/code/controllers/master.dm
@@ -35,6 +35,8 @@ var/CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING
var/init_time
var/tickdrift = 0
+ var/sleep_delta
+
var/make_runtime = 0
// Has round started? (So we know what subsystems to run)
@@ -280,6 +282,7 @@ var/CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING
iteration++
last_run = world.time
+ src.sleep_delta = MC_AVERAGE_FAST(src.sleep_delta, sleep_delta)
sleep(world.tick_lag * (processing + sleep_delta))
diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm
index b39fca4a6e1..f86153f34f0 100644
--- a/code/controllers/subsystem/mapping.dm
+++ b/code/controllers/subsystem/mapping.dm
@@ -34,7 +34,7 @@ var/datum/subsystem/mapping/SSmapping
else
space_zlevels += i
- seedRuins(space_zlevels, rand(8,16), /area/space, space_ruins_templates)
+ seedRuins(space_zlevels, config.space_budget, /area/space, space_ruins_templates)
// Set up Z-level transistions.
setup_map_transitions()
diff --git a/code/controllers/subsystem/minimap.dm b/code/controllers/subsystem/minimap.dm
index 421d9ba312d..d651cabd498 100644
--- a/code/controllers/subsystem/minimap.dm
+++ b/code/controllers/subsystem/minimap.dm
@@ -13,25 +13,55 @@ var/datum/subsystem/minimap/SSminimap
NEW_SS_GLOBAL(SSminimap)
/datum/subsystem/minimap/Initialize(timeofday)
- if(!config.generate_minimaps)
- world << "Minimap generation disabled... Skipping"
- return
var/hash = md5(file2text("_maps/[MAP_PATH]/[MAP_FILE]"))
- if(hash == trim(file2text(hash_path())))
- return ..()
-
- for(var/z in z_levels)
- generate(z)
- register_asset("minimap_[z].png", fcopy_rsc(map_path(z)))
- fdel(hash_path())
- text2file(hash, hash_path())
+ if(config.generate_minimaps)
+ if(hash == trim(file2text(hash_path())))
+ for(var/z in z_levels) //We have these files cached, let's register them
+ register_asset("minimap_[z].png", fcopy_rsc(map_path(z)))
+ return ..()
+ for(var/z in z_levels)
+ generate(z)
+ register_asset("minimap_[z].png", fcopy_rsc(map_path(z)))
+ fdel(hash_path())
+ text2file(hash, hash_path())
+ else
+ world << "Minimap generation disabled. Loading from cache..."
+ var/fileloc = 0
+ if(check_files(0)) //Let's first check if we have maps cached in the data folder. NOTE: This will override the backup files even if this map is older.
+ world.log << "cache"
+ if(hash != trim(file2text(hash_path())))
+ world << "Loaded cached minimap is outdated. There may be minor discrepancies in layout." //Disclaimer against players saying map is wrong.
+ fileloc = 0
+ else
+ if(!check_files(1))
+ world << "Failed to load backup minimap file. Aborting." //We couldn't find something. Bail to prevent issues with null files
+ return
+ fileloc = 1 //No map image cached with the current map, and we have a backup. Let's fall back to it.
+ world << "No cached minimaps detected. Backup files loaded."
+ for(var/z in z_levels)
+ register_asset("minimap_[z].png", fcopy_rsc(map_path(z,fileloc)))
..()
-/datum/subsystem/minimap/proc/hash_path()
- return "data/minimaps/[MAP_NAME].md5"
+/datum/subsystem/minimap/proc/check_files(backup) // If the backup argument is true, looks in the icons folder. If false looks in the data folder.
+ for(var/z in z_levels)
+ if(!fexists(file(map_path(z,backup)))) //Let's make sure we have a file for this map
+ if(backup)
+ world.log << "Failed to find backup file for map [MAP_NAME] on zlevel [z]."
+ return FALSE
+ return TRUE
-/datum/subsystem/minimap/proc/map_path(z)
- return "data/minimaps/[MAP_NAME]_[z].png"
+
+/datum/subsystem/minimap/proc/hash_path(backup)
+ if(backup)
+ return "icons/minimaps/[MAP_NAME].md5"
+ else
+ return "data/minimaps/[MAP_NAME].md5"
+
+/datum/subsystem/minimap/proc/map_path(z,backup)
+ if(backup)
+ return "icons/minimaps/[MAP_NAME]_[z].png"
+ else
+ return "data/minimaps/[MAP_NAME]_[z].png"
/datum/subsystem/minimap/proc/send(client/client)
for(var/z in z_levels)
@@ -43,24 +73,10 @@ var/datum/subsystem/minimap/SSminimap
// Scale it up to our target size.
minimap.Scale(MINIMAP_SIZE, MINIMAP_SIZE)
- var/counter = 512
// Loop over turfs and generate icons.
for(var/T in block(locate(x1, y1, z), locate(x2, y2, z)))
generate_tile(T, minimap)
- //byond bug, this fixes OOM crashes by flattening and reseting the minimap icon holder every so and so tiles
- counter--
- if(counter <= 0)
- counter = 512
- var/icon/flatten = new /icon()
- flatten.Insert(minimap, "", SOUTH, 1, 0)
- del(minimap)
- minimap = flatten
- stoplag() //we have to sleep in order to get byond to clear out the proc's garbage bin
-
- CHECK_TICK
-
-
// Create a new icon and insert the generated minimap, so that BYOND doesn't generate different directions.
var/icon/final = new /icon()
final.Insert(minimap, "", SOUTH, 1, 0)
@@ -69,7 +85,7 @@ var/datum/subsystem/minimap/SSminimap
/datum/subsystem/minimap/proc/generate_tile(turf/tile, icon/minimap)
var/icon/tile_icon
var/obj/obj
- var/list/obj_icons = list()
+ var/list/obj_icons
// Don't use icons for space, just add objects in space if they exist.
if(istype(tile, /turf/open/space))
obj = locate(/obj/structure/lattice/catwalk) in tile
@@ -86,18 +102,20 @@ var/datum/subsystem/minimap/SSminimap
tile_icon = new /icon('icons/obj/atmospherics/pipes/transit_tube.dmi', obj.icon_state, obj.dir)
else
tile_icon = new /icon(tile.icon, tile.icon_state, tile.dir)
- obj_icons.Cut()
+ obj_icons = list()
obj = locate(/obj/structure) in tile
if(obj)
- obj_icons += getFlatIcon(obj)
+ obj_icons += new /icon(obj.icon, obj.icon_state, obj.dir, 1, 0)
obj = locate(/obj/machinery) in tile
if(obj)
obj_icons += new /icon(obj.icon, obj.icon_state, obj.dir, 1, 0)
obj = locate(/obj/structure/window) in tile
if(obj)
obj_icons += new /icon('icons/obj/smooth_structures/window.dmi', "window", SOUTH)
-
+ obj = locate(/obj/structure/table) in tile
+ if(obj)
+ obj_icons += new /icon('icons/obj/smooth_structures/table.dmi', "table", SOUTH)
for(var/I in obj_icons)
var/icon/obj_icon = I
tile_icon.Blend(obj_icon, ICON_OVERLAY)
@@ -107,4 +125,3 @@ var/datum/subsystem/minimap/SSminimap
tile_icon.Scale(TILE_SIZE, TILE_SIZE)
// Add the tile to the minimap.
minimap.Blend(tile_icon, ICON_OVERLAY, ((tile.x - 1) * TILE_SIZE), ((tile.y - 1) * TILE_SIZE))
- del(tile_icon)
diff --git a/code/controllers/subsystem/spacedrift.dm b/code/controllers/subsystem/spacedrift.dm
new file mode 100644
index 00000000000..856f51ce7ac
--- /dev/null
+++ b/code/controllers/subsystem/spacedrift.dm
@@ -0,0 +1,64 @@
+var/datum/subsystem/spacedrift/SSspacedrift
+
+/datum/subsystem/spacedrift
+ name = "Space Drift"
+ priority = 40
+ wait = 5
+ flags = SS_NO_INIT|SS_BACKGROUND
+
+ var/list/currentrun = list()
+ var/list/processing = list()
+
+/datum/subsystem/spacedrift/New()
+ NEW_SS_GLOBAL(SSspacedrift)
+
+
+/datum/subsystem/spacedrift/stat_entry()
+ ..("P:[processing.len]")
+
+
+/datum/subsystem/spacedrift/fire(resumed = 0)
+ if (!resumed)
+ src.currentrun = processing.Copy()
+
+ //cache for sanic speed (lists are references anyways)
+ var/list/currentrun = src.currentrun
+
+ while (currentrun.len)
+ var/atom/movable/AM = currentrun[currentrun.len]
+ currentrun.len--
+ if (!AM)
+ processing -= AM
+ if (MC_TICK_CHECK)
+ return
+ continue
+
+ if (AM.inertia_next_move > world.time)
+ if (MC_TICK_CHECK)
+ return
+ continue
+
+ if (!AM.loc || AM.loc != AM.inertia_last_loc || AM.Process_Spacemove(0))
+ AM.inertia_dir = 0
+
+ if (!AM.inertia_dir)
+ AM.inertia_last_loc = null
+ processing -= AM
+ if (MC_TICK_CHECK)
+ return
+ continue
+
+ var/old_dir = AM.dir
+ var/old_loc = AM.loc
+ AM.inertia_moving = TRUE
+ step(AM, AM.inertia_dir)
+ AM.inertia_moving = FALSE
+ AM.inertia_next_move = world.time + AM.inertia_move_delay
+ if (AM.loc == old_loc)
+ AM.inertia_dir = 0
+
+ AM.setDir(old_dir)
+ AM.inertia_last_loc = AM.loc
+ if (MC_TICK_CHECK)
+ return
+
diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm
index b9609214cc3..c00950a6fee 100644
--- a/code/datums/helper_datums/teleport.dm
+++ b/code/datums/helper_datums/teleport.dm
@@ -106,6 +106,8 @@
if(!center)
center = destination
for(var/turf/T in range(precision,center))
+ if(T.is_transition_turf())
+ continue // Avoid picking these.
var/area/A = T.loc
if(!A.noteleport)
posturfs.Add(T)
@@ -114,7 +116,7 @@
else
destturf = get_turf(destination)
- if(!destturf || !curturf)
+ if(!destturf || !curturf || destturf.is_transition_turf())
return 0
var/area/A = get_area(curturf)
diff --git a/code/datums/hud.dm b/code/datums/hud.dm
index 62c1700f58d..75adb165d3a 100644
--- a/code/datums/hud.dm
+++ b/code/datums/hud.dm
@@ -12,8 +12,6 @@ var/datum/atom_hud/huds = list( \
ANTAG_HUD_OPS = new/datum/atom_hud/antag(), \
ANTAG_HUD_WIZ = new/datum/atom_hud/antag(), \
ANTAG_HUD_SHADOW = new/datum/atom_hud/antag(), \
- ANTAG_HUD_HOG_BLUE = new/datum/atom_hud/antag(),\
- ANTAG_HUD_HOG_RED = new/datum/atom_hud/antag(),\
ANTAG_HUD_TRAITOR = new/datum/atom_hud/antag/hidden(),\
ANTAG_HUD_NINJA = new/datum/atom_hud/antag/hidden(),\
ANTAG_HUD_CHANGELING = new/datum/atom_hud/antag/hidden(),\
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 61c61673d11..b335ccdd762 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -174,16 +174,6 @@
ticker.mode.remove_gangster(src,0,1,1)
remove_objectives()
-/datum/mind/proc/remove_hog_follower_prophet()
- ticker.mode.red_deity_followers -= src
- ticker.mode.red_deity_prophets -= src
- ticker.mode.blue_deity_prophets -= src
- ticker.mode.blue_deity_followers -= src
- ticker.mode.update_hog_icons_removed(src, "red")
- ticker.mode.update_hog_icons_removed(src, "blue")
-
-
-
/datum/mind/proc/remove_antag_equip()
var/list/Mob_Contents = current.get_contents()
for(var/obj/item/I in Mob_Contents)
@@ -221,12 +211,6 @@
else if(is_gangster(creator))
ticker.mode.add_gangster(src, creator.mind.gang_datum, TRUE)
- else if(is_handofgod_redcultist(creator) || is_handofgod_redprophet(creator))
- ticker.mode.add_hog_follower(src, "Red")
-
- else if(is_handofgod_bluecultist(creator) || is_handofgod_blueprophet(creator))
- ticker.mode.add_hog_follower(src, "Blue")
-
else if(is_revolutionary_in_general(creator))
ticker.mode.add_revolutionary(src)
@@ -490,38 +474,6 @@
sections["traitor"] = text
- /** HAND OF GOD **/
- text = "hand of god"
- if(ticker.mode.config_tag == "handofgod")
- text = uppertext(text)
- text = "[text]: "
- if (src in ticker.mode.red_deities)
- text += "RED GOD|red prophet|red follower|employee|blue god|blue prophet|blue follower"
- else if(src in ticker.mode.red_deity_prophets)
- text += "red god|RED PROPHET|red follower|employee|blue god|blue prophet|blue follower"
- else if (src in ticker.mode.red_deity_followers)
- text += "red god|red prophet|RED FOLLOWER|employee|blue god|blue prophet|blue follower"
- else if (src in ticker.mode.blue_deities)
- text += "red god|red prophet|red follower|employee|BLUE GOD|blue prophet|blue follower"
- else if (src in ticker.mode.blue_deity_prophets)
- text += "red god|red prophet|red follower|employee|blue god|BLUE PROPHET|blue follower"
- else if (src in ticker.mode.blue_deity_followers)
- text += "red god|red prophet|red follower|employee|blue god|blue prophet|BLUE FOLLOWER"
- else
- text += "red god|red prophet|red follower|EMPLOYEE|blue god|blue prophet|blue follower"
-
- if(current && current.client && (ROLE_HOG_GOD in current.client.prefs.be_special))
- text += "|HOG God Enabled in Prefs"
- else
- text += "|HOG God Disabled in Prefs"
-
- if(current && current.client && (ROLE_HOG_CULTIST in current.client.prefs.be_special))
- text += "|HOG Cultist Enabled in Prefs"
- else
- text += "|HOG Disabled in Prefs"
-
- sections["follower"] = text
-
if(ishuman(current) || ismonkey(current))
/** CHANGELING ***/
@@ -696,7 +648,7 @@
if(!def_value)//If it's a custom objective, it will be an empty string.
def_value = "custom"
- var/new_obj_type = input("Select objective type:", "Objective type", def_value) as null|anything in list("assassinate", "maroon", "debrain", "protect", "destroy", "prevent", "hijack", "escape", "survive", "martyr", "steal", "download", "nuclear", "capture", "absorb", "custom","follower block (HOG)","build (HOG)","deicide (HOG)", "follower escape (HOG)", "sacrifice prophet (HOG)")
+ var/new_obj_type = input("Select objective type:", "Objective type", def_value) as null|anything in list("assassinate", "maroon", "debrain", "protect", "destroy", "prevent", "hijack", "escape", "survive", "martyr", "steal", "download", "nuclear", "capture", "absorb", "custom")
if (!new_obj_type)
return
@@ -798,22 +750,6 @@
new_objective.owner = src
new_objective.target_amount = target_number
- if("follower block (HOG)")
- new_objective = new /datum/objective/follower_block
- new_objective.owner = src
- if("build (HOG)")
- new_objective = new /datum/objective/build
- new_objective.owner = src
- if("deicide (HOG)")
- new_objective = new /datum/objective/deicide
- new_objective.owner = src
- if("follower escape (HOG)")
- new_objective = new /datum/objective/escape_followers
- new_objective.owner = src
- if("sacrifice prophet (HOG)")
- new_objective = new /datum/objective/sacrifice_prophet
- new_objective.owner = src
-
if ("custom")
var/expl = stripped_input(usr, "Custom objective:", "Objective", objective ? objective.explanation_text : "")
if (!expl)
@@ -850,46 +786,6 @@
objective.completed = !objective.completed
log_admin("[key_name(usr)] toggled the win state for [current]'s objective: [objective.explanation_text]")
- else if (href_list["handofgod"])
- switch(href_list["handofgod"])
- if("clear") //wipe handofgod status
- if((src in ticker.mode.red_deity_followers) || (src in ticker.mode.blue_deity_followers) || (src in ticker.mode.red_deity_prophets) || (src in ticker.mode.blue_deity_prophets))
- remove_hog_follower_prophet()
- current << "You have been brainwashed... again! Your faith is no more!"
- message_admins("[key_name_admin(usr)] has de-hand of god'ed [current].")
- log_admin("[key_name(usr)] has de-hand of god'ed [current].")
-
- if("red follower")
- make_Handofgod_follower("red")
- message_admins("[key_name_admin(usr)] has red follower'ed [current].")
- log_admin("[key_name(usr)] has red follower'ed [current].")
-
- if("red prophet")
- make_Handofgod_prophet("red")
- message_admins("[key_name_admin(usr)] has red prophet'ed [current].")
- log_admin("[key_name(usr)] has red prophet'ed [current].")
-
- if("blue follower")
- make_Handofgod_follower("blue")
- message_admins("[key_name_admin(usr)] has blue follower'ed [current].")
- log_admin("[key_name(usr)] has blue follower'ed [current].")
-
- if("blue prophet")
- make_Handofgod_prophet("blue")
- message_admins("[key_name_admin(usr)] has blue prophet'ed [current].")
- log_admin("[key_name(usr)] has blue prophet'ed [current].")
-
- if("red god")
- make_Handofgod_god("red")
- message_admins("[key_name_admin(usr)] has red god'ed [current].")
- log_admin("[key_name(usr)] has red god'ed [current].")
-
- if("blue god")
- make_Handofgod_god("blue")
- message_admins("[key_name_admin(usr)] has blue god'ed [current].")
- log_admin("[key_name(usr)] has blue god'ed [current].")
-
-
else if (href_list["revolution"])
switch(href_list["revolution"])
if("clear")
@@ -1563,119 +1459,6 @@
L = agent_landmarks[team]
H.loc = L.loc
-
-/datum/mind/proc/make_Handofgod_follower(colour)
- . = 0
- switch(colour)
- if("red")
- //Remove old allegiances
- if(src in ticker.mode.blue_deity_followers || src in ticker.mode.blue_deity_prophets)
- current << "You are no longer a member of the Blue cult!"
-
- ticker.mode.blue_deity_followers -= src
- ticker.mode.blue_deity_prophets -= src
- current.faction |= "red god"
- current.faction -= "blue god"
-
- if(src in ticker.mode.red_deity_prophets)
- current << "You have lost the connection with your deity, but you still believe in their grand design, You are no longer a prophet!"
- ticker.mode.red_deity_prophets -= src
-
- ticker.mode.red_deity_followers |= src
- current << "You are now a follower of the red cult's god!"
-
- special_role = "Hand of God: Red Follower"
- . = 1
- if("blue")
- //Remove old allegiances
- if(src in ticker.mode.red_deity_followers || src in ticker.mode.red_deity_prophets)
- current << "You are no longer a member of the Red cult!"
-
- ticker.mode.red_deity_followers -= src
- ticker.mode.red_deity_prophets -= src
- current.faction -= "red god"
- current.faction |= "blue god"
-
- if(src in ticker.mode.blue_deity_prophets)
- current << "You have lost the connection with your deity, but you still believe in their grand design, You are no longer a prophet!"
- ticker.mode.blue_deity_prophets -= src
-
- ticker.mode.blue_deity_followers |= src
- current << "You are now a follower of the blue cult's god!"
-
- special_role = "Hand of God: Blue Follower"
- . = 1
- else
- return 0
-
- ticker.mode.update_hog_icons_removed(src,"red")
- ticker.mode.update_hog_icons_removed(src,"blue")
- //ticker.mode.greet_hog_follower(src,colour)
- ticker.mode.update_hog_icons_added(src, colour)
-
-/datum/mind/proc/make_Handofgod_prophet(colour)
- . = 0
- switch(colour)
- if("red")
- //Remove old allegiances
-
- if(src in ticker.mode.blue_deity_followers || src in ticker.mode.blue_deity_prophets)
- current << "You are no longer a member of the Blue cult!"
- current.faction -= "blue god"
- current.faction |= "red god"
-
- ticker.mode.blue_deity_followers -= src
- ticker.mode.blue_deity_prophets -= src
- ticker.mode.red_deity_followers -= src
-
- ticker.mode.red_deity_prophets |= src
- current << "You are now a prophet of the red cult's god!"
-
- special_role = "Hand of God: Red Prophet"
- . = 1
- if("blue")
- //Remove old allegiances
-
- if(src in ticker.mode.red_deity_followers || src in ticker.mode.red_deity_prophets)
- current << "You are no longer a member of the Red cult!"
- current.faction -= "red god"
- current.faction |= "blue god"
-
- ticker.mode.red_deity_followers -= src
- ticker.mode.red_deity_prophets -= src
- ticker.mode.blue_deity_followers -= src
-
- ticker.mode.blue_deity_prophets |= src
- current << "You are now a prophet of the blue cult's god!"
-
- special_role = "Hand of God: Blue Prophet"
- . = 1
-
- else
- return 0
-
- ticker.mode.update_hog_icons_removed(src,"red")
- ticker.mode.update_hog_icons_removed(src,"blue")
- ticker.mode.greet_hog_follower(src,colour)
- ticker.mode.update_hog_icons_added(src, colour)
-
-/datum/mind/proc/make_Handofgod_god(colour)
- switch(colour)
- if("red")
- current.become_god("red")
- ticker.mode.add_god(src,"red")
- if("blue")
- current.become_god("blue")
- ticker.mode.add_god(src,"blue")
- else
- return 0
- ticker.mode.forge_deity_objectives(src)
- ticker.mode.remove_hog_follower(src,0)
- ticker.mode.update_hog_icons_added(src, colour)
-// ticker.mode.greet_hog_follower(src,colour)
- return 1
-
-
/datum/mind/proc/AddSpell(obj/effect/proc_holder/spell/S)
spell_list += S
S.action.Grant(current)
diff --git a/code/datums/weather/weather.dm b/code/datums/weather/weather.dm
index c1afdea4ca6..a02e516c942 100644
--- a/code/datums/weather/weather.dm
+++ b/code/datums/weather/weather.dm
@@ -109,7 +109,8 @@
update_areas()
/datum/weather/proc/can_impact(mob/living/L) //Can this weather impact a mob?
- if(L.z != target_z)
+ var/turf/mob_turf = get_turf(L)
+ if(mob_turf.z != target_z)
return
if(immunity_type in L.weather_immunities)
return
diff --git a/code/datums/wires/wires.dm b/code/datums/wires/wires.dm
index bf749e18e5f..cf4b1f1e862 100644
--- a/code/datums/wires/wires.dm
+++ b/code/datums/wires/wires.dm
@@ -1,121 +1,20 @@
-var/list/wire_colors = list( // http://www.crockford.com/wrrrld/color.html
- "aliceblue",
- "antiquewhite",
- "aqua",
- "aquamarine",
- "beige",
- "blanchedalmond",
+var/list/wire_colors = list(
"blue",
- "blueviolet",
"brown",
- "burlywood",
- "cadetblue",
- "chartreuse",
- "chocolate",
- "coral",
- "cornflowerblue",
- "cornsilk",
"crimson",
"cyan",
- "deeppink",
- "deepskyblue",
- "dimgray",
- "dodgerblue",
- "firebrick",
- "floralwhite",
- "forestgreen",
- "fuchsia",
- "gainsboro",
- "ghostwhite",
"gold",
- "goldenrod",
- "gray",
+ "grey",
"green",
- "greenyellow",
- "honeydew",
- "hotpink",
- "indianred",
- "ivory",
- "khaki",
- "lavender",
- "lavenderblush",
- "lawngreen",
- "lemonchiffon",
- "lightblue",
- "lightcoral",
- "lightcyan",
- "lightgoldenrodyellow",
- "lightgray",
- "lightgreen",
- "lightpink",
- "lightsalmon",
- "lightseagreen",
- "lightskyblue",
- "lightslategray",
- "lightsteelblue",
- "lightyellow",
- "lime",
- "limegreen",
- "linen",
"magenta",
- "maroon",
- "mediumaquamarine",
- "mediumblue",
- "mediumorchid",
- "mediumpurple",
- "mediumseagreen",
- "mediumslateblue",
- "mediumspringgreen",
- "mediumturquoise",
- "mediumvioletred",
- "mintcream",
- "mistyrose",
- "moccasin",
- "navajowhite",
- "oldlace",
- "olive",
- "olivedrab",
"orange",
- "orangered",
- "orchid",
- "palegoldenrod",
- "palegreen",
- "paleturquoise",
- "palevioletred",
- "papayawhip",
- "peachpuff",
- "peru",
"pink",
- "plum",
- "powderblue",
"purple",
"red",
- "rosybrown",
- "royalblue",
- "saddlebrown",
- "salmon",
- "sandybrown",
- "seagreen",
- "seashell",
- "sienna",
"silver",
- "skyblue",
- "slateblue",
- "slategray",
- "snow",
- "springgreen",
- "steelblue",
- "tan",
- "teal",
- "thistle",
- "tomato",
- "turquoise",
"violet",
- "wheat",
"white",
- "whitesmoke",
"yellow",
- "yellowgreen",
)
var/list/wire_color_directory = list()
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 8162b451dc8..e71b533d3c8 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -13,6 +13,10 @@
var/verb_exclaim = "exclaims"
var/verb_yell = "yells"
var/inertia_dir = 0
+ var/atom/inertia_last_loc
+ var/inertia_moving = 0
+ var/inertia_next_move = 0
+ var/inertia_move_delay = 5
var/pass_flags = 0
var/moving_diagonally = 0 //0: not doing a diagonal move. 1 and 2: doing the first/second step of the diagonal move
glide_size = 8
@@ -70,20 +74,16 @@
last_move = direct
setDir(direct)
-
- spawn(5) // Causes space drifting. /tg/station has no concept of speed, we just use 5
- if(loc && direct && last_move == direct)
- if(loc == newloc) //Remove this check and people can accelerate. Not opening that can of worms just yet.
- newtonian_move(last_move)
-
if(. && has_buckled_mobs() && !handle_buckled_mob_movement(loc,direct)) //movement failed due to buckled mob(s)
. = 0
//Called after a successful Move(). By this point, we've already moved
/atom/movable/proc/Moved(atom/OldLoc, Dir)
+ if (!inertia_moving)
+ inertia_next_move = world.time + inertia_move_delay
+ newtonian_move(Dir)
return 1
-
/atom/movable/Destroy()
. = ..()
if(loc)
@@ -172,13 +172,16 @@
if(pulledby)
return 1
+ if(throwing)
+ return 1
+
if(locate(/obj/structure/lattice) in range(1, get_turf(src))) //Not realistic but makes pushing things in space easier
return 1
return 0
-/atom/movable/proc/newtonian_move(direction) //Only moves the object if it's under no gravity
+/atom/movable/proc/newtonian_move(direction) //Only moves the object if it's under no gravity
if(!loc || Process_Spacemove(0))
inertia_dir = 0
return 0
@@ -186,10 +189,9 @@
inertia_dir = direction
if(!direction)
return 1
-
- var/old_dir = dir
- . = step(src, direction)
- setDir(old_dir)
+ inertia_last_loc = loc
+ SSspacedrift.processing[src] = src
+ return 1
/atom/movable/proc/checkpass(passflag)
return pass_flags&passflag
@@ -294,6 +296,7 @@
return 1
throw_impact(get_turf(src)) // we haven't hit something yet and we still must, let's hit the ground.
+ newtonian_move(init_dir)
return 1
/atom/movable/proc/hitcheck()
@@ -305,26 +308,6 @@
throw_impact(AM)
return 1
-//Overlays
-/atom/movable/overlay
- var/atom/master = null
- anchored = 1
-
-/atom/movable/overlay/New()
- verbs.Cut()
-
-/atom/movable/overlay/attackby(a, b, c)
- if (src.master)
- return src.master.attackby(a, b, c)
-
-/atom/movable/overlay/attack_paw(a, b, c)
- if (src.master)
- return src.master.attack_paw(a, b, c)
-
-/atom/movable/overlay/attack_hand(a, b, c)
- if (src.master)
- return src.master.attack_hand(a, b, c)
-
/atom/movable/proc/handle_buckled_mob_movement(newloc,direct)
for(var/m in buckled_mobs)
var/mob/living/buckled_mob = m
diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm
index fe14f5486f8..8cd3b7d2f89 100644
--- a/code/game/data_huds.dm
+++ b/code/game/data_huds.dm
@@ -61,10 +61,16 @@
//called when a carbon changes virus
/mob/living/carbon/proc/check_virus()
+ var/threat = 0
for(var/datum/disease/D in viruses)
- if((!(D.visibility_flags & HIDDEN_SCANNER)) && (D.severity != NONTHREAT))
- return 1
- return 0
+ if(!(D.visibility_flags & HIDDEN_SCANNER))
+ if (D.severity != NONTHREAT) //a buffing virus gets an icon
+ threat = 2
+ return threat //harmful viruses have priority
+ else
+ threat = 1 //aka good virus
+
+ return threat
//helper for getting the appropriate health status
/proc/RoundHealth(mob/living/M)
@@ -155,13 +161,16 @@
/mob/living/carbon/med_hud_set_status()
var/image/holder = hud_list[STATUS_HUD]
var/icon/I = icon(icon, icon_state, dir)
+ var/virus_state = check_virus()
holder.pixel_y = I.Height() - world.icon_size
if(status_flags & XENO_HOST)
holder.icon_state = "hudxeno"
else if(stat == DEAD || (status_flags & FAKEDEATH))
holder.icon_state = "huddead"
- else if(check_virus())
+ else if(virus_state == 2)
holder.icon_state = "hudill"
+ else if(virus_state == 1)
+ holder.icon_state = "hudbuff"
else
holder.icon_state = "hudhealthy"
diff --git a/code/game/gamemodes/clock_cult/clock_items.dm b/code/game/gamemodes/clock_cult/clock_items.dm
index d3164bffe80..a69220d5fe5 100644
--- a/code/game/gamemodes/clock_cult/clock_items.dm
+++ b/code/game/gamemodes/clock_cult/clock_items.dm
@@ -223,7 +223,7 @@
else
user << "That section of scripture is still locked!"
return 0
- for(var/S in subtypesof(/datum/clockwork_scripture))
+ for(var/S in sortList(subtypesof(/datum/clockwork_scripture), /proc/cmp_clockscripture_priority))
var/datum/clockwork_scripture/C = S
if(initial(C.tier) == scripture_tier)
available_scriptures += "[initial(C.name)] ([initial(C.descname)])"
@@ -265,121 +265,73 @@
universe and Reebe (the Celestial Derelict) can be created and utilized. This is typically done via the creation of a slab akin to the one you are holding right now. The slabs tap into the \
tidal flow of energy and information keeping Reebe sealed and presents it as meaningless images to preserve sanity. This slab can utilize the power in many different ways.
\
\
- This is done through Components - pieces of the Justiciar's body that have since fallen off in the countless years since his imprisonment. Ratvar's unfortunate condition results \
- in the fragmentation of his body. These components still house great power on their own, and can slowly be drawn from Reebe by links capable of doing so. The most basic of these links lies \
- in the clockwork slab, which will slowly generate components over time - one component of a random type is produced every 1 minute and 30 seconds, plus 30 seconds per each servant above 5, \
- which is obviously inefficient. There are other ways to create these components through scripture and certain structures.
\
+ This is done through Components - pieces of the Justiciar's body that have since fallen off in the countless years since his imprisonment. Ratvar's unfortunate condition results \
+ in the fragmentation of his body. These components still house great power on their own, and can slowly be drawn from Reebe by links capable of doing so.
\
+ The most basic of these links lies in the clockwork slab, which will slowly generate components over time - one component of a random type is produced every 1 minute and 30 seconds, plus 30 seconds per each servant above 5, \
+ which is obviously inefficient. There are other, more efficient, ways to create these components through scripture and certain structures.
\
\
- In addition to their ability to pull components, slabs also possess other functionalities...
\
+ In addition to their ability to generate components, slabs also possess other functionalities...
\
\
- The first functionality of the slab is Recital. This allows you to consume components either from your slab or from the global cache (more on that in the scripture list) to perform \
- effects usually considered magical in nature. Effects vary considerably - you might drain the power of nearby APCs, cause mass confusion, or force people to walk. Nevertheless, scripture \
- is extremely important to a successful takeover.
\
+ The first functionality of the slab is Recital. This allows you to consume components either from your slab or from the global cache (more on that in the scripture list) to perform \
+ effects usually considered magical in nature.
\
+ Effects vary considerably, including mass conversion, construction of various structures, or causing a massive global hallucination. Nevertheless, scripture is extremely important to a successful takeover.
\
\
- The second functionality of the clockwork slab is Recollection, which will display this guide.
\
+ The second functionality of the clockwork slab is Recollection, which will display this guide.
\
\
The third to fifth functionalities are several buttons in the top left while holding the slab, from left to right, they are:
\
- Hierophant Network, which allows communication to other servants.
\
- Guvax, which simply allows you to quickly invoke the Guvax scripture.
\
- Vanguard, which, like Guvax, simply allows you to quickly invoke the Vanguard scripture.
\
+ Hierophant Network, which allows communication to other servants.
\
+ Guvax, which simply allows you to quickly invoke the Guvax scripture.
\
+ Vanguard, which, like Guvax, simply allows you to quickly invoke the Vanguard scripture.
\
\
Examine the slab for component amount information.
\
\
- A complete list of scripture, its effects, and its requirements can be found below. Note that anything above a driver always consumes the components listed unless otherwise \
- specified.
"
+ A complete list of scripture, its effects, and its requirements can be found below.
\
+ Key:
BE = Belligerent Eyes
\
+ VC = Vanguard Cogwheels
\
+ GC = Guvax Capacitors
\
+ RA = Replicant Alloy
\
+ HA = Hierophant Ansibles
"
var/text_to_add = ""
- var/drivers = "[SCRIPTURE_DRIVER]"
- var/scripts = "[SCRIPTURE_SCRIPT]
These scriptures require at least five servants and a tinkerer's cache."
- var/applications = "[SCRIPTURE_APPLICATION]
These scriptures require at least eight servants, three tinkerer's caches, and 100CV."
- var/revenant = "[SCRIPTURE_REVENANT]
These scriptures require at least ten servants and 200CV."
- var/judgement = "[SCRIPTURE_REVENANT]
These scriptures require at least twelve servants and 300CV. In addition, there may not be any active non-servant AIs."
- for(var/V in subtypesof(/datum/clockwork_scripture))
+ var/drivers = "
[SCRIPTURE_DRIVER]
These scriptures are always unlocked.
"
+ var/scripts = "
[SCRIPTURE_SCRIPT]
These scriptures require at least five servants and a tinkerer's cache.
"
+ var/applications = "[SCRIPTURE_APPLICATION]
These scriptures require at least eight servants, three tinkerer's caches, and 100CV.
"
+ var/revenant = "
[SCRIPTURE_REVENANT]
These scriptures require at least ten servants and 200CV.
"
+ var/judgement = "
[SCRIPTURE_JUDGEMENT]
These scriptures require at least twelve servants and 300CV. In addition, there may not be any active non-servant AIs.
"
+ for(var/V in sortList(subtypesof(/datum/clockwork_scripture), /proc/cmp_clockscripture_priority))
var/datum/clockwork_scripture/S = V
var/datum/clockwork_scripture/S2 = new V
var/list/req_comps = S2.required_components
var/list/cons_comps = S2.consumed_components
qdel(S2)
- switch(initial(S.tier))
- if(SCRIPTURE_DRIVER)
- drivers += "
[initial(S.name)]: [initial(S.desc)]
Invocation Time: [initial(S.channel_time) / 10] seconds
\
- \
- Component Requirement: \
- [req_comps["belligerent_eye"] ? "[req_comps["belligerent_eye"]] Belligerent Eyes" : ""] \
- [req_comps["vanguard_cogwheel"] ? "[req_comps["vanguard_cogwheel"]] Vanguard Cogwheels" : ""] \
- [req_comps["guvax_capacitor"] ? "[req_comps["guvax_capacitor"]] Guvax Capacitors" : ""] \
- [req_comps["replicant_alloy"] ? "[req_comps["replicant_alloy"]] Replicant Alloys" : ""] \
- [req_comps["hierophant_ansible"] ? "[req_comps["hierophant_ansible"]] Hierophant Ansibles" : ""]
\
- Component Cost: \
- [cons_comps["belligerent_eye"] ? "[cons_comps["belligerent_eye"]] Belligerent Eyes" : ""] \
- [cons_comps["vanguard_cogwheel"] ? "[cons_comps["vanguard_cogwheel"]] Vanguard Cogwheels" : ""] \
- [cons_comps["guvax_capacitor"] ? "[cons_comps["guvax_capacitor"]] Guvax Capacitors" : ""] \
- [cons_comps["replicant_alloy"] ? "[cons_comps["replicant_alloy"]] Replicant Alloys" : ""] \
- [cons_comps["hierophant_ansible"] ? "[cons_comps["hierophant_ansible"]] Hierophant Ansibles" : ""]
\
- Tip: [initial(S.usage_tip)]
"
- if(SCRIPTURE_SCRIPT)
- scripts += "
[initial(S.name)]: [initial(S.desc)]
Invocation Time: [initial(S.channel_time) / 10] seconds
\
- \
- Component Requirement: \
- [req_comps["belligerent_eye"] ? "[req_comps["belligerent_eye"]] Belligerent Eyes" : ""] \
- [req_comps["vanguard_cogwheel"] ? "[req_comps["vanguard_cogwheel"]] Vanguard Cogwheels" : ""] \
- [req_comps["guvax_capacitor"] ? "[req_comps["guvax_capacitor"]] Guvax Capacitors" : ""] \
- [req_comps["replicant_alloy"] ? "[req_comps["replicant_alloy"]] Replicant Alloys" : ""] \
- [req_comps["hierophant_ansible"] ? "[req_comps["hierophant_ansible"]] Hierophant Ansibles" : ""]
\
- Component Cost: \
- [cons_comps["belligerent_eye"] ? "[cons_comps["belligerent_eye"]] Belligerent Eyes" : ""] \
- [cons_comps["vanguard_cogwheel"] ? "[cons_comps["vanguard_cogwheel"]] Vanguard Cogwheels" : ""] \
- [cons_comps["guvax_capacitor"] ? "[cons_comps["guvax_capacitor"]] Guvax Capacitors" : ""] \
- [cons_comps["replicant_alloy"] ? "[cons_comps["replicant_alloy"]] Replicant Alloys" : ""] \
- [cons_comps["hierophant_ansible"] ? "[cons_comps["hierophant_ansible"]] Hierophant Ansibles" : ""]
\
- Tip: [initial(S.usage_tip)]
"
- if(SCRIPTURE_APPLICATION)
- applications += "
[initial(S.name)]: [initial(S.desc)]
Invocation Time: [initial(S.channel_time) / 10] seconds
\
- \
- Component Requirement: \
- [req_comps["belligerent_eye"] ? "[req_comps["belligerent_eye"]] Belligerent Eyes" : ""] \
- [req_comps["vanguard_cogwheel"] ? "[req_comps["vanguard_cogwheel"]] Vanguard Cogwheels" : ""] \
- [req_comps["guvax_capacitor"] ? "[req_comps["guvax_capacitor"]] Guvax Capacitors" : ""] \
- [req_comps["replicant_alloy"] ? "[req_comps["replicant_alloy"]] Replicant Alloys" : ""] \
- [req_comps["hierophant_ansible"] ? "[req_comps["hierophant_ansible"]] Hierophant Ansibles" : ""]
\
- Component Cost: \
- [cons_comps["belligerent_eye"] ? "[cons_comps["belligerent_eye"]] Belligerent Eyes" : ""] \
- [cons_comps["vanguard_cogwheel"] ? "[cons_comps["vanguard_cogwheel"]] Vanguard Cogwheels" : ""] \
- [cons_comps["guvax_capacitor"] ? "[cons_comps["guvax_capacitor"]] Guvax Capacitors" : ""] \
- [cons_comps["replicant_alloy"] ? "[cons_comps["replicant_alloy"]] Replicant Alloys" : ""] \
- [cons_comps["hierophant_ansible"] ? "[cons_comps["hierophant_ansible"]] Hierophant Ansibles" : ""]
\
- Tip: [initial(S.usage_tip)]
"
- if(SCRIPTURE_REVENANT)
- revenant += "
[initial(S.name)]: [initial(S.desc)]
Invocation Time: [initial(S.channel_time) / 10] seconds
\
- \
- Component Requirement: \
- [req_comps["belligerent_eye"] ? "[req_comps["belligerent_eye"]] Belligerent Eyes" : ""] \
- [req_comps["vanguard_cogwheel"] ? "[req_comps["vanguard_cogwheel"]] Vanguard Cogwheels" : ""] \
- [req_comps["guvax_capacitor"] ? "[req_comps["guvax_capacitor"]] Guvax Capacitors" : ""] \
- [req_comps["replicant_alloy"] ? "[req_comps["replicant_alloy"]] Replicant Alloys" : ""] \
- [req_comps["hierophant_ansible"] ? "[req_comps["hierophant_ansible"]] Hierophant Ansibles" : ""]
\
- Component Cost: \
- [cons_comps["belligerent_eye"] ? "[cons_comps["belligerent_eye"]] Belligerent Eyes" : ""] \
- [cons_comps["vanguard_cogwheel"] ? "[cons_comps["vanguard_cogwheel"]] Vanguard Cogwheels" : ""] \
- [cons_comps["guvax_capacitor"] ? "[cons_comps["guvax_capacitor"]] Guvax Capacitors" : ""] \
- [cons_comps["replicant_alloy"] ? "[cons_comps["replicant_alloy"]] Replicant Alloys" : ""] \
- [cons_comps["hierophant_ansible"] ? "[cons_comps["hierophant_ansible"]] Hierophant Ansibles" : ""]
\
- Tip: [initial(S.usage_tip)]
"
- if(SCRIPTURE_JUDGEMENT)
- judgement += "
[initial(S.name)]: [initial(S.desc)]
Invocation Time: [initial(S.channel_time) / 10] seconds
\
- \
- Component Requirement: \
- [req_comps["belligerent_eye"] ? "[req_comps["belligerent_eye"]] Belligerent Eyes" : ""] \
- [req_comps["vanguard_cogwheel"] ? "[req_comps["vanguard_cogwheel"]] Vanguard Cogwheels" : ""] \
- [req_comps["guvax_capacitor"] ? "[req_comps["guvax_capacitor"]] Guvax Capacitors" : ""] \
- [req_comps["replicant_alloy"] ? "[req_comps["replicant_alloy"]] Replicant Alloys" : ""] \
- [req_comps["hierophant_ansible"] ? "[req_comps["hierophant_ansible"]] Hierophant Ansibles" : ""]
\
- Component Cost: \
- [cons_comps["belligerent_eye"] ? "[cons_comps["belligerent_eye"]] Belligerent Eyes" : ""] \
- [cons_comps["vanguard_cogwheel"] ? "[cons_comps["vanguard_cogwheel"]] Vanguard Cogwheels" : ""] \
- [cons_comps["guvax_capacitor"] ? "[cons_comps["guvax_capacitor"]] Guvax Capacitors" : ""] \
- [cons_comps["replicant_alloy"] ? "[cons_comps["replicant_alloy"]] Replicant Alloys" : ""] \
- [cons_comps["hierophant_ansible"] ? "[cons_comps["hierophant_ansible"]] Hierophant Ansibles" : ""]
\
- Tip: [initial(S.usage_tip)]
"
+ if(initial(S.tier) != SCRIPTURE_PERIPHERAL)
+ var/scripture_text = "
[initial(S.name)]:
[initial(S.desc)]
Invocation Time: [initial(S.channel_time) / 10] seconds
\
+ Component Requirement: \
+ [req_comps["belligerent_eye"] ? "[req_comps["belligerent_eye"]] BE" : ""] \
+ [req_comps["vanguard_cogwheel"] ? "[req_comps["vanguard_cogwheel"]] VC" : ""] \
+ [req_comps["guvax_capacitor"] ? "[req_comps["guvax_capacitor"]] GC" : ""] \
+ [req_comps["replicant_alloy"] ? "[req_comps["replicant_alloy"]] RA" : ""] \
+ [req_comps["hierophant_ansible"] ? "[req_comps["hierophant_ansible"]] HA" : ""]
"
+ for(var/i in cons_comps)
+ if(cons_comps[i])
+ scripture_text += "Component Cost: \
+ [cons_comps["belligerent_eye"] ? "[cons_comps["belligerent_eye"]] BE" : ""] \
+ [cons_comps["vanguard_cogwheel"] ? "[cons_comps["vanguard_cogwheel"]] VC" : ""] \
+ [cons_comps["guvax_capacitor"] ? "[cons_comps["guvax_capacitor"]] GC" : ""] \
+ [cons_comps["replicant_alloy"] ? "[cons_comps["replicant_alloy"]] RA" : ""] \
+ [cons_comps["hierophant_ansible"] ? "[cons_comps["hierophant_ansible"]] HA" : ""]
"
+ break //we want this to only show up if the scripture has a cost of some sort
+ scripture_text += "Tip: [initial(S.usage_tip)]
"
+ switch(initial(S.tier))
+ if(SCRIPTURE_DRIVER)
+ drivers += scripture_text
+ if(SCRIPTURE_SCRIPT)
+ scripts += scripture_text
+ if(SCRIPTURE_APPLICATION)
+ applications += scripture_text
+ if(SCRIPTURE_REVENANT)
+ revenant += scripture_text
+ if(SCRIPTURE_JUDGEMENT)
+ judgement += scripture_text
text_to_add += "[drivers]
[scripts]
[applications]
[revenant]
[judgement]
"
text_to_add += "
Purge all untruths and honor Ratvar."
text += text_to_add
@@ -407,7 +359,7 @@
var/message = stripped_input(user, "Enter a message to send to your fellow servants.", "Hierophant")
if(!message || !user || !user.canUseTopic(src))
return 0
- clockwork_say(user, text2ratvar("Servants, hear my words. [message]"), TRUE)
+ clockwork_say(user, text2ratvar("Servants, hear my words. [html_decode(message)]"), TRUE)
titled_hierophant_message(user, message)
return 1
@@ -616,7 +568,7 @@
icon = 'icons/obj/clothing/clockwork_garb.dmi'
icon_state = "clockwork_helmet"
w_class = 3
- armor = list(melee = 80, bullet = 50, laser = -15, energy = 5, bomb = 35, bio = 0, rad = 0)
+ armor = list(melee = 80, bullet = 50, laser = -15, energy = 0, bomb = 35, bio = 0, rad = 0)
/obj/item/clothing/head/helmet/clockwork/equipped(mob/living/user, slot)
..()
@@ -647,7 +599,7 @@
icon_state = "clockwork_cuirass"
w_class = 4
body_parts_covered = CHEST|GROIN|LEGS
- armor = list(melee = 80, bullet = 50, laser = -15, energy = 5, bomb = 35, bio = 0, rad = 0)
+ armor = list(melee = 80, bullet = 50, laser = -15, energy = 0, bomb = 35, bio = 0, rad = 0)
allowed = list(/obj/item/clockwork, /obj/item/clothing/glasses/wraith_spectacles, /obj/item/clothing/glasses/judicial_visor, /obj/item/device/mmi/posibrain/soul_vessel)
/obj/item/clothing/suit/armor/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
@@ -686,7 +638,7 @@
burn_state = FIRE_PROOF
siemens_coefficient = 0
permeability_coefficient = 0.05
- armor = list(melee = 80, bullet = 50, laser = -15, energy = 5, bomb = 35, bio = 0, rad = 0)
+ armor = list(melee = 80, bullet = 50, laser = -15, energy = 0, bomb = 35, bio = 0, rad = 0)
/obj/item/clothing/gloves/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
if(equipper && !is_servant_of_ratvar(equipper))
@@ -820,13 +772,13 @@
impale_cooldown = world.time + initial(impale_cooldown)
attack_cooldown = world.time + initial(attack_cooldown)
if(target)
- PoolOrNew(/obj/effect/overlay/temp/bloodsplatter, list(get_turf(target), get_dir(user, target)))
+ PoolOrNew(/obj/effect/overlay/temp/dir_setting/bloodsplatter, list(get_turf(target), get_dir(user, target)))
target.Stun(2)
user << "You prepare to remove your ratvarian spear from [target]..."
var/remove_verb = pick("pull", "yank", "drag")
if(do_after(user, 10, 1, target))
var/turf/T = get_turf(target)
- var/obj/effect/overlay/temp/bloodsplatter/B = PoolOrNew(/obj/effect/overlay/temp/bloodsplatter, list(T, get_dir(target, user)))
+ var/obj/effect/overlay/temp/dir_setting/bloodsplatter/B = PoolOrNew(/obj/effect/overlay/temp/dir_setting/bloodsplatter, list(T, get_dir(target, user)))
playsound(T, 'sound/misc/splort.ogg', 200, 1)
playsound(T, 'sound/weapons/pierce.ogg', 200, 1)
if(target.stat != CONSCIOUS)
@@ -1117,7 +1069,15 @@
/obj/item/clockwork/component/replicant_alloy/examine(mob/user)
..()
if(is_servant_of_ratvar(user))
- user << "Can be used to fuel Clockwork Proselytizers and Mending Motors."
+ user << "Can be used to fuel Clockwork Proselytizers and Mending Motors, or shaped into brass sheets."
+
+/obj/item/clockwork/component/replicant_alloy/attack_self(mob/user)
+ if(is_servant_of_ratvar(user))
+ var/obj/item/stack/sheet/brass/B = new /obj/item/stack/sheet/brass(get_turf(src), 10)
+ user.unEquip(src, TRUE)
+ user.put_in_hands(B)
+ user << "You shape the alloy into some brass sheets."
+ qdel(src)
/obj/item/clockwork/component/replicant_alloy/smashed_anima_fragment
name = "smashed anima fragment"
diff --git a/code/game/gamemodes/clock_cult/clock_machines.dm b/code/game/gamemodes/clock_cult/clock_machines.dm
index c682142aa5d..4509cf916c8 100644
--- a/code/game/gamemodes/clock_cult/clock_machines.dm
+++ b/code/game/gamemodes/clock_cult/clock_machines.dm
@@ -138,8 +138,8 @@
active_icon = "mending_motor"
inactive_icon = "mending_motor_inactive"
construction_value = 20
- max_health = 150
- health = 150
+ max_health = 125
+ health = 125
break_message = "The prism collapses with a heavy thud!"
debris = list(/obj/item/clockwork/alloy_shards/small = 5, \
/obj/item/clockwork/alloy_shards/medium = 1, \
@@ -439,46 +439,14 @@
CHECK_TICK
for(var/M in atoms_to_test)
- if(istype(M, /obj/machinery/power/apc))
- var/obj/machinery/power/apc/A = M
- if(A.cell && A.cell.charge)
- successfulprocess = TRUE
- playsound(A, "sparks", 50, 1)
- flick("apc-spark", A)
- power_drained += min(A.cell.charge, 100)
- A.cell.charge = max(0, A.cell.charge - 100)
- if(!A.cell.charge && !A.shorted)
- A.shorted = 1
- A.visible_message("The [A.name]'s screen blurs with static.")
- A.update()
- A.update_icon()
- else if(istype(M, /obj/machinery/power/smes))
- var/obj/machinery/power/smes/S = M
- if(S.charge)
- successfulprocess = TRUE
- power_drained += min(S.charge, 500)
- S.charge = max(0, S.charge - 50000) //SMES units contain too much power and could run an interdiction lens basically forever, or provide power forever
- if(!S.charge && !S.panel_open)
- S.panel_open = TRUE
- S.icon_state = "[initial(S.icon_state)]-o"
- var/datum/effect_system/spark_spread/spks = new(get_turf(S))
- spks.set_up(10, 0, get_turf(S))
- spks.start()
- S.visible_message("[S]'s panel flies open with a flurry of sparks.")
- S.update_icon()
- else if(isrobot(M))
- var/mob/living/silicon/robot/R = M
- if(!is_servant_of_ratvar(R) && R.cell && R.cell.charge)
- successfulprocess = TRUE
- power_drained += min(R.cell.charge, 200)
- R.cell.charge = max(0, R.cell.charge - 200)
- R << "ERROR: Power loss detected!"
- var/datum/effect_system/spark_spread/spks = new(get_turf(R))
- spks.set_up(3, 0, get_turf(R))
- spks.start()
+ var/atom/movable/A = M
+ power_drained += A.power_drain(TRUE)
CHECK_TICK
+ if(power_drained)
+ successfulprocess = TRUE
+
if(!return_power(power_drained) || power_drained < 50) //failed to return power drained or too little power to return
successfulprocess = FALSE
if(try_use_power(disrupt_cost) && total_accessable_power() >= disrupt_cost) //if we can disable at least one object
@@ -537,8 +505,8 @@
active_icon = "obelisk"
inactive_icon = "obelisk_inactive"
construction_value = 20
- max_health = 200
- health = 200
+ max_health = 150
+ health = 150
break_message = "The obelisk falls to the ground, undamaged!"
debris = list(/obj/item/clockwork/alloy_shards/small = 3, \
/obj/item/clockwork/component/hierophant_ansible/obelisk = 1)
diff --git a/code/game/gamemodes/clock_cult/clock_mobs.dm b/code/game/gamemodes/clock_cult/clock_mobs.dm
index d8d3025e088..4793b33766d 100644
--- a/code/game/gamemodes/clock_cult/clock_mobs.dm
+++ b/code/game/gamemodes/clock_cult/clock_mobs.dm
@@ -38,8 +38,8 @@
health = 90
maxHealth = 90
speed = -1
- melee_damage_lower = 20
- melee_damage_upper = 20
+ melee_damage_lower = 18
+ melee_damage_upper = 18
attacktext = "crushes"
attack_sound = 'sound/magic/clockwork/anima_fragment_attack.ogg'
loot = list(/obj/item/clockwork/component/replicant_alloy/smashed_anima_fragment)
diff --git a/code/game/gamemodes/clock_cult/clock_powerdrain.dm b/code/game/gamemodes/clock_cult/clock_powerdrain.dm
new file mode 100644
index 00000000000..3f2ae58d4ae
--- /dev/null
+++ b/code/game/gamemodes/clock_cult/clock_powerdrain.dm
@@ -0,0 +1,54 @@
+//horrifying power drain proc made for clockcult's power drain in lieu of six istypes or six for(x in view) loops
+/atom/movable/proc/power_drain(clockcult_user)
+ return 0
+
+/obj/machinery/power/apc/power_drain(clockcult_user)
+ if(cell && cell.charge)
+ playsound(src, "sparks", 50, 1)
+ flick("apc-spark", src)
+ . += min(cell.charge, 500)
+ cell.charge = max(0, cell.charge - 500) //Better than a power sink!
+ if(!cell.charge && !shorted)
+ shorted = 1
+ visible_message("The [name]'s screen blurs with static.")
+ update()
+ update_icon()
+
+/obj/machinery/power/smes/power_drain(clockcult_user)
+ if(charge)
+ . += min(charge, 500)
+ charge = max(0, charge - 50000)
+ if(!charge && !panel_open)
+ panel_open = TRUE
+ icon_state = "[initial(icon_state)]-o"
+ var/datum/effect_system/spark_spread/spks = new(get_turf(src))
+ spks.set_up(10, 0, get_turf(src))
+ spks.start()
+ visible_message("[src]'s panel flies open with a flurry of spark")
+ update_icon()
+
+/obj/item/weapon/stock_parts/cell/power_drain(clockcult_user)
+ if(charge)
+ . += min(charge, 500)
+ charge = use(max(0, charge - 500))
+ updateicon()
+
+/obj/machinery/light/power_drain(clockcult_user)
+ if(on)
+ playsound(src, 'sound/effects/light_flicker.ogg', 50, 1)
+ flicker(2)
+ . += 50
+
+/mob/living/silicon/robot/power_drain(clockcult_user)
+ if((!clockcult_user || !is_servant_of_ratvar(src)) && cell && cell.charge)
+ . += min(cell.charge, 500)
+ cell.charge = max(0, cell.charge - 500)
+ src << "ERROR: Power loss detected!"
+ spark_system.start()
+
+/obj/mecha/power_drain(clockcult_user)
+ if((!clockcult_user || !occupant || occupant && !is_servant_of_ratvar(occupant)) && cell && cell.charge)
+ . += min(cell.charge, 500)
+ cell.charge = max(0, cell.charge - 500)
+ occupant_message("Power loss detected!")
+ spark_system.start()
\ No newline at end of file
diff --git a/code/game/gamemodes/clock_cult/clock_proselytizer.dm b/code/game/gamemodes/clock_cult/clock_proselytizer.dm
index a00443d6cfb..404452d064d 100644
--- a/code/game/gamemodes/clock_cult/clock_proselytizer.dm
+++ b/code/game/gamemodes/clock_cult/clock_proselytizer.dm
@@ -55,7 +55,7 @@
playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
new/obj/item/clockwork/component/replicant_alloy(user.loc)
user << "You force [stored_alloy ? "some":"all"] of the alloy in [src]'s compartments to reform and solidify. \
- It now contains [stored_alloy]/[max_alloy] units of liquified alloy."
+ It now contains [stored_alloy]/[max_alloy] units of liquified alloy."
/obj/item/clockwork/clockwork_proselytizer/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/clockwork/component/replicant_alloy) && is_servant_of_ratvar(user) && uses_alloy)
@@ -79,16 +79,17 @@
proselytize(target, user)
/obj/item/clockwork/clockwork_proselytizer/proc/modify_stored_alloy(amount)
- if(can_use_alloy(0)) //Ratvar makes it free
+ if(can_use_alloy(RATVAR_ALLOY_CHECK)) //Ratvar makes it free
amount = 0
stored_alloy = Clamp(stored_alloy + amount, 0, max_alloy)
return 1
/obj/item/clockwork/clockwork_proselytizer/proc/can_use_alloy(amount)
- if(ratvar_awakens || !uses_alloy)
- return TRUE
- if(!amount) //functions thus as a check for if ratvar is up/it doesn't use alloy if no amount is provided
- return FALSE
+ if(amount == RATVAR_ALLOY_CHECK)
+ if(ratvar_awakens || !uses_alloy)
+ return TRUE
+ else
+ return FALSE
if(stored_alloy - amount < 0)
return FALSE
if(stored_alloy - amount > max_alloy)
@@ -100,10 +101,9 @@
return 0
var/target_type = target.type
var/list/proselytize_values = target.proselytize_vals(user, src) //relevant values for proselytizing stuff, given as an associated list
- if(proselytize_values == TRUE) //if we get true, fail, but don't send a message for whatever reason
- return 0
if(!islist(proselytize_values))
- user << "[target] cannot be proselytized!"
+ if(proselytize_values != TRUE) //if we get true, fail, but don't send a message for whatever reason
+ user << "[target] cannot be proselytized!"
return 0
if(repairing)
user << "You are currently repairing [repairing] with [src]!"
@@ -118,7 +118,7 @@
user << "You have too much liquified alloy stored to proselytize [target]!"
return 0
- if(can_use_alloy(0)) //Ratvar makes it faster
+ if(can_use_alloy(RATVAR_ALLOY_CHECK)) //Ratvar makes it faster
proselytize_values["operation_time"] *= 0.5
user.visible_message("[user]'s [name] begins tearing apart [target]!", "You begin proselytizing [target]...")
@@ -171,7 +171,7 @@
/turf/open/floor/plating/asteroid/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
return FALSE
-/turf/open/floor/plating/ash/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
+/turf/open/floor/plating/ashplanet/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
return FALSE
/turf/open/floor/plating/lava/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
@@ -185,22 +185,44 @@
return list("operation_time" = 100, "new_obj_type" = /turf/closed/wall/clockwork, "alloy_cost" = REPLICANT_WALL_MINUS_FLOOR, "spawn_dir" = SOUTH)
/obj/item/stack/rods/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
- if(!proselytizer.metal_to_alloy)
- return 0
- var/prosel_costtime = -amount
- return list("operation_time" = -prosel_costtime, "new_obj_type" = /obj/effect/overlay/temp/ratvar/beam/itemconsume, "alloy_cost" = prosel_costtime, "spawn_dir" = SOUTH)
+ if(get_amount() >= 10)
+ var/sheets_to_make = round(get_amount() * 0.1)
+ var/remainder = get_amount() - (sheets_to_make * 10)
+ if(remainder)
+ new type(loc, remainder)
+ return list("operation_time" = 0, "new_obj_type" = /obj/item/stack/sheet/brass, "alloy_cost" = 0, "spawn_dir" = sheets_to_make, "dir_in_new" = TRUE)
+ else
+ user << "You need at least 10 rods to convert into brass."
+ return TRUE
/obj/item/stack/sheet/metal/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
- if(!proselytizer.metal_to_alloy)
- return 0
- var/prosel_costtime = -amount*2
- return list("operation_time" = -prosel_costtime, "new_obj_type" = /obj/effect/overlay/temp/ratvar/beam/itemconsume, "alloy_cost" = prosel_costtime, "spawn_dir" = SOUTH)
+ if(src.get_amount() >= 5)
+ var/sheets_to_make = round(src.get_amount() * 0.2)
+ var/remainder = src.get_amount() - (sheets_to_make * 5)
+ if(remainder)
+ new type(loc, remainder)
+ return list("operation_time" = 0, "new_obj_type" = /obj/item/stack/sheet/brass, "alloy_cost" = 0, "spawn_dir" = sheets_to_make, "dir_in_new" = TRUE)
+ else
+ user << "You need at least 5 sheets of metal to convert into brass."
+ return TRUE
/obj/item/stack/sheet/plasteel/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
+ if(get_amount() >= 10)
+ var/sheets_to_make = round(get_amount() * 0.4)
+ var/remainder = get_amount() - (sheets_to_make * 2.5)
+ if(remainder)
+ new type(loc, remainder)
+ return list("operation_time" = 0, "new_obj_type" = /obj/item/stack/sheet/brass, "alloy_cost" = 0, "spawn_dir" = sheets_to_make, "dir_in_new" = TRUE)
+ else
+ user << "You need at least 10 sheets of plasteel to convert into brass."
+ return TRUE
+
+/obj/item/stack/sheet/brass/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
if(!proselytizer.metal_to_alloy)
- return 0
- var/prosel_costtime = -amount*3
- return list("operation_time" = -prosel_costtime, "new_obj_type" = /obj/effect/overlay/temp/ratvar/beam/itemconsume, "alloy_cost" = prosel_costtime, "spawn_dir" = SOUTH)
+ return FALSE
+ var/prosel_cost = -amount*10
+ var/prosel_time = -amount*1
+ return list("operation_time" = -prosel_time, "new_obj_type" = /obj/effect/overlay/temp/ratvar/beam/itemconsume, "alloy_cost" = prosel_cost, "spawn_dir" = SOUTH)
/obj/machinery/door/airlock/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
var/doortype = /obj/machinery/door/airlock/clockwork
@@ -319,7 +341,7 @@
return
/obj/structure/destructible/clockwork/wall_gear/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
- return list("operation_time" = 10, "new_obj_type" = /obj/effect/overlay/temp/ratvar/beam/itemconsume, "alloy_cost" = -REPLICANT_WALL_MINUS_FLOOR, "spawn_dir" = SOUTH)
+ return list("operation_time" = 10, "new_obj_type" = /obj/effect/overlay/temp/ratvar/beam/itemconsume, "alloy_cost" = -REPLICANT_GEAR, "spawn_dir" = SOUTH)
/obj/item/clockwork/alloy_shards/proselytize_vals(mob/living/user, obj/item/clockwork/clockwork_proselytizer/proselytizer)
return list("operation_time" = 5, "new_obj_type" = /obj/effect/overlay/temp/ratvar/beam/itemconsume, "alloy_cost" = -REPLICANT_STANDARD, "spawn_dir" = SOUTH)
diff --git a/code/game/gamemodes/clock_cult/clock_scripture.dm b/code/game/gamemodes/clock_cult/clock_scripture.dm
index a05c1fe0b7c..ad2615e54a1 100644
--- a/code/game/gamemodes/clock_cult/clock_scripture.dm
+++ b/code/game/gamemodes/clock_cult/clock_scripture.dm
@@ -25,6 +25,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
var/multiple_invokers_used = FALSE //If scripture requires more than one invoker
var/multiple_invokers_optional = FALSE //If scripture can have multiple invokers to bolster its effects
var/tier = SCRIPTURE_PERIPHERAL //The scripture's tier
+ var/sort_priority = 1 //what position the scripture should have in a list of scripture. Should be based off of component costs/reqs, but you can't initial() lists.
//components the scripture used from a slab
var/list/used_slab_components = list("belligerent_eye" = 0, "vanguard_cogwheel" = 0, "guvax_capacitor" = 0, "replicant_alloy" = 0, "hierophant_ansible" = 0)
@@ -160,6 +161,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
var/observer_message
var/one_per_tile = FALSE
var/prevent_path
+ var/space_allowed = FALSE
/datum/clockwork_scripture/create_object/New()
..()
@@ -167,7 +169,11 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
prevent_path = object_path
/datum/clockwork_scripture/create_object/check_special_requirements()
- if(one_per_tile && (locate(prevent_path) in get_turf(invoker)))
+ var/turf/T = get_turf(invoker)
+ if(!space_allowed && istype(T, /turf/open/space))
+ invoker << "You need solid ground to place this object!"
+ return 0
+ if(one_per_tile && (locate(prevent_path) in T))
invoker << "You can only place one of this object on each tile!"
return 0
return 1
@@ -194,19 +200,22 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
required_components = list("belligerent_eye" = 1)
usage_tip = "Useful for crowd control in a populated area and disrupting mass movement."
tier = SCRIPTURE_DRIVER
+ sort_priority = 1
+ var/noncultist_damage = 2 //damage per chant to noncultists
+ var/cultist_damage = 8 //damage per chant to non-walking cultists
/datum/clockwork_scripture/channeled/belligerent/chant_effects(chant_number)
for(var/mob/living/carbon/C in hearers(7, invoker))
if(!is_servant_of_ratvar(C) && !C.null_rod_check() && C.get_num_legs()) //you have legs right
- C.apply_damage(1, BURN, "l_leg")
- C.apply_damage(1, BURN, "r_leg")
+ C.apply_damage(noncultist_damage * 0.5, BURN, "l_leg")
+ C.apply_damage(noncultist_damage * 0.5, BURN, "r_leg")
if(C.m_intent != "walk")
if(!iscultist(C))
C << "Your legs shiver with pain!"
else //Cultists take extra burn damage
C << "Your legs burn with pain!"
- C.apply_damage(4, BURN, "l_leg")
- C.apply_damage(4, BURN, "r_leg")
+ C.apply_damage(cultist_damage * 0.5, BURN, "l_leg")
+ C.apply_damage(cultist_damage * 0.5, BURN, "r_leg")
C.m_intent = "walk"
@@ -225,6 +234,8 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
creator_message = "You form a judicial visor, which is capable of smiting the unworthy."
usage_tip = "The visor has a thirty-second cooldown once used, and the marker it creates has a delay of 3 seconds before exploding."
tier = SCRIPTURE_DRIVER
+ space_allowed = TRUE
+ sort_priority = 2
@@ -238,6 +249,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
required_components = list("vanguard_cogwheel" = 1)
usage_tip = "You cannot reactivate Vanguard while still shielded by it."
tier = SCRIPTURE_DRIVER
+ sort_priority = 3
/datum/clockwork_scripture/vanguard/check_special_requirements()
if(islist(invoker.stun_absorption) && invoker.stun_absorption["vanguard"] && invoker.stun_absorption["vanguard"]["end_time"] > world.time)
@@ -254,13 +266,14 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
/datum/clockwork_scripture/sentinels_compromise //Sentinel's Compromise: Allows the invoker to select a nearby servant convert their brute and burn damage into half as much toxin damage.
descname = "Convert Brute/Burn to Half Toxin"
name = "Sentinel's Compromise"
- desc = "Heals all brute and burn damage on a nearby living, friendly servant, but deals 50% of that amount as toxin damage."
+ desc = "Heals all brute and burn damage on a nearby living, friendly servant, but deals 50% of the damage they had as toxin damage."
invocations = list("Mend the wounds of...", "...my inferior flesh.")
channel_time = 30
required_components = list("vanguard_cogwheel" = 2)
consumed_components = list("vanguard_cogwheel" = 1)
usage_tip = "The Compromise is very fast to invoke."
tier = SCRIPTURE_DRIVER
+ sort_priority = 4
/datum/clockwork_scripture/sentinels_compromise/scripture_effects()
var/list/nearby_cultists = list()
@@ -303,6 +316,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
required_components = list("guvax_capacitor" = 1)
usage_tip = "Only works on those in melee range and does not penetrate mindshield implants. Much more efficient than a Sigil of Submission at low Servant amounts."
tier = SCRIPTURE_DRIVER
+ sort_priority = 5
/datum/clockwork_scripture/guvax/run_scripture()
var/servants = 0
@@ -338,6 +352,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
consumed_components = list("guvax_capacitor" = 1)
usage_tip = "Useful for fleeing attackers, as few will be able to follow someone using this scripture."
tier = SCRIPTURE_DRIVER
+ sort_priority = 6
var/flee_time = 47 //allow fleeing for 5 seconds
var/grace_period = 3 //very short grace period so you don't have to stop immediately
var/datum/progressbar/progbar
@@ -373,11 +388,12 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
name = "Replicant"
desc = "Creates a new clockwork slab."
invocations = list("Metal, become greater!")
- channel_time = 0
+ channel_time = 10
required_components = list("replicant_alloy" = 1)
whispered = TRUE
usage_tip = "This is inefficient as a way to produce components, as the slab produced must be held by someone with no other slabs to produce components."
tier = SCRIPTURE_DRIVER
+ sort_priority = 7
/datum/clockwork_scripture/replicant/scripture_effects()
invoker << "You copy a piece of replicant alloy and command it into a new slab." //No visible message, for stealth purposes
@@ -401,6 +417,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
usage_tip = "Slabs will draw components from the global cache after the slab's own repositories, making caches very efficient."
tier = SCRIPTURE_DRIVER
one_per_tile = TRUE
+ sort_priority = 8
/datum/clockwork_scripture/create_object/tinkerers_cache/New()
var/cache_cost_increase = min(round(clockwork_caches*0.2), 5)
@@ -426,6 +443,8 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
creator_message = "You form a pair of wraith spectacles, which will grant true sight when worn."
usage_tip = "\"True sight\" means that you are able to see through walls and in darkness."
tier = SCRIPTURE_DRIVER
+ space_allowed = TRUE
+ sort_priority = 9
@@ -443,6 +462,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
usage_tip = "The sigil, while fairly powerful in its stun, does not induce muteness in its victim."
tier = SCRIPTURE_DRIVER
one_per_tile = TRUE
+ sort_priority = 10
/////////////
// SCRIPTS //
@@ -462,6 +482,8 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
usage_tip = "Although powerful, the warden is very weak and should optimally be placed behind barricades."
tier = SCRIPTURE_SCRIPT
one_per_tile = TRUE
+ space_allowed = TRUE
+ sort_priority = 11
/datum/clockwork_scripture/create_object/ocular_warden/check_special_requirements()
for(var/obj/structure/destructible/clockwork/ocular_warden/W in range(3, invoker))
@@ -481,6 +503,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
consumed_components = list("guvax_capacitor" = 1, "hierophant_ansible" = 1)
usage_tip = "If standing on a Sigil of Transmission, will transfer power to it. Augumented limbs will also be healed unless above a very high threshhold."
tier = SCRIPTURE_SCRIPT
+ sort_priority = 20
var/total_power_drained = 0
var/power_damage_threshhold = 3000
var/augument_damage_threshhold = 6000
@@ -488,47 +511,8 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
/datum/clockwork_scripture/channeled/volt_void/chant_effects(chant_number)
playsound(invoker, 'sound/effects/EMPulse.ogg', 50, 1)
var/power_drained = 0
- for(var/obj/machinery/power/apc/A in view(7, invoker))
- if(A.cell && A.cell.charge)
- playsound(A, "sparks", 50, 1)
- flick("apc-spark", A)
- power_drained += min(A.cell.charge, 500)
- A.cell.charge = max(0, A.cell.charge - 500) //Better than a power sink!
- if(!A.cell.charge && !A.shorted)
- A.shorted = 1
- A.visible_message("The [A.name]'s screen blurs with static.")
- A.update()
- A.update_icon()
- for(var/obj/machinery/power/smes/S in view(7, invoker))
- if(S.charge)
- power_drained += min(S.charge, 500)
- S.charge = max(0, S.charge - 50000)
- if(!S.charge && !S.panel_open)
- S.panel_open = TRUE
- S.icon_state = "[initial(S.icon_state)]-o"
- var/datum/effect_system/spark_spread/spks = new(get_turf(S))
- spks.set_up(10, 0, get_turf(S))
- spks.start()
- S.visible_message("[S]'s panel flies open with a flurry of sparks.")
- S.update_icon()
- for(var/obj/item/weapon/stock_parts/cell/C in view(7, invoker))
- if(C.charge)
- power_drained += min(C.charge, 500)
- C.charge = C.use(max(0, C.charge - 500))
- C.updateicon()
- for(var/obj/machinery/light/L in view(7, invoker))
- if(L.on)
- playsound(L, 'sound/effects/light_flicker.ogg', 50, 1)
- L.flicker(2)
- power_drained += 50
- for(var/mob/living/silicon/robot/R in view(7, invoker))
- if(!is_servant_of_ratvar(R) && R.cell && R.cell.charge)
- power_drained += min(R.cell.charge, 500)
- R.cell.charge = max(0, R.cell.charge - 500)
- R << "ERROR: Power loss detected!"
- var/datum/effect_system/spark_spread/spks = new(get_turf(R))
- spks.set_up(3, 0, get_turf(R))
- spks.start()
+ for(var/atom/movable/A in view(7, invoker))
+ power_drained += A.power_drain(TRUE)
var/obj/effect/clockwork/sigil/transmission/ST = locate(/obj/effect/clockwork/sigil/transmission) in get_turf(invoker)
if(ST && power_drained >= 50)
var/sigil_drain = 0
@@ -546,7 +530,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
var/mob/living/carbon/human/H = invoker
for(var/X in H.bodyparts)
var/obj/item/bodypart/BP = X
- if(ratvar_awakens || BP.status == BODYPART_ROBOTIC && total_power_drained < augument_damage_threshhold) //if ratvar is alive, it won't damage and will always heal augumented limbs
+ if(ratvar_awakens || (BP.status == BODYPART_ROBOTIC && total_power_drained < augument_damage_threshhold)) //if ratvar is alive, it won't damage and will always heal augumented limbs
if(BP.heal_damage(power_damage, power_damage, 1, 0)) //heals one point of burn and brute for every ~100W drained on augumented limbs
H.update_damage_overlays()
else
@@ -572,6 +556,8 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
creator_message = "You form a clockwork proselytizer, which is already pre-loaded with a small amount of replicant alloy."
usage_tip = "Clockwork walls cause adjacent tinkerer's caches to generate components passively, making them a vital tool. Clockwork floors heal servants standing on them."
tier = SCRIPTURE_SCRIPT
+ space_allowed = TRUE
+ sort_priority = 17
@@ -588,6 +574,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
tier = SCRIPTURE_SCRIPT
multiple_invokers_used = TRUE
multiple_invokers_optional = TRUE
+ sort_priority = 14
/datum/clockwork_scripture/fellowship_armory/run_scripture()
for(var/mob/living/L in range(1, invoker))
@@ -621,12 +608,13 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
whispered = TRUE
usage_tip = "You can impale human targets with the spear by pulling them, then attacking. Throwing the spear at a mob will do massive damage and stun them, but break the spear."
tier = SCRIPTURE_SCRIPT
+ sort_priority = 18
/datum/clockwork_scripture/function_call/check_special_requirements()
for(var/datum/action/innate/function_call/F in invoker.actions)
invoker << "You have already bound a Ratvarian spear to yourself!"
return 0
- return ishuman(invoker)
+ return invoker.can_hold_items()
/datum/clockwork_scripture/function_call/scripture_effects()
invoker.visible_message("A shimmer of yellow light infuses [invoker]!", \
@@ -649,6 +637,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
multiple_invokers_optional = TRUE
usage_tip = "This gateway is strictly one-way and will only allow things through the invoker's portal."
tier = SCRIPTURE_SCRIPT
+ sort_priority = 19
/datum/clockwork_scripture/spatial_gateway/check_special_requirements()
if(!isturf(invoker.loc))
@@ -684,7 +673,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
name = "Soul Vessel"
desc = "Forms an ancient positronic brain with an overriding directive to serve Ratvar."
invocations = list("Herd the souls of...", "...the blasphemous damned!")
- channel_time = 20
+ channel_time = 30
required_components = list("vanguard_cogwheel" = 1, "guvax_capacitor" = 2)
consumed_components = list("vanguard_cogwheel" = 1, "guvax_capacitor" = 1)
whispered = TRUE
@@ -692,6 +681,8 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
creator_message = "You form a soul vessel, which can be used in-hand to attract spirits, or used on an unconscious or dead human to extract their consciousness."
usage_tip = "The vessel can be used as a teleport target for Spatial Gateway, though it is generally better-used by placing it in a shell."
tier = SCRIPTURE_SCRIPT
+ space_allowed = TRUE
+ sort_priority = 16
@@ -700,7 +691,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
name = "Cogscarab"
desc = "Creates a small shell fitted for soul vessels. Adding an active soul vessel to it results in a small construct with tools and an inbuilt proselytizer."
invocations = list("Call forth...", "...the workers of Armorer.")
- channel_time = 50
+ channel_time = 60
required_components = list("belligerent_eye" = 2, "hierophant_ansible" = 1)
consumed_components = list("belligerent_eye" = 1, "hierophant_ansible" = 1)
object_path = /obj/structure/destructible/clockwork/shell/cogscarab
@@ -708,6 +699,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
observer_message = "The slab disgorges a puddle of black metal that contracts and forms into a strange shell!"
usage_tip = "Useless without a soul vessel and should not be created without one."
tier = SCRIPTURE_SCRIPT
+ sort_priority = 12
@@ -725,6 +717,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
usage_tip = "This is not a primary conversion method - use Guvax for that. It is advantageous as a trap, however, as it will transmit the name of the newly-converted."
tier = SCRIPTURE_SCRIPT
one_per_tile = TRUE
+ sort_priority = 15
//////////////////
@@ -737,7 +730,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
desc = "Creates a large shell fitted for soul vessels. Adding an active soul vessel to it results in a powerful construct with decent health, notable melee power, \
and exceptional speed, though taking damage will temporarily slow it down."
invocations = list("Call forth...", "...the soldiers of Armorer.")
- channel_time = 70
+ channel_time = 80
required_components = list("belligerent_eye" = 1, "vanguard_cogwheel" = 1, "replicant_alloy" = 3)
consumed_components = list("belligerent_eye" = 1, "vanguard_cogwheel" = 1, "replicant_alloy" = 2)
object_path = /obj/structure/destructible/clockwork/shell/fragment
@@ -745,6 +738,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
observer_message = "The slab disgorges a puddle of black metal that expands and forms into a strange shell!"
usage_tip = "Useless without a soul vessel and should not be created without one."
tier = SCRIPTURE_APPLICATION
+ sort_priority = 25
@@ -764,6 +758,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
usage_tip = "It will remain after converting a target, unless that target has a mindshield implant, which it will break to convert them, but consume itself in the process."
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
+ sort_priority = 22
@@ -781,6 +776,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
usage_tip = "Can be recharged by using Volt Void while standing on it."
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
+ sort_priority = 26
@@ -799,14 +795,15 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
usage_tip = "To revive a servant, the sigil must have 20 vitality plus the target servant's non-oxygen damage. It will still heal dead servants if it lacks the vitality to outright revive them."
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
+ sort_priority = 23
/datum/clockwork_scripture/memory_allocation //Memory Allocation: Finds a willing ghost and makes them into a clockwork marauders for the invoker.
descname = "Guardian"
name = "Memory Allocation"
- desc = "Allocates part of your consciousness to a Clockwork Marauder, a vigilent fighter similar to the alien holoparasites employed by the Syndicate; It lives within you, able to be \
+ desc = "Allocates part of your consciousness to a Clockwork Marauder, a vigilent fighter that lives within you, able to be \
called forth by Speaking its True Name or if you become exceptionally low on health.
\
- Unlike holoparasites, however, it does not transfer the damage it takes to you, instead simply gaining Fatigue as it is attacked. Marauders cannot move too far from their hosts, \
+ It gains Fatigue as it is attacked, weakening it. Marauders cannot move too far from their hosts, \
and will gain Fatigue at an increasing rate as they grow farther away. At maximum Fatigue, the marauder is forced to return to you and will be unable to manifest until its Fatigue is at zero."
invocations = list("Fright's will...", "...call forth...")
channel_time = 100
@@ -814,6 +811,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
consumed_components = list("belligerent_eye" = 1, "vanguard_cogwheel" = 1, "guvax_capacitor" = 2)
usage_tip = "Marauders are useful as personal bodyguards and frontline warriors, although they do little damage."
tier = SCRIPTURE_APPLICATION
+ sort_priority = 24
/datum/clockwork_scripture/memory_allocation/check_special_requirements()
for(var/mob/living/simple_animal/hostile/clockwork/marauder/M in living_mob_list)
@@ -884,6 +882,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
usage_tip = "If it fails to funnel power into a nearby Sigil of Transmission and fails to disable even one thing, it will disable itself for two minutes."
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
+ sort_priority = 29
@@ -903,6 +902,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
usage_tip = "Powerful healing but power use is very inefficient, and its alloy use is little better."
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
+ sort_priority = 27
@@ -922,6 +922,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
usage_tip = "Producing a gateway has a high power cost. Gateways to or between clockwork obelisks recieve double duration and uses."
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
+ sort_priority = 30
@@ -941,13 +942,14 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
usage_tip = "Eligible human servants next to the motor will be converted at an additional power cost. It will also cure hallucinations and brain damage in nearby servants."
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
+ sort_priority = 28
/datum/clockwork_scripture/create_object/tinkerers_daemon //Tinkerer's Daemon: Creates a shell that can be attached to a tinkerer's cache to grant it passive component creation.
descname = "Component Generator"
name = "Tinkerer's Daemon"
- desc = "Forms a daemon shell that can be attached to a tinkerer's cache to add new components at a healthy rate. It will only function if it is outnumbered by servants in a ratio of 5:1."
+ desc = "Forms a daemon shell that can be attached to a tinkerer's cache to add new components at a healthy rate. It will only function if it is outnumbered by servants by a ratio of 5:1."
invocations = list("Collect Engine parts...", "...that yet hold greatness!")
channel_time = 80
required_components = list("belligerent_eye" = 3, "vanguard_cogwheel" = 3, "guvax_capacitor" = 3, "replicant_alloy" = 3, "hierophant_ansible" = 3)
@@ -956,6 +958,8 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
creator_message = "You form a daemon shell. Attach it to a tinkerer's cache to increase its rate of production."
usage_tip = "Vital to your success!"
tier = SCRIPTURE_APPLICATION
+ space_allowed = TRUE
+ sort_priority = 21
/datum/clockwork_scripture/create_object/tinkerers_daemon/check_special_requirements()
var/servants = 0
@@ -987,6 +991,9 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
usage_tip = "Ocular wardens will become empowered, clockwork proselytizers will require no alloy, tinkerer's daemons will produce twice as quickly, \
and interdiction lenses, mending motors, mania motors, and clockwork obelisks will all require no power."
tier = SCRIPTURE_REVENANT
+ sort_priority = 33
+ invokers_required = 3
+ multiple_invokers_used = TRUE
/datum/clockwork_scripture/invoke_nezbere/check_special_requirements()
if(!slab.no_cost && clockwork_generals_invoked["nezbere"] > world.time)
@@ -1038,6 +1045,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
consumed_components = list("belligerent_eye" = 3, "vanguard_cogwheel" = 3, "guvax_capacitor" = 6, "hierophant_ansible" = 3)
usage_tip = "Causes brain damage, hallucinations, confusion, and dizziness in massive amounts."
tier = SCRIPTURE_REVENANT
+ sort_priority = 32
invokers_required = 3
multiple_invokers_used = TRUE
var/list/mindbreaksayings = list("\"Oh, great. I get to shatter some minds.\"", "\"More minds to crush.\"", \
@@ -1108,6 +1116,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
consumed_components = list("belligerent_eye" = 3, "guvax_capacitor" = 3, "replicant_alloy" = 3, "hierophant_ansible" = 6)
usage_tip = "Struck targets will also be knocked down for about sixteen seconds."
tier = SCRIPTURE_REVENANT
+ sort_priority = 34
/datum/clockwork_scripture/invoke_nzcrentr/check_special_requirements()
if(!slab.no_cost && clockwork_generals_invoked["nzcrentr"] > world.time)
@@ -1137,7 +1146,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
for(var/mob/living/L in view(7, invoker))
if(is_servant_of_ratvar(L))
continue
- invoker.Beam(L, icon_state = "nzcrentrs_power", icon = 'icons/effects/beam.dmi', time = 10)
+ invoker.Beam(L, icon_state = "nzcrentrs_power", time = 10)
var/randdamage = rand(40, 60)
if(iscarbon(L))
L.electrocute_act(randdamage, "Nzcrentr's power", 1, randdamage)
@@ -1169,6 +1178,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
consumed_components = list("vanguard_cogwheel" = 6, "guvax_capacitor" = 3, "replicant_alloy" = 3, "hierophant_ansible" = 3)
usage_tip = "Those affected by this scripture are only weak to things that outright destroy bodies, such as bombs or the singularity."
tier = SCRIPTURE_REVENANT
+ sort_priority = 31
var/total_duration = 150
/datum/clockwork_scripture/invoke_inathneq/check_special_requirements()
@@ -1209,6 +1219,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
usage_tip = "The gateway is completely vulnerable to attack during its five-minute duration. It will periodically give indication of its general position to everyone on the station \
as well as being loud enough to be heard throughout the entire sector. Defend it with your life!"
tier = SCRIPTURE_JUDGEMENT
+ sort_priority = 35
/datum/clockwork_scripture/ark_of_the_clockwork_justiciar/New()
if(ticker && ticker.mode && ticker.mode.clockwork_objective != CLOCKCULT_GATEWAY)
diff --git a/code/game/gamemodes/clock_cult/clock_structures.dm b/code/game/gamemodes/clock_cult/clock_structures.dm
index ca63657de88..a543a5d2d3b 100644
--- a/code/game/gamemodes/clock_cult/clock_structures.dm
+++ b/code/game/gamemodes/clock_cult/clock_structures.dm
@@ -174,7 +174,7 @@
/obj/structure/destructible/clockwork/ocular_warden //Ocular warden: Low-damage, low-range turret. Deals constant damage to whoever it makes eye contact with.
name = "ocular warden"
desc = "A large brass eye with tendrils trailing below it and a wide red iris."
- clockwork_desc = "A stalwart turret that will deal sustained damage to any non-faithful it sees."
+ clockwork_desc = "A fragile turret that will deal sustained damage to any non-faithful it sees."
icon_state = "ocular_warden"
health = 25
max_health = 25
@@ -187,7 +187,7 @@
var/sight_range = 3
var/atom/movable/target
var/list/idle_messages = list(" sulkily glares around.", " lazily drifts from side to side.", " looks around for something to burn.", " slowly turns in circles.")
- var/mech_damage_cycle = 0 //only hits every few cycles so mechs have a chance against it
+ var/mech_damage_cycle = 0 //so that people in mechs don't get murderspammed with messages
/obj/structure/destructible/clockwork/ocular_warden/New()
..()
@@ -218,12 +218,14 @@
L.adjust_fire_stacks(damage_per_tick)
L.IgniteMob()
else if(istype(target,/obj/mecha))
- if(mech_damage_cycle)
- var/obj/mecha/M = target
- M.take_directional_damage(damage_per_tick, "fire", get_dir(src, M), 0) //does about half of standard damage to mechs * whatever their fire armor is
- mech_damage_cycle--
+ var/sending_message = FALSE
+ if(mech_damage_cycle > 1)
+ mech_damage_cycle = 0
+ sending_message = TRUE
else
mech_damage_cycle++
+ var/obj/mecha/M = target
+ M.take_directional_damage(damage_per_tick, "fire", get_dir(src, M), 0, 1, sending_message)
setDir(get_dir(get_turf(src), get_turf(target)))
if(!target)
if(validtargets.len)
@@ -331,15 +333,48 @@
/obj/item/clockwork/alloy_shards/medium = 4, \
/obj/item/clockwork/alloy_shards/small = 2) //slightly more debris than the default, totals 26 alloy
+/obj/structure/destructible/clockwork/wall_gear/displaced
+ anchored = FALSE
+
/obj/structure/destructible/clockwork/wall_gear/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/wrench))
default_unfasten_wrench(user, I, 10)
return 1
+ else if(istype(I, /obj/item/stack/sheet/brass))
+ var/obj/item/stack/sheet/brass/W = I
+ if(W.get_amount() < 1)
+ user << "You need one brass sheet to do this!"
+ return
+ var/turf/T = get_turf(src)
+ if(istype(T, /turf/closed/wall))
+ user << "There is already a wall present!"
+ return
+ if(!istype(T, /turf/open/floor))
+ user << "A floor must be present to build a [anchored ? "false ":""]wall!"
+ return
+ if(locate(/obj/structure/falsewall) in T.contents)
+ user << "There is already a false wall present!"
+ return
+ user << "You start adding [W] to [src]..."
+ if(do_after(user, 20, target = src))
+ var/brass_floor = FALSE
+ if(istype(T, /turf/open/floor/clockwork)) //if the floor is already brass, costs less to make(conservation of masssssss)
+ brass_floor = TRUE
+ if(W.use(2 - brass_floor))
+ if(anchored)
+ T.ChangeTurf(/turf/closed/wall/clockwork)
+ else
+ T.ChangeTurf(/turf/open/floor/clockwork)
+ new /obj/structure/falsewall/brass(T)
+ qdel(src)
+ else
+ user << "You need more brass to make a [anchored ? "false ":""]wall!"
+ return 1
return ..()
/obj/structure/destructible/clockwork/wall_gear/examine(mob/user)
..()
- user << "[src] is [anchored ? "secured to the floor":"mobile, and not secured"]."
+ user << "[src] is [anchored ? "":"not "]secured to the floor."
///////////////////////
// CLOCKWORK EFFECTS //
@@ -579,7 +614,7 @@
name = "clockwork wall"
icon = 'icons/turf/walls/clockwork_wall.dmi'
icon_state = "clockwork_wall"
- canSmoothWith = list(/obj/effect/clockwork/overlay/wall)
+ canSmoothWith = list(/obj/effect/clockwork/overlay/wall, /obj/structure/falsewall/brass)
smooth = SMOOTH_TRUE
layer = CLOSED_TURF_LAYER
diff --git a/code/game/gamemodes/cult/cult_comms.dm b/code/game/gamemodes/cult/cult_comms.dm
index accff66ebdd..13f1c4acf2a 100644
--- a/code/game/gamemodes/cult/cult_comms.dm
+++ b/code/game/gamemodes/cult/cult_comms.dm
@@ -30,9 +30,9 @@
if(!user)
return
if(!ishuman(user))
- user.say(message)
+ user.say(html_decode(message))
else
- user.whisper(message)
+ user.whisper(html_decode(message))
var/my_message = "[(ishuman(user) ? "Acolyte" : "Construct")] [user]: [message]"
for(var/mob/M in mob_list)
if(iscultist(M))
diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm
index 0f419ad2fec..499c09eca84 100644
--- a/code/game/gamemodes/cult/cult_items.dm
+++ b/code/game/gamemodes/cult/cult_items.dm
@@ -345,14 +345,14 @@
if(uses <= 0)
icon_state ="shifter_drained"
playsound(mobloc, "sparks", 50, 1)
- PoolOrNew(/obj/effect/overlay/temp/cult/phase/out, list(mobloc, C.dir))
+ PoolOrNew(/obj/effect/overlay/temp/dir_setting/cult/phase/out, list(mobloc, C.dir))
var/atom/movable/pulled = handle_teleport_grab(destination, C)
C.forceMove(destination)
if(pulled)
C.start_pulling(pulled) //forcemove resets pulls, so we need to re-pull
- PoolOrNew(/obj/effect/overlay/temp/cult/phase, list(destination, C.dir))
+ PoolOrNew(/obj/effect/overlay/temp/dir_setting/cult/phase, list(destination, C.dir))
playsound(destination, 'sound/effects/phasein.ogg', 25, 1)
playsound(destination, "sparks", 50, 1)
diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm
index 405b6512001..980fbc9dd11 100644
--- a/code/game/gamemodes/cult/cult_structures.dm
+++ b/code/game/gamemodes/cult/cult_structures.dm
@@ -33,7 +33,7 @@
if(istype(M, /mob/living/simple_animal/hostile/construct/builder))
if(health < max_health)
health = min(max_health, health + 5)
- Beam(M, icon_state="sendbeam", icon='icons/effects/effects.dmi', time=4)
+ Beam(M, icon_state="sendbeam", time=4)
M.visible_message("[M] repairs \the [src].", \
"You repair [src], leaving it at [health]/[max_health] stability.")
else
diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm
index 92922f8e5ba..0b1d11cd3c4 100644
--- a/code/game/gamemodes/cult/ritual.dm
+++ b/code/game/gamemodes/cult/ritual.dm
@@ -67,20 +67,15 @@ This file contains the arcane tome files.
invoking it and choosing which talisman you desire, the paper will be converted, after some delay into a talisman.
"
text += "Teleport
This rune is unique in that it requires a keyword before the scribing can begin. When invoked, it will find any other Teleport runes; \
- If any are found, the user can choose which rune to send to. Upon activation, the rune teleports everything above it to the selected rune.
"
+ If any are found, the user can choose which rune to send to. Upon activation, the rune teleports everything above it to the selected rune, provided the selected rune is unblocked.
"
- text += "Convert
This rune is critical to the success of the cult. It will allow you to convert normal crew members into cultists. \
- To do this, simply place the crew member upon the rune and invoke it. This rune requires two invokers to use. If the target to be converted is mindshield-implanted or a certain assignment, they will \
- be unable to be converted. People the Geometer wishes sacrificed will also be ineligible for conversion, and anyone with a shielding presence like the null rod will not be converted.
\
- Successful conversions will produce a tome for the new cultist.
"
+ text += "Offer
This rune is necessary to achieve your goals. Placing a noncultist above it will convert them if it can and sacrifice them otherwise. \
+ It requires two invokers to convert a target and three to sacrifice a living target or the sacrifice target.
\
+ Successful conversions will produce a tome for the new cultist, in addition to healing them.
\
+ Successful sacrifices will please the Geometer, can complete your objective if it sacrificed the sacrifice target, and will attempt to place the target into a soulstone.
"
- text += "Sacrifice
This rune is necessary to achieve your goals. Simply place any dead creature upon the rune and invoke it (this will not \
- target cultists!). If this creature has a mind, a soulstone will be created and the creature's soul transported to it. Sacrificing the dead can be done alone, but sacrificing living crew or your cult's target will require 3 cultists. \
- Soulstones used on construct shells will move that soul into a powerful construct of your choice.
"
-
- text += "Raise Dead
This rune requires two corpses. To perform the ritual, place the corpse you wish to revive onto \
- the rune and the offering body adjacent to it. When the rune is invoked, the body to be sacrificed will turn to dust, the life force flowing into the revival target. Assuming the target is not moved \
- within a few seconds, they will be brought back to life, healed of all ailments.
"
+ text += "Raise Dead
This rune requires the corpse of a cultist placed upon the rune, and one person sacrificed for each revival you wish to do.\
+ Provided there are remaining revivals from those sacrificed, invoking the rune will revive the cultist placed upon it.
"
text += "Electromagnetic Disruption
Robotic lifeforms have time and time again been the downfall of fledgling cults. This rune may allow you to gain the upper \
hand against these pests. By using the rune, a large electromagnetic pulse will be emitted from the rune's location. The size of the EMP will grow significantly for each additional adjacent cultist when the \
@@ -91,14 +86,14 @@ This file contains the arcane tome files.
The body will also take constant damage while in this form, and may even die. The user's spirit will contain their consciousness, and will allow them to freely wander the station as a ghost. This may \
also be used to commune with the dead.
"
- text += "Form Barrier
While simple, this rune serves an important purpose in defense and hindering passage. When invoked, the \
- rune will draw a small amount of life force from the user and make the space above the rune completely dense, rendering it impassable to all but the most complex means. The rune may be invoked again to \
- undo this effect and allow passage again.
"
+ text += "Form Barrier
While simple, this rune serves an important purpose in defense and hindering passage. When invoked, the rune will draw a small amount of blood from the user \
+ and make the space above the rune completely dense, rendering it impassable for about a minute and a half. This effect will spread to other nearby Barrier Runes. \
+ The rune may be invoked again to undo this effect and allow passage again.
"
text += "Summon Cultist
This rune allows the cult to free other cultists with ease. When invoked, it will allow the user to summon a single cultist to the rune from \
any location. It requires two invokers, and will damage each invoker slightly.
"
- text += "Blood Boil
When invoked, this rune will do a massive amount of damage to all non-cultist viewers, but it will also emit a small explosion upon invocation. \
+ text += "Blood Boil
When invoked, this rune will rapidly do a massive amount of damage to all non-cultist viewers, but it will also emit a burst of flame once it finishes. \
It requires three invokers.
"
text += "Drain Life
This rune will drain the life of every living creature above the rune, healing the invoker for each creature drained by it.
"
diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm
index abfdfa813d6..d42b1bdeaff 100644
--- a/code/game/gamemodes/cult/runes.dm
+++ b/code/game/gamemodes/cult/runes.dm
@@ -1,4 +1,4 @@
-/var/list/sacrificed = list()
+/var/list/sacrificed = list() //a mixed list of minds and mobs
var/list/non_revealed_runes = (subtypesof(/obj/effect/rune) - /obj/effect/rune/malformed)
/*
@@ -23,10 +23,11 @@ To draw a rune, use an arcane tome.
icon_state = "1"
unacidable = 1
layer = ABOVE_NORMAL_TURF_LAYER
- color = rgb(255,0,0)
+ color = "#FF0000"
var/invocation = "Aiy ele-mayo!" //This is said by cultists when the rune is invoked.
var/req_cultists = 1 //The amount of cultists required around the rune to invoke it. If only 1, any cultist can invoke it.
+ var/req_cultists_text //if we have a description override for required cultists to invoke
var/rune_in_use = 0 // Used for some runes, this is for when you want a rune to not be usable when in use.
var/scribe_delay = 50 //how long the rune takes to create
@@ -48,7 +49,7 @@ To draw a rune, use an arcane tome.
if(iscultist(user) || user.stat == DEAD) //If they're a cultist or a ghost, tell them the effects
user << "Name: [cultist_name]"
user << "Effects: [capitalize(cultist_desc)]"
- user << "Required Acolytes: [req_cultists]"
+ user << "Required Acolytes: [req_cultists_text ? "[req_cultists_text]":"[req_cultists]"]"
if(req_keyword && keyword)
user << "Keyword: [keyword]"
@@ -137,6 +138,9 @@ structure_check() searches for nearby cultist structures required for the invoca
for(var/M in invokers)
var/mob/living/L = M
L.say(invocation)
+ do_invoke_glow()
+
+/obj/effect/rune/proc/do_invoke_glow()
var/oldtransform = transform
spawn(0) //animate is a delay, we want to avoid being delayed
animate(src, transform = matrix()*2, alpha = 0, time = 5) //fade out
@@ -187,7 +191,7 @@ structure_check() searches for nearby cultist structures required for the invoca
cultist_desc = "transforms paper into powerful magic talismans."
invocation = "H'drak v'loso, mir'kanas verbot!"
icon_state = "3"
- color = rgb(0, 0, 255)
+ color = "#0000FF"
/obj/effect/rune/imbue/invoke(var/list/invokers)
var/mob/living/user = invokers[1] //the first invoker is always the user
@@ -296,6 +300,11 @@ var/list/teleport_runes = list()
return
var/turf/T = get_turf(src)
+ var/turf/target = get_turf(actual_selected_rune)
+ if(is_blocked_turf(target))
+ user << "The target rune is blocked. Attempting to teleport to it would be massively unwise."
+ fail_invoke()
+ return
var/movedsomething = 0
var/moveuserlater = 0
for(var/atom/movable/A in T)
@@ -305,158 +314,134 @@ var/list/teleport_runes = list()
continue
if(!A.anchored)
movedsomething = 1
- A.forceMove(get_turf(actual_selected_rune))
+ A.forceMove(target)
if(movedsomething)
..()
visible_message("There is a sharp crack of inrushing air, and everything above the rune disappears!")
user << "You[moveuserlater ? "r vision blurs, and you suddenly appear somewhere else":" send everything above the rune away"]."
if(moveuserlater)
- user.forceMove(get_turf(actual_selected_rune))
+ user.forceMove(target)
else
fail_invoke()
-//Rite of Enlightenment: Converts a normal crewmember to the cult.
+//Rite of Offering: Converts or sacrifices a target.
/obj/effect/rune/convert
- cultist_name = "Convert"
- cultist_desc = "converts a normal crewmember on top of it to the cult. Does not work on mindshield-implanted crew."
+ cultist_name = "Offer"
+ cultist_desc = "offers a noncultist above it to Nar-Sie, either converting them or sacrificing them."
+ req_cultists_text = "2 for conversion, 3 for living sacrifices and sacrifice targets."
invocation = "Mah'weyh pleggh at e'ntrath!"
icon_state = "3"
- color = rgb(200, 0, 0)
- req_cultists = 2
+ color = "#FFFFFF"
+ req_cultists = 1
+ allow_excess_invokers = 1
+ rune_in_use = FALSE
+
+/obj/effect/rune/convert/do_invoke_glow()
+ return
/obj/effect/rune/convert/invoke(var/list/invokers)
- var/list/convertees = list()
- var/turf/T = get_turf(src)
- for(var/mob/living/M in T)
- if(M.stat != DEAD && !iscultist(M) && is_convertable_to_cult(M.mind))
- convertees |= M
- else if(is_sacrifice_target(M.mind))
- for(var/C in invokers)
- C << "\"I desire this one for myself. SACRIFICE THEM!\""
- else if(is_servant_of_ratvar(M))
- M.visible_message("[M]'s eyes glow a defiant yellow!", \
- "\"Stop resisting. You will be mi-\" \"Give up and you will feel pain unlike anything you've ever felt!\"")
- M.Weaken(4)
- if(!convertees.len)
- fail_invoke()
- log_game("Convert rune failed - no eligible convertees")
- return
- var/mob/living/new_cultist = pick(convertees)
- if(new_cultist.null_rod_check())
- for(var/M in invokers)
- M << "Something is shielding [new_cultist]'s mind!"
- fail_invoke()
- log_game("Convert rune failed - convertee had null rod")
- return
- ..()
- new_cultist.visible_message("[new_cultist] writhes in pain as the markings below them glow a bloody red!", \
- "AAAAAAAAAAAAAA-")
- ticker.mode.add_cultist(new_cultist.mind, 1)
- new /obj/item/weapon/tome(get_turf(src))
- new_cultist.mind.special_role = "Cultist"
- new_cultist << "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible, truth. The veil of reality has been ripped away \
- and something evil takes root."
- new_cultist << "Assist your new compatriots in their dark dealings. Your goal is theirs, and theirs is yours. You serve the Geometer above all else. Bring it back.\
- "
-
-//Rite of Tribute: Sacrifices a crew member to Nar-Sie. Places them into a soul shard if they're in their body.
-/obj/effect/rune/sacrifice
- cultist_name = "Sacrifice"
- cultist_desc = "sacrifices a crew member to the Geometer. May place them into a soul shard if their spirit remains in their body."
- icon_state = "3"
- allow_excess_invokers = 1
- invocation = "Barhah hra zar'garis!"
- color = rgb(255, 255, 255)
- rune_in_use = 0
-
-/obj/effect/rune/sacrifice/New()
- ..()
- icon_state = "[rand(1,7)]"
-
-/obj/effect/rune/sacrifice/invoke(var/list/invokers)
if(rune_in_use)
return
- rune_in_use = 1
- var/mob/living/user = invokers[1] //the first invoker is always the user
+ var/list/myriad_targets = list()
var/turf/T = get_turf(src)
- var/list/possible_targets = list()
- for(var/mob/living/M in T.contents)
- if(M.mind)
- if(M.mind in sacrificed)
- continue
+ for(var/mob/living/M in T)
if(!iscultist(M))
- possible_targets.Add(M)
- var/mob/offering
- if(possible_targets.len > 1) //If there's more than one target, allow choice
- offering = input(user, "Choose an offering to sacrifice.", "Unholy Tribute") as null|anything in possible_targets
- if(!Adjacent(user) || !src || qdeleted(src) || user.incapacitated())
- return
- else if(possible_targets.len) //Otherwise, if there's a target at all, pick the only one
- offering = possible_targets[possible_targets.len]
- if(!offering)
- rune_in_use = 0
- return
- /*var/obj/item/weapon/nullrod/N = offering.null_rod_check()
- if(N)
- user << "Something is blocking the Geometer's magic!"
- log_game("Sacrifice rune failed - target has \a [N]!")
+ myriad_targets |= M
+ if(!myriad_targets.len)
fail_invoke()
- rune_in_use = 0
- return*/
- if(((ishuman(offering) || isrobot(offering)) && offering.stat != DEAD) || is_sacrifice_target(offering.mind)) //Requires three people to sacrifice living targets
- if(invokers.len < 3)
- for(var/M in invokers)
- M << "[offering] is too greatly linked to the world! You need three acolytes!"
- fail_invoke()
- log_game("Sacrifice rune failed - not enough acolytes and target is living")
- rune_in_use = 0
- return
+ log_game("Offer rune failed - no eligible targets")
+ return
+ rune_in_use = TRUE
visible_message("[src] pulses blood red!")
- color = rgb(126, 23, 23)
- ..()
- sac(invokers, offering)
- color = initial(color)
+ color = "#7D1717"
+ var/mob/living/L = pick(myriad_targets)
+ var/is_clock = is_servant_of_ratvar(L)
+ var/is_convertable = is_convertable_to_cult(L.mind)
+ if(L.stat != DEAD && (is_clock || is_convertable))
+ invocation = "Mah'weyh pleggh at e'ntrath!"
+ ..()
+ if(is_clock)
+ L.visible_message("[L]'s eyes glow a defiant yellow!", \
+ "\"Stop resisting. You will be mi-\"\n\
+ \"Give up and you will feel pain unlike anything you've ever felt!\"")
+ L.Weaken(4)
+ else if(is_convertable)
+ do_convert(L, invokers)
+ else
+ invocation = "Barhah hra zar'garis!"
+ ..()
+ do_sacrifice(L, invokers)
+ animate(src, color = initial(color), time = 5)
+ rune_in_use = FALSE
-/obj/effect/rune/sacrifice/proc/sac(var/list/invokers, mob/living/T)
- var/sacrifice_fulfilled
- if(T)
- if(istype(T, /mob/living/simple_animal/pet/dog))
- for(var/M in invokers)
- var/mob/living/L = M
- L << "\"Even I have standards, such as they are!\""
- if(L.reagents)
- L.reagents.add_reagent("hell_water", 2)
- if(T.mind)
- sacrificed.Add(T.mind)
- if(is_sacrifice_target(T.mind))
- sacrifice_fulfilled = 1
- PoolOrNew(/obj/effect/overlay/temp/cult/sac, src.loc)
+/obj/effect/rune/convert/proc/do_convert(mob/living/convertee, list/invokers)
+ if(invokers.len < 2)
for(var/M in invokers)
- if(sacrifice_fulfilled)
- M << "\"Yes! This is the one I desire! You have done well.\""
- else
- if(ishuman(T) || isrobot(T))
- M << "\"I accept this sacrifice.\""
- else
- M << "\"I accept this meager sacrifice.\""
- if(T.mind)
- var/obj/item/device/soulstone/stone = new /obj/item/device/soulstone(get_turf(src))
- stone.invisibility = INVISIBILITY_MAXIMUM //so it's not picked up during transfer_soul()
- if(!stone.transfer_soul("FORCE", T, usr)) //If it cannot be added
- qdel(stone)
- if(stone)
- stone.invisibility = 0
- if(!T)
- rune_in_use = 0
- return
- if(isrobot(T))
- playsound(T, 'sound/magic/Disable_Tech.ogg', 100, 1)
- T.dust() //To prevent the MMI from remaining
+ M << "You need more invokers to convert [convertee]!"
+ log_game("Offer rune failed - tried conversion with one invoker")
+ return 0
+ if(convertee.null_rod_check())
+ for(var/M in invokers)
+ M << "Something is shielding [convertee]'s mind!"
+ log_game("Offer rune failed - convertee had null rod")
+ return 0
+ var/brutedamage = convertee.getBruteLoss()
+ var/burndamage = convertee.getFireLoss()
+ if(brutedamage || burndamage)
+ convertee.adjustBruteLoss(-(brutedamage * 0.75))
+ convertee.adjustFireLoss(-(burndamage * 0.75))
+ convertee.visible_message("[convertee] writhes in pain \
+ [brutedamage || burndamage ? "even as their wounds heal and close" : "as the markings below them glow a bloody red"]!", \
+ "AAAAAAAAAAAAAA-")
+ ticker.mode.add_cultist(convertee.mind, 1)
+ new /obj/item/weapon/tome(get_turf(src))
+ convertee.mind.special_role = "Cultist"
+ convertee << "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible, truth. The veil of reality has been ripped away \
+ and something evil takes root."
+ convertee << "Assist your new compatriots in their dark dealings. Your goal is theirs, and theirs is yours. You serve the Geometer above all else. Bring it back.\
+ "
+ return 1
+
+/obj/effect/rune/convert/proc/do_sacrifice(mob/living/sacrificial, list/invokers)
+ if((((ishuman(sacrificial) || isrobot(sacrificial)) && sacrificial.stat != DEAD) || is_sacrifice_target(sacrificial.mind)) && invokers.len < 3)
+ for(var/M in invokers)
+ M << "[sacrificial] is too greatly linked to the world! You need three acolytes!"
+ log_game("Offer rune failed - not enough acolytes and target is living or sac target")
+ return FALSE
+ var/sacrifice_fulfilled = FALSE
+
+ if(sacrificial.mind)
+ sacrificed += sacrificial.mind
+ if(is_sacrifice_target(sacrificial.mind))
+ sacrifice_fulfilled = TRUE
+ else
+ sacrificed += sacrificial
+
+ PoolOrNew(/obj/effect/overlay/temp/cult/sac, get_turf(src))
+ for(var/M in invokers)
+ if(sacrifice_fulfilled)
+ M << "\"Yes! This is the one I desire! You have done well.\""
else
- playsound(T, 'sound/magic/Disintegrate.ogg', 100, 1)
- T.gib()
- rune_in_use = 0
+ if(ishuman(sacrificial) || isrobot(sacrificial))
+ M << "\"I accept this sacrifice.\""
+ else
+ M << "\"I accept this meager sacrifice.\""
+
+ var/obj/item/device/soulstone/stone = new /obj/item/device/soulstone(get_turf(src))
+ if(sacrificial.mind)
+ stone.invisibility = INVISIBILITY_MAXIMUM //so it's not picked up during transfer_soul()
+ stone.transfer_soul("FORCE", sacrificial, usr)
+ stone.invisibility = 0
+
+ if(sacrificial)
+ if(isrobot(sacrificial))
+ playsound(sacrificial, 'sound/magic/Disable_Tech.ogg', 100, 1)
+ sacrificial.dust() //To prevent the MMI from remaining
+ else
+ playsound(sacrificial, 'sound/magic/Disintegrate.ogg', 100, 1)
+ sacrificial.gib()
+ return TRUE
//Ritual of Dimensional Rending: Calls forth the avatar of Nar-Sie upon the station.
/obj/effect/rune/narsie
@@ -465,7 +450,7 @@ var/list/teleport_runes = list()
invocation = "TOK-LYR RQA-NAP G'OLT-ULOFT!!"
req_cultists = 9
icon = 'icons/effects/96x96.dmi'
- color = rgb(125,23,23)
+ color = "#7D1717"
icon_state = "rune_large"
pixel_x = -32 //So the big ol' 96x96 sprite shows up right
pixel_y = -32
@@ -501,6 +486,7 @@ var/list/teleport_runes = list()
M << "Nar-Sie does not respond!"
fail_invoke()
log_game("Summon Nar-Sie rune failed - gametype is not cult")
+ return
if(locate(/obj/singularity/narsie) in poi_list)
for(var/M in invokers)
@@ -514,7 +500,7 @@ var/list/teleport_runes = list()
var/turf/T = get_turf(src)
sleep(40)
if(src)
- color = rgb(255, 0, 0)
+ color = "#FF0000"
new /obj/singularity/narsie/large(T) //Causes Nar-Sie to spawn even if the rune has been removed
if(cult_mode)
cult_mode.eldergod = 0
@@ -534,50 +520,47 @@ var/list/teleport_runes = list()
..()
return
-//Rite of Resurrection: Requires two corpses. Revives one and gibs the other.
+//Rite of Resurrection: Requires the corpse of a cultist and that there have been less revives than the number of people sacrificed
/obj/effect/rune/raise_dead
cultist_name = "Raise Dead"
- cultist_desc = "requires two corpses, one on the rune and one adjacent to the rune. The one on the rune is brought to life, the other is turned to ash."
+ cultist_desc = "requires the corpse of a cultist placed upon the rune. Provided there have been sufficient sacrifices, they will be revived."
invocation = null //Depends on the name of the user - see below
icon_state = "1"
- color = rgb(200, 0, 0)
+ color = "#C80000"
+ var/static/revives_used = 0
+
+/obj/effect/rune/raise_dead/examine(mob/user)
+ ..()
+ if(iscultist(user) || user.stat == DEAD)
+ var/revive_number = 0
+ if(sacrificed.len)
+ revive_number = sacrificed.len - revives_used
+ user << "Revives Remaining: [revive_number]"
/obj/effect/rune/raise_dead/invoke(var/list/invokers)
var/turf/T = get_turf(src)
- var/mob/living/mob_to_sacrifice
var/mob/living/mob_to_revive
- var/list/potential_sacrifice_mobs = list()
var/list/potential_revive_mobs = list()
var/mob/living/user = invokers[1]
if(rune_in_use)
return
- for(var/mob/living/M in orange(1,T))
- if(M.stat == DEAD && !iscultist(M))
- potential_sacrifice_mobs |= M
- if(!potential_sacrifice_mobs.len)
- user << "There are no eligible sacrifices nearby!"
- log_game("Raise Dead rune failed - no catalyst corpses")
- fail_invoke()
- return
for(var/mob/living/M in T.contents)
- if(M.stat == DEAD)
+ if(iscultist(M) && M.stat == DEAD)
potential_revive_mobs |= M
if(!potential_revive_mobs.len)
- user << "There is no eligible revival target on the rune!"
+ user << "There are no dead cultists on the rune!"
log_game("Raise Dead rune failed - no corpses to revive")
fail_invoke()
return
- if(potential_sacrifice_mobs.len > 1)
- mob_to_sacrifice = input(user, "Choose a corpse to sacrifice.", "Corpse to Sacrifice") as null|anything in potential_sacrifice_mobs
- else
- mob_to_sacrifice = potential_sacrifice_mobs[1]
- if(!src || qdeleted(src) || rune_in_use || !validness_checks(mob_to_sacrifice, user, TRUE))
+ if(!sacrificed.len || sacrificed.len <= revives_used)
+ user << "You have sacrificed too few people to revive a cultist!"
+ fail_invoke()
return
if(potential_revive_mobs.len > 1)
- mob_to_revive = input(user, "Choose a corpse to revive.", "Corpse to Revive") as null|anything in potential_revive_mobs
+ mob_to_revive = input(user, "Choose a cultist to revive.", "Cultist to Revive") as null|anything in potential_revive_mobs
else
mob_to_revive = potential_revive_mobs[1]
- if(!src || qdeleted(src) || rune_in_use || !validness_checks(mob_to_sacrifice, user, TRUE) || !validness_checks(mob_to_revive, user, FALSE))
+ if(!src || qdeleted(src) || rune_in_use || !validness_checks(mob_to_revive, user))
return
rune_in_use = 1
if(user.name == "Herbert West")
@@ -585,19 +568,7 @@ var/list/teleport_runes = list()
else
user.say("Pasnar val'keriam usinar. Savrae ines amutan. Yam'toth remium il'tarat!")
..()
- mob_to_sacrifice.visible_message("[mob_to_sacrifice]'s body rises into the air, connected to [mob_to_revive] by a glowing tendril!")
- mob_to_revive.Beam(mob_to_sacrifice,icon_state="sendbeam",icon='icons/effects/effects.dmi',time=20)
- sleep(20)
- if(!mob_to_sacrifice || !in_range(mob_to_sacrifice, src))
- rune_in_use = 0
- return
- if(!mob_to_revive || mob_to_revive.stat != DEAD)
- visible_message("The glowing tendril snaps against the rune with a shocking crack.")
- rune_in_use = 0
- fail_invoke()
- return
- mob_to_sacrifice.visible_message("[mob_to_sacrifice] disintegrates into a pile of bones.")
- mob_to_sacrifice.dust()
+ revives_used++
mob_to_revive.revive(1, 1) //This does remove disabilities and such, but the rune might actually see some use because of it!
mob_to_revive.grab_ghost()
mob_to_revive << "\"PASNAR SAVRAE YAM'TOTH. Arise.\""
@@ -605,7 +576,7 @@ var/list/teleport_runes = list()
"You awaken suddenly from the void. You're alive!")
rune_in_use = 0
-/obj/effect/rune/raise_dead/proc/validness_checks(mob/living/target_mob, mob/living/user, saccing)
+/obj/effect/rune/raise_dead/proc/validness_checks(mob/living/target_mob, mob/living/user)
var/turf/T = get_turf(src)
if(!user)
return 0
@@ -614,28 +585,28 @@ var/list/teleport_runes = list()
if(!target_mob)
fail_invoke()
return 0
- if(saccing)
- if(!in_range(target_mob, src))
- user << "The sacrificial target has been moved!"
- fail_invoke()
- log_game("Raise Dead rune failed - catalyst corpse moved")
- return 0
- if(target_mob.stat != DEAD)
- user << "The sacrificial target must be dead!"
- fail_invoke()
- log_game("Raise Dead rune failed - catalyst corpse is not dead")
- return 0
- else if(!(target_mob in T.contents))
- user << "The corpse to revive has been moved!"
+ if(!(target_mob in T.contents))
+ user << "The cultist to revive has been moved!"
fail_invoke()
log_game("Raise Dead rune failed - revival target moved")
return 0
+ var/mob/dead/observer/ghost = target_mob.get_ghost(TRUE)
+ if(!ghost)
+ user << "The corpse to revive has no spirit!"
+ fail_invoke()
+ log_game("Raise Dead rune failed - revival target has no ghost")
+ return 0
+ if(!sacrificed.len || sacrificed.len <= revives_used)
+ user << "You have sacrificed too few people to revive a cultist!"
+ fail_invoke()
+ log_game("Raise Dead rune failed - too few sacrificed")
+ return 0
return 1
/obj/effect/rune/raise_dead/fail_invoke()
..()
for(var/mob/living/M in range(1,src))
- if(M.stat == DEAD)
+ if(iscultist(M) && M.stat == DEAD)
M.visible_message("[M] twitches.")
@@ -646,7 +617,7 @@ var/list/teleport_runes = list()
invocation = "Ta'gh fara'qha fel d'amar det!"
icon_state = "5"
allow_excess_invokers = 1
- color = rgb(77, 148, 255)
+ color = "#4D94FF"
/obj/effect/rune/emp/invoke(var/list/invokers)
var/turf/E = get_turf(src)
@@ -676,7 +647,7 @@ var/list/teleport_runes = list()
cultist_desc = "severs the link between one's spirit and body. This effect is taxing and one's physical body will take damage while this is active."
invocation = "Fwe'sh mah erl nyag r'ya!"
icon_state = "7"
- color = rgb(126, 23, 23)
+ color = "#7D1717"
rune_in_use = 0 //One at a time, please!
construct_invoke = 0
var/mob/living/affecting = null
@@ -704,7 +675,7 @@ var/list/teleport_runes = list()
var/turf/T = get_turf(src)
rune_in_use = 1
affecting = user
- user.color = "#7e1717"
+ user.color = "#7D1717"
user.visible_message("[user] freezes statue-still, glowing an unearthly red.", \
"You see what lies beyond. All is revealed. While this is a wondrous experience, your physical form will waste away in this state. Hurry...")
user.ghostize(1)
@@ -717,7 +688,7 @@ var/list/teleport_runes = list()
affecting.apply_damage(0.1, BRUTE)
if(!(user in T))
user.visible_message("A spectral tendril wraps around [user] and pulls them back to the rune!")
- Beam(user,icon_state="drainbeam",icon='icons/effects/effects.dmi',time=2)
+ Beam(user,icon_state="drainbeam",time=2)
user.forceMove(get_turf(src)) //NO ESCAPE :^)
if(user.key)
user.visible_message("[user] slowly relaxes, the glow around them dimming.", \
@@ -742,13 +713,20 @@ var/list/teleport_runes = list()
rune_in_use = 0
+var/list/wall_runes = list()
//Rite of the Corporeal Shield: When invoked, becomes solid and cannot be passed. Invoke again to undo.
/obj/effect/rune/wall
cultist_name = "Form Barrier"
- cultist_desc = "when invoked, makes an invisible wall to block passage. Can be invoked again to reverse this."
+ cultist_desc = "when invoked, makes a temporary invisible wall to block passage. Can be invoked again to reverse this."
invocation = "Khari'd! Eske'te tannin!"
icon_state = "1"
- color = rgb(255, 0, 0)
+ color = "#C80000"
+ var/density_timer
+ var/recharging = FALSE
+
+/obj/effect/rune/wall/New()
+ ..()
+ wall_runes += src
/obj/effect/rune/wall/examine(mob/user)
..()
@@ -757,6 +735,7 @@ var/list/teleport_runes = list()
/obj/effect/rune/wall/Destroy()
density = 0
+ wall_runes -= src
air_update_turf(1)
return ..()
@@ -767,24 +746,55 @@ var/list/teleport_runes = list()
return density
/obj/effect/rune/wall/invoke(var/list/invokers)
+ if(recharging)
+ return
var/mob/living/user = invokers[1]
..()
density = !density
- air_update_turf(1)
+ update_state()
+ if(density)
+ spread_density()
user.visible_message("[user] [iscarbon(user) ? "places their hands on":"stares intently at"] [src], and [density ? "the air above it begins to shimmer" : "the shimmer above it fades"].", \
- "You channel your life energy into [src], [density ? "preventing" : "allowing"] passage above it.")
+ "You channel your life energy into [src], [density ? "temporarily preventing" : "allowing"] passage above it.")
+ if(iscarbon(user))
+ var/mob/living/carbon/C = user
+ C.apply_damage(2, BRUTE, pick("l_arm", "r_arm"))
+
+/obj/effect/rune/wall/proc/spread_density()
+ for(var/R in wall_runes)
+ var/obj/effect/rune/wall/W = R
+ if(W.z == z && get_dist(src, W) <= 2 && !W.density && !W.recharging)
+ W.density = TRUE
+ W.update_state()
+ W.spread_density()
+ density_timer = addtimer(src, "lose_density", 900)
+
+/obj/effect/rune/wall/proc/lose_density()
+ if(density)
+ recharging = TRUE
+ density = FALSE
+ update_state()
+ color = "#696969"
+ animate(src, color = initial(color), time = 50, easing = EASE_IN)
+ addtimer(src, "recharge", 50)
+
+/obj/effect/rune/wall/proc/recharge()
+ recharging = FALSE
+ color = initial(color)
+
+/obj/effect/rune/wall/proc/update_state()
+ deltimer(density_timer)
+ air_update_turf(1)
if(density)
var/image/I = image(layer = ABOVE_MOB_LAYER, icon = 'icons/effects/effects.dmi', icon_state = "barriershimmer")
I.appearance_flags = RESET_COLOR
I.alpha = 60
I.color = "#701414"
- overlays += I
+ add_overlay(I)
+ color = "#FF0000"
else
- overlays.Cut()
- if(iscarbon(user))
- var/mob/living/carbon/C = user
- C.apply_damage(2, BRUTE, pick("l_arm", "r_arm"))
-
+ cut_overlays()
+ color = "#C80000"
//Rite of Joined Souls: Summons a single cultist.
/obj/effect/rune/summon
@@ -794,7 +804,7 @@ var/list/teleport_runes = list()
req_cultists = 2
allow_excess_invokers = 1
icon_state = "5"
- color = rgb(0, 255, 0)
+ color = "#00FF00"
/obj/effect/rune/summon/invoke(var/list/invokers)
var/mob/living/user = invokers[1]
@@ -836,35 +846,67 @@ var/list/teleport_runes = list()
//Rite of Boiling Blood: Deals extremely high amounts of damage to non-cultists nearby
/obj/effect/rune/blood_boil
cultist_name = "Boil Blood"
- cultist_desc = "boils the blood of non-believers who can see the rune, dealing extreme amounts of damage. Requires 3 invokers."
+ cultist_desc = "boils the blood of non-believers who can see the rune, rapidly dealing extreme amounts of damage. Requires 3 invokers."
invocation = "Dedo ol'btoh!"
icon_state = "4"
- color = rgb(200, 0, 0)
+ color = "#C80000"
req_cultists = 3
construct_invoke = 0
+ var/tick_damage = 25
+ rune_in_use = FALSE
+
+/obj/effect/rune/blood_boil/do_invoke_glow()
+ return
/obj/effect/rune/blood_boil/invoke(var/list/invokers)
+ if(rune_in_use)
+ return
..()
+ rune_in_use = TRUE
var/turf/T = get_turf(src)
- visible_message("[src] briefly bubbles before exploding!")
- for(var/mob/living/carbon/C in viewers(T))
- if(!iscultist(C))
- var/obj/item/weapon/nullrod/N = C.null_rod_check()
- if(N)
- C << "\The [N] suddenly burns hotly before returning to normal!"
- continue
- C << "Your blood boils in your veins!"
- C.take_overall_damage(45,45)
- C.Stun(7)
- if(is_servant_of_ratvar(C))
- C << "You feel unholy darkness dimming the Justiciar's light!"
- C.adjustStaminaLoss(30)
+ visible_message("[src] turns a bright, glowing orange!")
+ SetLuminosity(6)
+ color = "#FC9B54"
for(var/M in invokers)
var/mob/living/L = M
- L.apply_damage(15, BRUTE, pick("l_arm", "r_arm"))
+ L.apply_damage(10, BRUTE, pick("l_arm", "r_arm"))
L << "[src] saps your strength!"
+ for(var/mob/living/L in viewers(T))
+ if(!iscultist(L) && L.blood_volume)
+ var/obj/item/weapon/nullrod/N = L.null_rod_check()
+ if(N)
+ L << "\The [N] suddenly burns hotly before returning to normal!"
+ continue
+ L << "Your blood boils in your veins!"
+ if(is_servant_of_ratvar(L))
+ L << "You feel an unholy darkness dimming the Justiciar's light!"
+ animate(src, color = "#FCB56D", time = 4)
+ sleep(4)
+ if(!src)
+ return
+ do_area_burn(T, 0.5)
+ animate(src, color = "#FFDF80", time = 5)
+ sleep(5)
+ if(!src)
+ return
+ do_area_burn(T, 1)
+ animate(src, color = "#FFFDF4", time = 6)
+ sleep(6)
+ if(!src)
+ return
+ do_area_burn(T, 1.5)
+ PoolOrNew(/obj/effect/hotspot, T)
qdel(src)
- explosion(T, -1, 0, 1, 5)
+
+/obj/effect/rune/blood_boil/proc/do_area_burn(turf/T, multiplier)
+ for(var/mob/living/L in viewers(T))
+ if(!iscultist(L) && L.blood_volume)
+ var/obj/item/weapon/nullrod/N = L.null_rod_check()
+ if(N)
+ continue
+ L.take_overall_damage(tick_damage*multiplier, tick_damage*multiplier)
+ if(is_servant_of_ratvar(L))
+ L.adjustStaminaLoss(tick_damage*0.5)
//Deals brute damage to all targets on the rune and heals the invoker for each target drained.
@@ -873,7 +915,7 @@ var/list/teleport_runes = list()
cultist_desc = "drains the life of all targets on the rune, restoring life to the user."
invocation = "Yu'gular faras desdae. Umathar uf'kal thenar!"
icon_state = "3"
- color = rgb(159, 28, 52)
+ color = "#9F1C34"
/obj/effect/rune/leeching/can_invoke(mob/living/user)
if(world.time <= user.next_move)
@@ -900,7 +942,7 @@ var/list/teleport_runes = list()
M.apply_damage(drained_amount, BRUTE, "chest")
user.adjustBruteLoss(-drained_amount)
M << "You feel extremely weak."
- user.Beam(T,icon_state="drainbeam",icon='icons/effects/effects.dmi',time=5)
+ user.Beam(T,icon_state="drainbeam",time=5)
user.visible_message("Blood flows from the rune into [user]!", \
"Blood flows into you, healing your wounds and revitalizing your spirit.")
@@ -912,7 +954,7 @@ var/list/teleport_runes = list()
invocation = "Gal'h'rfikk harfrandid mud'gib!" //how the fuck do you pronounce this
icon_state = "6"
construct_invoke = 0
- color = rgb(200, 0, 0)
+ color = "#C80000"
/obj/effect/rune/manifest/New(loc)
..()
diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm
index 93a2cb6e18a..9a27ad81c6c 100644
--- a/code/game/gamemodes/cult/talisman.dm
+++ b/code/game/gamemodes/cult/talisman.dm
@@ -149,9 +149,13 @@
var/obj/effect/rune/teleport/actual_selected_rune = potential_runes[input_rune_key] //what rune does that key correspond to?
if(!actual_selected_rune)
return ..(user, 0)
+ var/turf/target = get_turf(actual_selected_rune)
+ if(is_blocked_turf(target))
+ user << "The target rune is blocked. Attempting to teleport to it would be massively unwise."
+ return ..(user, 0)
user.visible_message("Dust flows from [user]'s hand, and they disappear in a flash of red light!", \
"You speak the words of the talisman and find yourself somewhere else!")
- user.forceMove(get_turf(actual_selected_rune))
+ user.forceMove(target)
return ..()
@@ -345,8 +349,8 @@
/obj/item/weapon/paper/talisman/construction/afterattack(obj/item/stack/sheet/target, mob/user, proximity_flag, click_parameters)
..()
if(proximity_flag && iscultist(user))
+ var/turf/T = get_turf(target)
if(istype(target, /obj/item/stack/sheet/metal))
- var/turf/T = get_turf(target)
if(target.use(25))
new /obj/structure/constructshell(T)
user << "The talisman clings to the metal and twists it into a construct shell!"
@@ -355,16 +359,16 @@
qdel(src)
else
user << "You need more metal to produce a construct shell!"
- if(istype(target, /obj/item/stack/sheet/plasteel))
- var/quantity = min(target.amount, uses)
- uses -= quantity
- new /obj/item/stack/sheet/runed_metal(T,quantity)
- target.use(quantity)
- user << "The talisman clings to the plasteel, transforming it into runed metal!"
- user << sound('sound/effects/magic.ogg',0,1,25)
- invoke(user, 1)
- if(uses <= 0)
- qdel(src)
+ else if(istype(target, /obj/item/stack/sheet/plasteel))
+ var/quantity = min(target.amount, uses)
+ uses -= quantity
+ new /obj/item/stack/sheet/runed_metal(T,quantity)
+ target.use(quantity)
+ user << "The talisman clings to the plasteel, transforming it into runed metal!"
+ user << sound('sound/effects/magic.ogg',0,1,25)
+ invoke(user, 1)
+ if(uses <= 0)
+ qdel(src)
else
user << "The talisman must be used on metal or plasteel!"
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 09ca3b85fab..e4311624dc5 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -283,7 +283,7 @@
intercepttext += i_text.build(V)
if(station_goals.len)
- intercepttext += "Special Orders for [station_name()]:"
+ intercepttext += "
Special Orders for [station_name()]:"
for(var/datum/station_goal/G in station_goals)
G.on_report()
intercepttext += G.get_report()
@@ -526,7 +526,7 @@
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, 100, M)
+ 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)
@@ -539,7 +539,6 @@
ticker.mode.remove_cultist(newborgie, 0, 0)
ticker.mode.remove_revolutionary(newborgie, 0)
ticker.mode.remove_gangster(newborgie, 0, remove_bosses=1)
- ticker.mode.remove_hog_follower(newborgie, 0)
remove_servant_of_ratvar(newborgie.current, TRUE)
diff --git a/code/game/gamemodes/handofgod/_handofgod.dm b/code/game/gamemodes/handofgod/_handofgod.dm
deleted file mode 100644
index 2de6b0f782d..00000000000
--- a/code/game/gamemodes/handofgod/_handofgod.dm
+++ /dev/null
@@ -1,476 +0,0 @@
-
-var/global/list/global_handofgod_traptypes = list()
-var/global/list/global_handofgod_structuretypes = list()
-
-#define CONDUIT_RANGE 15
-
-
-/datum/game_mode
- var/list/datum/mind/red_deities = list()
- var/list/datum/mind/red_deity_prophets = list()
- var/list/datum/mind/red_deity_followers = list()
-
- var/list/datum/mind/blue_deities = list()
- var/list/datum/mind/blue_deity_prophets = list()
- var/list/datum/mind/blue_deity_followers = list()
-
- var/list/datum/mind/unassigned_followers = list() //for roundstart team assigning
- var/list/datum/mind/assigned_to_red = list()
- var/list/datum/mind/assigned_to_blue = list()
-
-
-/datum/game_mode/hand_of_god
- name = "hand of god"
- config_tag = "handofgod"
- antag_flag = ROLE_HOG_CULTIST //Followers use ROLE_HOG_CULTIST, Gods are picked later on with ROLE_HOG_GOD
-
- required_players = 25
- required_enemies = 8
- recommended_enemies = 8
- restricted_jobs = list("Chaplain","AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel")
-
- announce_span = "danger"
- announce_text = "Two cults are trying to overthrow one another!\n\
- Gods: Protect your nexus and eliminate the enemy god.\n\
- Prophets: Lead your cult by your deity's will.\n\
- Followers: Follow your prophet's orders and lead your deity to victory.\n\
- Crew: Destroy both cults before they can grow in strength."
-
-
-/////////////
-//Pre setup//
-/////////////
-
-/datum/game_mode/hand_of_god/pre_setup()
- if(config.protect_roles_from_antagonist)
- restricted_jobs += protected_jobs
-
- if(config.protect_assistant_from_antagonist)
- restricted_jobs += "Assistant"
-
- for(var/F in 1 to recommended_enemies)
- if(!antag_candidates.len)
- break
- var/datum/mind/follower = pick_n_take(antag_candidates)
- unassigned_followers += follower
- follower.restricted_roles = restricted_jobs
- log_game("[follower.key] (ckey) has been selected as a follower, however teams have not been decided yet.")
-
- while(unassigned_followers.len > (required_enemies / 2))
- var/datum/mind/chosen = pick_n_take(unassigned_followers)
- add_hog_follower(chosen,"red")
-
- while(unassigned_followers.len)
- var/datum/mind/chosen = pick_n_take(unassigned_followers)
- add_hog_follower(chosen,"blue")
-
- return 1
-
-
-//////////////
-//Post Setup//
-//////////////
-
-//Pick a follower to uplift into a god
-/datum/game_mode/hand_of_god/post_setup()
-
- //Find viable red god
- var/list/red_god_possibilities = get_players_for_role(ROLE_HOG_GOD)
- red_god_possibilities &= red_deity_followers //followers only
- if(!red_god_possibilities.len) //No candidates? just pick any follower regardless of prefs
- red_god_possibilities = red_deity_followers
-
- //Make red god
- var/datum/mind/red_god = pick_n_take(red_god_possibilities)
- if(red_god)
- red_god.current.become_god("red")
- remove_hog_follower(red_god,0)
- add_god(red_god,"red")
-
- //Find viable blue god
- var/list/blue_god_possibilities = get_players_for_role(ROLE_HOG_GOD)
- blue_god_possibilities &= blue_deity_followers //followers only
- if(!blue_god_possibilities.len) //No candidates? just pick any follower regardless of prefs
- blue_god_possibilities = blue_deity_followers
-
- //Make blue god
- var/datum/mind/blue_god = pick_n_take(blue_god_possibilities)
- if(blue_god)
- blue_god.current.become_god("blue")
- remove_hog_follower(blue_god,0)
- add_god(blue_god,"blue")
-
-
- //Forge objectives
- //This is done here so that both gods exist
- if(red_god)
- ticker.mode.forge_deity_objectives(red_god)
- if(blue_god)
- ticker.mode.forge_deity_objectives(blue_god)
-
-
- ..()
-
-///////////////////
-//Objective Procs//
-///////////////////
-
-/datum/game_mode/proc/forge_deity_objectives(datum/mind/deity)
- switch(rand(1,100))
- if(1 to 30)
- var/datum/objective/deicide/deicide = new
- deicide.owner = deity
- if(deicide.find_target())//Hard to kill the other god if there is none
- deity.objectives += deicide
-
- if(!(locate(/datum/objective/escape_followers) in deity.objectives))
- var/datum/objective/escape_followers/recruit = new
- recruit.owner = deity
- deity.objectives += recruit
- recruit.gen_amount_goal(8, 12)
-
- if(31 to 60)
- var/datum/objective/sacrifice_prophet/sacrifice = new
- sacrifice.owner = deity
- deity.objectives += sacrifice
-
- if(!(locate(/datum/objective/escape_followers) in deity.objectives))
- var/datum/objective/escape_followers/recruit = new
- recruit.owner = deity
- deity.objectives += recruit
- recruit.gen_amount_goal(8, 12)
-
- if(61 to 85)
- var/datum/objective/build/build = new
- build.owner = deity
- deity.objectives += build
- build.gen_amount_goal(8, 16)
-
- var/datum/objective/sacrifice_prophet/sacrifice = new
- sacrifice.owner = deity
- deity.objectives += sacrifice
-
- if(!(locate(/datum/objective/escape_followers) in deity.objectives))
- var/datum/objective/escape_followers/recruit = new
- recruit.owner = deity
- deity.objectives += recruit
- recruit.gen_amount_goal(8, 12)
-
- else
- if (!locate(/datum/objective/follower_block) in deity.objectives)
- var/datum/objective/follower_block/block = new
- block.owner = deity
- deity.objectives += block
-
-///////////////
-//Greet procs//
-///////////////
-
-/datum/game_mode/proc/greet_hog_follower(datum/mind/follower_mind,colour)
- if(follower_mind in blue_deity_prophets || follower_mind in red_deity_prophets)
- follower_mind.current << "You have been appointed as the prophet of the [colour] deity! You are the only one who can communicate with your deity at will. Guide your followers, but be wary, for many will want you dead."
- else if(colour)
- follower_mind.current << "You are a follower of the [colour] cult's deity!"
- else
- follower_mind.current << "You are a follower of a cult's deity!"
-
-
-/////////////////
-//Convert procs//
-/////////////////
-
-/datum/game_mode/proc/add_hog_follower(datum/mind/follower_mind, colour = "No Colour")
- var/mob/living/carbon/human/H = follower_mind.current
- if(isloyal(H))
- H << "Your mindshield implant blocked the influence of the [colour] deity. "
- return 0
- if((follower_mind in red_deity_followers) || (follower_mind in red_deity_prophets) || (follower_mind in blue_deity_followers) || (follower_mind in blue_deity_prophets))
- H << "You already belong to a deity. Your strong faith has blocked out the conversion attempt by the followers of the [colour] deity."
- return 0
- var/obj/item/weapon/nullrod/N = H.null_rod_check()
- if(N)
- H << "Your holy weapon prevented the [colour] deity from brainwashing you."
- return 0
-
- if(colour == "red")
- red_deity_followers += follower_mind
- if(colour == "blue")
- blue_deity_followers += follower_mind
-
- H.faction |= "[colour] god"
- follower_mind.current << "You are now a follower of the [colour] deity! Follow your deity's prophet in order to complete your deity's objectives. Convert crewmembers to your cause by using your deity's nexus. And remember - there is no you, there is only the cult."
- update_hog_icons_added(follower_mind, colour)
- follower_mind.special_role = "Hand of God: [capitalize(colour)] Follower"
- follower_mind.current.attack_log += "\[[time_stamp()]\] Has been converted to the [colour] follower cult!"
- return 1
-
-
-/datum/game_mode/proc/add_god(datum/mind/god_mind, colour = "No Colour")
- remove_hog_follower(god_mind, announce = 0)
- if(colour == "red")
- red_deities += god_mind
- if(colour == "blue")
- blue_deities += god_mind
- god_mind.current.attack_log += "\[[time_stamp()]\] Has been made into a [colour] deity!"
- god_mind.special_role = "Hand of God: [colour] God"
- update_hog_icons_added(god_mind, colour)
-
-//////////////////
-//Deconvert proc//
-//////////////////
-
-/datum/game_mode/proc/remove_hog_follower(datum/mind/follower_mind, announce = 1)//deconverts both
- if(follower_mind.current)
- if(is_handofgod_cultist(follower_mind.current) || is_handofgod_prophet(follower_mind.current))
- follower_mind.remove_hog_follower_prophet()
- update_hog_icons_removed(follower_mind,"red")
- update_hog_icons_removed(follower_mind,"blue")
-
- var/mob/living/carbon/human/H = follower_mind.current
- H.faction -= "red god"
- H.faction -= "blue god"
-
- if(announce)
- follower_mind.current.attack_log += "\[[time_stamp()]\] Has been deconverted from a deity's cult!"
- follower_mind.current << "Your mind has been cleared from the brainwashing the followers have done to you. Now you serve yourself and the crew."
- for(var/mob/living/M in view(follower_mind.current))
- M << "[follower_mind.current] looks like their faith is shattered. They're no longer a cultist!"
-
-
-
-//////////////////////
-// Mob helper procs //
-//////////////////////
-
-/proc/is_handofgod_god(A)
- if(istype(A, /mob/camera/god))
- return 1
- return 0
-
-
-/proc/is_handofgod_bluecultist(A)
- if(ishuman(A))
- var/mob/living/carbon/human/H = A
- if(H.mind)
- if(H.mind in ticker.mode.blue_deity_followers|ticker.mode.blue_deity_prophets)
- return 1
- return 0
-
-
-/proc/is_handofgod_redcultist(A)
- if(ishuman(A))
- var/mob/living/carbon/human/H = A
- if(H.mind)
- if(H.mind in ticker.mode.red_deity_followers|ticker.mode.red_deity_prophets)
- return 1
- return 0
-
-
-/proc/is_handofgod_blueprophet(A)
- if(ishuman(A))
- var/mob/living/carbon/human/H = A
- if(H.mind)
- if(H.mind in ticker.mode.blue_deity_prophets)
- return 1
- return 0
-
-
-/proc/is_handofgod_redprophet(A)
- if(ishuman(A))
- var/mob/living/carbon/human/H = A
- if(H.mind)
- if(H.mind in ticker.mode.red_deity_prophets)
- return 1
- return 0
-
-
-
-/proc/is_handofgod_cultist(A) //any of them what so ever, blue, red, hot pink, whatever.
- if(is_handofgod_redcultist(A))
- return 1
- if(is_handofgod_bluecultist(A))
- return 1
- return 0
-
-
-/proc/is_handofgod_prophet(A) //any of them what so ever, blue, red, hot pink, whatever
- if(ishuman(A))
- var/mob/living/carbon/human/H = A
- if(H.mind)
- if(H.mind in ticker.mode.blue_deity_prophets|ticker.mode.red_deity_prophets)
- return 1
- return 0
-
-
-/mob/camera/god/proc/is_handofgod_myprophet(A)
- if(!ishuman(A))
- return 0
- var/mob/living/carbon/human/H = A
- if(!H.mind)
- return 0
- if(side == "red")
- if(H.mind in ticker.mode.red_deity_prophets)
- return 1
- else if(side == "blue")
- if(H.mind in ticker.mode.blue_deity_prophets)
- return 1
-
-
-/mob/camera/god/proc/is_handofgod_myfollowers(mob/A)
- if(!ishuman(A))
- return 0
- var/mob/living/carbon/human/H = A
- if(!H.mind)
- return 0
- if(side == "red")
- if(H.mind in ticker.mode.red_deity_prophets|ticker.mode.red_deity_followers)
- return 1
- else if(side == "blue")
- if(H.mind in ticker.mode.blue_deity_prophets|ticker.mode.blue_deity_followers)
- return 1
-
-//////////////////////
-//Roundend Reporting//
-//////////////////////
-
-
-/datum/game_mode/hand_of_god/declare_completion()
- if(red_deities.len)
- var/text = "
The red cult:"
- for(var/datum/mind/red_god in red_deities)
- var/godwin = 1
-
- text += "
[red_god.key] was the red deity, [red_god.name] ("
- if(red_god.current)
- if(red_god.current.stat == DEAD)
- text += "died"
- else
- text += "survived"
- else
- text += "ceased existing"
- text += ")"
- if(red_deity_prophets.len)
- for(var/datum/mind/red_prophet in red_deity_prophets)
- text += "
The red prophet was [red_prophet.name] ([red_prophet.key])"
- else
- text += "
the red prophet was killed for their beliefs."
-
- text += "
Red follower count: [red_deity_followers.len]"
- text += "
Red followers: "
- for(var/datum/mind/player in red_deity_followers)
- text += "[player.name] ([player.key]), "
-
- var/objectives = ""
- if(red_god.objectives.len)
- var/count = 1
- for(var/datum/objective/O in red_god.objectives)
- if(O.check_completion())
- objectives += "
Objective #[count]: [O.explanation_text] Success!"
- feedback_add_details("god_objective","[O.type]|SUCCESS")
- else
- objectives += "
Objective #[count]: [O.explanation_text] Fail."
- feedback_add_details("god_objective","[O.type]|FAIL")
- godwin = 0
- count++
-
- text += objectives
-
- if(godwin)
- text += "
The red cult and deity were successful!"
- feedback_add_details("god_success","SUCCESS")
- else
- text += "
The red cult and deity have failed!"
- feedback_add_details("god_success","FAIL")
-
- text += "
"
-
- world << text
-
- if(blue_deities.len)
- var/text = "
The blue cult:"
- for(var/datum/mind/blue_god in blue_deities)
- var/godwin = 1
-
- text += "
[blue_god.key] was the blue deity, [blue_god.name] ("
- if(blue_god.current)
- if(blue_god.current.stat == DEAD)
- text += "died"
- else
- text += "survived"
- else
- text += "ceased existing"
- text += ")"
- if(blue_deity_prophets.len)
- for(var/datum/mind/blue_prophet in blue_deity_prophets)
- text += "
The blue prophet was [blue_prophet.name] ([blue_prophet.key])"
- else
- text += "
the blue prophet was killed for their beliefs."
-
- text += "
Blue follower count: [blue_deity_followers.len]"
- text += "
Blue followers: "
- for(var/datum/mind/player in blue_deity_followers)
- text += "[player.name] ([player.key])"
-
- var/objectives = ""
- if(blue_god.objectives.len)
- var/count = 1
- for(var/datum/objective/O in blue_god.objectives)
- if(O.check_completion())
- objectives += "
Objective #[count]: [O.explanation_text] Success!"
- feedback_add_details("god_objective","[O.type]|SUCCESS")
- else
- objectives += "
Objective #[count]: [O.explanation_text] Fail."
- feedback_add_details("god_objective","[O.type]|FAIL")
- godwin = 0
- count++
-
- text += objectives
-
- if(godwin)
- text += "
The blue cult and deity were successful!"
- feedback_add_details("god_success","SUCCESS")
- else
- text += "
The blue cult and deity have failed!"
- feedback_add_details("god_success","FAIL")
-
- text += "
"
-
- world << text
-
- ..()
- return 1
-
-
-/datum/game_mode/proc/update_hog_icons_added(datum/mind/hog_mind,side)
- var/hud_key
- var/rank = 0
- if(side == "red")
- hud_key = ANTAG_HUD_HOG_RED
- if(is_handofgod_redprophet(hog_mind.current))
- rank = 1
-
- else if(side == "blue")
- hud_key = ANTAG_HUD_HOG_BLUE
- if(is_handofgod_blueprophet(hog_mind.current))
- rank = 1
-
- if(is_handofgod_god(hog_mind.current))
- rank = 2
-
- if(hud_key)
- var/datum/atom_hud/antag/hog_hud = huds[hud_key]
- hog_hud.join_hud(hog_mind.current)
- set_antag_hud(hog_mind.current, "hog-[side]-[rank]")
-
-
-/datum/game_mode/proc/update_hog_icons_removed(datum/mind/hog_mind,side)
- var/hud_key
- if(side == "red")
- hud_key = ANTAG_HUD_HOG_RED
- else if(side == "blue")
- hud_key = ANTAG_HUD_HOG_BLUE
-
- if(hud_key)
- var/datum/atom_hud/antag/hog_hud = huds[hud_key]
- hog_hud.leave_hud(hog_mind.current)
- set_antag_hud(hog_mind.current,null)
diff --git a/code/game/gamemodes/handofgod/actions.dm b/code/game/gamemodes/handofgod/actions.dm
deleted file mode 100644
index 766a2522fde..00000000000
--- a/code/game/gamemodes/handofgod/actions.dm
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Prophet's innate godspeak */
-/datum/action/innate/godspeak
- name = "Godspeak"
- button_icon_state = "godspeak"
- check_flags = AB_CHECK_CONSCIOUS
- var/mob/camera/god/god = null
-
-/datum/action/innate/godspeak/IsAvailable()
- if(..())
- if(god)
- return 1
- return 0
-
-/datum/action/innate/godspeak/Activate()
- var/msg = input(owner,"Speak to your god","Godspeak","") as null|text
- if(!msg)
- return
- var/rendered = "Prophet [owner]: [msg]"
- god << rendered
- owner << rendered
- for(var/mob/M in mob_list)
- if(isobserver(M))
- var/link = FOLLOW_LINK(M, owner)
- M << "[link] [rendered]"
-
-/datum/action/innate/godspeak/Destroy()
- god = null
- return ..()
diff --git a/code/game/gamemodes/handofgod/god.dm b/code/game/gamemodes/handofgod/god.dm
deleted file mode 100644
index 5a238736052..00000000000
--- a/code/game/gamemodes/handofgod/god.dm
+++ /dev/null
@@ -1,290 +0,0 @@
-
-/mob/camera/god
- name = "deity" //Auto changes to the player's deity name/random name
- real_name = "deity"
- icon = 'icons/mob/mob.dmi'
- icon_state = "marker"
- invisibility = 60
- see_in_dark = 0
- see_invisible = 55
- sight = SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF
- languages_spoken = ALL
- languages_understood = ALL
- hud_possible = list(ANTAG_HUD)
- mouse_opacity = 0 //can't be clicked
-
- var/faith = 100 //For initial prophet appointing/stupid purchase
- var/max_faith = 100
- var/side = "neutral" //Red or Blue for the gamemode
- var/obj/structure/divine/nexus/god_nexus = null //The source of the god's power in this realm, kill it and the god is kill
- var/nexus_required = FALSE //If the god dies from losing it's nexus, defaults to off so that gods don't instantly die at roundstart
- var/followers_required = 0 //Same as above
- var/alive_followers = 0
- var/list/structures = list()
- var/list/conduits = list()
- var/prophets_sacrificed_in_name = 0
- var/image/ghostimage = null //For observer with darkness off visiblity
- var/list/prophets = list()
- var/datum/action/innate/godspeak/speak2god
-
-/mob/camera/god/New()
- ..()
- update_icons()
- build_hog_construction_lists()
-
- //Force nexuses after 15 minutes in hand of god mode
- if(ticker && ticker.mode && ticker.mode.name == "hand of god")
- addtimer(src, "forceplacenexus", 9000, FALSE)
-
-
-//Rebuilds the list based on the gamemode's lists
-//As they are the most accurate each tick
-/mob/camera/god/proc/get_my_followers()
- switch(side)
- if("red")
- . = ticker.mode.red_deity_followers|ticker.mode.red_deity_prophets
- if("blue")
- . = ticker.mode.blue_deity_followers|ticker.mode.blue_deity_prophets
- else
- . = list()
-
-
-/mob/camera/god/Destroy()
- var/list/followers = get_my_followers()
- for(var/datum/mind/F in followers)
- if(F.current)
- F.current << "Your god is DEAD!"
- for(var/X in prophets)
- speak2god.Remove(X)
- ghost_darkness_images -= ghostimage
- updateallghostimages()
- return ..()
-
-
-
-/mob/camera/god/proc/forceplacenexus()
- if(god_nexus)
- return
-
- if(ability_cost(0,1,0))
- place_nexus()
-
- else
- if(blobstart.len) //we're on invalid turf, try to pick from blobstart
- loc = pick(blobstart)
- place_nexus() //if blobstart fails, places on dense turf, but better than nothing
- src << "You failed to place your nexus, and it has been placed for you!"
-
-
-/mob/camera/god/update_icons()
- icon_state = "[initial(icon_state)]-[side]"
-
- if(ghostimage)
- ghost_darkness_images -= ghostimage
-
- ghostimage = image(src.icon,src,src.icon_state)
- ghost_darkness_images |= ghostimage
- updateallghostimages()
-
-
-/mob/camera/god/Stat()
- ..()
- if(statpanel("Status"))
- if(god_nexus)
- stat("Nexus health: ", god_nexus.health)
- stat("Followers: ", alive_followers)
- stat("Faith: ", "[faith]/[max_faith]")
-
-
-/mob/camera/god/Login()
- ..()
- sync_mind()
- src << "You are a deity!"
- src << "You are a deity and are worshipped by a cult! You are rather weak right now, but that will change as you gain more followers."
- src << "You will need to place an anchor to this world, a Nexus, in two minutes. If you don't, one will be placed immediately below you."
- src << "Your Follower count determines how many people believe in you and are a part of your cult."
- src << "Your Nexus Integrity tells you the condition of your nexus. If your nexus is destroyed, you will die. Place your Nexus on a safe, isolated place, that is still accessible to your followers."
- src << "Your Faith is used to interact with the world. This will regenerate on its own, and it goes faster when you have more followers and power pylons."
- src << "The first thing you should do after placing your nexus is to appoint a prophet. Only prophets can hear you talk, unless you use an expensive power."
- update_health_hud()
-
-
-/mob/camera/god/update_health_hud()
- if(god_nexus && hud_used && hud_used.healths)
- hud_used.healths.maptext = " [god_nexus.health]
"
-
-
-/mob/camera/god/proc/add_faith(faith_amt)
- if(faith_amt)
- faith = round(Clamp(faith+faith_amt, 0, max_faith))
- if(hud_used && hud_used.deity_power_display)
- hud_used.deity_power_display.maptext = " [faith]
"
-
-
-
-/mob/camera/god/proc/place_nexus()
- if(god_nexus || (z != 1))
- return 0
-
- var/obj/structure/divine/nexus/N = new(get_turf(src))
- N.assign_deity(src)
- god_nexus = N
- nexus_required = TRUE
- verbs -= /mob/camera/god/verb/constructnexus
- //verbs += /mob/camera/god/verb/movenexus //Translocators have no sprite
- update_health_hud()
-
- var/area/A = get_area(src)
- if(A)
- var/areaname = A.name
- var/list/followers = get_my_followers()
- for(var/datum/mind/F in followers)
- if(F.current)
- F.current << "Your god's nexus is in \the [areaname]"
-
-
-/mob/camera/god/verb/freeturret()
- set category = "Deity"
- set name = "Free Turret (0)"
- set desc = "Place a single turret, for 0 faith."
-
- if(!ability_cost(0,1,1))
- return
- var/obj/structure/divine/defensepylon/DP = new(get_turf(src))
- DP.assign_deity(src)
- verbs -= /mob/camera/god/verb/freeturret
-
-
-
-/mob/camera/god/proc/update_followers()
- alive_followers = 0
- var/list/all_followers = get_my_followers()
- for(var/datum/mind/F in all_followers)
- if(F.current && F.current.stat != DEAD)
- alive_followers++
-
- if(hud_used && hud_used.deity_follower_display)
- hud_used.deity_follower_display.maptext = " [alive_followers]
"
-
-
-/mob/camera/god/proc/check_death()
- if(!alive_followers)
- src << "You no longer have any followers. You shudder as you feel your existence cease..."
- if(god_nexus && !qdeleted(god_nexus))
- god_nexus.visible_message("\The [src] suddenly disappears!")
- qdel(god_nexus)
- qdel(src)
-
-
-/mob/camera/god/say(msg)
- if(!msg)
- return
- if(client)
- if(client.prefs.muted & MUTE_IC)
- src << "You cannot send IC messages (muted)."
- return
- if(src.client.handle_spam_prevention(msg,MUTE_IC))
- return
- if(stat)
- return
-
- god_speak(msg)
-
-
-/mob/camera/god/proc/god_speak(msg)
- log_say("Hand of God: [capitalize(side)] God/[key_name(src)] : [msg]")
- msg = trim(copytext(sanitize(msg), 1, MAX_MESSAGE_LEN))
- if(!msg)
- return
-
- msg = say_quote(msg, get_spans())
- var/rendered = "Divine Telepathy, [name] [msg]"
- src << rendered
-
- for(var/mob/M in mob_list)
- if(is_handofgod_myfollowers(M))
- M << rendered
- if(isobserver(M))
- var/link = FOLLOW_LINK(M, src)
- M << "[link] [rendered]"
-
-
-/mob/camera/god/emote(act,m_type = 1 ,msg = null)
- return
-
-
-/mob/camera/god/Move(NewLoc, Dir = 0)
- loc = NewLoc
-
-
-
-/mob/camera/god/Topic(href, href_list)
- if(href_list["create_structure"])
- if(!ability_cost(75,1,1))
- return
-
- var/obj/structure/divine/construct_type = text2path(href_list["create_structure"]) //it's a path but we need to initial() some vars
- if(!construct_type)
- return
-
- add_faith(-75)
- var/obj/structure/divine/construction_holder/CH = new(get_turf(src))
- CH.assign_deity(src)
- CH.setup_construction(construct_type)
- CH.visible_message("[src] has created a transparent, unfinished [initial(construct_type.name)]. It can be finished by adding materials.")
- src << "You may click a construction site to cancel it, but only faith is refunded."
- structure_construction_ui(src)
- return
-
- if(href_list["place_trap"])
- if(!ability_cost(20,1,1))
- return
-
- var/atom/trap_type = text2path(href_list["place_trap"])
- if(!trap_type)
- return
-
- src << "You lay \a [initial(trap_type.name)]"
- add_faith(-20)
- new trap_type(get_turf(src))
- return
-
- ..()
-
-
-/mob/camera/god/proc/structure_construction_ui(mob/camera/god/user)
- var/dat = ""
- for(var/t in global_handofgod_structuretypes)
- if(global_handofgod_structuretypes[t])
- var/obj/structure/divine/apath = global_handofgod_structuretypes[t]
- dat += "[capitalize(t)]
"
- var/imgstate = initial(apath.autocolours) ? "[initial(apath.icon_state)]-[side]" : "[initial(apath.icon_state)]"
- var/icon/I = icon('icons/obj/hand_of_god_structures.dmi',imgstate)
- var/img_component = lowertext(t)
- //I hate byond, but atleast it autocaches these so it's only 1*number_of_structures worth of actual calls
- user << browse_rsc(I,"hog_structure-[img_component].png")
- dat += "
"
- dat += "Description: [initial(apath.desc)]
"
- dat += "Construct [capitalize(t)]
"
-
- var/datum/browser/popup = new(src, "structures","Construct Structure",350,500)
- popup.set_content(dat)
- popup.open()
-
-
-/mob/camera/god/proc/trap_construction_ui(mob/camera/god/user)
- var/dat = ""
- for(var/t in global_handofgod_traptypes)
- if(global_handofgod_traptypes[t])
- var/obj/structure/divine/trap/T = global_handofgod_traptypes[t]
- dat += "[capitalize(t)]
"
- var/icon/I = icon('icons/obj/hand_of_god_structures.dmi',"[initial(T.icon_state)]")
- var/img_component = lowertext(t)
- user << browse_rsc(I,"hog_trap-[img_component].png")
- dat += "
"
- dat += "Description: [initial(T.desc)]
"
- dat += "Place [capitalize(t)]
"
-
- var/datum/browser/popup = new(src, "traps", "Place Trap",350,500)
- popup.set_content(dat)
- popup.open()
diff --git a/code/game/gamemodes/handofgod/objectives.dm b/code/game/gamemodes/handofgod/objectives.dm
deleted file mode 100644
index dc31d67f46c..00000000000
--- a/code/game/gamemodes/handofgod/objectives.dm
+++ /dev/null
@@ -1,129 +0,0 @@
-
-/datum/objective/build
- dangerrating = 15
- martyr_compatible = 1
-
-
-/datum/objective/build/proc/gen_amount_goal(lower, upper)
- target_amount = rand(lower, upper)
- explanation_text = "Build [target_amount] shrines."
- return target_amount
-
-
-/datum/objective/build/check_completion()
- if(!owner || !owner.current)
- return 0
-
- var/shrines = 0
- if(is_handofgod_god(owner.current))
- var/mob/camera/god/G = owner.current
- for(var/obj/structure/divine/shrine/S in G.structures)
- S++
-
- return (shrines >= target_amount)
-
-
-
-/datum/objective/deicide
- dangerrating = 20
- martyr_compatible = 1
-
-/datum/objective/deicide/check_completion()
- if(target)
- if(target.current) //Gods are deleted when they lose
- return 0
- return 1
-
-
-/datum/objective/deicide/find_target()
- if(!owner || !owner.current)
- return
-
- if(is_handofgod_god(owner.current))
- var/mob/camera/god/G = owner.current
- if(G.side == "red")
- if(ticker.mode.blue_deities.len)
- target = ticker.mode.blue_deities[1]
- if(G.side == "blue")
- if(ticker.mode.red_deities.len)
- target = ticker.mode.red_deities[1]
- if(!target)
- return 0
- update_explanation_text()
-
-/datum/objective/deicide/update_explanation_text()
- ..()
- if(target && target.current)
- explanation_text = "Phase [target.name], the false god, out of this plane of existence.."
- else
- explanation_text = "Free Objective"
-
-
-
-/datum/objective/follower_block
- explanation_text = "Do not allow any followers of the false god to escape on the station's shuttle alive."
- dangerrating = 25
- martyr_compatible = 1
-
-/datum/objective/follower_block/check_completion()
- var/side = "ABORT"
- if(is_handofgod_redcultist(owner.current))
- side = "red"
- else if(is_handofgod_bluecultist(owner.current))
- side = "blue"
- if(side == "ABORT")
- return 0
-
- var/area/A = SSshuttle.emergency.areaInstance
-
- for(var/mob/living/player in player_list)
- if(player.mind && player.stat != DEAD && get_area(player) == A)
- if(side == "red")
- if(is_handofgod_bluecultist(player))
- return 0
- else if(side == "blue")
- if(is_handofgod_redcultist(player))
- return 0
- return 1
-
-
-
-/datum/objective/escape_followers
- dangerrating = 5
-
-
-/datum/objective/escape_followers/proc/gen_amount_goal(lower,upper)
- target_amount = rand(lower,upper)
- explanation_text = "Your will must surpass this station. Having [target_amount] followers escape on the shuttle or pods will allow that."
- return target_amount
-
-
-/datum/objective/escape_followers/check_completion()
- var/escaped = 0
- if(is_handofgod_god(owner.current))
- var/mob/camera/god/G = owner.current
- if(G.side == "red")
- for(var/datum/mind/follower_mind in ticker.mode.red_deity_followers)
- if(follower_mind.current && follower_mind.current.stat != DEAD)
- if(follower_mind.current.onCentcom())
- escaped++
-
- if(G.side == "blue")
- for(var/datum/mind/follower_mind in ticker.mode.blue_deity_followers)
- if(follower_mind.current && follower_mind.current.stat != DEAD)
- if(follower_mind.current.onCentcom())
- escaped++
-
- return (escaped >= target_amount)
-
-
-/datum/objective/sacrifice_prophet
- explanation_text = "A false prophet is preaching their god's faith on the station. Sacrificing them will show the mortals who the true god is."
- dangerrating = 10
-
-
-/datum/objective/sacrifice_prophet/check_completion()
- var/mob/camera/god/G = owner.current
- if(istype(G))
- return G.prophets_sacrificed_in_name
- return 0
diff --git a/code/game/gamemodes/handofgod/powers.dm b/code/game/gamemodes/handofgod/powers.dm
deleted file mode 100644
index 30b3365cfcd..00000000000
--- a/code/game/gamemodes/handofgod/powers.dm
+++ /dev/null
@@ -1,363 +0,0 @@
-/mob/camera/god/proc/ability_cost(cost = 0,structures = 0, requires_conduit = 0, can_place_near_enemy_nexus = 0)
- if(faith < cost)
- src << "You lack the faith!"
- return 0
-
- if(structures)
- if(!isturf(loc) || istype(loc, /turf/open/space))
- src << "Your structure would just float away, you need stable ground!"
- return 0
-
- var/turf/T = get_turf(src)
- if(T)
- if(T.density)
- src << "There is something blocking your structure!"
- return 0
-
- for(var/atom/movable/AM in T)
- if(AM == src)
- continue
- if(AM.density)
- src << "There is something blocking your structure!"
- return 0
-
- if(requires_conduit)
- //Organised this way as there can be multiple conduits, so it's more likely to be a conduit check.
- var/valid = 0
-
- for(var/obj/structure/divine/conduit/C in conduits)
- if(get_dist(src, C) <= CONDUIT_RANGE)
- valid++
- break
-
- if(!valid)
- if(get_dist(src, god_nexus) <= CONDUIT_RANGE)
- valid++
-
- if(!valid)
- src << "You must be near your Nexus or a Conduit to do this!"
- return 0
-
- if(!can_place_near_enemy_nexus)
- var/datum/mind/enemy
- switch(side)
- if("red")
- if(ticker.mode.blue_deities.len)
- enemy = ticker.mode.blue_deities[1]
- if("blue")
- if(ticker.mode.red_deities.len)
- enemy = ticker.mode.red_deities[1]
-
- if(enemy && is_handofgod_god(enemy.current))
- var/mob/camera/god/enemy_god = enemy.current
- if(enemy_god.god_nexus && (get_dist(src,enemy_god.god_nexus) <= CONDUIT_RANGE*2))
- src << "You are too close to the other god's stronghold!"
- return 0
-
- return 1
-
-
-/mob/camera/god/verb/returntonexus()
- set category = "Deity"
- set name = "Goto Nexus"
- set desc = "Teleports you to your next instantly."
-
- if(god_nexus)
- Move(get_turf(god_nexus))
- else
- src << "You don't even have a Nexus, construct one."
-
-
-/mob/camera/god/verb/jumptofollower()
- set category = "Deity"
- set name = "Jump to Follower"
- set desc = "Teleports you to one of your followers."
- var/list/following = list()
- if(side == "red")
- following = ticker.mode.red_deity_followers|ticker.mode.red_deity_prophets
- else if(side == "blue")
- following = ticker.mode.blue_deity_followers|ticker.mode.blue_deity_prophets
- else
- src << "You are unaligned, and thus do not have followers"
- return
-
- var/datum/mind/choice = input("Choose a follower","Jump to Follower") as null|anything in following
- if(choice && choice.current)
- Move(get_turf(choice.current))
-
-
-/mob/camera/god/verb/newprophet()
- set category = "Deity"
- set name = "Appoint Prophet (100)"
- set desc = "Appoint one of your followers as your Prophet, who can hear your words"
-
- var/list/following = list()
-
- if(!ability_cost(100))
- return
- if(side == "red")
- var/datum/mind/old_proph = locate() in ticker.mode.red_deity_prophets
- if(old_proph && old_proph.current && old_proph.current.stat != DEAD)
- src << "You can only have one prophet alive at a time."
- return
- else
- following = ticker.mode.red_deity_followers
- else if(side == "blue")
- var/datum/mind/old_proph = locate() in ticker.mode.blue_deity_prophets
- if(old_proph && old_proph.current && old_proph.current.stat != DEAD)
- src << "You can only have one prophet alive at a time."
- return
- else
- following = ticker.mode.blue_deity_followers
-
- else
- src << "You are unalligned, and thus do not have prophets"
- return
-
- var/datum/mind/choice = input("Choose a follower to make into your prophet","Prophet Uplifting") as null|anything in following
- if(choice && choice.current && choice.current.stat != DEAD)
- src << "You choose [choice.current] as your prophet."
- choice.make_Handofgod_prophet(side)
- speak2god = new()
- speak2god.god = src
- speak2god.Grant(choice.current)
-
- //Prophet gear
- var/mob/living/carbon/human/H = choice.current
- var/popehat = null
- var/popestick = null
- var/success = ""
- switch(side)
- if("red")
- popehat = /obj/item/clothing/head/helmet/plate/crusader/prophet/red
- popestick = /obj/item/weapon/godstaff/red
- if("blue")
- popehat = /obj/item/clothing/head/helmet/plate/crusader/prophet/blue
- popestick = /obj/item/weapon/godstaff/blue
-
- if(popehat)
- var/obj/item/clothing/head/helmet/plate/crusader/prophet/P = new popehat()
-
- if(H.equip_to_slot_if_possible(P,slot_in_backpack,0,1,1))
- success = "It is in your backpack."
- else
- H.unEquip(H.head)
- H.equip_to_slot_or_del(P,slot_head)
- success = "It is on your head."
-
- if(success)
- H << "A powerful hat has been bestowed upon you, you will need to wear it to utilize your staff fully."
- H << "[success]"
-
- if(popestick)
- var/obj/item/weapon/godstaff/G = new popestick()
- G.god = src
- if(!H.equip_to_slot_if_possible(G,slot_in_backpack,0,1,1))
- if(!H.put_in_hands(G))
- G.loc = get_turf(H)
- success = "It is on the floor..."
- else
- success = "It is in your hands..."
- else
- success = "It is in your backpack..."
-
- if(success)
- H << "A powerful staff has been bestowed upon you, you can use this to convert the false god's structures!"
- H << "[success]"
- //end prophet gear
-
- add_faith(-100)
-
-
-/mob/camera/god/verb/talk(msg as text)
- set category = "Deity"
- set name = "Talk to Anyone (20)"
- set desc = "Allows you to send a message to anyone, regardless of their faith."
- if(!ability_cost(20))
- return
- var/mob/choice = input("Choose who you wish to talk to", "Talk to ANYONE") as null|anything in mob_list
- if(choice)
- var/original = msg
- msg = "You hear a voice coming from everywhere and nowhere... [msg]"
- choice << msg
- src << "You say the following to [choice], [original]"
- add_faith(-20)
-
-
-/mob/camera/god/verb/smite()
- set category = "Deity"
- set name = "Smite (40)"
- set desc = "Hits anything under you with a moderate amount of damage."
-
- if(!ability_cost(40,0,1))
- return
- if(!range(7,god_nexus))
- src << "You lack the strength to smite this far from your nexus."
- return
-
- var/has_smitten = 0 //Hast thou been smitten, infidel?
- for(var/mob/living/L in get_turf(src))
- L.adjustFireLoss(20)
- L.adjustBruteLoss(20)
- L << "You feel the wrath of [name]!"
- has_smitten = 1
- if(has_smitten)
- add_faith(-40)
-
-
-/mob/camera/god/verb/disaster()
- set category = "Deity"
- set name = "Invoke Disaster (300)" //difficult to reach without lots of followers
- set desc = "Tug at the fibres of reality itself and bend it to your whims!"
-
- if(!ability_cost(300,0,1))
- return
-
- var/event = pick(/datum/round_event/meteor_wave, /datum/round_event/communications_blackout, /datum/round_event/radiation_storm, /datum/round_event/carp_migration,
- /datum/round_event/spacevine, /datum/round_event/vent_clog, /datum/round_event/wormholes)
- if(event)
- new event()
- add_faith(-300)
-
-
-/mob/camera/god/verb/constructnexus()
- set category = "Deity"
- set name = "Construct Nexus"
- set desc = "Instantly creates your nexus, You can only do this once, make sure you're happy with it!"
-
- if(!ability_cost(0,1,0))
- return
-
- place_nexus()
-
-
-/* //Transolocators have no sprite
-/mob/camera/god/verb/movenexus()
- set category = "Deity"
- set name = "Relocate Nexus (50)"
- set desc = "Instantly relocates your nexus to an existing translocator belonging to your faith, this destroys the translocator in the process"
-
- if(ability_cost(50,0,0) && god_nexus)
- var/list/translocators = list()
- var/list/used_keys = list()
- for(var/obj/structure/divine/translocator/T in structures)
- translocators["[T.name] ([get_area(T)])"] = T
-
- if(!translocators.len)
- src << "You have no translocators!"
- return
-
- var/picked = input(src,"Choose a translocator","Relocate Nexus") as null|anything in translocators
- if(!picked || !translocators[picked])
- return
-
- var/obj/structure/divine/translocator/T = translocators[T]
- var/turf/Tturf = get_turf(T)
- god_nexus.loc = T
- translocators[picked] = null
- add_faith(-50)
- qdel(T)
-*/
-
-/mob/camera/god/verb/construct_structures()
- set category = "Deity"
- set name = "Construct Structure (75)"
- set desc = "Create the foundation of a divine object."
-
- if(!ability_cost(75,1,1))
- return
-
- structure_construction_ui(src)
-
-
-/mob/camera/god/verb/construct_traps()
- set category = "Deity"
- set name = "Construct Trap (20)"
- set desc = "Creates a ward or trap."
-
- if(!ability_cost(20,1,1))
- return
-
- trap_construction_ui(src)
-
-
-
-/mob/camera/god/verb/construct_items()
- set category = "Deity"
- set name = "Construct Items (20)"
- set desc = "Construct some items for your followers"
-
- if(!ability_cost(20,1,1))
- return
-
- var/list/item_types = list("claymore sword" = /obj/item/weapon/claymore/hog)
- if(side == "red")
- item_types["red banner"] = /obj/item/weapon/banner/red
- item_types["red bannerbackpack"] = /obj/item/weapon/storage/backpack/bannerpack/red
- item_types["red armour"] = /obj/item/weapon/storage/box/itemset/crusader/red
-
- else if(side == "blue")
- item_types["blue banner"] = /obj/item/weapon/banner/blue
- item_types["blue bannerbackpack"] = /obj/item/weapon/storage/backpack/bannerpack/blue
- item_types["blue armour"] = /obj/item/weapon/storage/box/itemset/crusader/blue
-
-
- var/item = input("Choose what you wish to create.", "Divine Items") as null|anything in item_types
- if(!item || !item_types[item] || !ability_cost(20,1,1))
- return
-
- src << "You produce \a [item]"
- add_faith(-20)
-
- var/itemtype = item_types[item]
- new itemtype (get_turf(src))
-
-
-
-/mob/camera/god/verb/veil_structures()
- set category = "Deity"
- set name = "Veil Structures (20)"
- set desc = "Hide your structures from sight and touch, but prevent yourself from using them."
-
- if(!ability_cost(20,1,1))
- return
-
- src << "You focus your powers and start dragging your influence into the spiritual plane."
- for(var/mob/M in orange(3,src))//Yes I know this is terrible, but visible message doesnt work for this
- M << "The air begins to shimmer..."
- if(do_after(src, 30, 0, src))
- for(var/obj/structure/divine/R in orange(3,src))
- if(istype(R, /obj/structure/divine/nexus)|| istype(R, /obj/structure/divine/trap)||(src.side != R.side))
- continue
- R.visible_message("[R] fades away.")
- R.invisibility = 55
- R.alpha = 100 //To help ghosts distinguish hidden structures
- R.density = 0
- R.deactivate()
- src << "You hide your influence from view"
- add_faith(-20)
-
-
-/mob/camera/god/verb/reveal_structures()
- set category = "Deity"
- set name = "Reveal Structures (20)"
- set desc = "Make your structures visible again and allow them to be used."
-
- if(!ability_cost(20,1,1))
- return
-
- src << "You focus your powers and start dragging your influence into the material plane."
- for(var/mob/M in orange(3,src))//Yes I know this is terrible, but visible message doesnt work for this
- M << "The air begins to shimmer..."
- if(do_after(src, 40, 0, src))
- for(var/obj/structure/divine/R in orange(3,src))
- if(istype(R, /obj/structure/divine/nexus)|| istype(R, /obj/structure/divine/trap)||(src.side != R.side))
- continue
- R.visible_message("[R] suddenly appears!")
- R.invisibility = 0
- R.alpha = initial(R.alpha)
- R.density = initial(R.density)
- R.activate()
- src << "You bring your influence into view"
- add_faith(-20)
-
diff --git a/code/game/gamemodes/handofgod/structures.dm b/code/game/gamemodes/handofgod/structures.dm
deleted file mode 100644
index 79d6615d06b..00000000000
--- a/code/game/gamemodes/handofgod/structures.dm
+++ /dev/null
@@ -1,661 +0,0 @@
-
-/proc/build_hog_construction_lists()
- if(global_handofgod_traptypes.len && global_handofgod_structuretypes.len)
- return
-
- var/list/types = subtypesof(/obj/structure/divine) - /obj/structure/divine/trap
- for(var/T in types)
- var/obj/structure/divine/D = T
- if(initial(D.constructable))
- if(initial(D.trap))
- global_handofgod_traptypes[initial(D.name)] = T
- else
- global_handofgod_structuretypes[initial(D.name)] = T
-
-/obj/structure/divine
- name = "divine construction site"
- icon = 'icons/obj/hand_of_god_structures.dmi'
- desc = "An unfinished divine building"
- anchored = 1
- density = 1
- var/constructable = TRUE
- var/trap = FALSE
- var/metal_cost = 0
- var/glass_cost = 0
- var/lesser_gem_cost = 0
- var/greater_gem_cost = 0
- var/mob/camera/god/deity
- var/side = "neutral" //"blue" or "red", also used for colouring structures when construction is started by a deity
- var/health = 100
- var/maxhealth = 100
- var/deactivated = 0 //Structures being hidden can't be used. Mainly to prevent invisible defense pylons.
- var/autocolours = TRUE //do we colour to our side?
-
-/obj/structure/divine/New()
- ..()
-
-/obj/structure/divine/proc/deactivate()
- deactivated = 1
-
-/obj/structure/divine/proc/activate()
- deactivated = 0
-
-
-/obj/structure/divine/proc/update_icons()
- if(autocolours)
- icon_state = "[initial(icon_state)]-[side]"
-
-
-/obj/structure/divine/Destroy()
- if(deity)
- deity.structures -= src
- return ..()
-
-
-
-/obj/structure/divine/attackby(obj/item/I, mob/user)
-
- //Structure conversion/capture
- if(istype(I, /obj/item/weapon/godstaff))
- if(!is_handofgod_cultist(user))
- user << "You're not quite sure what the hell you're even doing."
- return
- var/obj/item/weapon/godstaff/G = I
- if(G.god && deity != G.god)
- assign_deity(G.god, alert_old_deity = TRUE)
- visible_message("\The [src] has been captured by [user]!")
- else
- return ..()
-
-/obj/structure/divine/attacked_by(obj/item/I, mob/living/user)
- ..()
- take_damage(I.force, I.damtype, 1)
-
-/obj/structure/divine/proc/take_damage(damage, damage_type = BRUTE, sound_effect = 1)
- switch(damage_type)
- if(BRUTE)
- if(sound_effect)
- if(damage)
- playsound(loc, 'sound/weapons/smash.ogg', 50, 1)
- else
- playsound(loc, 'sound/weapons/tap.ogg', 50, 1)
- if(BURN)
- if(sound_effect)
- playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
- else
- return
- health -= damage
- if(!health)
- visible_message("\The [src] was destroyed!")
- qdel(src)
-
-
-/obj/structure/divine/bullet_act(obj/item/projectile/P)
- . = ..()
- take_damage(P.damage, P.damage_type, 0)
-
-
-/obj/structure/divine/attack_alien(mob/living/carbon/alien/humanoid/user)
- user.changeNext_move(CLICK_CD_MELEE)
- user.do_attack_animation(src)
- add_hiddenprint(user)
- visible_message("\The [user] slashes at [src]!")
- playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1)
- take_damage(20, BRUTE, 0)
-
-/obj/machinery/attack_animal(mob/living/simple_animal/M)
- M.changeNext_move(CLICK_CD_MELEE)
- M.do_attack_animation(src)
- if(M.melee_damage_upper > 0 || M.obj_damage)
- M.visible_message("[M.name] smashes against \the [src.name].",\
- "You smash against the [src.name].")
- if(M.obj_damage)
- take_damage(M.obj_damage, M.melee_damage_type, 1)
- else
- take_damage(rand(M.melee_damage_lower,M.melee_damage_upper), M.melee_damage_type, 1)
-
-
-/obj/structure/divine/proc/assign_deity(mob/camera/god/new_deity, alert_old_deity = TRUE)
- if(!new_deity)
- return 0
- if(deity)
- if(alert_old_deity)
- deity << "Your [name] was captured by [new_deity]'s cult!"
- deity.structures -= src
- deity = new_deity
- deity.structures |= src
- side = deity.side
- update_icons()
- return 1
-
-
-/obj/structure/divine/construction_holder
- alpha = 125
- constructable = FALSE
- var/obj/structure/divine/construction_result = /obj/structure/divine //a path, but typed to /obj/structure/divine for initial()
-
-
-
-/obj/structure/divine/construction_holder/assign_deity(mob/camera/god/new_deity, alert_old_deity = TRUE)
- if(..())
- color = side
-
-
-/obj/structure/divine/construction_holder/attack_god(mob/camera/god/user)
- if(user.side == side && construction_result)
- user.add_faith(75)
- visible_message("[user] has cancelled \the [initial(construction_result.name)]")
- qdel(src)
-
-
-/obj/structure/divine/construction_holder/proc/setup_construction(construct_type)
- if(ispath(construct_type))
- construction_result = construct_type
- name = "[initial(construction_result.name)] construction site "
- icon_state = initial(construction_result.icon_state)
- metal_cost = initial(construction_result.metal_cost)
- glass_cost = initial(construction_result.glass_cost)
- lesser_gem_cost = initial(construction_result.lesser_gem_cost)
- greater_gem_cost = initial(construction_result.greater_gem_cost)
- desc = "An unfinished [initial(construction_result.name)]."
-
-
-/obj/structure/divine/construction_holder/attackby(obj/item/I, mob/user)
- if(!I || !user)
- return 0
-
- if(istype(I, /obj/item/stack/sheet/metal))
- var/obj/item/stack/sheet/metal/M = I
- if(metal_cost)
- var/spend = min(metal_cost, M.amount)
- user << "You add [spend] metal to \the [src]."
- metal_cost = max(0, metal_cost - spend)
- M.use(spend)
- check_completion()
- else
- user << "\The [src] does not require any more metal!"
- return
-
- if(istype(I, /obj/item/stack/sheet/glass))
- var/obj/item/stack/sheet/glass/G = I
- if(glass_cost)
- var/spend = min(glass_cost, G.amount)
- user << "You add [spend] glass to \the [src]."
- glass_cost = max(0, glass_cost - spend)
- G.use(spend)
- check_completion()
- else
- user << "\The [src] does not require any more glass!"
- return
-
- if(istype(I, /obj/item/stack/sheet/lessergem))
- var/obj/item/stack/sheet/lessergem/LG = I
- if(lesser_gem_cost)
- var/spend = min(lesser_gem_cost, LG.amount)
- user << "You add [spend] lesser gems to \the [src]."
- lesser_gem_cost = max(0, lesser_gem_cost - spend)
- LG.use(spend)
- check_completion()
- else
- user << "\The [src] does not require any more lesser gems!"
- return
-
- if(istype(I, /obj/item/stack/sheet/greatergem))
- var/obj/item/stack/sheet/greatergem/GG = I //GG!
- if(greater_gem_cost)
- var/spend = min(greater_gem_cost, GG.amount)
- user << "You add [spend] greater gems to \the [src]."
- greater_gem_cost = max(0, greater_gem_cost - spend)
- GG.use(spend)
- check_completion()
- else
- user << "\The [src] does not require any more greater gems!"
- return
-
- else
- return ..()
-
-
-/obj/structure/divine/construction_holder/proc/check_completion()
- if(!metal_cost && !glass_cost && !lesser_gem_cost && !greater_gem_cost)
- visible_message("\The [initial(construction_result.name)] is complete!")
- var/obj/structure/divine/D = new construction_result (get_turf(src))
- D.assign_deity(deity)
- qdel(src)
-
-
-/obj/structure/divine/construction_holder/examine(mob/user)
- ..()
-
- if(metal_cost || glass_cost || lesser_gem_cost || greater_gem_cost)
- user << "To finish construction it requires the following materials:"
- if(metal_cost)
- user << "[metal_cost] metal
"
- if(glass_cost)
- user << "[glass_cost] glass
"
- if(lesser_gem_cost)
- user << "[lesser_gem_cost] lesser gems
"
- if(greater_gem_cost)
- user << "[greater_gem_cost] greater gems
"
-
-
-/obj/structure/divine/nexus
- name = "nexus"
- desc = "It anchors a deity to this world. It radiates an unusual aura. Cultists protect this at all costs. It looks well protected from explosive shock."
- icon_state = "nexus"
- health = 500
- maxhealth = 500
- constructable = FALSE
- var/faith_regen_rate = 1
- var/list/powerpylons = list()
-
-
-/obj/structure/divine/nexus/ex_act()
- return
-
-/obj/structure/divine/nexus/take_damage(damage, damage_type = BRUTE, sound_effect = 1)
- switch(damage_type)
- if(BRUTE)
- if(sound_effect)
- if(damage)
- playsound(loc, 'sound/weapons/smash.ogg', 50, 1)
- else
- playsound(loc, 'sound/weapons/tap.ogg', 50, 1)
- if(BURN)
- if(sound_effect)
- playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
- else
- return
- health -= damage
- if(deity)
- deity.update_health_hud()
- if(!health)
- if(!qdeleted(deity) && deity.nexus_required)
- deity << "Your nexus was destroyed. You feel yourself fading..."
- qdel(deity)
- visible_message("\The [src] was destroyed!")
- qdel(src)
-
-
-/obj/structure/divine/nexus/New()
- START_PROCESSING(SSobj, src)
-
-
-/obj/structure/divine/nexus/process()
- if(deity)
- deity.update_followers()
- deity.add_faith(faith_regen_rate + (powerpylons.len / 5) + (deity.alive_followers / 3))
- deity.max_faith = initial(deity.max_faith) + (deity.alive_followers*10) //10 followers = 100 max faith, so disaster() at around 20 followers
- deity.check_death()
-
-
-/obj/structure/divine/nexus/Destroy()
- STOP_PROCESSING(SSobj, src)
- return ..()
-
-
-/obj/structure/divine/conduit
- name = "conduit"
- desc = "It allows a deity to extend their reach. Their powers are just as potent near a conduit as a nexus."
- icon_state = "conduit"
- health = 150
- maxhealth = 150
- metal_cost = 10
- glass_cost = 5
-
-
-/obj/structure/divine/conduit/assign_deity(mob/camera/god/new_deity, alert_old_deity = TRUE)
- if(deity)
- deity.conduits -= src
- ..()
- if(deity)
- deity.conduits += src
-
-/obj/structure/divine/conduit/deactivate()
- ..()
- if(deity)
- deity.conduits -= src
-
-/obj/structure/divine/conduit/activate()
- ..()
- if(deity)
- deity.conduits += src
-
-/* //No good sprites, and not enough items to make it viable yet
-/obj/structure/divine/forge
- name = "forge"
- desc = "A forge fueled by divine might, it allows the creation of sacred and powerful artifacts. It requires common materials to craft objects."
- icon_state = "forge"
- health = 250
- maxhealth = 250
- density = 0
- maxhealth = 250
- metal_cost = 40
-*/
-
-/obj/structure/divine/convertaltar
- name = "conversion altar"
- desc = "An altar dedicated to a deity. Cultists can \"forcefully teach\" their non-aligned crewmembers to join their side and take up their deity."
- icon_state = "convertaltar"
- density = 0
- metal_cost = 10
- can_buckle = 1
-
-
-/obj/structure/divine/convertaltar/attack_hand(mob/living/user)
- ..()
- if(deactivated)
- return
- var/mob/living/carbon/human/H = locate() in get_turf(src)
- if(!is_handofgod_cultist(user))
- user << "You try to use it, but unfortunately you don't know any rituals."
- return
- if(!H)
- return
- if(!H.mind)
- user << "Only sentients may serve your deity."
- return
- if((side == "red" && is_handofgod_redcultist(user) && !is_handofgod_redcultist(H)) || (side == "blue" && is_handofgod_bluecultist(user) && !is_handofgod_bluecultist(H)))
- user << "You invoke the conversion ritual."
- ticker.mode.add_hog_follower(H.mind, side)
- else
- user << "You invoke the conversion ritual."
- user << "But the altar ignores your words..."
-
-
-/obj/structure/divine/sacrificealtar
- name = "sacrificial altar"
- desc = "An altar designed to perform blood sacrifice for a deity. The cultists performing the sacrifice will gain a powerful material to use in their forge. Sacrificing a prophet will yield even better results."
- icon_state = "sacrificealtar"
- density = 0
- metal_cost = 15
- can_buckle = 1
-
-
-/obj/structure/divine/sacrificealtar/attack_hand(mob/living/user)
- ..()
- if(deactivated)
- return
- var/mob/living/L = locate() in get_turf(src)
- if(!is_handofgod_cultist(user))
- user << "You try to use it, but unfortunately you don't know any rituals."
- return
- if(!L)
- return
- if((side == "red" && is_handofgod_redcultist(user)) || (side == "blue" && is_handofgod_bluecultist(user)))
- if((side == "red" && is_handofgod_redcultist(L)) || (side == "blue" && is_handofgod_bluecultist(L)))
- user << "You cannot sacrifice a fellow cultist."
- return
- user << "You attempt to sacrifice [L] by invoking the sacrificial ritual."
- sacrifice(L)
- else
- user << "You attempt to sacrifice [L] by invoking the sacrificial ritual."
- user << "But the altar ignores your words..."
-
-
-/obj/structure/divine/sacrificealtar/proc/sacrifice(mob/living/L)
- if(!L)
- L = locate() in get_turf(src)
- if(L)
- if(ismonkey(L))
- var/luck = rand(1,4)
- if(luck > 3)
- new /obj/item/stack/sheet/lessergem(get_turf(src))
-
- else if(ishuman(L))
- var/mob/living/carbon/human/H = L
-
- //Sacrifice altars can't teamkill
- if(side == "red" && is_handofgod_redcultist(H))
- return
- else if(side == "blue" && is_handofgod_bluecultist(H))
- return
-
- if(is_handofgod_prophet(H))
- new /obj/item/stack/sheet/greatergem(get_turf(src))
- if(deity)
- deity.prophets_sacrificed_in_name++
- else
- new /obj/item/stack/sheet/lessergem(get_turf(src))
-
- else if(isAI(L) || istype(L, /mob/living/carbon/alien/humanoid/royal/queen))
- new /obj/item/stack/sheet/greatergem(get_turf(src))
- else
- new /obj/item/stack/sheet/lessergem(get_turf(src))
- L.gib()
-
-
-/obj/structure/divine/healingfountain
- name = "healing fountain"
- desc = "A fountain containing the waters of life... or death, depending on where your allegiances lie."
- icon_state = "fountain"
- metal_cost = 10
- glass_cost = 5
- autocolours = FALSE
- var/time_between_uses = 1800
- var/last_process = 0
- var/cult_only = TRUE
-
-/obj/structure/divine/healingfountain/anyone
- desc = "A fountain containing the waters of life."
- cult_only = FALSE
-
-/obj/structure/divine/healingfountain/attack_hand(mob/living/user)
- if(deactivated)
- return
- if(last_process + time_between_uses > world.time)
- user << "The fountain appears to be empty."
- return
- last_process = world.time
- if(!is_handofgod_cultist(user) && cult_only)
- user << "The water burns!"
- user.reagents.add_reagent("hell_water",20)
- else
- user << "The water feels warm and soothing as you touch it. The fountain immediately dries up shortly afterwards."
- user.reagents.add_reagent("godblood",20)
- update_icons()
- addtimer(src, "update_icons", time_between_uses)
-
-
-/obj/structure/divine/healingfountain/update_icons()
- if(last_process + time_between_uses > world.time)
- icon_state = "fountain"
- else
- icon_state = "fountain-[side]"
-
-
-/obj/structure/divine/powerpylon
- name = "power pylon"
- desc = "A pylon which increases the deity's rate it can influence the world."
- icon_state = "powerpylon"
- density = 1
- health = 30
- maxhealth = 30
- metal_cost = 5
- glass_cost = 15
-
-
-/obj/structure/divine/powerpylon/New()
- ..()
- if(deity && deity.god_nexus)
- deity.god_nexus.powerpylons += src
-
-
-/obj/structure/divine/powerpylon/Destroy()
- if(deity && deity.god_nexus)
- deity.god_nexus.powerpylons -= src
- return ..()
-
-
-/obj/structure/divine/powerpylon/deactivate()
- ..()
- if(deity)
- deity.god_nexus.powerpylons -= src
-
-/obj/structure/divine/powerpylon/activate()
- ..()
- if(deity)
- deity.god_nexus.powerpylons += src
-
-/obj/structure/divine/defensepylon
- name = "defense pylon"
- desc = "A pylon which is blessed to withstand many blows, and fire strong bolts at nonbelievers. A god can toggle it."
- icon_state = "defensepylon"
- health = 150
- maxhealth = 150
- metal_cost = 25
- glass_cost = 30
- var/obj/machinery/porta_turret/defensepylon_internal_turret/pylon_gun
-
-
-/obj/structure/divine/defensepylon/New()
- ..()
- pylon_gun = new(src)
- pylon_gun.base = src
- pylon_gun.faction = list("[side] god")
-
-
-/obj/structure/divine/defensepylon/Destroy()
- qdel(pylon_gun) //just in case
- return ..()
-
-
-/obj/structure/divine/defensepylon/examine(mob/user)
- ..()
- user << "\The [src] looks [pylon_gun.on ? "on" : "off"]."
-
-
-/obj/structure/divine/defensepylon/assign_deity(mob/camera/god/new_deity, alert_old_deity = TRUE)
- if(..() && pylon_gun)
- pylon_gun.faction = list("[side] god")
- pylon_gun.side = side
-
-/obj/structure/divine/defensepylon/attack_god(mob/camera/god/user)
- if(user.side == side)
- if(deactivated)
- user << "You need to reveal it first!"
- return
- pylon_gun.on = !pylon_gun.on
- icon_state = (pylon_gun.on) ? "defensepylon-[side]" : "defensepylon"
-
-/obj/structure/divine/defensepylon/deactivate()
- ..()
- pylon_gun.on = 0
- icon_state = (pylon_gun.on) ? "defensepylon-[side]" : "defensepylon"
-
-/obj/structure/divine/defensepylon/activate()
- ..()
- pylon_gun.on = 1
- icon_state = (pylon_gun.on) ? "defensepylon-[side]" : "defensepylon"
-
-//This sits inside the defensepylon, to avoid copypasta
-/obj/machinery/porta_turret/defensepylon_internal_turret
- name = "defense pylon"
- desc = "A plyon which is blessed to withstand many blows, and fire strong bolts at nonbelievers."
- icon = 'icons/obj/hand_of_god_structures.dmi'
- installation = null
- always_up = 1
- use_power = 0
- has_cover = 0
- health = 200
- projectile = /obj/item/projectile/beam/pylon_bolt
- eprojectile = /obj/item/projectile/beam/pylon_bolt
- shot_sound = 'sound/weapons/emitter2.ogg'
- eshot_sound = 'sound/weapons/emitter2.ogg'
- base_icon_state = "defensepylon"
- active_state = ""
- off_state = ""
- faction = null
- emp_vunerable = 0
- var/side = "neutral"
-
-/obj/machinery/porta_turret/defensepylon_internal_turret/setup()
- return
-
-/obj/machinery/porta_turret/defensepylon_internal_turret/shootAt(atom/movable/target)
- var/obj/item/projectile/A = ..()
- if(A)
- A.color = side
-
-/obj/machinery/porta_turret/defensepylon_internal_turret/assess_perp(mob/living/carbon/human/perp)
- if(perp.handcuffed) //dishonourable to kill somebody who might be converted.
- return 0
- var/badtarget = 0
- switch(side)
- if("blue")
- badtarget = is_handofgod_bluecultist(perp)
- if("red")
- badtarget = is_handofgod_redcultist(perp)
- else
- badtarget = 1
- if(badtarget)
- return 0
- return 10
-
-
-
-/obj/item/projectile/beam/pylon_bolt
- name = "divine bolt"
- icon_state = "greyscale_bolt"
- damage = 15
-
-
-/obj/structure/divine/shrine
- name = "shrine"
- desc = "A shrine dedicated to a deity."
- icon_state = "shrine"
- metal_cost = 15
- glass_cost = 15
-
-
-/obj/structure/divine/shrine/assign_deity(mob/camera/god/new_deity, alert_old_deity = TRUE)
- if(..())
- name = "shrine to [new_deity.name]"
- desc = "A shrine dedicated to [new_deity.name]"
-
-
-
-
-//Functional, but need sprites
-/*
-/obj/structure/divine/translocator
- name = "translocator"
- desc = "A powerful structure, made with a greater gem. It allows a deity to move their nexus to where this stands"
- icon_state = "translocator"
- health = 100
- maxhealth = 100
- metal_cost = 20
- glass_cost = 20
- greater_gem_cost = 1
-
-
-/obj/structure/divine/lazarusaltar
- name = "lazarus altar"
- desc = "A very powerful altar capable of bringing life back to the recently deceased, made with a greater gem. It can revive anyone and will heal virtually all wounds, but they are but a shell of their former self."
- icon_state = "lazarusaltar"
- density = 0
- health = 100
- maxhealth = 100
- metal_cost = 20
- greater_gem_cost = 1
-
-
-/obj/structure/divine/lazarusaltar/attack_hand(mob/living/user)
- var/mob/living/L = locate() in get_turf(src)
- if(!is_handofgod_culstist(user))
- user << "You try to use it, but unfortunately you don't know any rituals."
- return
- if(!L)
- return
-
- if((side == "red" && is_handofgod_redcultist(user))) || (side == "blue" && is_handofgod_bluecultist(user)))
- user << "You attempt to revive [L] by invoking the rebirth ritual."
- L.revive()
- L.adjustCloneLoss(50)
- L.adjustStaminaLoss(100)
- else
- user << "You attempt to revive [L] by invoking the rebirth ritual."
- user << "But the altar ignores your words..."
-*/
-
-
diff --git a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm
index 116d910e056..55a703913be 100644
--- a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm
+++ b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm
@@ -50,11 +50,10 @@
if(disguise == null)
return
stealth_active = 1
- if(istype(src.loc, /mob/living/carbon/human))
- var/mob/living/carbon/human/M = src.loc
- addtimer(GLOBAL_PROC, "anim", 0, FALSE, M.loc, M, 'icons/mob/mob.dmi',
- null, "cloak", null, M.dir)
-
+ if(istype(loc, /mob/living/carbon/human))
+ var/mob/living/carbon/human/M = loc
+ PoolOrNew(/obj/effect/overlay/temp/dir_setting/ninja/cloak,
+ list(get_turf(M), M.dir))
M.name_override = disguise.name
M.icon = disguise.icon
M.icon_state = disguise.icon_state
@@ -65,10 +64,10 @@
if(!stealth_active)
return
stealth_active = 0
- if(istype(src.loc, /mob/living/carbon/human))
- var/mob/living/carbon/human/M = src.loc
- addtimer(GLOBAL_PROC, "anim", 0, FALSE, M.loc, M, 'icons/mob/mob.dmi',
- null, "uncloak", null, M.dir)
+ if(istype(loc, /mob/living/carbon/human))
+ var/mob/living/carbon/human/M = loc
+ PoolOrNew(/obj/effect/overlay/temp/dir_setting/ninja,
+ list(get_turf(M), M.dir))
M.name_override = null
M.cut_overlays()
M.regenerate_icons()
@@ -92,11 +91,11 @@
ActivateStealth()
/obj/item/clothing/suit/armor/abductor/vest/proc/Adrenaline()
- if(istype(src.loc, /mob/living/carbon/human))
+ if(istype(loc, /mob/living/carbon/human))
if(combat_cooldown != initial(combat_cooldown))
- src.loc << "Combat injection is still recharging."
+ loc << "Combat injection is still recharging."
return
- var/mob/living/carbon/human/M = src.loc
+ var/mob/living/carbon/human/M = loc
M.adjustStaminaLoss(-75)
M.SetParalysis(0)
M.SetStunned(0)
diff --git a/code/game/gamemodes/miniantags/abduction/machinery/pad.dm b/code/game/gamemodes/miniantags/abduction/machinery/pad.dm
index 1e3a5428a10..b5434dbfdd1 100644
--- a/code/game/gamemodes/miniantags/abduction/machinery/pad.dm
+++ b/code/game/gamemodes/miniantags/abduction/machinery/pad.dm
@@ -16,13 +16,11 @@
flick("alien-pad", src)
for(var/mob/living/target in loc)
target.forceMove(teleport_target)
- spawn(0)
- anim(target.loc,target,'icons/mob/mob.dmi',,"uncloak",,target.dir)
+ PoolOrNew(/obj/effect/overlay/temp/dir_setting/ninja, list(get_turf(target), target.dir))
/obj/machinery/abductor/pad/proc/Retrieve(mob/living/target)
flick("alien-pad", src)
- spawn(0)
- anim(target.loc,target,'icons/mob/mob.dmi',,"uncloak",,target.dir)
+ PoolOrNew(/obj/effect/overlay/temp/dir_setting/ninja, list(get_turf(target), target.dir))
Warp(target)
/obj/machinery/abductor/pad/proc/MobToLoc(place,mob/living/target)
@@ -30,7 +28,7 @@
sleep(80)
flick("alien-pad", src)
target.forceMove(place)
- anim(target.loc,target,'icons/mob/mob.dmi',,"uncloak",,target.dir)
+ PoolOrNew(/obj/effect/overlay/temp/dir_setting/ninja, list(get_turf(target), target.dir))
/obj/machinery/abductor/pad/proc/PadToLoc(place)
PoolOrNew(/obj/effect/overlay/temp/teleport_abductor, place)
@@ -38,8 +36,7 @@
flick("alien-pad", src)
for(var/mob/living/target in get_turf(src))
target.forceMove(place)
- spawn(0)
- anim(target.loc,target,'icons/mob/mob.dmi',,"uncloak",,target.dir)
+ PoolOrNew(/obj/effect/overlay/temp/dir_setting/ninja, list(get_turf(target), target.dir))
/obj/effect/overlay/temp/teleport_abductor
diff --git a/code/game/gamemodes/miniantags/morph/morph.dm b/code/game/gamemodes/miniantags/morph/morph.dm
index 1d98760553f..f1b34bdebf9 100644
--- a/code/game/gamemodes/miniantags/morph/morph.dm
+++ b/code/game/gamemodes/miniantags/morph/morph.dm
@@ -121,8 +121,6 @@
form = null
alpha = initial(alpha)
- //anim(loc,src,'icons/mob/mob.dmi',,"morph",,src.dir)
-
visible_message("[src] suddenly collapses in on itself, dissolving into a pile of green flesh!", \
"You reform to your normal body.")
name = initial(name)
diff --git a/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm b/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm
index b1420d8cb03..85e729c3962 100644
--- a/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm
+++ b/code/game/gamemodes/miniantags/revenant/revenant_abilities.dm
@@ -54,7 +54,7 @@
reveal(46)
stun(46)
target.visible_message("[target] suddenly rises slightly into the air, their skin turning an ashy gray.")
- var/datum/beam/B = Beam(target,icon_state="drain_life",icon='icons/effects/effects.dmi',time=46)
+ var/datum/beam/B = Beam(target,icon_state="drain_life",time=46)
if(do_after(src, 46, 0, target)) //As one cannot prove the existance of ghosts, ghosts cannot prove the existance of the target they were draining.
qdel(B)
change_essence_amount(essence_drained, 0, target)
@@ -220,7 +220,7 @@
for(var/mob/living/carbon/human/M in view(shock_range, L))
if(M == user)
continue
- L.Beam(M,icon_state="purple_lightning",icon='icons/effects/effects.dmi',time=5)
+ L.Beam(M,icon_state="purple_lightning",time=5)
M.electrocute_act(shock_damage, L, safety=1)
var/datum/effect_system/spark_spread/z = new /datum/effect_system/spark_spread
z.set_up(4, 0, M)
diff --git a/code/game/gamemodes/miniantags/revenant/revenant_blight.dm b/code/game/gamemodes/miniantags/revenant/revenant_blight.dm
index 19cb12d0205..9133fa69c22 100644
--- a/code/game/gamemodes/miniantags/revenant/revenant_blight.dm
+++ b/code/game/gamemodes/miniantags/revenant/revenant_blight.dm
@@ -14,9 +14,11 @@
severity = BIOHAZARD
var/stagedamage = 0 //Highest stage reached.
var/finalstage = 0 //Because we're spawning off the cure in the final stage, we need to check if we've done the final stage's effects.
+ var/old_color = ""
/datum/disease/revblight/cure()
if(affected_mob)
+ affected_mob.color = old_color
affected_mob << "You feel better."
if(affected_mob.dna && affected_mob.dna.species)
affected_mob.dna.species.handle_mutant_bodyparts(affected_mob)
@@ -58,11 +60,8 @@
affected_mob.dna.species.handle_mutant_bodyparts(affected_mob,"#1d2953")
affected_mob.dna.species.handle_hair(affected_mob,"#1d2953")
affected_mob.visible_message("[affected_mob] looks terrifyingly gaunt...", "You suddenly feel like your skin is wrong...")
- var/old_color = affected_mob.color
+ old_color = affected_mob.color
affected_mob.color = "#1d2953"
- spawn(100)
- if(affected_mob)
- affected_mob = old_color
- cure()
+ addtimer(src, "cure", 100, FALSE)
else
- return
\ No newline at end of file
+ return
diff --git a/code/game/gamemodes/miniantags/slaughter/slaughter.dm b/code/game/gamemodes/miniantags/slaughter/slaughter.dm
index f63dfae041e..2ac221435fc 100644
--- a/code/game/gamemodes/miniantags/slaughter/slaughter.dm
+++ b/code/game/gamemodes/miniantags/slaughter/slaughter.dm
@@ -63,6 +63,7 @@
icon = 'icons/obj/surgery.dmi'
name = "pile of viscera"
desc = "A repulsive pile of guts and gore."
+ gender = NEUTER
random_icon_states = list("innards")
/mob/living/simple_animal/slaughter/phasein()
diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm
index 98d0f963433..e0d0fdb3d00 100644
--- a/code/game/gamemodes/nuclear/nuclearbomb.dm
+++ b/code/game/gamemodes/nuclear/nuclearbomb.dm
@@ -91,7 +91,7 @@ var/bomb_set
if (istype(I, /obj/item/weapon/disk/nuclear))
if(!user.drop_item())
return
- I.loc = src
+ I.forceMove(src)
auth = I
add_fingerprint(user)
return
@@ -496,6 +496,20 @@ This is here to make the tiles around the station mininuke change when it's arme
poi_list |= src
START_PROCESSING(SSobj, src)
+/obj/item/weapon/disk/nuclear/attackby(obj/item/I, mob/living/user, params)
+ if(istype(I, /obj/item/weapon/claymore/highlander))
+ var/obj/item/weapon/claymore/highlander/H = I
+ if(H.nuke_disk)
+ user << "Wait... what?"
+ qdel(H.nuke_disk)
+ H.nuke_disk = null
+ return
+ user.visible_message("[user] captures [src]!", "You've got the disk! Defend it with your life!")
+ loc = H
+ H.nuke_disk = src
+ return 1
+ return ..()
+
/obj/item/weapon/disk/nuclear/suicide_act(mob/user)
user.visible_message("[user] is \
going delta! It looks like they're comitting suicide.")
diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm
index 8e0793ff4a5..0cb14a1f13d 100644
--- a/code/game/gamemodes/wizard/soulstone.dm
+++ b/code/game/gamemodes/wizard/soulstone.dm
@@ -220,12 +220,7 @@
/obj/item/device/soulstone/proc/init_shade(mob/living/carbon/human/T, mob/U, vic = 0)
new /obj/effect/decal/remains/human(T.loc) //Spawns a skeleton
T.invisibility = INVISIBILITY_ABSTRACT
- var/atom/movable/overlay/animation = new /atom/movable/overlay( T.loc )
- animation.icon_state = "blank"
- animation.icon = 'icons/mob/mob.dmi'
- animation.master = T
- flick("dust-h", animation)
- qdel(animation)
+ T.dust_animation()
var/mob/living/simple_animal/shade/S = new /mob/living/simple_animal/shade(src)
S.status_flags |= GODMODE //So they won't die inside the stone somehow
S.canmove = 0//Can't move out of the soul stone
@@ -256,7 +251,7 @@
break
if(!chosen_ghost) //Failing that, we grab a ghost
- var/list/consenting_candidates = pollCandidates("Would you like to play as a Shade?", "Cultist", null, ROLE_CULTIST, poll_time = 100)
+ var/list/consenting_candidates = pollCandidates("Would you like to play as a Shade?", "Cultist", null, ROLE_CULTIST, poll_time = 50)
if(consenting_candidates.len)
chosen_ghost = pick(consenting_candidates)
if(!T)
diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm
index 2e26c95e67f..db81c9efeef 100644
--- a/code/game/machinery/Sleeper.dm
+++ b/code/game/machinery/Sleeper.dm
@@ -19,7 +19,7 @@
var/controls_inside = FALSE
var/list/possible_chems = list(
list("epinephrine", "morphine", "salbutamol", "bicaridine", "kelotane"),
- list("oculine"),
+ list("oculine","inacusiate"),
list("antitoxin", "mutadone", "mannitol", "pen_acid"),
list("omnizine")
)
diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm
index 866daf1fbe1..e66248b0a9a 100644
--- a/code/game/machinery/computer/computer.dm
+++ b/code/game/machinery/computer/computer.dm
@@ -19,7 +19,10 @@
..(location)
if(C && istype(C))
circuit = C
- else if(circuit)
+ //Some machines, oldcode arcades mostly, new themselves, so circuit
+ //can already be an instance of a type and trying to new that will
+ //cause a runtime
+ else if(ispath(circuit))
circuit = new circuit(null)
power_change()
update_icon()
diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm
index ab820645505..d929f800cdd 100644
--- a/code/game/machinery/computer/crew.dm
+++ b/code/game/machinery/computer/crew.dm
@@ -7,6 +7,11 @@
idle_power_usage = 250
active_power_usage = 500
circuit = /obj/item/weapon/circuitboard/computer/crew
+ var/monitor = null //For VV debugging purposes
+
+/obj/machinery/computer/crew/New()
+ monitor = crewmonitor
+ return ..()
/obj/machinery/computer/crew/attack_ai(mob/user)
if(stat & (BROKEN|NOPOWER))
@@ -103,6 +108,7 @@ var/global/datum/crewmonitor/crewmonitor = new
src.update(z, TRUE)
else
hi = src.interfaces["[z]"]
+ src.update(z,TRUE)
// Debugging purposes
mob << browse_rsc(file("code/game/machinery/computer/crew.js"), "crew.js")
@@ -204,6 +210,9 @@ var/global/datum/crewmonitor/crewmonitor = new
for (z in src.interfaces)
if (src.interfaces[z] == hi) break
+ if(hclient.client.mob && IsAdminGhost(hclient.client.mob))
+ return TRUE
+
if (hclient.client.mob && hclient.client.mob.stat == 0 && hclient.client.mob.z == text2num(z))
if (isAI(hclient.client.mob)) return TRUE
else if (isrobot(hclient.client.mob))
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index a85e3bd2bd6..50edc96d054 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -342,17 +342,20 @@
base_state = "clockwork"
shards = 0
rods = 0
+ var/made_glow = FALSE
/obj/machinery/door/window/clockwork/New(loc, set_dir)
..()
- var/obj/effect/E = PoolOrNew(/obj/effect/overlay/temp/ratvar/door/window, get_turf(src))
- if(set_dir)
- E.setDir(set_dir)
- else
- E.setDir(dir)
- debris += new/obj/item/clockwork/component/vanguard_cogwheel(src)
+ debris += new/obj/item/stack/sheet/brass(src, 2)
change_construction_value(2)
+/obj/machinery/door/window/clockwork/setDir(direct)
+ if(!made_glow)
+ var/obj/effect/E = PoolOrNew(/obj/effect/overlay/temp/ratvar/door/window, get_turf(src))
+ E.setDir(direct)
+ made_glow = TRUE
+ ..()
+
/obj/machinery/door/window/clockwork/Destroy()
change_construction_value(-2)
return ..()
diff --git a/code/game/machinery/limbgrower.dm b/code/game/machinery/limbgrower.dm
new file mode 100644
index 00000000000..14c8415adf8
--- /dev/null
+++ b/code/game/machinery/limbgrower.dm
@@ -0,0 +1,238 @@
+#define LIMBGROWER_MAIN_MENU 1
+#define LIMBGROWER_CATEGORY_MENU 2
+#define LIMBGROWER_CHEMICAL_MENU 3
+//use these for the menu system
+
+
+/obj/machinery/limbgrower
+ name = "limb grower"
+ desc = "It grows new limbs using Synthflesh."
+ icon = 'icons/obj/machines/limbgrower.dmi'
+ icon_state = "limbgrower_idleoff"
+ density = 1
+ flags = OPENCONTAINER
+
+ var/operating = 0
+ anchored = 1
+ use_power = 1
+ var/disabled = 0
+ idle_power_usage = 10
+ active_power_usage = 100
+ var/busy = 0
+ var/prod_coeff = 1
+
+ var/datum/design/being_built
+ var/datum/research/files
+ var/selected_category
+ var/screen = 1
+ var/emag = FALSE //Gives access to other cool stuff
+
+ var/list/categories = list(
+ "human",
+ "lizard",
+ "plasmaman",
+ "special"
+ )
+
+/obj/machinery/limbgrower/New()
+ ..()
+ create_reagents(0)
+ var/obj/item/weapon/circuitboard/machine/B = new /obj/item/weapon/circuitboard/machine/limbgrower(null)
+ B.apply_default_parts(src)
+ files = new /datum/research/limbgrower(src)
+
+/obj/item/weapon/circuitboard/machine/limbgrower
+ name = "circuit board (Limb Grower)"
+ build_path = /obj/machinery/limbgrower
+ origin_tech = "programming=2;biotech=2"
+ req_components = list(
+ /obj/item/weapon/stock_parts/manipulator = 1,
+ /obj/item/weapon/reagent_containers/glass/beaker = 2,
+ /obj/item/weapon/stock_parts/console_screen = 1)
+
+/obj/machinery/limbgrower/interact(mob/user)
+ if(!is_operational())
+ return
+
+ var/dat = main_win(user)
+
+ switch(screen)
+ if(LIMBGROWER_MAIN_MENU)
+ dat = main_win(user)
+ if(LIMBGROWER_CATEGORY_MENU)
+ dat = category_win(user,selected_category)
+ if(LIMBGROWER_CHEMICAL_MENU)
+ dat = chemical_win(user)
+
+ var/datum/browser/popup = new(user, "Limb Grower", name, 400, 500)
+ popup.set_content(dat)
+ popup.open()
+
+/obj/machinery/limbgrower/deconstruction()
+ for(var/obj/item/weapon/reagent_containers/glass/G in component_parts)
+ reagents.trans_to(G, G.reagents.maximum_volume)
+
+/obj/machinery/limbgrower/attackby(obj/item/O, mob/user, params)
+ if (busy)
+ user << "The Limb Grower is busy. Please wait for completion of previous operation."
+ return
+
+ if(default_deconstruction_screwdriver(user, "limbgrower_panelopen", "limbgrower_idleoff", O))
+ updateUsrDialog()
+ return
+
+ if(exchange_parts(user, O))
+ return
+
+ if(panel_open && default_deconstruction_crowbar(O))
+ return
+
+ if(user.a_intent == "harm") //so we can hit the machine
+ return ..()
+
+/obj/machinery/limbgrower/Topic(href, href_list)
+ if(..())
+ return
+ if (!busy)
+ if(href_list["menu"])
+ screen = text2num(href_list["menu"])
+
+ if(href_list["category"])
+ selected_category = href_list["category"]
+
+ if(href_list["disposeI"]) //Get rid of a reagent incase you add the wrong one by mistake
+ reagents.del_reagent(href_list["disposeI"])
+
+ if(href_list["make"])
+
+ /////////////////
+ //href protection
+ being_built = files.FindDesignByID(href_list["make"]) //check if it's a valid design
+ if(!being_built)
+ return
+
+
+ var/synth_cost = being_built.reagents["synthflesh"]*prod_coeff
+ var/power = max(2000, synth_cost/5)
+
+ if(reagents.has_reagent("synthflesh", being_built.reagents["synthflesh"]*prod_coeff))
+ busy = 1
+ use_power(power)
+ flick("limbgrower_fill",src)
+ icon_state = "limbgrower_idleon"
+ addtimer(src, "build_item",32*prod_coeff)
+
+ else
+ usr << "The limb grower is busy. Please wait for completion of previous operation."
+
+ updateUsrDialog()
+ return
+
+/obj/machinery/limbgrower/proc/build_item()
+ if(reagents.has_reagent("synthflesh", being_built.reagents["synthflesh"]*prod_coeff)) //sanity check, if this happens we are in big trouble
+ reagents.remove_reagent("synthflesh",being_built.reagents["synthflesh"]*prod_coeff)
+ var/buildpath = being_built.build_path
+ if(ispath(buildpath, /obj/item/bodypart)) //This feels like spatgheti code, but i need to initilise a limb somehow
+ build_limb(buildpath)
+ else
+ //Just build whatever it is
+ new buildpath(loc)
+ else
+ src.visible_message(" Something went very wrong and there isnt enough synthflesh anymore!")
+ busy = 0
+ flick("limbgrower_unfill",src)
+ icon_state = "limbgrower_idleoff"
+ updateUsrDialog()
+
+/obj/machinery/limbgrower/proc/build_limb(buildpath)
+ //i need to create a body part manually using a set icon (otherwise it doesnt appear)
+ var/obj/item/bodypart/limb
+ limb = new buildpath(loc)
+ if(selected_category=="human" || selected_category=="lizard") // Doing this because plasmamen have their limbs in a different icon file
+ limb.icon = 'icons/mob/human_parts_greyscale.dmi'
+ else
+ limb.icon = 'icons/mob/human_parts.dmi'
+ // Set this limb up using the specias name and body zone
+ limb.icon_state = "[selected_category]_[limb.body_zone]_s"
+ limb.name = "Synthetic [selected_category] [parse_zone(limb.body_zone)]"
+ limb.desc = "A synthetic [selected_category] limb that will morph on its first use in surgery. This one is for the [parse_zone(limb.body_zone)]"
+
+/obj/machinery/limbgrower/RefreshParts()
+ reagents.maximum_volume = 0
+ for(var/obj/item/weapon/reagent_containers/glass/G in component_parts)
+ reagents.maximum_volume += G.volume
+ G.reagents.trans_to(src, G.reagents.total_volume)
+ var/T=1.2
+ for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
+ T -= M.rating*0.2
+ prod_coeff = min(1,max(0,T)) // Coeff going 1 -> 0,8 -> 0,6 -> 0,4
+
+/obj/machinery/limbgrower/proc/main_win(mob/user)
+ var/dat = "Limb Grower Menu:
"
+ dat += "
Chemical Storage"
+ dat += materials_printout()
+ dat += "
"
+
+ for(var/C in categories)
+ if(C=="special" && !emag) //Only want to show special when console is emagged
+ continue
+
+ dat += "| [C] | "
+ dat += "
"
+ //one category per line
+
+ dat += "
"
+ return dat
+
+/obj/machinery/limbgrower/proc/category_win(mob/user,selected_category)
+ var/dat = "Return to main menu"
+ dat += "Browsing [selected_category]:
"
+ dat += materials_printout()
+
+ for(var/v in files.known_designs)
+ var/datum/design/D = files.known_designs[v]
+ if(!(selected_category in D.category))
+ continue
+ if(disabled || !can_build(D))
+ dat += "
[D.name]"
+ else
+ dat += "
[D.name]"
+ dat += "[get_design_cost(D)]
"
+
+ dat += "
"
+ return dat
+
+
+/obj/machinery/limbgrower/proc/chemical_win(mob/user)
+ var/dat = "Return to main menu"
+ dat += "Browsing Chemical Storage:
"
+ dat += materials_printout()
+
+ for(var/datum/reagent/R in reagents.reagent_list)
+ dat += "[R.name]: [R.volume]"
+ dat += "
Purge"
+
+ dat += "
"
+ return dat
+
+/obj/machinery/limbgrower/proc/materials_printout()
+ var/dat = "Total amount:> [reagents.total_volume] / [reagents.maximum_volume] cm3
"
+ return dat
+
+/obj/machinery/limbgrower/proc/can_build(datum/design/D)
+ return (reagents.has_reagent("synthflesh", D.reagents["synthflesh"]*prod_coeff)) //Return whether the machine has enough synthflesh to produce the design
+
+/obj/machinery/limbgrower/proc/get_design_cost(datum/design/D)
+ var/dat
+ if(D.reagents["synthflesh"])
+ dat += "[D.reagents["synthflesh"] * prod_coeff] Synthetic flesh "
+ return dat
+
+/obj/machinery/limbgrower/emag_act(mob/user)
+ if(emag==TRUE)
+ return
+ for(var/datum/design/D in files.possible_designs)
+ if((D.build_type & LIMBGROWER) && ("special" in D.category))
+ files.AddDesign2Known(D)
+ user << "A warning flashes onto the screen, stating that safety overrides have been deactivated"
+ emag = TRUE
\ No newline at end of file
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index 4203573df56..2b7232cfc6d 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -459,9 +459,9 @@ Class Procs:
. = 1
-/obj/machinery/tesla_act(var/power)
+/obj/machinery/tesla_act(power, explosive = FALSE)
..()
- if(prob(85))
+ if(prob(85) && explosive)
explosion(src.loc,1,2,4,flame_range = 2, adminlog = 0, smoke = 0)
else if(prob(50))
emp_act(2)
diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm
index 8f24ecfc84d..5254b3b511f 100644
--- a/code/game/machinery/recharger.dm
+++ b/code/game/machinery/recharger.dm
@@ -132,8 +132,9 @@
if(istype(charging, /obj/item/device/modular_computer))
var/obj/item/device/modular_computer/C = charging
- if(C.battery_module)
- var/obj/item/weapon/computer_hardware/battery/B = C.battery_module
+ var/obj/item/weapon/computer_hardware/battery/battery_module = C.all_components[MC_CELL]
+ if(battery_module)
+ var/obj/item/weapon/computer_hardware/battery/B = battery_module
if(B.battery)
if(B.battery.charge < B.battery.maxcharge)
B.battery.give(B.battery.chargerate * recharge_coeff)
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index e30be6c7de3..a23ec04811d 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -32,9 +32,8 @@
mask_type = /obj/item/clothing/mask/breath
/obj/machinery/suit_storage_unit/captain
- suit_type = /obj/item/clothing/suit/space/captain
- helmet_type = /obj/item/clothing/head/helmet/space/captain
- mask_type = /obj/item/clothing/mask/gas
+ suit_type = /obj/item/clothing/suit/space/hardsuit/captain
+ mask_type = /obj/item/clothing/mask/gas/sechailer
storage_type = /obj/item/weapon/tank/jetpack/oxygen/captain
/obj/machinery/suit_storage_unit/engine
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index 95e8c2d397c..04930677270 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -909,7 +909,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
desc = "A kitchen and restaurant equipment vendor"
product_ads = "Mm, food stuffs!;Food and food accessories.;Get your plates!;You like forks?;I like forks.;Woo, utensils.;You don't really need these..."
icon_state = "dinnerware"
- products = list(/obj/item/weapon/storage/bag/tray = 8,/obj/item/weapon/kitchen/fork = 6,/obj/item/weapon/kitchen/knife = 6,/obj/item/weapon/kitchen/rollingpin = 2,/obj/item/weapon/reagent_containers/food/drinks/drinkingglass = 8,/obj/item/clothing/suit/apron/chef = 2,/obj/item/weapon/reagent_containers/food/condiment/pack/ketchup = 5,/obj/item/weapon/reagent_containers/food/condiment/pack/hotsauce = 5,/obj/item/weapon/reagent_containers/food/condiment/saltshaker = 5,/obj/item/weapon/reagent_containers/food/condiment/peppermill = 5,/obj/item/weapon/reagent_containers/glass/bowl = 20,/obj/item/weapon/sharpener = 2)
+ products = list(/obj/item/weapon/storage/bag/tray = 8,/obj/item/weapon/kitchen/fork = 6,/obj/item/weapon/kitchen/knife = 6,/obj/item/weapon/kitchen/rollingpin = 2,/obj/item/weapon/reagent_containers/food/drinks/drinkingglass = 8,/obj/item/clothing/suit/apron/chef = 2,/obj/item/weapon/reagent_containers/food/condiment/pack/ketchup = 5,/obj/item/weapon/reagent_containers/food/condiment/pack/hotsauce = 5,/obj/item/weapon/reagent_containers/food/condiment/saltshaker = 5,/obj/item/weapon/reagent_containers/food/condiment/peppermill = 5,/obj/item/weapon/reagent_containers/glass/bowl = 20)
contraband = list(/obj/item/weapon/kitchen/rollingpin = 2, /obj/item/weapon/kitchen/knife/butcher = 2)
/obj/machinery/vending/sovietsoda
diff --git a/code/game/mecha/mecha_defense.dm b/code/game/mecha/mecha_defense.dm
index 7043e0bf508..438c868d041 100644
--- a/code/game/mecha/mecha_defense.dm
+++ b/code/game/mecha/mecha_defense.dm
@@ -9,7 +9,7 @@
return 1 //always return non-0
-/obj/mecha/proc/take_damage(amount, type="brute", booster_deflection_modifier = 1, booster_damage_modifier = 1)
+/obj/mecha/proc/take_damage(amount, type="brute", booster_deflection_modifier = 1, booster_damage_modifier = 1, send_message = 1)
if(prob(deflect_chance * booster_deflection_modifier))
visible_message("[src]'s armour deflects the attack!")
log_append_to_last("Armor saved.")
@@ -19,18 +19,19 @@
damage = damage * booster_damage_modifier
health -= damage
update_health()
- occupant_message("Taking damage!")
+ if(send_message)
+ occupant_message("Taking damage!")
log_append_to_last("Took [damage] points of damage. Damage type: \"[type]\".",1)
return 1
-/obj/mecha/proc/take_directional_damage(amount, type="brute", adir = 0, booster_deflection_modifier = 1, booster_damage_modifier = 1)
+/obj/mecha/proc/take_directional_damage(amount, type="brute", adir = 0, booster_deflection_modifier = 1, booster_damage_modifier = 1, send_message = 1)
var/facing_modifier = get_armour_facing(dir2angle(adir) - dir2angle(src))
booster_damage_modifier /= facing_modifier
booster_deflection_modifier *= facing_modifier
- return take_damage(amount, type, booster_deflection_modifier, booster_damage_modifier)
+ return take_damage(amount, type, booster_deflection_modifier, booster_damage_modifier, send_message)
/obj/mecha/proc/absorbDamage(damage,damage_type)
diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm
index 4924c0470de..0b6b6cae361 100644
--- a/code/game/mecha/working/ripley.dm
+++ b/code/game/mecha/working/ripley.dm
@@ -2,7 +2,9 @@
desc = "Autonomous Power Loader Unit. This newer model is refitted with powerful armour against the dangers of the EVA mining process."
name = "\improper APLU \"Ripley\""
icon_state = "ripley"
- step_in = 5
+ step_in = 4 //Move speed, lower is faster.
+ var/hi_pres_step_in = 4 //step_in while in high pressure.
+ var/lo_pres_step_in = 2 //step_in while in low/zero pressure.
max_temperature = 20000
health = 200
lights_power = 7
@@ -72,7 +74,7 @@
desc = "OH SHIT IT'S THE DEATHSQUAD WE'RE ALL GONNA DIE"
name = "\improper DEATH-RIPLEY"
icon_state = "deathripley"
- step_in = 3
+ hi_pres_step_in = 3
opacity=0
lights_power = 7
wreckage = /obj/structure/mecha_wreckage/ripley/deathripley
@@ -150,11 +152,11 @@
var/pressure = environment.return_pressure()
if(pressure < 40)
- step_in = 3
+ step_in = lo_pres_step_in
for(var/obj/item/mecha_parts/mecha_equipment/drill/drill in equipment)
drill.equip_cooldown = initial(drill.equip_cooldown)/2
else
- step_in = 5
+ step_in = hi_pres_step_in
for(var/obj/item/mecha_parts/mecha_equipment/drill/drill in equipment)
drill.equip_cooldown = initial(drill.equip_cooldown)
diff --git a/code/game/objects/effects/decals/Cleanable/aliens.dm b/code/game/objects/effects/decals/Cleanable/aliens.dm
index a0e5d4a3dc3..fbc74142fd9 100644
--- a/code/game/objects/effects/decals/Cleanable/aliens.dm
+++ b/code/game/objects/effects/decals/Cleanable/aliens.dm
@@ -3,9 +3,6 @@
/obj/effect/decal/cleanable/xenoblood
name = "xeno blood"
desc = "It's green and acidic. It looks like... blood?"
- gender = PLURAL
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
icon = 'icons/effects/blood.dmi'
icon_state = "xfloor1"
random_icon_states = list("xfloor1", "xfloor2", "xfloor3", "xfloor4", "xfloor5", "xfloor6", "xfloor7")
@@ -43,7 +40,6 @@
/obj/effect/decal/cleanable/xenoblood/xgibs
name = "xeno gibs"
desc = "Gnarly..."
- gender = PLURAL
icon = 'icons/effects/blood.dmi'
icon_state = "xgib1"
random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6")
diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm
index 916bd7d2cf3..34118d95ac3 100644
--- a/code/game/objects/effects/decals/Cleanable/humans.dm
+++ b/code/game/objects/effects/decals/Cleanable/humans.dm
@@ -1,9 +1,6 @@
/obj/effect/decal/cleanable/blood
name = "blood"
desc = "It's red and gooey. Perhaps it's the chef's cooking?"
- gender = PLURAL
- density = 0
- layer = ABOVE_NORMAL_TURF_LAYER
icon = 'icons/effects/blood.dmi'
icon_state = "floor1"
random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7")
@@ -29,16 +26,12 @@
/obj/effect/decal/cleanable/blood/tracks
icon_state = "tracks"
desc = "They look like tracks left by wheels."
- gender = PLURAL
random_icon_states = null
/obj/effect/decal/cleanable/trail_holder //not a child of blood on purpose
name = "blood"
icon_state = "ltrails_1"
desc = "Your instincts say you shouldn't be following these."
- gender = PLURAL
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
random_icon_states = null
var/list/existing_dirs = list()
blood_DNA = list()
@@ -51,9 +44,6 @@
/obj/effect/decal/cleanable/blood/gibs
name = "gibs"
desc = "They look bloody and gruesome."
- gender = PLURAL
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
icon = 'icons/effects/blood.dmi'
icon_state = "gibbl5"
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6")
@@ -108,7 +98,6 @@
/obj/effect/decal/cleanable/blood/drip
name = "drips of blood"
desc = "It's red."
- gender = PLURAL
icon_state = "1"
random_icon_states = list("drip1","drip2","drip3","drip4","drip5")
bloodiness = 0
@@ -125,7 +114,6 @@
icon = 'icons/effects/footprints.dmi'
icon_state = "nothingwhatsoever"
desc = "where might they lead?"
- gender = PLURAL
random_icon_states = null
var/entered_dirs = 0
var/exited_dirs = 0
diff --git a/code/game/objects/effects/decals/Cleanable/misc.dm b/code/game/objects/effects/decals/Cleanable/misc.dm
index ebf8ab3f8c5..5e460de0b80 100644
--- a/code/game/objects/effects/decals/Cleanable/misc.dm
+++ b/code/game/objects/effects/decals/Cleanable/misc.dm
@@ -1,16 +1,12 @@
/obj/effect/decal/cleanable/generic
name = "clutter"
desc = "Someone should clean that up."
- gender = PLURAL
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
icon = 'icons/obj/objects.dmi'
icon_state = "shards"
/obj/effect/decal/cleanable/ash
name = "ashes"
desc = "Ashes to ashes, dust to dust, and into space."
- gender = PLURAL
icon = 'icons/obj/objects.dmi'
icon_state = "ash"
@@ -24,25 +20,16 @@
name = "dirt"
desc = "Someone should clean that up."
icon_state = "dirt"
- gender = PLURAL
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
mouse_opacity = 0
/obj/effect/decal/cleanable/flour
name = "flour"
desc = "It's still good. Four second rule!"
- gender = PLURAL
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
icon_state = "flour"
/obj/effect/decal/cleanable/greenglow
name = "glowing goo"
desc = "Jeez. I hope that's not for lunch."
- gender = PLURAL
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
luminosity = 1
icon_state = "greenglow"
@@ -52,36 +39,34 @@
/obj/effect/decal/cleanable/cobweb
name = "cobweb"
desc = "Somebody should remove that."
- density = 0
- layer = OBJ_LAYER
+ gender = NEUTER
+ layer = WALL_OBJ_LAYER
icon_state = "cobweb1"
- burntime = 1
/obj/effect/decal/cleanable/cobweb/fire_act()
qdel(src)
+/obj/effect/decal/cleanable/cobweb2
+ name = "cobweb"
+ desc = "Somebody should remove that."
+ gender = NEUTER
+ layer = WALL_OBJ_LAYER
+ icon_state = "cobweb2"
+
+/obj/effect/decal/cleanable/cobweb2/fire_act()
+ qdel(src)
+
/obj/effect/decal/cleanable/molten_item
name = "gooey grey mass"
desc = "It looks like a melted... something."
- density = 0
- layer = OBJ_LAYER
+ gender = NEUTER
icon = 'icons/obj/chemical.dmi'
icon_state = "molten"
-/obj/effect/decal/cleanable/cobweb2
- name = "cobweb"
- desc = "Somebody should remove that."
- density = 0
- layer = OBJ_LAYER
- icon_state = "cobweb2"
-
//Vomit (sorry)
/obj/effect/decal/cleanable/vomit
name = "vomit"
desc = "Gosh, how unpleasant."
- gender = PLURAL
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
icon = 'icons/effects/blood.dmi'
icon_state = "vomit_1"
random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4")
@@ -112,38 +97,34 @@
/obj/effect/decal/cleanable/tomato_smudge
name = "tomato smudge"
desc = "It's red."
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
+ gender = NEUTER
icon = 'icons/effects/tomatodecal.dmi'
random_icon_states = list("tomato_floor1", "tomato_floor2", "tomato_floor3")
/obj/effect/decal/cleanable/plant_smudge
name = "plant smudge"
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
+ gender = NEUTER
icon = 'icons/effects/tomatodecal.dmi'
random_icon_states = list("smashed_plant")
/obj/effect/decal/cleanable/egg_smudge
name = "smashed egg"
desc = "Seems like this one won't hatch."
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
+ gender = NEUTER
icon = 'icons/effects/tomatodecal.dmi'
random_icon_states = list("smashed_egg1", "smashed_egg2", "smashed_egg3")
/obj/effect/decal/cleanable/pie_smudge //honk
name = "smashed pie"
desc = "It's pie cream from a cream pie."
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
+ gender = NEUTER
icon = 'icons/effects/tomatodecal.dmi'
random_icon_states = list("smashed_pie")
/obj/effect/decal/cleanable/chem_pile
name = "chemical pile"
desc = "A pile of chemicals. You can't quite tell what's inside it."
- gender = PLURAL
+ gender = NEUTER
icon = 'icons/obj/objects.dmi'
icon_state = "ash"
@@ -152,8 +133,6 @@
desc = "The shredded remains of what appears to be clothing."
icon_state = "shreds"
gender = PLURAL
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
/obj/effect/decal/cleanable/shreds/New()
pixel_x = rand(-5, 5)
@@ -165,3 +144,4 @@
desc = "A sizable pile of table salt. Someone must be upset."
icon = 'icons/effects/tomatodecal.dmi'
icon_state = "salt_pile"
+ gender = NEUTER
diff --git a/code/game/objects/effects/decals/Cleanable/robots.dm b/code/game/objects/effects/decals/Cleanable/robots.dm
index 7c0666a0c6e..5b56853cff2 100644
--- a/code/game/objects/effects/decals/Cleanable/robots.dm
+++ b/code/game/objects/effects/decals/Cleanable/robots.dm
@@ -3,9 +3,6 @@
/obj/effect/decal/cleanable/robot_debris
name = "robot debris"
desc = "It's a useless heap of junk... or is it?"
- gender = PLURAL
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
icon = 'icons/mob/robots.dmi'
icon_state = "gib1"
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7")
@@ -45,9 +42,6 @@
/obj/effect/decal/cleanable/oil
name = "motor oil"
desc = "It's black and greasy. Looks like Beepsky made another mess."
- gender = PLURAL
- density = 0
- layer = ABOVE_OPEN_TURF_LAYER
icon = 'icons/mob/robots.dmi'
icon_state = "floor1"
var/viruses = list()
diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm
index 9a24696cc87..b4a78c247b2 100644
--- a/code/game/objects/effects/decals/cleanable.dm
+++ b/code/game/objects/effects/decals/cleanable.dm
@@ -1,4 +1,6 @@
/obj/effect/decal/cleanable
+ gender = PLURAL
+ layer = ABOVE_NORMAL_TURF_LAYER
var/list/random_icon_states = list()
var/blood_state = "" //I'm sorry but cleanable/blood code is ass, and so is blood_DNA
var/bloodiness = 0 //0-100, amount of blood in this decal, used for making footprints and affecting the alpha of bloody footprints
diff --git a/code/game/objects/effects/decals/crayon.dm b/code/game/objects/effects/decals/crayon.dm
index c629ff1e768..4a0175076a1 100644
--- a/code/game/objects/effects/decals/crayon.dm
+++ b/code/game/objects/effects/decals/crayon.dm
@@ -3,15 +3,9 @@
desc = "Graffiti. Damn kids."
icon = 'icons/effects/crayondecal.dmi'
icon_state = "rune1"
- layer = ABOVE_NORMAL_TURF_LAYER
+ gender = NEUTER
var/do_icon_rotate = TRUE
-/obj/effect/decal/cleanable/crayon/examine()
- set src in view(2)
- ..()
- return
-
-
/obj/effect/decal/cleanable/crayon/New(location, main = "#FFFFFF", var/type = "rune1", var/e_name = "rune", var/rotation = 0, var/alt_icon = null)
..()
loc = location
diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm
index d0d79764c09..e63dcbb7840 100644
--- a/code/game/objects/effects/overlays.dm
+++ b/code/game/objects/effects/overlays.dm
@@ -42,17 +42,26 @@
timerid = QDEL_IN(src, duration)
-/obj/effect/overlay/temp/bloodsplatter
+/obj/effect/overlay/temp/dir_setting
+ randomdir = FALSE
+
+/obj/effect/overlay/temp/dir_setting/New(loc, set_dir)
+ if(set_dir)
+ setDir(set_dir)
+ ..()
+
+/obj/effect/overlay/temp/dir_setting/bloodsplatter
icon = 'icons/effects/blood.dmi'
duration = 5
randomdir = FALSE
layer = BELOW_MOB_LAYER
+ var/splatter_type = "splatter"
-/obj/effect/overlay/temp/bloodsplatter/New(loc, set_dir)
+/obj/effect/overlay/temp/dir_setting/bloodsplatter/New(loc, set_dir)
if(set_dir in diagonals)
- icon_state = "splatter[pick(1, 2, 6)]"
+ icon_state = "[splatter_type][pick(1, 2, 6)]"
else
- icon_state = "splatter[pick(3, 4, 5)]"
+ icon_state = "[splatter_type][pick(3, 4, 5)]"
..()
var/target_pixel_x = 0
var/target_pixel_y = 0
@@ -80,47 +89,88 @@
target_pixel_x = -16
target_pixel_y = -16
layer = ABOVE_MOB_LAYER
- setDir(set_dir)
animate(src, pixel_x = target_pixel_x, pixel_y = target_pixel_y, alpha = 0, time = duration)
+/obj/effect/overlay/temp/dir_setting/bloodsplatter/xenosplatter
+ splatter_type = "xsplatter"
-/obj/effect/overlay/temp/heal //color is white by default, set to whatever is needed
- name = "healing glow"
- icon_state = "heal"
- duration = 15
+/obj/effect/overlay/temp/dir_setting/firing_effect
+ icon = 'icons/effects/effects.dmi'
+ icon_state = "firing_effect"
+ duration = 2
-/obj/effect/overlay/temp/heal/New(loc, colour)
+/obj/effect/overlay/temp/dir_setting/firing_effect/setDir(newdir)
+ switch(newdir)
+ if(NORTH)
+ layer = BELOW_MOB_LAYER
+ pixel_x = rand(-3,3)
+ pixel_y = rand(4,6)
+ if(SOUTH)
+ pixel_x = rand(-3,3)
+ pixel_y = rand(-1,1)
+ else
+ pixel_x = rand(-1,1)
+ pixel_y = rand(-1,1)
..()
- pixel_x = rand(-12, 12)
- pixel_y = rand(-9, 0)
- if(colour)
- color = colour
-/obj/effect/overlay/temp/kinetic_blast
- name = "kinetic explosion"
- icon = 'icons/obj/projectiles.dmi'
- icon_state = "kinetic_blast"
- layer = ABOVE_ALL_MOB_LAYER
- duration = 4
+/obj/effect/overlay/temp/dir_setting/firing_effect/energy
+ icon_state = "firing_effect_energy"
+ duration = 3
-/obj/effect/overlay/temp/explosion
- name = "explosion"
- icon = 'icons/effects/96x96.dmi'
- icon_state = "explosion"
- pixel_x = -32
- pixel_y = -32
- duration = 8
+/obj/effect/overlay/temp/dir_setting/firing_effect/magic
+ icon_state = "shieldsparkles"
+ duration = 3
-/obj/effect/overlay/temp/explosion/fast
- icon_state = "explosionfast"
- duration = 4
+/obj/effect/overlay/temp/dir_setting/ninja
+ name = "ninja shadow"
+ icon = 'icons/mob/mob.dmi'
+ icon_state = "uncloak"
+ duration = 9
-/obj/effect/overlay/temp/blob
- name = "blob"
- icon_state = "blob_attack"
- alpha = 140
- randomdir = 0
- duration = 6
+/obj/effect/overlay/temp/dir_setting/ninja/cloak
+ icon_state = "cloak"
+
+/obj/effect/overlay/temp/dir_setting/ninja/shadow
+ icon_state = "shadow"
+
+/obj/effect/overlay/temp/dir_setting/ninja/phase
+ name = "ninja energy"
+ icon_state = "phasein"
+
+/obj/effect/overlay/temp/dir_setting/ninja/phase/out
+ icon_state = "phaseout"
+
+/obj/effect/overlay/temp/dir_setting/wraith
+ name = "blood"
+ icon = 'icons/mob/mob.dmi'
+ icon_state = "phase_shift2"
+ duration = 12
+
+/obj/effect/overlay/temp/dir_setting/wraith/out
+ icon_state = "phase_shift"
+
+/obj/effect/overlay/temp/wizard
+ name = "water"
+ icon = 'icons/mob/mob.dmi'
+ icon_state = "reappear"
+ duration = 5
+
+/obj/effect/overlay/temp/wizard/out
+ icon_state = "liquify"
+ duration = 12
+
+/obj/effect/overlay/temp/monkeyify
+ icon = 'icons/mob/mob.dmi'
+ icon_state = "h2monkey"
+ duration = 22
+
+/obj/effect/overlay/temp/monkeyify/humanify
+ icon_state = "monkey2h"
+
+/obj/effect/overlay/temp/borgflash
+ icon = 'icons/mob/mob.dmi'
+ icon_state = "blspell"
+ duration = 5
/obj/effect/overlay/temp/guardian
randomdir = 0
@@ -158,17 +208,12 @@
name = "blood sparks"
icon_state = "bloodsparkles"
-/obj/effect/overlay/temp/cult/phase
+/obj/effect/overlay/temp/dir_setting/cult/phase
name = "phase glow"
duration = 7
icon_state = "cultin"
-/obj/effect/overlay/temp/cult/phase/New(loc, set_dir)
- ..()
- if(set_dir)
- setDir(set_dir)
-
-/obj/effect/overlay/temp/cult/phase/out
+/obj/effect/overlay/temp/dir_setting/cult/phase/out
icon_state = "cultout"
/obj/effect/overlay/temp/cult/sac
@@ -291,7 +336,7 @@
/obj/effect/overlay/temp/emp/pulse
name = "emp pulse"
- icon_state = "emp pulse"
+ icon_state = "emppulse"
duration = 8
randomdir = 0
@@ -340,6 +385,80 @@
/obj/effect/overlay/temp/sparkle/tailsweep
icon_state = "tailsweep"
+
+/obj/effect/overlay/temp/heal //color is white by default, set to whatever is needed
+ name = "healing glow"
+ icon_state = "heal"
+ duration = 15
+
+/obj/effect/overlay/temp/heal/New(loc, colour)
+ ..()
+ pixel_x = rand(-12, 12)
+ pixel_y = rand(-9, 0)
+ if(colour)
+ color = colour
+
+/obj/effect/overlay/temp/kinetic_blast
+ name = "kinetic explosion"
+ icon = 'icons/obj/projectiles.dmi'
+ icon_state = "kinetic_blast"
+ layer = ABOVE_ALL_MOB_LAYER
+ duration = 4
+
+/obj/effect/overlay/temp/explosion
+ name = "explosion"
+ icon = 'icons/effects/96x96.dmi'
+ icon_state = "explosion"
+ pixel_x = -32
+ pixel_y = -32
+ duration = 8
+
+/obj/effect/overlay/temp/explosion/fast
+ icon_state = "explosionfast"
+ duration = 4
+
+/obj/effect/overlay/temp/blob
+ name = "blob"
+ icon_state = "blob_attack"
+ alpha = 140
+ randomdir = 0
+ duration = 6
+
+/obj/effect/overlay/temp/impact_effect
+ icon = 'icons/effects/effects.dmi'
+ icon_state = "impact_bullet"
+ duration = 5
+
+/obj/effect/overlay/temp/impact_effect/New(loc, atom/target, obj/item/projectile/P)
+ if(target == P.original) //the projectile hit the target originally clicked
+ pixel_x = P.p_x + target.pixel_x - 16 + rand(-4,4)
+ pixel_y = P.p_y + target.pixel_y - 16 + rand(-4,4)
+ else
+ pixel_x = target.pixel_x + rand(-4,4)
+ pixel_y = target.pixel_y + rand(-4,4)
+ ..()
+
+/obj/effect/overlay/temp/impact_effect/red_laser
+ icon_state = "impact_laser"
+ duration = 4
+
+/obj/effect/overlay/temp/impact_effect/blue_laser
+ icon_state = "impact_laser_blue"
+ duration = 4
+
+/obj/effect/overlay/temp/impact_effect/green_laser
+ icon_state = "impact_laser_green"
+ duration = 4
+
+/obj/effect/overlay/temp/impact_effect/purple_laser
+ icon_state = "impact_laser_purple"
+ duration = 4
+
+/obj/effect/overlay/temp/impact_effect/ion
+ icon_state = "shieldsparkles"
+ duration = 6
+
+
/obj/effect/overlay/palmtree_r
name = "Palm tree"
icon = 'icons/misc/beach2.dmi'
diff --git a/code/game/objects/effects/step_triggers.dm b/code/game/objects/effects/step_triggers.dm
index abebb75a63a..1754dfa6e46 100644
--- a/code/game/objects/effects/step_triggers.dm
+++ b/code/game/objects/effects/step_triggers.dm
@@ -3,7 +3,7 @@
/obj/effect/step_trigger
var/affect_ghosts = 0
var/stopper = 1 // stops throwers
- var/mobs_only = 0
+ var/mobs_only = FALSE
invisibility = INVISIBILITY_ABSTRACT // nope cant see this shit
anchored = 1
@@ -25,6 +25,7 @@
/obj/effect/step_trigger/message
var/message //the message to give to the mob
var/once = 1
+ mobs_only = TRUE
/obj/effect/step_trigger/message/Trigger(mob/M)
if(M.client)
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 8877f17bc51..1e0b83f6ffd 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -344,6 +344,8 @@ var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_s
var/datum/action/A = X
A.Remove(user)
if(DROPDEL & flags)
+ //Prevents infinite loops where Destroy() calls an objects dropped() function
+ flags &= ~DROPDEL
qdel(src)
// called just as an item is picked up (loc is not yet changed)
@@ -536,7 +538,7 @@ obj/item/proc/item_action_slot_check(slot, mob/user)
itempush = 0 //too light to push anything
return A.hitby(src, 0, itempush)
-/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1)
+/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0)
thrownby = thrower
. = ..()
throw_speed = initial(throw_speed) //explosions change this.
@@ -585,3 +587,8 @@ obj/item/proc/item_action_slot_check(slot, mob/user)
. = "[user] lights [A] with [src]."
else
. = ""
+
+
+//when an item modify our speech spans when in our active hand. Override this to modify speech spans.
+/obj/item/proc/get_held_item_speechspans(mob/living/carbon/user)
+ return
diff --git a/code/game/objects/items/devices/chameleonproj.dm b/code/game/objects/items/devices/chameleonproj.dm
index 6e89ab267a0..07bfc457c92 100644
--- a/code/game/objects/items/devices/chameleonproj.dm
+++ b/code/game/objects/items/devices/chameleonproj.dm
@@ -23,6 +23,7 @@
disrupt()
/obj/item/device/chameleon/equipped()
+ ..()
disrupt()
/obj/item/device/chameleon/attack_self()
diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm
index 34861d8e5c3..afa79892484 100644
--- a/code/game/objects/items/devices/megaphone.dm
+++ b/code/game/objects/items/devices/megaphone.dm
@@ -6,54 +6,22 @@
w_class = 2
flags = FPRINT
siemens_coefficient = 1
-
var/spamcheck = 0
var/emagged = 0
- var/insults = 0
- var/voicespan = "command_headset" // sic
- var/list/insultmsg = list("FUCK EVERYONE!", "DEATH TO LIZARDS!", "ALL SECURITY TO SHOOT ME ON SIGHT!", "I HAVE A BOMB!", "CAPTAIN IS A COMDOM!", "FOR THE SYNDICATE!", "VIVA!", "HONK!")
-
-/obj/item/device/megaphone/attack_self(mob/living/carbon/human/user)
- if(user.client)
- if(user.client.prefs.muted & MUTE_IC)
- src << "You cannot speak in IC (muted)."
- return
-
- if(!ishuman(user))
- user << "You don't know how to use this!"
- return
+ var/list/voicespan = list(SPAN_COMMAND)
+/obj/item/device/megaphone/get_held_item_speechspans(mob/living/carbon/user)
if(spamcheck > world.time)
user << "\The [src] needs to recharge!"
- return
-
- var/message = copytext(sanitize(input(user, "Shout a message?", "Megaphone", null) as text),1,MAX_MESSAGE_LEN)
- if(!message)
- return
-
- message = capitalize(message)
- if(!user.can_speak(message))
- user << "You find yourself unable to speak at all!"
- return
-
- if ((src.loc == user && user.stat == 0))
- if(emagged)
- if(insults)
- user.say(pick(insultmsg),"machine", list(voicespan))
- insults--
- else
- user << "*BZZZZzzzzzt*"
- else
- user.say(message,"machine", list(voicespan))
-
+ else
playsound(loc, 'sound/items/megaphone.ogg', 100, 0, 1)
spamcheck = world.time + 50
- return
+ return voicespan
/obj/item/device/megaphone/emag_act(mob/user)
user << "You overload \the [src]'s voice synthesizer."
emagged = 1
- insults = rand(1, 3) //to prevent dickflooding
+ voicespan = list(SPAN_REALLYBIG, "userdanger")
/obj/item/device/megaphone/sec
name = "security megaphone"
@@ -71,4 +39,4 @@
name = "clown's megaphone"
desc = "Something that should not exist."
icon_state = "megaphone-clown"
- voicespan = "clown"
\ No newline at end of file
+ voicespan = list(SPAN_CLOWN)
\ No newline at end of file
diff --git a/code/game/gamemodes/handofgod/items.dm b/code/game/objects/items/religion.dm
similarity index 55%
rename from code/game/gamemodes/handofgod/items.dm
rename to code/game/objects/items/religion.dm
index f512c5c11cb..4f6fa7ad3f0 100644
--- a/code/game/gamemodes/handofgod/items.dm
+++ b/code/game/objects/items/religion.dm
@@ -7,29 +7,19 @@
var/moralecooldown = 0
var/moralewait = 600
-
/obj/item/weapon/banner/attack_self(mob/living/carbon/human/user)
if(moralecooldown + moralewait > world.time)
return
- var/side = ""
- if(is_handofgod_redcultist(user))
- side = "red"
- else if (is_handofgod_bluecultist(user))
- side = "blue"
-
- if(!side)
- return
user << "You increase the morale of your fellows!"
moralecooldown = world.time
for(var/mob/living/carbon/human/H in range(4,get_turf(src)))
- if((side == "red") && is_handofgod_redcultist(H) || (side == "blue") && is_handofgod_bluecultist(H))
- H << "Your morale is increased by [user]'s banner!"
- H.adjustBruteLoss(-15)
- H.adjustFireLoss(-15)
- H.AdjustStunned(-2)
- H.AdjustWeakened(-2)
- H.AdjustParalysis(-2)
+ H << "Your morale is increased by [user]'s banner!"
+ H.adjustBruteLoss(-15)
+ H.adjustFireLoss(-15)
+ H.AdjustStunned(-2)
+ H.AdjustWeakened(-2)
+ H.AdjustParalysis(-2)
/obj/item/weapon/banner/red
@@ -38,52 +28,32 @@
item_state = "banner-red"
desc = "A banner with the logo of the red deity."
-/obj/item/weapon/banner/red/examine(mob/user)
- ..()
- if(is_handofgod_redcultist(user))
- user << "A banner representing our might against the heretics. We may use it to increase the morale of our fellow members!"
- else if(is_handofgod_bluecultist(user))
- user << "A heretical banner that should be destroyed posthaste."
-
-
/obj/item/weapon/banner/blue
name = "blue banner"
icon_state = "banner-blue"
item_state = "banner-blue"
desc = "A banner with the logo of the blue deity"
-/obj/item/weapon/banner/blue/examine(mob/user)
- ..()
-
- if(is_handofgod_redcultist(user))
- user << "A heretical banner that should be destroyed posthaste."
- else if(is_handofgod_bluecultist(user))
- user << "A banner representing our might against the heretics. We may use it to increase the morale of our fellow members!"
-
-
/obj/item/weapon/storage/backpack/bannerpack
name = "nanotrasen banner backpack"
desc = "It's a backpack with lots of extra room. A banner with Nanotrasen's logo is attached, that can't be removed."
max_combined_w_class = 27 //6 more then normal, for the tradeoff of declaring yourself an antag at all times.
icon_state = "bannerpack"
-
/obj/item/weapon/storage/backpack/bannerpack/red
name = "red banner backpack"
desc = "It's a backpack with lots of extra room. A red banner is attached, that can't be removed."
icon_state = "bannerpack-red"
-
/obj/item/weapon/storage/backpack/bannerpack/blue
name = "blue banner backpack"
desc = "It's a backpack with lots of extra room. A blue banner is attached, that can't be removed."
icon_state = "bannerpack-blue"
-
-
//this is all part of one item set
/obj/item/clothing/suit/armor/plate/crusader
name = "Crusader's Armour"
+ desc = "Armour that's comprised of metal and cloth."
icon_state = "crusader"
w_class = 4 //bulky
slowdown = 2.0 //gotta pretend we're balanced.
@@ -96,16 +66,9 @@
/obj/item/clothing/suit/armor/plate/crusader/blue
icon_state = "crusader-blue"
-/obj/item/clothing/suit/armor/plate/crusader/examine(mob/user)
- ..()
- if(!is_handofgod_cultist(user))
- user << "Armour that's comprised of metal and cloth."
- else
- user << "Armour that was used to protect from backstabs, gunshots, explosives, and lasers. The original wearers of this type of armour were trying to avoid being murdered. Since they're not around anymore, you're not sure if they were successful or not."
-
-
/obj/item/clothing/head/helmet/plate/crusader
name = "Crusader's Hood"
+ desc = "A brownish hood."
icon_state = "crusader"
w_class = 3 //normal
flags_inv = HIDEHAIR|HIDEEARS|HIDEFACE
@@ -117,140 +80,67 @@
/obj/item/clothing/head/helmet/plate/crusader/red
icon_state = "crusader-red"
-
-/obj/item/clothing/head/helmet/plate/crusader/examine(mob/user)
- ..()
- if(!is_handofgod_cultist(user))
- user << "A brownish hood."
- else
- user << "A hood that's very protective, despite being made of cloth. Due to the tendency of the wearer to be targeted for assassinations, being protected from being shot in the face was very important.."
-
-
-
//Prophet helmet
/obj/item/clothing/head/helmet/plate/crusader/prophet
name = "Prophet's Hat"
+ desc = "A religious-looking hat."
alternate_worn_icon = 'icons/mob/large-worn-icons/64x64/head.dmi'
flags = 0
armor = list(melee = 60, bullet = 60, laser = 60, energy = 50, bomb = 70, bio = 50, rad = 50) //religion protects you from disease and radiation, honk.
worn_x_dimension = 64
worn_y_dimension = 64
- var/side = "neither"
-
-/obj/item/clothing/head/helmet/plate/crusader/prophet/equipped(mob/living/carbon/user, slot)
- var/faithful = 0
- if(slot == slot_head)
- switch(side)
- if("blue")
- faithful = is_handofgod_bluecultist(user)
- if("red")
- faithful = is_handofgod_redcultist(user)
- else
- faithful = 1
- if(!faithful)
- user << "Your mind is assaulted by a vast power, furious at your desecration!"
- user.emote("scream")
- user.adjustFireLoss(10)
- user.unEquip(src)
- user.head = null
- user.update_inv_head()
- src.screen_loc = null
- user.Weaken(1)
/obj/item/clothing/head/helmet/plate/crusader/prophet/red
icon_state = "prophet-red"
- side = "red"
-
/obj/item/clothing/head/helmet/plate/crusader/prophet/blue
icon_state = "prophet-blue"
- side = "blue"
-
-
-/obj/item/clothing/head/helmet/plate/crusader/prophet/examine(mob/user)
- ..()
- if(!is_handofgod_cultist(user))
- user << "A brownish, religious-looking hat."
- else
- user << "A hat bestowed upon a prophet of gods and demigods."
- user << "This hat belongs to the [side] god."
-
-
//Structure conversion staff
/obj/item/weapon/godstaff
name = "godstaff"
+ desc = "It's a stick..?"
icon_state = "godstaff-red"
- var/mob/camera/god/god = null
+ var/conversion_color = "#ffffff"
var/staffcooldown = 0
var/staffwait = 30
-/obj/item/weapon/godstaff/examine(mob/user)
- ..()
- if(!is_handofgod_cultist(user))
- user << "It's a stick..?"
- else
- user << "A powerful staff capable of changing the allegiance of god/demigod structures."
-
-
-/obj/item/weapon/godstaff/attack_self(mob/living/carbon/user)
- if((god && !god.is_handofgod_myprophet(user)) || !god)
- user << "YOU ARE NOT THE CHOSEN ONE!"
- return
- if(!(istype(user.head, /obj/item/clothing/head/helmet/plate/crusader/prophet)))
- user << "Your connection to your diety isn't strong enough! You must wear your big hat!"
- return
+/obj/item/weapon/godstaff/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
if(staffcooldown + staffwait > world.time)
return
- user.visible_message("[user] chants deeply and waves their staff")
+ user.visible_message("[user] chants deeply and waves their staff!")
if(do_after(user, 20,1,src))
- for(var/obj/structure/divine/R in orange(3,user))
- user.say("Grant us true sight my god!")
- if(istype(R, /obj/structure/divine/nexus)|| istype(R, /obj/structure/divine/trap))
- continue
- R.visible_message("[R] suddenly appears!")
- R.invisibility = 0
- R.alpha = initial(R.alpha)
- R.density = initial(R.density)
- R.activate()
+ target.color = conversion_color //wololo
staffcooldown = world.time
/obj/item/weapon/godstaff/red
icon_state = "godstaff-red"
+ conversion_color = "#ff0000"
/obj/item/weapon/godstaff/blue
icon_state = "godstaff-blue"
-
-
+ conversion_color = "#0000ff"
/obj/item/clothing/gloves/plate
name = "Plate Gauntlets"
icon_state = "crusader"
+ desc = "They're like gloves, but made of metal."
siemens_coefficient = 0
cold_protection = HANDS
min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT
heat_protection = HANDS
max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT
-
/obj/item/clothing/gloves/plate/red
icon_state = "crusader-red"
/obj/item/clothing/gloves/plate/blue
icon_state = "crusader-blue"
-
-/obj/item/clothing/gloves/plate/examine(mob/user)
- ..()
- if(!is_handofgod_cultist(user))
- usr << "They're like gloves, but made of metal."
- else
- usr << "Protective gloves that are also blessed to protect from heat and shock."
-
-
/obj/item/clothing/shoes/plate
name = "Plate Boots"
+ desc = "Metal boots, they look heavy."
icon_state = "crusader"
w_class = 3 //normal
armor = list(melee = 50, bullet = 50, laser = 50, energy = 40, bomb = 60, bio = 0, rad = 0) //does this even do anything on boots?
@@ -268,14 +158,6 @@
icon_state = "crusader-blue"
-/obj/item/clothing/shoes/plate/examine(mob/user)
- ..()
- if(!is_handofgod_cultist(user))
- usr << "Metal boots, they look heavy."
- else
- usr << "Heavy boots that are blessed for sure footing. You'll be safe from being taken down by the heresy that is the banana peel."
-
-
/obj/item/weapon/storage/box/itemset/crusader
name = "Crusader's Armour Set" //i can't into ck2 references
desc = "This armour is said to be based on the armor of kings on another world thousands of years ago, who tended to assassinate, conspire, and plot against everyone who tried to do the same to them. Some things never change."
@@ -301,6 +183,7 @@
new /obj/item/clothing/shoes/plate/red(src)
-/obj/item/weapon/claymore/hog
+/obj/item/weapon/claymore/weak
+ desc = "This one is rusted."
force = 30
armour_penetration = 15
\ No newline at end of file
diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm
index 5e8b75b987a..5f1e514cde7 100644
--- a/code/game/objects/items/robot/robot_items.dm
+++ b/code/game/objects/items/robot/robot_items.dm
@@ -10,15 +10,16 @@
icon_state = "elecarm"
var/charge_cost = 30
-/obj/item/borg/stun/attack(mob/living/M, mob/living/silicon/robot/user)
+/obj/item/borg/stun/attack(mob/living/M, mob/living/user)
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.check_shields(0, "[M]'s [name]", src, MELEE_ATTACK))
playsound(M, 'sound/weapons/Genhit.ogg', 50, 1)
return 0
-
- if(!user.cell.use(charge_cost))
- return
+ if(isrobot(user))
+ var/mob/living/silicon/robot/R = user
+ if(!R.cell.use(charge_cost))
+ return
user.do_attack_animation(M)
M.Weaken(5)
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index 1622d8cb791..86bbfa50683 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -6,6 +6,7 @@
* Cloth
* Cardboard
* Runed Metal (cult)
+ * Brass (clockwork cult)
*/
/*
@@ -61,6 +62,10 @@ var/global/list/datum/stack_recipe/metal_recipes = list ( \
flags = CONDUCT
origin_tech = "materials=1"
+/obj/item/stack/sheet/metal/ratvar_act()
+ new /obj/item/stack/sheet/brass(loc, amount)
+ qdel(src)
+
/obj/item/stack/sheet/metal/narsie_act()
if(prob(20))
new /obj/item/stack/sheet/runed_metal(loc, amount)
@@ -236,11 +241,15 @@ var/global/list/datum/stack_recipe/runed_metal_recipes = list ( \
/obj/item/stack/sheet/runed_metal
name = "runed metal"
desc = "Sheets of cold metal with shifting inscriptions writ upon them."
- singular_name = "runed metal"
+ singular_name = "runed metal sheet"
icon_state = "sheet-runed"
icon = 'icons/obj/items.dmi'
sheettype = "runed"
+/obj/item/stack/sheet/runed_metal/ratvar_act()
+ new /obj/item/stack/sheet/brass(loc, amount)
+ qdel(src)
+
/obj/item/stack/sheet/runed_metal/attack_self(mob/living/user)
if(!iscultist(user))
user << "Only one with forbidden knowledge could hope to work this metal..."
@@ -260,6 +269,36 @@ var/global/list/datum/stack_recipe/runed_metal_recipes = list ( \
recipes = runed_metal_recipes
return ..()
+/*
+ * Metal
+ */
+var/global/list/datum/stack_recipe/brass_recipes = list ( \
+ new/datum/stack_recipe("wall gear", /obj/structure/destructible/clockwork/wall_gear, 3, time = 30, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("pinion airlock", /obj/machinery/door/airlock/clockwork, 5, time = 50, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("brass pinion airlock", /obj/machinery/door/airlock/clockwork/brass, 5, time = 50, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("brass windoor", /obj/machinery/door/window/clockwork, 2, time = 30, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("directional brass window", /obj/structure/window/reinforced/clockwork, time = 15, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("brass window", /obj/structure/window/reinforced/clockwork/fulltile, 2, time = 30, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("brass table frame", /obj/structure/table_frame/brass, 1, time = 5, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe("brass floor tile", /obj/item/stack/tile/brass, 1, 1, 50) \
+)
+
+/obj/item/stack/sheet/brass
+ name = "brass"
+ desc = "Sheets made out of brass."
+ singular_name = "brass sheet"
+ icon_state = "sheet-brass"
+ throwforce = 10
+
+/obj/item/stack/sheet/brass/narsie_act()
+ if(prob(20))
+ new /obj/item/stack/sheet/runed_metal(loc, amount)
+ qdel(src)
+
+/obj/item/stack/sheet/brass/New(var/loc, var/amount=null)
+ recipes = brass_recipes
+ return ..()
+
/obj/item/stack/sheet/lessergem
name = "lesser gems"
desc = "Rare kind of gems which are only gained by blood sacrifice to minor deities. They are needed in crafting powerful objects."
diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm
index 2e765ab4e05..74be2659ad9 100644
--- a/code/game/objects/items/stacks/stack.dm
+++ b/code/game/objects/items/stacks/stack.dm
@@ -137,6 +137,7 @@
if (R.max_res_amount > 1)
var/obj/item/stack/new_item = O
new_item.amount = R.res_amount*multiplier
+ new_item.update_icon()
if(new_item.amount <= 0)//if the stack is empty, i.e it has been merged with an existing stack and has been garbage collected
return
@@ -232,7 +233,7 @@
..()
return
-/obj/item/stack/AltClick(mob/user)
+/obj/item/stack/AltClick(mob/living/user)
if(user.incapacitated())
user << "You can't do that right now!"
return
diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm
index b44b5a9a7cc..4977360b0df 100644
--- a/code/game/objects/items/stacks/tiles/tile_types.dm
+++ b/code/game/objects/items/stacks/tiles/tile_types.dm
@@ -148,6 +148,13 @@
icon_state = "tile_poddark"
turf_type = /turf/open/floor/pod/dark
+/obj/item/stack/tile/brass
+ name = "brass floor tile"
+ singular_name = "brass floor tile"
+ desc = "A brass floor tile. It vibrates slightly."
+ icon_state = "tile_brass"
+ turf_type = /turf/open/floor/clockwork
+
//Plasteel (normal)
/obj/item/stack/tile/plasteel
name = "floor tile"
diff --git a/code/game/objects/items/weapons/dice.dm b/code/game/objects/items/weapons/dice.dm
index b844dad596a..001ae42f67d 100644
--- a/code/game/objects/items/weapons/dice.dm
+++ b/code/game/objects/items/weapons/dice.dm
@@ -108,10 +108,10 @@
/obj/item/weapon/dice/attack_self(mob/user)
diceroll(user)
-/obj/item/weapon/dice/throw_at(atom/target, range, speed, mob/user, spin=1)
+/obj/item/weapon/dice/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0)
if(!..())
return
- diceroll(user)
+ diceroll(thrower)
/obj/item/weapon/dice/proc/diceroll(mob/user)
result = rand(1, sides)
@@ -143,4 +143,4 @@
/obj/item/weapon/dice/update_icon()
cut_overlays()
- add_overlay("[src.icon_state][src.result]")
\ No newline at end of file
+ add_overlay("[src.icon_state][src.result]")
diff --git a/code/game/objects/items/weapons/grenades/grenade.dm b/code/game/objects/items/weapons/grenades/grenade.dm
index 60f8799ae76..c5e24fc13a4 100644
--- a/code/game/objects/items/weapons/grenades/grenade.dm
+++ b/code/game/objects/items/weapons/grenades/grenade.dm
@@ -52,10 +52,10 @@
add_fingerprint(user)
var/turf/bombturf = get_turf(src)
var/area/A = get_area(bombturf)
- var/message = "[ADMIN_LOOKUPFLW(user)]) has primed a [name] for detonation at [ADMIN_COORDJMP(src)]"
+ var/message = "[ADMIN_LOOKUPFLW(user)]) has primed a [name] for detonation at [ADMIN_COORDJMP(bombturf)]"
bombers += message
message_admins(message)
- log_game("[key_name(usr)] has primed a [name] for detonation at [A.name] [COORD(src)].")
+ log_game("[key_name(usr)] has primed a [name] for detonation at [A.name] [COORD(bombturf)].")
if(iscarbon(user))
var/mob/living/carbon/C = user
C.throw_mode_on()
diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm
index 810048f5782..439a3584df0 100644
--- a/code/game/objects/items/weapons/handcuffs.dm
+++ b/code/game/objects/items/weapons/handcuffs.dm
@@ -320,7 +320,7 @@
origin_tech = "engineering=3;combat=1"
var/weaken = 0
-/obj/item/weapon/restraints/legcuffs/bola/throw_at(atom/target, range, speed, mob/thrower, spin)
+/obj/item/weapon/restraints/legcuffs/bola/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0)
if(!..())
return
playsound(src.loc,'sound/weapons/bolathrow.ogg', 75, 1)
diff --git a/code/game/objects/items/weapons/implants/implant_loyality.dm b/code/game/objects/items/weapons/implants/implant_loyality.dm
index c669b279ccc..fe9a59d0df5 100644
--- a/code/game/objects/items/weapons/implants/implant_loyality.dm
+++ b/code/game/objects/items/weapons/implants/implant_loyality.dm
@@ -32,7 +32,7 @@
return -1
if(target.mind in ticker.mode.revolutionaries)
ticker.mode.remove_revolutionary(target.mind)
- if((target.mind in ticker.mode.cult) || (target.mind in ticker.mode.blue_deity_prophets|ticker.mode.red_deity_prophets|ticker.mode.red_deity_followers|ticker.mode.blue_deity_followers))
+ if(target.mind in ticker.mode.cult)
target << "You feel something interfering with your mental conditioning, but you resist it!"
else
target << "You feel a sense of peace and security. You are now protected from brainwashing."
@@ -46,7 +46,6 @@
return 1
return 0
-
/obj/item/weapon/implanter/mindshield
name = "implanter (mindshield)"
diff --git a/code/game/objects/items/weapons/kitchen.dm b/code/game/objects/items/weapons/kitchen.dm
index efac43f30ea..ee4a454f671 100644
--- a/code/game/objects/items/weapons/kitchen.dm
+++ b/code/game/objects/items/weapons/kitchen.dm
@@ -121,6 +121,7 @@
desc = "A sharpened bone. The bare mimimum in survival."
force = 15
throwforce = 15
+ materials = list()
/obj/item/weapon/kitchen/knife/combat/cyborg
name = "cyborg knife"
diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm
index 9f93c93eca3..b9d3a17e023 100644
--- a/code/game/objects/items/weapons/melee/energy.dm
+++ b/code/game/objects/items/weapons/melee/energy.dm
@@ -238,7 +238,6 @@
/obj/item/weapon/melee/energy/blade/dropped()
..()
- qdel(src)
/obj/item/weapon/melee/energy/blade/attack_self(mob/user)
return
diff --git a/code/game/objects/items/weapons/melee/misc.dm b/code/game/objects/items/weapons/melee/misc.dm
index 3f35613f442..6c20ea10f6f 100644
--- a/code/game/objects/items/weapons/melee/misc.dm
+++ b/code/game/objects/items/weapons/melee/misc.dm
@@ -1,6 +1,7 @@
/obj/item/weapon/melee
needs_permit = 1
+
/obj/item/weapon/melee/chainofcommand
name = "chain of command"
desc = "A tool used by great men to placate the frothing masses."
@@ -20,6 +21,17 @@
user.visible_message("[user] is strangling \himself with the [src.name]! It looks like \he's trying to commit suicide.")
return (OXYLOSS)
+/obj/item/weapon/melee/synthetic_arm_blade
+ name = "synthetic arm blade"
+ desc = "A grotesque blade that on closer inspection seems made of synthentic flesh, it still feels like it would hurt very badly as a weapon."
+ icon = 'icons/obj/weapons.dmi'
+ icon_state = "arm_blade"
+ item_state = "arm_blade"
+ origin_tech = "combat=5,biotech=5"
+ w_class = 5.0
+ force = 15
+ throwforce = 10
+ sharpness = IS_SHARP
/obj/item/weapon/melee/sabre
name = "officer's sabre"
@@ -27,6 +39,7 @@
icon_state = "sabre"
item_state = "sabre"
flags = CONDUCT
+ unique_rename = 1
force = 15
throwforce = 10
w_class = 4
diff --git a/code/game/objects/items/weapons/mop.dm b/code/game/objects/items/weapons/mop.dm
index 2f4c84ba913..feeab19e611 100644
--- a/code/game/objects/items/weapons/mop.dm
+++ b/code/game/objects/items/weapons/mop.dm
@@ -1,5 +1,3 @@
-#define is_cleanable(A) (istype(A, /obj/effect/decal/cleanable) || istype(A, /obj/effect/rune))
-
/obj/item/weapon/mop
desc = "The world of janitalia wouldn't be complete without a mop."
name = "mop"
@@ -42,16 +40,14 @@ obj/item/weapon/mop/proc/clean(turf/A)
user << "Your mop is dry!"
return
- var/turf/turf = A
- if(is_cleanable(A))
- turf = A.loc
+ var/turf/T = get_turf(A)
- if(istype(turf))
- user.visible_message("[user] begins to clean \the [turf] with [src].", "You begin to clean \the [turf] with [src]...")
+ if(T)
+ user.visible_message("[user] begins to clean \the [T] with [src].", "You begin to clean \the [T] with [src]...")
- if(do_after(user, src.mopspeed, target = turf))
+ if(do_after(user, src.mopspeed, target = T))
user << "You finish mopping."
- clean(turf)
+ clean(T)
/obj/effect/attackby(obj/item/I, mob/user, params)
diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm
index 0fbd8d72b33..21014fb080d 100644
--- a/code/game/objects/items/weapons/storage/backpack.dm
+++ b/code/game/objects/items/weapons/storage/backpack.dm
@@ -58,7 +58,7 @@
playsound(src, alt_sound, 40, 1)
else
playsound(src, pshoom, 40, 1)
- user.Beam(dest_object,icon_state="rped_upgrade",icon='icons/effects/effects.dmi',time=5)
+ user.Beam(dest_object,icon_state="rped_upgrade",time=5)
return 1
user << "The [src.name] buzzes."
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm
index d9a8e0e779a..c7c2889afb2 100644
--- a/code/game/objects/items/weapons/storage/storage.dm
+++ b/code/game/objects/items/weapons/storage/storage.dm
@@ -121,7 +121,7 @@
is_seeing |= user
-/obj/item/weapon/storage/throw_at(atom/target, range, speed, mob/thrower, spin)
+/obj/item/weapon/storage/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0)
close_all()
return ..()
diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm
index 9f27404afae..38ade34e247 100644
--- a/code/game/objects/items/weapons/storage/uplink_kits.dm
+++ b/code/game/objects/items/weapons/storage/uplink_kits.dm
@@ -2,7 +2,7 @@
/obj/item/weapon/storage/box/syndicate/New()
..()
- switch (pickweight(list("bloodyspai" = 3, "stealth" = 2, "bond" = 2, "screwed" = 2, "sabotage" = 3, "guns" = 2, "murder" = 2, "implant" = 1, "hacker" = 3, "lordsingulo" = 1, "darklord" = 1, "sniper" = 1, "metaops" = 1)))
+ switch (pickweight(list("bloodyspai" = 3, "stealth" = 2, "bond" = 2, "screwed" = 2, "sabotage" = 3, "guns" = 2, "murder" = 2, "implant" = 1, "hacker" = 3, "lordsingulo" = 1, "darklord" = 1, "sniper" = 1, "metaops" = 1, "ninja" = 1)))
if("bloodyspai") // 27 tc now this is more right
new /obj/item/clothing/under/chameleon(src) // 2 tc since it's not the full set
new /obj/item/clothing/mask/chameleon(src) // Goes with above
@@ -131,6 +131,19 @@
new /obj/item/weapon/grenade/plastic/c4 (src) // 1 tc
new /obj/item/weapon/card/emag(src) // 6 tc
return
+
+ if("ninja") // 33 tc worth
+ new /obj/item/weapon/katana(src) // Unique , hard to tell how much tc this is worth. 8 tc?
+ new /obj/item/weapon/implanter/adrenalin(src) // 8 tc
+ new /obj/item/weapon/throwing_star(src) // ~5 tc for all 6
+ new /obj/item/weapon/throwing_star(src)
+ new /obj/item/weapon/throwing_star(src)
+ new /obj/item/weapon/throwing_star(src)
+ new /obj/item/weapon/throwing_star(src)
+ new /obj/item/weapon/throwing_star(src)
+ new /obj/item/weapon/storage/belt/military/assault(src) // 3 tc
+ new /obj/item/weapon/card/id/syndicate(src) // 2 tc
+ new /obj/item/device/chameleon(src) // 7 tc
/obj/item/weapon/storage/box/syndie_kit
name = "box"
diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm
index 91dc8cbc17b..1b71da0cdf6 100644
--- a/code/game/objects/items/weapons/stunbaton.dm
+++ b/code/game/objects/items/weapons/stunbaton.dm
@@ -26,7 +26,8 @@
/obj/item/weapon/melee/baton/throw_impact(atom/hit_atom)
..()
- if(status && prob(throw_hit_chance))
+ //Only mob/living types have stun handling
+ if(status && prob(throw_hit_chance) && isliving(hit_atom))
baton_stun(hit_atom)
/obj/item/weapon/melee/baton/loaded/New() //this one starts with a cell pre-installed.
@@ -113,6 +114,7 @@
if(isrobot(M))
..()
return
+
if(!isliving(M))
return
diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm
index 0434b288c9c..07d09d07451 100644
--- a/code/game/objects/items/weapons/weaponry.dm
+++ b/code/game/objects/items/weapons/weaponry.dm
@@ -1,3 +1,28 @@
+/obj/item/weapon
+
+ var/unique_rename = 0 //allows renaming with a pen
+
+/obj/item/weapon/examine(mob/user)
+ ..()
+ if(unique_rename)
+ user << "Use a pen on it to rename it."
+
+/obj/item/weapon/attackby(obj/item/I, mob/user, params)
+ if(unique_rename)
+ if(istype(I, /obj/item/weapon/pen))
+ rename_weapon(user)
+ ..()
+
+/obj/item/weapon/proc/rename_weapon(mob/M)
+ var/input = stripped_input(M,"What do you want to name the weapon?", ,"", MAX_NAME_LEN)
+
+ if(src && input && !M.stat && in_range(M,src) && !M.restrained() && M.canmove)
+ name = input
+ M << "You name the weapon [input]. Say hello to your new friend."
+ return
+
+
+
/obj/item/weapon/banhammer
desc = "A banhammer"
name = "banhammer"
@@ -57,10 +82,14 @@
var/highlander_claymores = 0
/obj/item/weapon/claymore/highlander //ALL COMMENTS MADE REGARDING THIS SWORD MUST BE MADE IN ALL CAPS
desc = "THERE CAN BE ONLY ONE, AND IT WILL BE YOU!!!\nActivate it in your hand to point to the nearest victim."
+ flags = CONDUCT | NODROP
+ slot_flags = null
block_chance = 0 //RNG WON'T HELP YOU NOW, PANSY
- attack_verb = list("brutalized", "eviscerated", "disemboweled", "hacked", "carved", "cleaved", "gored") //ONLY THE MOST VISCERAL ATTACK VERBS
+ attack_verb = list("brutalized", "eviscerated", "disemboweled", "hacked", "carved", "cleaved") //ONLY THE MOST VISCERAL ATTACK VERBS
var/notches = 0 //HOW MANY PEOPLE HAVE BEEN SLAIN WITH THIS BLADE
var/announced = FALSE //IF WE ARE THE ONLY ONE LEFT STANDING
+ var/bloodthirst_level = 0 //HOW THIRSTY WE ARE FOR BLOOD
+ var/obj/item/weapon/disk/nuclear/nuke_disk //OUR STORED NUKE DISK
/obj/item/weapon/claymore/highlander/New()
..()
@@ -70,19 +99,27 @@ var/highlander_claymores = 0
/obj/item/weapon/claymore/highlander/Destroy()
STOP_PROCESSING(SSobj, src)
highlander_claymores--
+ if(nuke_disk)
+ nuke_disk.forceMove(get_turf(src))
+ nuke_disk.visible_message("The nuke disk is vulnerable!")
+ nuke_disk = null
return ..()
/obj/item/weapon/claymore/highlander/process()
if(isliving(loc))
var/mob/living/L = loc
if(L.stat != DEAD)
+ if(!announced)
+ handle_bloodthirst(L)
if(announced || admin_spawned || highlander_claymores > 1)
return
announced = TRUE
L.fully_heal()
- world << "[L.real_name] IS THE ONLY ONE LEFT STANDING!"
+ world << "[uppertext(L.real_name)] IS THE ONLY ONE LEFT STANDING!"
world << sound('sound/misc/highlander_only_one.ogg')
L << "YOU ARE THE ONLY ONE LEFT STANDING!"
+ for(var/obj/item/weapon/bloodcrawl/B in L)
+ qdel(B)
/obj/item/weapon/claymore/highlander/pickup(mob/living/user)
user << "The power of Scotland protects you! You are shielded from all stuns and knockdowns."
@@ -95,12 +132,18 @@ var/highlander_claymores = 0
/obj/item/weapon/claymore/highlander/examine(mob/user)
..()
user << "It has [!notches ? "nothing" : "[notches] notches"] scratched into the blade."
+ if(nuke_disk)
+ user << "It's holding the nuke disk!"
/obj/item/weapon/claymore/highlander/attack(mob/living/target, mob/living/user)
var/old_target_stat = target.stat
. = ..()
+ bloodthirst_level = max(bloodthirst_level - (target.mind && target.mind.special_role == "highlander" ? 15 : 5), 0)
if(target && target.stat == DEAD && old_target_stat != DEAD && target.mind && target.mind.special_role == "highlander")
user.fully_heal() //STEAL THE LIFE OF OUR FALLEN FOES
+ if(bloodthirst_level >= 30)
+ user << "[src] shakes greedily as it devours [target]'s soul. Its bloodthirst is quenched for the moment..."
+ bloodthirst_level = 0
add_notch(user)
target.visible_message("[target] crumbles to dust beneath [user]'s blows!", "As you fall, your body crumbles to dust!")
target.dust()
@@ -113,6 +156,7 @@ var/highlander_claymores = 0
closest_victim = H
if(!closest_victim)
user << "[src] thrums for a moment and falls dark. Perhaps there's nobody nearby."
+ return
user << "[src] thrums and points to the [dir2text(get_dir(user, closest_victim))]."
/obj/item/weapon/claymore/highlander/IsReflect()
@@ -171,6 +215,22 @@ var/highlander_claymores = 0
name = new_name
playsound(user, 'sound/items/Screwdriver2.ogg', 50, 1)
+/obj/item/weapon/claymore/highlander/proc/handle_bloodthirst(mob/living/S) //THE BLADE THIRSTS FOR BLOOD AND WILL PUNISH THE WEAK OR PACIFISTIC
+ bloodthirst_level += (1 + min(notches, 10))
+ if(bloodthirst_level == 30)
+ S << "[src] shudders in your hand. It hungers for battle..."
+ if(bloodthirst_level == 60)
+ S << "[src] trembles violently. Kill someone already!"
+ if(bloodthirst_level == 90)
+ S << "[src] starts shaking viciously! Shed blood or it'll give you away!"
+ if(bloodthirst_level >= 120)
+ var/turf/T = get_turf(S)
+ for(var/mob/M in player_list - S)
+ if(M.z == T.z)
+ M << "THERE IS A COWARD WHO DOES NOT FIGHT TO THE [uppertext(dir2text(get_dir(M, T)))]. THEIR NAME IS [uppertext(S.real_name)] - SLAUGHTER THEM."
+ S << "you fucked up"
+ bloodthirst_level = 100
+
/obj/item/weapon/katana
name = "katana"
desc = "Woefully underpowered in D20"
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index 094eb17671c..89a48c7c22c 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -35,7 +35,8 @@
STOP_PROCESSING(SSobj, src) // TODO: Have a processing bitflag to reduce on unnecessary loops through the processing lists
SStgui.close_uis(src)
return ..()
-/obj/throw_at()
+
+/obj/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0)
..()
if(is_frozen)
visible_message("[src] shatters into a million pieces!")
@@ -215,10 +216,10 @@
if(burn)
Item.fire_act() //Set them on fire, too
-/obj/proc/tesla_act(var/power)
+/obj/proc/tesla_act(power, explosive = FALSE)
being_shocked = 1
var/power_bounced = power / 2
- tesla_zap(src, 3, power_bounced)
+ tesla_zap(src, 3, power_bounced, explosive)
addtimer(src, "reset_shocked", 10)
/obj/proc/reset_shocked()
@@ -228,4 +229,4 @@
. = !density
/obj/proc/check_uplink_validity()
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/objects/structures/divine.dm b/code/game/objects/structures/divine.dm
new file mode 100644
index 00000000000..51415356960
--- /dev/null
+++ b/code/game/objects/structures/divine.dm
@@ -0,0 +1,46 @@
+/obj/structure/sacrificealtar
+ name = "sacrificial altar"
+ desc = "An altar designed to perform blood sacrifice for a deity."
+ icon = 'icons/obj/hand_of_god_structures.dmi'
+ icon_state = "sacrificealtar"
+ anchored = 1
+ density = 0
+ can_buckle = 1
+
+/obj/structure/sacrificealtar/attack_hand(mob/living/user)
+ ..()
+ if(!has_buckled_mobs())
+ return
+ var/mob/living/L = locate() in buckled_mobs
+ if(!L)
+ return
+ user << "You attempt to sacrifice [L] by invoking the sacrificial ritual."
+ L.gib()
+ message_admins("[key_name_admin(user)] has sacrificed [key_name_admin(L)] on the sacrifical altar.")
+
+/obj/structure/healingfountain
+ name = "healing fountain"
+ desc = "A fountain containing the waters of life."
+ icon = 'icons/obj/hand_of_god_structures.dmi'
+ icon_state = "fountain"
+ anchored = 1
+ density = 1
+ var/time_between_uses = 1800
+ var/last_process = 0
+
+/obj/structure/healingfountain/attack_hand(mob/living/user)
+ if(last_process + time_between_uses > world.time)
+ user << "The fountain appears to be empty."
+ return
+ last_process = world.time
+ user << "The water feels warm and soothing as you touch it. The fountain immediately dries up shortly afterwards."
+ user.reagents.add_reagent("godblood",20)
+ update_icons()
+ addtimer(src, "update_icons", time_between_uses)
+
+
+/obj/structure/healingfountain/proc/update_icons()
+ if(last_process + time_between_uses > world.time)
+ icon_state = "fountain"
+ else
+ icon_state = "fountain-red"
\ No newline at end of file
diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm
index 12ee0f8d277..cd63c5713a8 100644
--- a/code/game/objects/structures/false_walls.dm
+++ b/code/game/objects/structures/false_walls.dm
@@ -7,8 +7,10 @@
anchored = 1
icon = 'icons/turf/walls/wall.dmi'
icon_state = "wall"
- var/mineral = "metal"
- var/walltype = "metal"
+ var/mineral = /obj/item/stack/sheet/metal
+ var/mineral_amount = 2
+ var/walltype = /turf/closed/wall
+ var/girder_type = /obj/structure/girder/displaced
var/opening = 0
density = 1
opacity = 1
@@ -17,9 +19,11 @@
/turf/closed/wall,
/turf/closed/wall/r_wall,
/obj/structure/falsewall,
+ /obj/structure/falsewall/brass,
/obj/structure/falsewall/reinforced,
/turf/closed/wall/rust,
- /turf/closed/wall/r_wall/rust)
+ /turf/closed/wall/r_wall/rust,
+ /turf/closed/wall/clockwork)
smooth = SMOOTH_TRUE
can_be_unanchored = 0
@@ -67,7 +71,7 @@
user.do_attack_animation(src)
playsound(src, 'sound/effects/meteorimpact.ogg', 100, 1)
visible_message("[user] smashes [src] apart!")
- qdel(src)
+ deconstruct()
/obj/structure/falsewall/proc/do_the_flick()
if(density)
@@ -87,10 +91,7 @@
/obj/structure/falsewall/proc/ChangeToWall(delete = 1)
var/turf/T = get_turf(src)
- if(!walltype || walltype == "metal")
- T.ChangeTurf(/turf/closed/wall)
- else
- T.ChangeTurf(text2path("/turf/closed/wall/mineral/[walltype]"))
+ T.ChangeTurf(walltype)
if(delete)
qdel(src)
return T
@@ -117,32 +118,28 @@
else if(istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
if(WT.remove_fuel(0,user))
- dismantle(user)
+ dismantle(user, TRUE)
else if(istype(W, /obj/item/weapon/gun/energy/plasmacutter))
- dismantle(user)
+ dismantle(user, TRUE)
else if(istype(W, /obj/item/weapon/pickaxe/drill/jackhammer))
var/obj/item/weapon/pickaxe/drill/jackhammer/D = W
D.playDigSound()
- dismantle(user)
+ dismantle(user, TRUE)
else
return ..()
-/obj/structure/falsewall/proc/dismantle(mob/user)
+/obj/structure/falsewall/proc/dismantle(mob/user, drop_girder)
user.visible_message("[user] dismantles the false wall.", "You dismantle the false wall.")
- new /obj/structure/girder/displaced(loc)
- if(mineral == "metal")
- if(istype(src, /obj/structure/falsewall/reinforced))
- new /obj/item/stack/sheet/plasteel(loc)
- new /obj/item/stack/sheet/plasteel(loc)
- else
- new /obj/item/stack/sheet/metal(loc)
- new /obj/item/stack/sheet/metal(loc)
- else
- var/P = text2path("/obj/item/stack/sheet/mineral/[mineral]")
- new P(loc)
- new P(loc)
playsound(src, 'sound/items/Welder.ogg', 100, 1)
- qdel(src)
+ deconstruct(drop_girder)
+
+/obj/structure/falsewall/deconstruct(drop_girder)
+ if(drop_girder)
+ new girder_type(loc)
+ if(mineral_amount)
+ for(var/i in 1 to mineral_amount)
+ new mineral(loc)
+ ..()
/obj/structure/falsewall/storage_contents_dump_act(obj/item/weapon/storage/src_object, mob/user)
return 0
@@ -156,14 +153,8 @@
desc = "A huge chunk of reinforced metal used to separate rooms."
icon = 'icons/turf/walls/reinforced_wall.dmi'
icon_state = "r_wall"
- walltype = "rwall"
-
-/obj/structure/falsewall/reinforced/ChangeToWall(delete = 1)
- var/turf/T = get_turf(src)
- T.ChangeTurf(/turf/closed/wall/r_wall)
- if(delete)
- qdel(src)
- return T
+ walltype = /turf/closed/wall/r_wall
+ mineral = /obj/item/stack/sheet/plasteel
/*
* Uranium Falsewalls
@@ -174,8 +165,8 @@
desc = "A wall with uranium plating. This is probably a bad idea."
icon = 'icons/turf/walls/uranium_wall.dmi'
icon_state = "uranium"
- mineral = "uranium"
- walltype = "uranium"
+ mineral = /obj/item/stack/sheet/mineral/uranium
+ walltype = /turf/closed/wall/mineral/uranium
var/active = null
var/last_event = 0
canSmoothWith = list(/obj/structure/falsewall/uranium, /turf/closed/wall/mineral/uranium)
@@ -208,8 +199,8 @@
desc = "A wall with gold plating. Swag!"
icon = 'icons/turf/walls/gold_wall.dmi'
icon_state = "gold"
- mineral = "gold"
- walltype = "gold"
+ mineral = /obj/item/stack/sheet/mineral/gold
+ walltype = /turf/closed/wall/mineral/gold
canSmoothWith = list(/obj/structure/falsewall/gold, /turf/closed/wall/mineral/gold)
/obj/structure/falsewall/silver
@@ -217,8 +208,8 @@
desc = "A wall with silver plating. Shiny."
icon = 'icons/turf/walls/silver_wall.dmi'
icon_state = "silver"
- mineral = "silver"
- walltype = "silver"
+ mineral = /obj/item/stack/sheet/mineral/silver
+ walltype = /turf/closed/wall/mineral/silver
canSmoothWith = list(/obj/structure/falsewall/silver, /turf/closed/wall/mineral/silver)
/obj/structure/falsewall/diamond
@@ -226,8 +217,8 @@
desc = "A wall with diamond plating. You monster."
icon = 'icons/turf/walls/diamond_wall.dmi'
icon_state = "diamond"
- mineral = "diamond"
- walltype = "diamond"
+ mineral = /obj/item/stack/sheet/mineral/diamond
+ walltype = /turf/closed/wall/mineral/diamond
canSmoothWith = list(/obj/structure/falsewall/diamond, /turf/closed/wall/mineral/diamond)
/obj/structure/falsewall/plasma
@@ -235,8 +226,8 @@
desc = "A wall with plasma plating. This is definitely a bad idea."
icon = 'icons/turf/walls/plasma_wall.dmi'
icon_state = "plasma"
- mineral = "plasma"
- walltype = "plasma"
+ mineral = /obj/item/stack/sheet/mineral/plasma
+ walltype = /turf/closed/wall/mineral/plasma
canSmoothWith = list(/obj/structure/falsewall/plasma, /turf/closed/wall/mineral/plasma)
/obj/structure/falsewall/plasma/attackby(obj/item/weapon/W, mob/user, params)
@@ -262,8 +253,8 @@
desc = "A wall with bananium plating. Honk!"
icon = 'icons/turf/walls/bananium_wall.dmi'
icon_state = "bananium"
- mineral = "bananium"
- walltype = "bananium"
+ mineral = /obj/item/stack/sheet/mineral/bananium
+ walltype = /turf/closed/wall/mineral/clown
canSmoothWith = list(/obj/structure/falsewall/clown, /turf/closed/wall/mineral/clown)
@@ -272,8 +263,8 @@
desc = "A wall with sandstone plating. Rough."
icon = 'icons/turf/walls/sandstone_wall.dmi'
icon_state = "sandstone"
- mineral = "sandstone"
- walltype = "sandstone"
+ mineral = /obj/item/stack/sheet/mineral/sandstone
+ walltype = /turf/closed/wall/mineral/sandstone
canSmoothWith = list(/obj/structure/falsewall/sandstone, /turf/closed/wall/mineral/sandstone)
/obj/structure/falsewall/wood
@@ -281,8 +272,8 @@
desc = "A wall with wooden plating. Stiff."
icon = 'icons/turf/walls/wood_wall.dmi'
icon_state = "wood"
- mineral = "wood"
- walltype = "wood"
+ mineral = /obj/item/stack/sheet/mineral/wood
+ walltype = /turf/closed/wall/mineral/wood
canSmoothWith = list(/obj/structure/falsewall/wood, /turf/closed/wall/mineral/wood)
/obj/structure/falsewall/iron
@@ -290,8 +281,8 @@
desc = "A wall with rough metal plating."
icon = 'icons/turf/walls/iron_wall.dmi'
icon_state = "iron"
- mineral = "metal"
- walltype = "iron"
+ mineral = /obj/item/stack/rods
+ walltype = /turf/closed/wall/mineral/iron
canSmoothWith = list(/obj/structure/falsewall/iron, /turf/closed/wall/mineral/iron)
/obj/structure/falsewall/abductor
@@ -299,8 +290,8 @@
desc = "A wall with alien alloy plating."
icon = 'icons/turf/walls/abductor_wall.dmi'
icon_state = "abductor"
- mineral = "abductor"
- walltype = "abductor"
+ mineral = /obj/item/stack/sheet/mineral/abductor
+ walltype = /turf/closed/wall/mineral/abductor
canSmoothWith = list(/obj/structure/falsewall/abductor, /turf/closed/wall/mineral/abductor)
/obj/structure/falsewall/titanium
@@ -308,8 +299,9 @@
desc = "A light-weight titanium wall used in shuttles."
icon = 'icons/turf/walls/shuttle_wall.dmi'
icon_state = "shuttle"
- mineral = "titanium"
- walltype = "shuttle"
+ mineral = /obj/item/stack/sheet/mineral/titanium
+ walltype = /turf/closed/wall/mineral/titanium
+ smooth = SMOOTH_MORE
canSmoothWith = list(/turf/closed/wall/mineral/titanium, /obj/machinery/door/airlock/shuttle, /obj/machinery/door/airlock/, /turf/closed/wall/shuttle, /obj/structure/window/shuttle, /obj/structure/shuttle/engine, /obj/structure/shuttle/engine/heater, )
/obj/structure/falsewall/plastitanium
@@ -317,6 +309,16 @@
desc = "An evil wall of plasma and titanium."
icon = 'icons/turf/shuttle.dmi'
icon_state = "wall3"
- mineral = "plastitanium"
- walltype = "syndieshuttle"
- smooth = SMOOTH_FALSE
\ No newline at end of file
+ mineral = /obj/item/stack/sheet/mineral/plastitanium
+ walltype = /turf/closed/wall/mineral/plastitanium
+ smooth = SMOOTH_FALSE
+
+/obj/structure/falsewall/brass
+ name = "clockwork wall"
+ desc = "A huge chunk of warm metal. The clanging of machinery emanates from within."
+ icon = 'icons/turf/walls/clockwork_wall.dmi'
+ icon_state = "clockwork_wall"
+ mineral_amount = 1
+ girder_type = /obj/structure/destructible/clockwork/wall_gear/displaced
+ walltype = /turf/closed/wall/clockwork
+ mineral = /obj/item/stack/sheet/brass
diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm
index 08a823f44be..a94dd50fe7a 100644
--- a/code/game/objects/structures/flora.dm
+++ b/code/game/objects/structures/flora.dm
@@ -25,6 +25,7 @@
playsound(get_turf(src), 'sound/effects/meteorimpact.ogg', 100 , 0, 0)
icon = 'icons/obj/flora/pinetrees.dmi'
icon_state = "tree_stump"
+ density = 0
pixel_x = -16
name += " stump"
cut = TRUE
diff --git a/code/game/objects/structures/fluff.dm b/code/game/objects/structures/fluff.dm
index c2fa1e72cf6..13ae66801be 100644
--- a/code/game/objects/structures/fluff.dm
+++ b/code/game/objects/structures/fluff.dm
@@ -120,3 +120,43 @@
name = "dense stack of papers"
desc = "A stack of various papers, childish scribbles scattered across each page."
icon_state = "paperstack"
+
+
+/obj/structure/fluff/divine
+ name = "Miracle"
+ icon = 'icons/obj/hand_of_god_structures.dmi'
+ anchored = 1
+ density = 1
+
+/obj/structure/fluff/divine/nexus
+ name = "nexus"
+ desc = "It anchors a deity to this world. It radiates an unusual aura. It looks well protected from explosive shock."
+ icon_state = "nexus-neutral"
+
+/obj/structure/fluff/divine/conduit
+ name = "conduit"
+ desc = "It allows a deity to extend their reach. Their powers are just as potent near a conduit as a nexus."
+ icon_state = "conduit-neutral"
+
+/obj/structure/fluff/divine/convertaltar
+ name = "conversion altar"
+ desc = "An altar dedicated to a deity."
+ icon_state = "convertaltar-neutral"
+ density = 0
+ can_buckle = 1
+
+/obj/structure/fluff/divine/powerpylon
+ name = "power pylon"
+ desc = "A pylon which increases the deity's rate it can influence the world."
+ icon_state = "powerpylon"
+ can_buckle = 1
+
+/obj/structure/fluff/divine/defensepylon
+ name = "defense pylon"
+ desc = "A pylon which is blessed to withstand many blows, and fire strong bolts at nonbelievers. A god can toggle it."
+ icon_state = "defensepylon"
+
+/obj/structure/fluff/divine/shrine
+ name = "shrine"
+ desc = "A shrine dedicated to a deity."
+ icon_state = "shrine"
\ No newline at end of file
diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm
index 6f92b8c0657..c6284f25056 100644
--- a/code/game/objects/structures/grille.dm
+++ b/code/game/objects/structures/grille.dm
@@ -271,9 +271,9 @@
if(dist <= 3)
closest_mob = A
if(closest_mob)
- var/shock_damage = C.powernet.avail * 0.08
- src.Beam(closest_mob, icon_state="lightning[rand(1,12)]", icon='icons/effects/effects.dmi', time=5)
- closest_mob.electrocute_act(shock_damage, src, 1, tesla_shock = 1)//ZAP for 1/5000 of the amount of power, which is from 15-25 with 200000W
+ var/shock_damage = C.powernet.avail * 0.0002//setting shock damage for later. equals 1/5000 the power in the grid
+ src.Beam(closest_mob, icon_state="lightning[rand(1,12)]", time=5)
+ closest_mob.electrocute_act(shock_damage, src, 1)//ZAP, damage should be about 40 with 200000W
playsound(src.loc, 'sound/magic/LightningShock.ogg', 100, 1, extrarange = 5)
take_damage(tforce)
diff --git a/code/game/objects/structures/kitchen_spike.dm b/code/game/objects/structures/kitchen_spike.dm
index 042ce6b307d..56e81172352 100644
--- a/code/game/objects/structures/kitchen_spike.dm
+++ b/code/game/objects/structures/kitchen_spike.dm
@@ -20,6 +20,22 @@
var/obj/F = new /obj/structure/kitchenspike(src.loc,)
transfer_fingerprints_to(F)
qdel(src)
+ else if(istype(I, /obj/item/weapon/weldingtool))
+ var/obj/item/weapon/weldingtool/WT = I
+ if(!WT.remove_fuel(0, user))
+ return
+ user << "You begin cutting \the [src] apart..."
+ playsound(src.loc, "sound/items/Welder.ogg", 40, 1)
+ if(do_after(user, 40/WT.toolspeed, 1, target = src))
+ if(!WT.isOn())
+ return
+ playsound(src.loc, "sound/items/Welder.ogg", 50, 1)
+ visible_message("[user] slices apart \the [src].",
+ "You cut \the [src] apart with \the [WT].",
+ "You hear welding.")
+ new /obj/item/stack/sheet/metal(src.loc, 4)
+ qdel(src)
+ return
else
return ..()
diff --git a/code/game/objects/structures/mineral_doors.dm b/code/game/objects/structures/mineral_doors.dm
index bd4e5504385..317ba4e9a37 100644
--- a/code/game/objects/structures/mineral_doors.dm
+++ b/code/game/objects/structures/mineral_doors.dm
@@ -2,7 +2,7 @@
//machineryness
/obj/structure/mineral_door
- name = "mineral door"
+ name = "metal door"
density = 1
anchored = 1
opacity = 1
@@ -10,21 +10,20 @@
icon = 'icons/obj/doors/mineral_doors.dmi'
icon_state = "metal"
- var/mineralType = "metal"
+ var/initial_state
var/state = 0 //closed, 1 == open
var/isSwitchingStates = 0
var/close_delay = -1 //-1 if does not auto close.
var/hardness = 1
- var/oreAmount = 7
+ var/sheetType = /obj/item/stack/sheet/metal
+ var/sheetAmount = 7
var/openSound = 'sound/effects/stonedoor_openclose.ogg'
var/closeSound = 'sound/effects/stonedoor_openclose.ogg'
/obj/structure/mineral_door/New(location)
..()
- icon_state = mineralType
- name = "[mineralType] door"
+ initial_state = icon_state
air_update_turf(1)
- return
/obj/structure/mineral_door/Destroy()
density = 0
@@ -40,7 +39,6 @@
..()
if(!state)
return TryToSwitchState(user)
- return
/obj/structure/mineral_door/attack_ai(mob/user) //those aren't machinery, they're just big fucking slabs of a mineral
if(isAI(user)) //so the AI can't open it
@@ -64,10 +62,12 @@
return !density
/obj/structure/mineral_door/proc/TryToSwitchState(atom/user)
- if(isSwitchingStates) return
+ if(isSwitchingStates)
+ return
if(isliving(user))
var/mob/living/M = user
- if(world.time - M.last_bumped <= 60) return //NOTE do we really need that?
+ if(world.time - M.last_bumped <= 60)
+ return //NOTE do we really need that?
if(M.client)
if(iscarbon(M))
var/mob/living/carbon/C = M
@@ -87,7 +87,7 @@
/obj/structure/mineral_door/proc/Open()
isSwitchingStates = 1
playsound(loc, openSound, 100, 1)
- flick("[mineralType]opening",src)
+ flick("[initial_state]opening",src)
sleep(10)
density = 0
opacity = 0
@@ -97,17 +97,17 @@
isSwitchingStates = 0
if(close_delay != -1)
- spawn(close_delay)
- if(!isSwitchingStates && state == 1)
- Close()
+ addtimer(src, "Close", close_delay)
/obj/structure/mineral_door/proc/Close()
+ if(isSwitchingStates || state != 1)
+ return
var/turf/T = get_turf(src)
for(var/mob/living/L in T)
return
isSwitchingStates = 1
playsound(loc, closeSound, 100, 1)
- flick("[mineralType]closing",src)
+ flick("[initial_state]closing",src)
sleep(10)
density = 1
opacity = 1
@@ -118,9 +118,9 @@
/obj/structure/mineral_door/update_icon()
if(state)
- icon_state = "[mineralType]open"
+ icon_state = "[initial_state]open"
else
- icon_state = mineralType
+ icon_state = initial_state
/obj/structure/mineral_door/attackby(obj/item/weapon/W, mob/user, params)
if(istype(W,/obj/item/weapon/pickaxe))
@@ -144,32 +144,19 @@
hardness -= Proj.damage
..()
CheckHardness()
- return
-
/obj/structure/mineral_door/proc/CheckHardness()
if(hardness <= 0)
Dismantle(1)
/obj/structure/mineral_door/proc/Dismantle(devastated = 0)
+ var/turf/T = get_turf(src)
if(!devastated)
- if (mineralType == "metal")
- var/ore = /obj/item/stack/sheet/metal
- for(var/i = 1, i <= oreAmount, i++)
- new ore(get_turf(src))
- else
- var/ore = text2path("/obj/item/stack/sheet/mineral/[mineralType]")
- for(var/i = 1, i <= oreAmount, i++)
- new ore(get_turf(src))
+ for(var/i in 1 to sheetAmount)
+ new sheetType(T)
else
- if (mineralType == "metal")
- var/ore = /obj/item/stack/sheet/metal
- for(var/i = 3, i <= oreAmount, i++)
- new ore(get_turf(src))
- else
- var/ore = text2path("/obj/item/stack/sheet/mineral/[mineralType]")
- for(var/i = 3, i <= oreAmount, i++)
- new ore(get_turf(src))
+ for(var/i in 3 to sheetAmount)
+ new sheetType(T)
qdel(src)
/obj/structure/mineral_door/ex_act(severity = 1)
@@ -185,28 +172,34 @@
if(3)
hardness -= 0.1
CheckHardness()
- return
-
/obj/structure/mineral_door/iron
- mineralType = "metal"
+ name = "iron door"
hardness = 3
/obj/structure/mineral_door/silver
- mineralType = "silver"
+ name = "silver door"
+ icon_state = "silver"
+ sheetType = /obj/item/stack/sheet/mineral/silver
hardness = 3
/obj/structure/mineral_door/gold
- mineralType = "gold"
+ name = "gold door"
+ icon_state = "gold"
+ sheetType = /obj/item/stack/sheet/mineral/gold
/obj/structure/mineral_door/uranium
- mineralType = "uranium"
+ name = "uranium door"
+ icon_state = "uranium"
+ sheetType = /obj/item/stack/sheet/mineral/uranium
hardness = 3
luminosity = 2
/obj/structure/mineral_door/sandstone
- mineralType = "sandstone"
+ name = "sandstone door"
+ icon_state = "sandstone"
+ sheetType = /obj/item/stack/sheet/mineral/sandstone
hardness = 0.5
/obj/structure/mineral_door/transparent
@@ -217,39 +210,38 @@
opacity = 0
/obj/structure/mineral_door/transparent/plasma
- mineralType = "plasma"
+ name = "plasma door"
+ icon_state = "plasma"
+ sheetType = /obj/item/stack/sheet/mineral/plasma
/obj/structure/mineral_door/transparent/plasma/attackby(obj/item/weapon/W, mob/user, params)
if(W.is_hot())
message_admins("Plasma mineral door ignited by [key_name_admin(user)](?) (FLW) in ([x],[y],[z] - JMP)",0,1)
log_game("Plasma mineral door ignited by [key_name(user)] in ([x],[y],[z])")
- TemperatureAct(100)
+ TemperatureAct()
else
return ..()
/obj/structure/mineral_door/transparent/plasma/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
if(exposed_temperature > 300)
- TemperatureAct(exposed_temperature)
+ TemperatureAct()
-/obj/structure/mineral_door/transparent/plasma/proc/TemperatureAct(temperature)
+/obj/structure/mineral_door/transparent/plasma/proc/TemperatureAct()
atmos_spawn_air("plasma=500;TEMP=1000")
- hardness = 0
- CheckHardness()
+ Dismantle(1)
/obj/structure/mineral_door/transparent/diamond
- mineralType = "diamond"
+ name = "diamond door"
+ icon_state = "diamond"
+ sheetType = /obj/item/stack/sheet/mineral/diamond
hardness = 10
/obj/structure/mineral_door/wood
- mineralType = "wood"
+ name = "wood door"
+ icon_state = "wood"
hardness = 1
openSound = 'sound/effects/doorcreaky.ogg'
closeSound = 'sound/effects/doorcreaky.ogg'
+ sheetType = /obj/item/stack/sheet/mineral/wood
burn_state = FLAMMABLE
burntime = 30
-
-/obj/structure/mineral_door/wood/Dismantle(devastated = 0)
- if(!devastated)
- for(var/i = 1, i <= oreAmount, i++)
- new/obj/item/stack/sheet/mineral/wood(get_turf(src))
- qdel(src)
diff --git a/code/game/objects/structures/table_frames.dm b/code/game/objects/structures/table_frames.dm
index 5115443a8bf..e5ead848f85 100644
--- a/code/game/objects/structures/table_frames.dm
+++ b/code/game/objects/structures/table_frames.dm
@@ -125,7 +125,21 @@
name = "brass table frame"
desc = "Four pieces of brass arranged in a square. It's slightly warm to the touch."
icon_state = "brass_frame"
- framestackamount = 0
+ framestack = /obj/item/stack/sheet/brass
+ framestackamount = 1
+
+/obj/structure/table_frame/brass/attackby(obj/item/I, mob/user, params)
+ if(istype(I, /obj/item/stack/sheet/brass))
+ var/obj/item/stack/sheet/brass/W = I
+ if(W.get_amount() < 1)
+ user << "You need one brass sheet to do this!"
+ return
+ user << "You start adding [W] to [src]..."
+ if(do_after(user, 20, target = src) && W.use(1))
+ new /obj/structure/table/reinforced/brass(src.loc)
+ qdel(src)
+ else
+ return ..()
/obj/structure/table_frame/brass/narsie_act()
..()
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index f2aad755601..9a9e11d2091 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -391,14 +391,12 @@
icon = 'icons/obj/smooth_structures/brass_table.dmi'
icon_state = "brass_table"
frame = /obj/structure/table_frame/brass
- framestackamount = 0
- buildstackamount = 0
+ framestack = /obj/item/stack/sheet/brass
+ buildstack = /obj/item/stack/sheet/brass
+ framestackamount = 1
+ buildstackamount = 1
canSmoothWith = list(/obj/structure/table/reinforced/brass)
-/obj/structure/table/reinforced/brass/table_destroy()
- new frame(src.loc)
- qdel(src)
-
/obj/structure/table/reinforced/brass/narsie_act()
take_damage(rand(15, 45), BRUTE)
if(src) //do we still exist?
diff --git a/code/game/gamemodes/handofgod/traps.dm b/code/game/objects/structures/traps.dm
similarity index 76%
rename from code/game/gamemodes/handofgod/traps.dm
rename to code/game/objects/structures/traps.dm
index b39475f0ce1..b6c9e0ba7bb 100644
--- a/code/game/gamemodes/handofgod/traps.dm
+++ b/code/game/objects/structures/traps.dm
@@ -1,19 +1,14 @@
-
-/obj/structure/divine/trap
+/obj/structure/trap
name = "IT'S A TARP"
desc = "stepping on me is a guaranteed bad day"
+ icon = 'icons/obj/hand_of_god_structures.dmi'
icon_state = "trap"
density = 0
alpha = 30 //initially quite hidden when not "recharging"
- health = 20
- maxhealth = 20
- trap = TRUE
- autocolours = FALSE
var/last_trigger = 0
var/time_between_triggers = 600 //takes a minute to recharge
-
-/obj/structure/divine/trap/Crossed(atom/movable/AM)
+/obj/structure/trap/Crossed(atom/movable/AM)
if(last_trigger + time_between_triggers > world.time)
return
alpha = initial(alpha)
@@ -24,8 +19,7 @@
trap_effect(L)
animate(src, alpha = initial(alpha), time = time_between_triggers)
-
-/obj/structure/divine/trap/examine(mob/user)
+/obj/structure/trap/examine(mob/user)
..()
if(!isliving(user)) //bad ghosts, stop trying to powergame from beyond the grave
return
@@ -34,17 +28,15 @@
animate(src, alpha = initial(alpha), time = time_between_triggers)
-/obj/structure/divine/trap/proc/trap_effect(mob/living/L)
+/obj/structure/trap/proc/trap_effect(mob/living/L)
return
-
-/obj/structure/divine/trap/stun
+/obj/structure/trap/stun
name = "shock trap"
desc = "A trap that will shock you, it will burn your flesh and render you immobile, You'd better avoid it."
icon_state = "trap-shock"
-
-/obj/structure/divine/trap/stun/trap_effect(mob/living/L)
+/obj/structure/trap/stun/trap_effect(mob/living/L)
L << "You are paralyzed from the intense shock!"
L.Weaken(5)
var/turf/Lturf = get_turf(L)
@@ -52,13 +44,13 @@
new /obj/effect/particle_effect/sparks(Lturf)
-/obj/structure/divine/trap/fire
+/obj/structure/trap/fire
name = "flame trap"
desc = "A trap that will set you ablaze. You'd better avoid it."
icon_state = "trap-fire"
-/obj/structure/divine/trap/fire/trap_effect(mob/living/L)
+/obj/structure/trap/fire/trap_effect(mob/living/L)
L << "Spontaneous combustion!"
L.Weaken(1)
var/turf/Lturf = get_turf(L)
@@ -66,26 +58,26 @@
new /obj/effect/particle_effect/sparks(Lturf)
-/obj/structure/divine/trap/chill
+/obj/structure/trap/chill
name = "frost trap"
desc = "A trap that will chill you to the bone. You'd better avoid it."
icon_state = "trap-frost"
-/obj/structure/divine/trap/chill/trap_effect(mob/living/L)
+/obj/structure/trap/chill/trap_effect(mob/living/L)
L << "You're frozen solid!"
L.Weaken(1)
L.bodytemperature -= 300
new /obj/effect/particle_effect/sparks(get_turf(L))
-/obj/structure/divine/trap/damage
+/obj/structure/trap/damage
name = "earth trap"
desc = "A trap that will summon a small earthquake, just for you. You'd better avoid it."
icon_state = "trap-earth"
-/obj/structure/divine/trap/damage/trap_effect(mob/living/L)
+/obj/structure/trap/damage/trap_effect(mob/living/L)
L << "The ground quakes beneath your feet!"
L.Weaken(5)
L.adjustBruteLoss(35)
@@ -94,16 +86,14 @@
new /obj/structure/flora/rock(Lturf)
-/obj/structure/divine/trap/ward
+/obj/structure/trap/ward
name = "divine ward"
desc = "A divine barrier, It looks like you could destroy it with enough effort, or wait for it to dissipate..."
icon_state = "ward"
- health = 150
- maxhealth = 150
density = 1
time_between_triggers = 1200 //Exists for 2 minutes
-/obj/structure/divine/trap/ward/New()
+/obj/structure/trap/ward/New()
..()
QDEL_IN(src, time_between_triggers)
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index 085a4444ddd..9b076bcd5c2 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -84,6 +84,10 @@
if(current_size >= STAGE_FIVE)
shatter()
+/obj/structure/window/setDir(direct)
+ if(!fulltile)
+ ..()
+
/obj/structure/window/CanPass(atom/movable/mover, turf/target, height=0)
if(istype(mover) && mover.checkpass(PASSGLASS))
return 1
@@ -508,22 +512,33 @@
icon_state = "clockwork_window_single"
maxhealth = 100
explosion_block = 2 //fancy AND hard to destroy. the most useful combination.
+ var/made_glow = FALSE
/obj/structure/window/reinforced/clockwork/New(loc, direct)
..()
- if(!fulltile)
- var/obj/effect/E = PoolOrNew(/obj/effect/overlay/temp/ratvar/window/single, get_turf(src))
- if(direct)
- setDir(direct)
- E.setDir(direct)
- else
- PoolOrNew(/obj/effect/overlay/temp/ratvar/window, get_turf(src))
for(var/obj/item/I in debris)
debris -= I
qdel(I)
- debris += new/obj/item/clockwork/component/vanguard_cogwheel(src)
+ if(!fulltile)
+ if(direct)
+ var/obj/effect/E = PoolOrNew(/obj/effect/overlay/temp/ratvar/window/single, get_turf(src))
+ setDir(direct)
+ E.setDir(direct)
+ made_glow = TRUE
+ debris += new/obj/item/stack/sheet/brass(src, 1)
+ else
+ PoolOrNew(/obj/effect/overlay/temp/ratvar/window, get_turf(src))
+ made_glow = TRUE
+ debris += new/obj/item/stack/sheet/brass(src, 2)
change_construction_value(fulltile ? 3 : 2)
+/obj/structure/window/reinforced/clockwork/setDir(direct)
+ if(!made_glow)
+ var/obj/effect/E = PoolOrNew(/obj/effect/overlay/temp/ratvar/window/single, get_turf(src))
+ E.setDir(direct)
+ made_glow = TRUE
+ ..()
+
/obj/structure/window/reinforced/clockwork/Destroy()
change_construction_value(fulltile ? -3 : -2)
return ..()
diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm
index e06fd5bf633..8e4841da760 100644
--- a/code/game/turfs/simulated/floor/plating.dm
+++ b/code/game/turfs/simulated/floor/plating.dm
@@ -235,6 +235,9 @@
slowdown = 2
luminosity = 1
+/turf/open/floor/plating/lava/ex_act()
+ return
+
/turf/open/floor/plating/lava/airless
initial_gas_mix = "TEMP=2.7"
diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm
index e1da895de41..4e0224b3c41 100644
--- a/code/game/turfs/simulated/walls.dm
+++ b/code/game/turfs/simulated/walls.dm
@@ -3,13 +3,11 @@
desc = "A huge chunk of metal used to separate rooms."
icon = 'icons/turf/walls/wall.dmi'
icon_state = "wall"
- var/mineral = "metal"
explosion_block = 1
thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT
heat_capacity = 312500 //a little over 5 cm thick , 312500 for 1 m by 2.5 m by 0.25 m plasteel wall
- var/walltype = "metal"
var/hardness = 40 //lower numbers are harder. Used to determine the probability of a hulk smashing through.
var/slicing_duration = 100 //default time taken to slice the wall
var/sheet_type = /obj/item/stack/sheet/metal
@@ -19,6 +17,7 @@
/turf/closed/wall,
/turf/closed/wall/r_wall,
/obj/structure/falsewall,
+ /obj/structure/falsewall/brass,
/obj/structure/falsewall/reinforced,
/turf/closed/wall/rust,
/turf/closed/wall/r_wall/rust,
diff --git a/code/game/turfs/simulated/walls_mineral.dm b/code/game/turfs/simulated/walls_mineral.dm
index 9e704b5dc97..56abbf90fbc 100644
--- a/code/game/turfs/simulated/walls_mineral.dm
+++ b/code/game/turfs/simulated/walls_mineral.dm
@@ -12,8 +12,6 @@
desc = "A wall with gold plating. Swag!"
icon = 'icons/turf/walls/gold_wall.dmi'
icon_state = "gold"
- walltype = "gold"
- mineral = "gold"
sheet_type = /obj/item/stack/sheet/mineral/gold
//var/electro = 1
//var/shocked = null
@@ -25,8 +23,6 @@
desc = "A wall with silver plating. Shiny!"
icon = 'icons/turf/walls/silver_wall.dmi'
icon_state = "silver"
- walltype = "silver"
- mineral = "silver"
sheet_type = /obj/item/stack/sheet/mineral/silver
//var/electro = 0.75
//var/shocked = null
@@ -37,8 +33,6 @@
desc = "A wall with diamond plating. You monster."
icon = 'icons/turf/walls/diamond_wall.dmi'
icon_state = "diamond"
- walltype = "diamond"
- mineral = "diamond"
sheet_type = /obj/item/stack/sheet/mineral/diamond
slicing_duration = 200 //diamond wall takes twice as much time to slice
explosion_block = 3
@@ -52,8 +46,6 @@
desc = "A wall with bananium plating. Honk!"
icon = 'icons/turf/walls/bananium_wall.dmi'
icon_state = "bananium"
- walltype = "bananium"
- mineral = "bananium"
sheet_type = /obj/item/stack/sheet/mineral/bananium
canSmoothWith = list(/turf/closed/wall/mineral/clown, /obj/structure/falsewall/clown)
@@ -62,8 +54,6 @@
desc = "A wall with sandstone plating. Rough."
icon = 'icons/turf/walls/sandstone_wall.dmi'
icon_state = "sandstone"
- walltype = "sandstone"
- mineral = "sandstone"
sheet_type = /obj/item/stack/sheet/mineral/sandstone
explosion_block = 0
canSmoothWith = list(/turf/closed/wall/mineral/sandstone, /obj/structure/falsewall/sandstone)
@@ -73,8 +63,6 @@
desc = "A wall with uranium plating. This is probably a bad idea."
icon = 'icons/turf/walls/uranium_wall.dmi'
icon_state = "uranium"
- walltype = "uranium"
- mineral = "uranium"
sheet_type = /obj/item/stack/sheet/mineral/uranium
canSmoothWith = list(/turf/closed/wall/mineral/uranium, /obj/structure/falsewall/uranium)
@@ -107,8 +95,6 @@
desc = "A wall with plasma plating. This is definitely a bad idea."
icon = 'icons/turf/walls/plasma_wall.dmi'
icon_state = "plasma"
- walltype = "plasma"
- mineral = "plasma"
sheet_type = /obj/item/stack/sheet/mineral/plasma
thermal_conductivity = 0.04
canSmoothWith = list(/turf/closed/wall/mineral/plasma, /obj/structure/falsewall/plasma)
@@ -148,8 +134,6 @@
desc = "A wall with wooden plating. Stiff."
icon = 'icons/turf/walls/wood_wall.dmi'
icon_state = "wood"
- walltype = "wood"
- mineral = "wood"
sheet_type = /obj/item/stack/sheet/mineral/wood
hardness = 70
explosion_block = 0
@@ -160,8 +144,6 @@
desc = "A wall with rough metal plating."
icon = 'icons/turf/walls/iron_wall.dmi'
icon_state = "iron"
- walltype = "iron"
- mineral = "rods"
sheet_type = /obj/item/stack/rods
canSmoothWith = list(/turf/closed/wall/mineral/iron, /obj/structure/falsewall/iron)
@@ -170,8 +152,6 @@
desc = "A wall made of densely packed snow blocks."
icon = 'icons/turf/walls/snow_wall.dmi'
icon_state = "snow"
- walltype = "snow"
- mineral = "snow"
hardness = 80
sheet_type = /obj/item/stack/sheet/mineral/snow
canSmoothWith = null
@@ -181,8 +161,6 @@
desc = "A wall with alien alloy plating."
icon = 'icons/turf/walls/abductor_wall.dmi'
icon_state = "abductor"
- walltype = "abductor"
- mineral = "abductor"
smooth = SMOOTH_TRUE|SMOOTH_DIAGONAL
sheet_type = /obj/item/stack/sheet/mineral/abductor
slicing_duration = 200 //alien wall takes twice as much time to slice
@@ -193,7 +171,6 @@
name = "wall"
icon = 'icons/turf/shuttle.dmi'
icon_state = "wall"
- walltype = "shuttle"
sheet_type = /obj/item/stack/sheet/mineral/titanium
smooth = SMOOTH_FALSE
@@ -202,7 +179,6 @@
desc = "A light-weight titanium wall used in shuttles."
icon = 'icons/turf/walls/shuttle_wall.dmi'
icon_state = "map-shuttle"
- walltype = "shuttle"
sheet_type = /obj/item/stack/sheet/mineral/titanium
smooth = SMOOTH_MORE|SMOOTH_DIAGONAL
canSmoothWith = list(/turf/closed/wall/mineral/titanium, /obj/machinery/door/airlock/shuttle, /obj/machinery/door/airlock/, /turf/closed/wall/shuttle, /obj/structure/window/shuttle, /obj/structure/shuttle/engine, /obj/structure/shuttle/engine/heater, )
@@ -245,7 +221,6 @@
/turf/closed/wall/mineral/plastitanium
name = "wall"
desc = "An evil wall of plasma and titanium."
- walltype = "syndieshuttle"
icon = 'icons/turf/shuttle.dmi'
icon_state = "wall3"
sheet_type = /obj/item/stack/sheet/mineral/plastitanium
diff --git a/code/game/turfs/simulated/walls_misc.dm b/code/game/turfs/simulated/walls_misc.dm
index 30ff871f894..73f79bd650a 100644
--- a/code/game/turfs/simulated/walls_misc.dm
+++ b/code/game/turfs/simulated/walls_misc.dm
@@ -3,7 +3,6 @@
desc = "A cold metal wall engraved with indecipherable symbols. Studying them causes your head to pound."
icon = 'icons/turf/walls/cult_wall.dmi'
icon_state = "cult"
- walltype = "cult"
builtin_sheet = null
canSmoothWith = null
@@ -44,6 +43,7 @@
name = "clockwork wall"
desc = "A huge chunk of warm metal. The clanging of machinery emanates from within."
explosion_block = 2
+ sheet_type = /obj/item/stack/sheet/brass
var/obj/effect/clockwork/overlay/wall/realappearence
var/obj/structure/destructible/clockwork/cache/linkedcache
@@ -123,6 +123,7 @@
O.loc = src
/turf/closed/wall/clockwork/break_wall()
+ new sheet_type(src)
return new/obj/structure/destructible/clockwork/wall_gear(src)
/turf/closed/wall/clockwork/devastate_wall()
@@ -142,7 +143,6 @@
icon = 'icons/turf/walls/icedmetal_wall.dmi'
icon_state = "iced"
desc = "A wall covered in a thick sheet of ice."
- walltype = "iced"
canSmoothWith = null
hardness = 35
slicing_duration = 150 //welding through the ice+metal
@@ -152,7 +152,6 @@
desc = "A rusted metal wall."
icon = 'icons/turf/walls/rusty_wall.dmi'
icon_state = "arust"
- walltype = "arust"
hardness = 45
/turf/closed/wall/r_wall/rust
@@ -160,26 +159,22 @@
desc = "A huge chunk of rusted reinforced metal."
icon = 'icons/turf/walls/rusty_reinforced_wall.dmi'
icon_state = "rrust"
- walltype = "rrust"
hardness = 15
/turf/closed/wall/shuttle
name = "wall"
icon = 'icons/turf/shuttle.dmi'
icon_state = "wall"
- walltype = "shuttle"
smooth = SMOOTH_FALSE
/turf/closed/wall/shuttle/syndie
icon_state = "wall3"
- walltype = "syndieshuttle"
sheet_type = /obj/item/stack/sheet/mineral/plastitanium
/turf/closed/wall/shuttle/smooth
name = "wall"
icon = 'icons/turf/walls/shuttle_wall.dmi'
icon_state = "shuttle"
- walltype = "shuttle"
sheet_type = /obj/item/stack/sheet/mineral/titanium
smooth = SMOOTH_MORE|SMOOTH_DIAGONAL
canSmoothWith = list(/turf/closed/wall/shuttle/smooth, /obj/structure/window/shuttle, /obj/structure/shuttle, /obj/machinery/door/airlock/glass, /obj/machinery/door/airlock/shuttle)
diff --git a/code/game/turfs/simulated/walls_reinforced.dm b/code/game/turfs/simulated/walls_reinforced.dm
index cfcaf0159c8..1c7ee6a608a 100644
--- a/code/game/turfs/simulated/walls_reinforced.dm
+++ b/code/game/turfs/simulated/walls_reinforced.dm
@@ -6,8 +6,6 @@
opacity = 1
density = 1
- walltype = "rwall"
-
var/d_state = 0
hardness = 10
sheet_type = /obj/item/stack/sheet/plasteel
diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm
index 5f529ef34ac..d13b8f9d2cd 100644
--- a/code/game/turfs/space/space.dm
+++ b/code/game/turfs/space/space.dm
@@ -170,3 +170,7 @@
/turf/open/space/proc/update_icon()
icon_state = SPACE_ICON_STATE
+
+/turf/open/space/is_transition_turf()
+ if(destination_x || destination_y || destination_z)
+ return 1
\ No newline at end of file
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index df8ae690ad0..4a73e76ba90 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -325,3 +325,6 @@
SSair.remove_from_active(T0)
T0.CalculateAdjacentTurfs()
SSair.add_to_active(T0,1)
+
+/turf/proc/is_transition_turf()
+ return
diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm
index 07da6355d06..199e00dfd23 100644
--- a/code/modules/admin/player_panel.dm
+++ b/code/modules/admin/player_panel.dm
@@ -478,66 +478,6 @@
dat += "FLW | "
dat += ""
- if(ticker.mode.red_deities.len || ticker.mode.red_deity_prophets.len || ticker.mode.blue_deity_prophets.len || ticker.mode.red_deity_followers.len || ticker.mode.blue_deity_followers.len)
- dat += "
| Red Deity | |
"
- for(var/datum/mind/N in ticker.mode.red_deities)
- var/mob/M = N.current
- if(M)
- dat += "| Red Deity: [M.real_name][M.client ? "" : " (No Client)"][M.stat == 2 ? " (DEAD)" : ""] | "
- dat += "PM | "
- dat += "FLW |
"
- dat += "
"
-
- if(ticker.mode.blue_deities.len)
- dat += "
| Blue Deity | |
"
- for(var/datum/mind/N in ticker.mode.blue_deities)
- var/mob/M = N.current
- if(M)
- dat += "| Blue Deity: [M.real_name][M.client ? "" : " (No Client)"][M.stat == 2 ? " (DEAD)" : ""] | "
- dat += "PM | "
- dat += "FLW |
"
- dat += "
"
-
- if(ticker.mode.red_deity_prophets.len)
- dat += "
| Red Deity Prophets | |
"
- for(var/datum/mind/N in ticker.mode.red_deity_prophets)
- var/mob/M = N.current
- if(M)
- dat += "| Red Deity Prophet: [M.real_name][M.client ? "" : " (No Client)"][M.stat == 2 ? " (DEAD)" : ""] | "
- dat += "PM | "
- dat += "FLW |
"
- dat += "
"
-
- if(ticker.mode.blue_deity_prophets.len)
- dat += "
| Blue Deity Prophets | |
"
- for(var/datum/mind/N in ticker.mode.blue_deity_prophets)
- var/mob/M = N.current
- if(M)
- dat += "| Blue Deity Prophet: [M.real_name][M.client ? "" : " (No Client)"][M.stat == 2 ? " (DEAD)" : ""] | "
- dat += "PM | "
- dat += "FLW |
"
- dat += "
"
-
- if(ticker.mode.red_deity_followers.len)
- dat += "
| Red Deity Followers | |
"
- for(var/datum/mind/N in ticker.mode.red_deity_followers)
- var/mob/M = N.current
- if(M)
- dat += "| Red Deity Followers: [M.real_name][M.client ? "" : " (No Client)"][M.stat == 2 ? " (DEAD)" : ""] | "
- dat += "PM | "
- dat += "FLW |
"
- dat += "
"
-
- if(ticker.mode.blue_deity_followers.len)
- dat += "
| Blue Deity Followers | |
"
- for(var/datum/mind/N in ticker.mode.blue_deity_followers)
- var/mob/M = N.current
- if(M)
- dat += "| Blue Deity Followers: [M.real_name][M.client ? "" : " (No Client)"][M.stat == 2 ? " (DEAD)" : ""] | "
- dat += "PM | "
- dat += "FLW |
"
- dat += "
"
-
if(ticker.mode.traitors.len > 0)
dat += "
| Traitors | | |
"
for(var/datum/mind/traitor in ticker.mode.traitors)
diff --git a/code/modules/admin/verbs/onlyone.dm b/code/modules/admin/verbs/onlyone.dm
index affb6b57bc9..fa8998008d6 100644
--- a/code/modules/admin/verbs/onlyone.dm
+++ b/code/modules/admin/verbs/onlyone.dm
@@ -1,60 +1,78 @@
-/client/proc/only_one()
+var/highlander = FALSE
+/client/proc/only_one() //Gives everyone kilts, berets, claymores, and pinpointers, with the objective to hijack the emergency shuttle.
if(!ticker || !ticker.mode)
alert("The game hasn't started yet!")
return
+ highlander = TRUE
world << "THERE CAN BE ONLY ONE!!!"
world << sound('sound/misc/highlander.ogg')
+ for(var/obj/item/weapon/disk/nuclear/N in poi_list)
+ N.relocate() //Gets it out of bags and such
+
for(var/mob/living/carbon/human/H in player_list)
- if(H.stat == DEAD || !(H.client)) continue
-
- ticker.mode.traitors += H.mind
- H.mind.special_role = "highlander"
-
- H.dna.species.specflags |= NOGUNS //nice try jackass
-
- var/datum/objective/steal/steal_objective = new
- steal_objective.owner = H.mind
- steal_objective.set_target(new /datum/objective_item/steal/nukedisc)
- H.mind.objectives += steal_objective
-
- var/datum/objective/hijack/hijack_objective = new
- hijack_objective.explanation_text = "Escape on the shuttle alone. Ensure nobody else makes it out."
- hijack_objective.owner = H.mind
- H.mind.objectives += hijack_objective
-
- H.mind.announce_objectives()
-
- for (var/obj/item/I in H)
- if (istype(I, /obj/item/weapon/implant))
- continue
- qdel(I)
-
- H.equip_to_slot_or_del(new /obj/item/clothing/under/kilt/highlander(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(H), slot_ears)
- H.equip_to_slot_or_del(new /obj/item/clothing/head/beret/highlander(H), slot_head)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/weapon/pinpointer(H.loc), slot_l_store)
-
- var/obj/item/weapon/card/id/W = new(H)
- W.icon_state = "centcom"
- W.access = get_all_accesses()
- W.access += get_all_centcom_access()
- W.assignment = "Highlander"
- W.registered_name = H.real_name
- W.flags |= NODROP
- W.update_label(H.real_name)
- H.equip_to_slot_or_del(W, slot_wear_id)
-
- var/obj/item/weapon/claymore/highlander/H1 = new(H)
- H.put_in_hands(H1)
- H1.pickup(H)
+ if(H.stat == DEAD || !(H.client))
+ continue
+ H.make_scottish()
message_admins("[key_name_admin(usr)] used THERE CAN BE ONLY ONE!")
log_admin("[key_name(usr)] used THERE CAN BE ONLY ONE.")
addtimer(SSshuttle.emergency, "request", 50, FALSE, null, 1)
+/mob/living/carbon/human/proc/make_scottish()
+ ticker.mode.traitors += mind
+ mind.special_role = "highlander"
+ dna.species.specflags |= NOGUNS //nice try jackass
+
+ var/datum/objective/steal/steal_objective = new
+ steal_objective.owner = mind
+ steal_objective.set_target(new /datum/objective_item/steal/nukedisc)
+ mind.objectives += steal_objective
+
+ var/datum/objective/hijack/hijack_objective = new
+ hijack_objective.explanation_text = "Escape on the shuttle alone. Ensure that nobody else makes it out."
+ hijack_objective.owner = mind
+ mind.objectives += hijack_objective
+
+ mind.announce_objectives()
+
+ for(var/obj/item/I in src)
+ if(istype(I, /obj/item/weapon/implant))
+ continue
+ qdel(I)
+ equip_to_slot_or_del(new /obj/item/clothing/under/kilt/highlander(src), slot_w_uniform)
+ equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(src), slot_ears)
+ equip_to_slot_or_del(new /obj/item/clothing/head/beret/highlander(src), slot_head)
+ equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(src), slot_shoes)
+ equip_to_slot_or_del(new /obj/item/weapon/pinpointer(src), slot_l_store)
+ for(var/obj/item/weapon/pinpointer/P in src)
+ P.attack_self(src)
+ var/obj/item/weapon/card/id/W = new(src)
+ W.icon_state = "centcom"
+ W.access = get_all_accesses()
+ W.access += get_all_centcom_access()
+ W.assignment = "Highlander"
+ W.registered_name = real_name
+ W.flags |= NODROP
+ W.update_label(real_name)
+ equip_to_slot_or_del(W, slot_wear_id)
+
+ var/obj/item/weapon/claymore/highlander/H1 = new(src)
+ if(!highlander)
+ H1.admin_spawned = TRUE //To prevent announcing
+ put_in_hands(H1)
+ H1.pickup(src) //For the stun shielding
+
+ var/obj/item/weapon/bloodcrawl/antiwelder = new(src)
+ antiwelder.name = "compulsion of honor"
+ antiwelder.desc = "You are unable to hold anything in this hand until you're the last one left!"
+ antiwelder.icon_state = "bloodhand_right"
+ put_in_hands(antiwelder)
+
+ src << "Your [H1.name] cries out for blood. Join in the slaughter, lest you be claimed yourself...\n\
+ Activate it in your hand, and it will lead to the nearest target. Attack the nuclear authentication disk with it, and you will store it."
+
/proc/only_me()
if(!ticker || !ticker.mode)
alert("The game hasn't started yet!")
diff --git a/code/modules/admin/verbs/pray.dm b/code/modules/admin/verbs/pray.dm
index 7190bb3f945..ba2ccc76d6d 100644
--- a/code/modules/admin/verbs/pray.dm
+++ b/code/modules/admin/verbs/pray.dm
@@ -20,13 +20,13 @@
var/image/cross = image('icons/obj/storage.dmi',"bible")
var/font_color = "purple"
var/prayer_type = "PRAYER"
- var/deity = "Space Jesus" // y'all need space jesus by default
- if (ticker && ticker.Bible_deity_name)
- deity = ticker.Bible_deity_name
+ var/deity
if(usr.job == "Chaplain")
cross = image('icons/obj/storage.dmi',"kingyellow")
font_color = "blue"
prayer_type = "CHAPLAIN PRAYER"
+ if (ticker && ticker.Bible_deity_name)
+ deity = ticker.Bible_deity_name
else if(iscultist(usr))
cross = image('icons/obj/storage.dmi',"tome")
font_color = "red"
@@ -34,7 +34,7 @@
deity = "Nar-Sie"
msg = "\icon[cross] \
- [prayer_type] (to [deity]): \
+ [prayer_type][deity ? " (to [deity])" : ""]: \
[ADMIN_FULLMONTY(src)] [ADMIN_SC(src)]: \
[msg]"
diff --git a/code/modules/assembly/flash.dm b/code/modules/assembly/flash.dm
index aece047550c..f174129c534 100644
--- a/code/modules/assembly/flash.dm
+++ b/code/modules/assembly/flash.dm
@@ -173,26 +173,15 @@
/obj/item/device/assembly/flash/cyborg/attack(mob/living/M, mob/user)
..()
- cyborg_flash_animation(user)
+ PoolOrNew(/obj/effect/overlay/temp/borgflash, get_turf(src))
/obj/item/device/assembly/flash/cyborg/attack_self(mob/user)
..()
- cyborg_flash_animation(user)
+ PoolOrNew(/obj/effect/overlay/temp/borgflash, get_turf(src))
/obj/item/device/assembly/flash/cyborg/attackby(obj/item/weapon/W, mob/user, params)
return
-/obj/item/device/assembly/flash/cyborg/proc/cyborg_flash_animation(mob/living/user)
- var/atom/movable/overlay/animation = new(user.loc)
- animation.layer = user.layer + 1
- animation.icon_state = "blank"
- animation.icon = 'icons/mob/mob.dmi'
- animation.master = user
- flick("blspell", animation)
- sleep(5)
- qdel(animation)
-
-
/obj/item/device/assembly/flash/memorizer
name = "memorizer"
desc = "If you see this, you're not likely to remember it any time soon."
@@ -201,3 +190,32 @@
item_state = "nullrod"
/obj/item/device/assembly/flash/handheld //this is now the regular pocket flashes
+
+/obj/item/device/assembly/flash/armimplant
+ name = "photon projector"
+ desc = "A high-powered photon projector implant normally used for lighting purposes, but also doubles as a flashbulb weapon. Self-repair protocals fix the flashbulb if it ever burns out."
+ var/flashcd = 20
+ var/overheat = 0
+ var/obj/item/organ/cyberimp/arm/flash/I = null
+
+/obj/item/device/assembly/flash/armimplant/burn_out()
+ if(I && I.owner)
+ I.owner << "Your photon projector implant overheats and deactivates!"
+ I.Retract()
+ overheat = FALSE
+ addtimer(src, "cooldown", flashcd * 2)
+
+/obj/item/device/assembly/flash/armimplant/try_use_flash(mob/user = null)
+ if(overheat)
+ if(I && I.owner)
+ I.owner << "Your photon projector is running too hot to be used again so quickly!"
+ return FALSE
+ overheat = TRUE
+ addtimer(src, "cooldown", flashcd)
+ playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1)
+ update_icon(1)
+ return TRUE
+
+
+/obj/item/device/assembly/flash/armimplant/proc/cooldown()
+ overheat = FALSE
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm
index 8208ada42d7..b61e862502c 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm
@@ -65,7 +65,7 @@ Acts like a normal vent, but has an input AND output.
..()
if(!on)
- return 0
+ return FALSE
var/datum/gas_mixture/air1 = AIR1
var/datum/gas_mixture/air2 = AIR2
@@ -85,6 +85,9 @@ Acts like a normal vent, but has an input AND output.
var/transfer_moles = pressure_delta*environment.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
var/datum/gas_mixture/removed = air1.remove(transfer_moles)
+ //Removed can be null if there is no atmosphere in air1
+ if(!removed)
+ return FALSE
loc.assume_air(removed)
air_update_turf()
@@ -105,6 +108,9 @@ Acts like a normal vent, but has an input AND output.
var/transfer_moles = pressure_delta*air2.volume/(environment.temperature * R_IDEAL_GAS_EQUATION)
var/datum/gas_mixture/removed = loc.remove_air(transfer_moles)
+ //removed can be null if there is no air in the location
+ if(!removed)
+ return FALSE
air2.merge(removed)
air_update_turf()
@@ -112,7 +118,7 @@ Acts like a normal vent, but has an input AND output.
var/datum/pipeline/parent2 = PARENT2
parent2.update = 1
- return 1
+ return TRUE
//Radio remote control
@@ -195,4 +201,4 @@ Acts like a normal vent, but has an input AND output.
#undef EXT_BOUND
#undef INPUT_MIN
-#undef OUTPUT_MAX
\ No newline at end of file
+#undef OUTPUT_MAX
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
index f95900688ec..b39fe29c0ff 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
@@ -184,9 +184,10 @@
//Take a gas sample
var/datum/gas_mixture/removed = tile.remove_air(transfer_moles)
- var/list/removed_gases = removed.gases
- if (isnull(removed)) //in space
+ //Nothing left to remove from the tile
+ if (isnull(removed))
return
+ var/list/removed_gases = removed.gases
//Filter it
var/datum/gas_mixture/filtered_out = new
diff --git a/code/modules/awaymissions/capture_the_flag.dm b/code/modules/awaymissions/capture_the_flag.dm
index e6cb0ad5723..c6c4e545d42 100644
--- a/code/modules/awaymissions/capture_the_flag.dm
+++ b/code/modules/awaymissions/capture_the_flag.dm
@@ -463,31 +463,27 @@
-/obj/structure/divine/trap/ctf
+/obj/structure/trap/ctf
name = "Spawn protection"
desc = "Stay outta the enemy spawn!"
icon_state = "trap"
- health = INFINITY
- maxhealth = INFINITY
var/team = WHITE_TEAM
- constructable = FALSE
time_between_triggers = 1
alpha = 255
-/obj/structure/divine/trap/examine(mob/user)
+/obj/structure/trap/examine(mob/user)
return
-/obj/structure/divine/trap/ctf/trap_effect(mob/living/L)
+/obj/structure/trap/ctf/trap_effect(mob/living/L)
if(!(src.team in L.faction))
L << "Stay out of the enemy spawn!"
L.death()
-
-/obj/structure/divine/trap/ctf/red
+/obj/structure/trap/ctf/red
team = RED_TEAM
icon_state = "trap-fire"
-/obj/structure/divine/trap/ctf/blue
+/obj/structure/trap/ctf/blue
team = BLUE_TEAM
icon_state = "trap-frost"
diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm
index 5764994c628..b1ed528cb40 100644
--- a/code/modules/cargo/packs.dm
+++ b/code/modules/cargo/packs.dm
@@ -5,6 +5,7 @@ datum/supply_pack
var/contraband = FALSE
var/cost = 700 // Minimum cost, or infinite points are possible.
var/access = FALSE
+ var/access_any = FALSE
var/list/contains = null
var/crate_name = "crate"
var/crate_type = /obj/structure/closet/crate
@@ -17,6 +18,8 @@ datum/supply_pack
C.name = crate_name
if(access)
C.req_access = list(access)
+ if(access_any)
+ C.req_one_access = access_any
fill(C)
@@ -452,6 +455,35 @@ datum/supply_pack
crate_name = "fuel tank crate"
crate_type = /obj/structure/closet/crate/large
+/datum/supply_pack/engineering/oxygen
+ name = "Oxygen Canister"
+ cost = 1500
+ contains = list(/obj/machinery/portable_atmospherics/canister/oxygen)
+ crate_name = "oxygen canister crate"
+ crate_type = /obj/structure/closet/crate/large
+
+/datum/supply_pack/engineering/nitrogen
+ name = "Nitrogen Canister"
+ cost = 2000
+ contains = list(/obj/machinery/portable_atmospherics/canister/nitrogen)
+ crate_name = "nitrogen canister crate"
+ crate_type = /obj/structure/closet/crate/large
+
+/datum/supply_pack/engineering/carbon_dio
+ name = "Carbon Dioxide Canister"
+ cost = 3000
+ contains = list(/obj/machinery/portable_atmospherics/canister/carbon_dioxide)
+ crate_name = "carbon dioxide canister crate"
+ crate_type = /obj/structure/closet/crate/large
+
+/datum/supply_pack/science/nitrous_oxide_canister
+ name = "Nitrous Oxide Canister"
+ cost = 3000
+ access = access_atmospherics
+ contains = list(/obj/machinery/portable_atmospherics/canister/nitrous_oxide)
+ crate_name = "nitrous oxide canister crate"
+ crate_type = /obj/structure/closet/crate/secure
+
/datum/supply_pack/engineering/tools
name = "Toolbox Crate"
contains = list(/obj/item/weapon/storage/toolbox/electrical,
@@ -829,6 +861,24 @@ datum/supply_pack
crate_type = /obj/structure/closet/crate/secure
dangerous = TRUE
+/datum/supply_pack/science/bz_canister
+ name = "BZ Canister"
+ cost = 4000
+ access_any = list(access_rd, access_atmospherics)
+ contains = list(/obj/machinery/portable_atmospherics/canister/bz)
+ crate_name = "bz canister crate"
+ crate_type = /obj/structure/closet/crate/secure
+ dangerous = TRUE
+
+/datum/supply_pack/science/freon_canister
+ name = "Freon Canister"
+ cost = 6000
+ access_any = list(access_rd, access_atmospherics)
+ contains = list(/obj/machinery/portable_atmospherics/canister/freon)
+ crate_name = "freon canister crate"
+ crate_type = /obj/structure/closet/crate/secure
+ dangerous = TRUE
+
/datum/supply_pack/science/research
name = "Machine Prototype Crate"
cost = 8000
@@ -1201,6 +1251,13 @@ datum/supply_pack
crate_name = "high-capacity water tank crate"
crate_type = /obj/structure/closet/crate/large
+/datum/supply_pack/misc/water_vapor
+ name = "Water Vapor Canister"
+ cost = 2500
+ contains = list(/obj/machinery/portable_atmospherics/canister/water_vapor)
+ crate_name = "water vapor canister crate"
+ crate_type = /obj/structure/closet/crate/large
+
/datum/supply_pack/misc/lasertag
name = "Laser Tag Crate"
cost = 1500
diff --git a/code/modules/client/client_colour.dm b/code/modules/client/client_colour.dm
index 8073b0abebf..7e78032f467 100644
--- a/code/modules/client/client_colour.dm
+++ b/code/modules/client/client_colour.dm
@@ -27,7 +27,7 @@
colour_type - a typepath (subtyped from /datum/client_colour)
*/
/mob/proc/add_client_colour(colour_type)
- if(!ispath(/datum/client_colour))
+ if(!ispath(colour_type, /datum/client_colour))
return
var/datum/client_colour/CC = new colour_type()
@@ -41,7 +41,7 @@
colour_type - a typepath (subtyped from /datum/client_colour)
*/
/mob/proc/remove_client_colour(colour_type)
- if(!ispath(/datum/client_colour))
+ if(!ispath(colour_type, /datum/client_colour))
return
for(var/cc in client_colours)
@@ -70,3 +70,39 @@
+/datum/client_colour/glass_colour
+ priority = 0
+ colour = "red"
+
+/datum/client_colour/glass_colour/green
+ colour = "#aaffaa"
+
+/datum/client_colour/glass_colour/lightgreen
+ colour = "#ccffcc"
+
+/datum/client_colour/glass_colour/blue
+ colour = "#aaaaff"
+
+/datum/client_colour/glass_colour/lightblue
+ colour = "#ccccff"
+
+/datum/client_colour/glass_colour/yellow
+ colour = "#ffff66"
+
+/datum/client_colour/glass_colour/red
+ colour = "#ffaaaa"
+
+/datum/client_colour/glass_colour/darkred
+ colour = "#bb5555"
+
+/datum/client_colour/glass_colour/orange
+ colour = "#ffbb99"
+
+/datum/client_colour/glass_colour/lightorange
+ colour = "#ffddaa"
+
+/datum/client_colour/glass_colour/purple
+ colour = "#ff99ff"
+
+/datum/client_colour/glass_colour/gray
+ colour = "#cccccc"
\ No newline at end of file
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 4fe0aeb1fc9..99d0d8d729f 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -41,6 +41,8 @@ var/list/preferences_datums = list()
var/allow_midround_antag = 1
var/preferred_map = null
+ var/uses_glasses_colour = 0
+
//character preferences
var/real_name //our character's name
var/be_random_name = 0 //whether we'll have a random name every round
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index 00bf7e50840..ee624a6c99f 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -97,7 +97,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
ignoring = list()
if(current_version < 15)
toggles |= SOUND_ANNOUNCEMENTS
-
+
//should this proc get fairly long (say 3 versions long),
//just increase SAVEFILE_VERSION_MIN so it's not as far behind
@@ -173,6 +173,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["ignoring"] >> ignoring
S["ghost_hud"] >> ghost_hud
S["inquisitive_ghost"] >> inquisitive_ghost
+ S["uses_glasses_colour"]>> uses_glasses_colour
//try to fix any outdated data if necessary
if(needs_update >= 0)
@@ -224,6 +225,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["ignoring"] << ignoring
S["ghost_hud"] << ghost_hud
S["inquisitive_ghost"] << inquisitive_ghost
+ S["uses_glasses_colour"]<< uses_glasses_colour
return 1
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index 0f64871a4ad..cacd3f60dd6 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -47,7 +47,7 @@
M.put_in_hand(src, H.held_index)
add_fingerprint(usr)
-/obj/item/clothing/throw_at(atom/target, range, speed, mob/thrower, spin)
+/obj/item/clothing/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0)
if(pockets)
pockets.close_all()
return ..()
diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm
index 19bf143a1cd..8ca4bf66cc4 100644
--- a/code/modules/clothing/glasses/glasses.dm
+++ b/code/modules/clothing/glasses/glasses.dm
@@ -1,6 +1,7 @@
/obj/item/clothing/glasses
name = "glasses"
materials = list(MAT_GLASS = 250)
+ var/glass_colour_type = null //colors your vision when worn
//called when thermal glasses are emped.
/obj/item/clothing/glasses/proc/thermal_overload()
@@ -23,6 +24,7 @@
darkness_view = 2
vision_flags = SEE_TURFS
invis_view = SEE_INVISIBLE_MINIMUM
+ glass_colour_type = /datum/client_colour/glass_colour/lightgreen
/obj/item/clothing/glasses/meson/night
name = "Night Vision Optical Meson Scanner"
@@ -31,6 +33,7 @@
item_state = "nvgmeson"
origin_tech = "magnets=4;engineering=5;plasmatech=4"
darkness_view = 8
+ glass_colour_type = /datum/client_colour/glass_colour/green
/obj/item/clothing/glasses/meson/gar
name = "gar mesons"
@@ -52,6 +55,7 @@
origin_tech = "magnets=2;engineering=1"
scan_reagents = 1 //You can see reagents while wearing science goggles
actions_types = list(/datum/action/item_action/toggle_research_scanner)
+ glass_colour_type = /datum/client_colour/glass_colour/purple
/obj/item/clothing/glasses/science/item_action_slot_check(slot)
if(slot == slot_glasses)
@@ -65,6 +69,7 @@
origin_tech = "materials=4;magnets=4;plasmatech=4;engineering=4"
darkness_view = 8
invis_view = SEE_INVISIBLE_MINIMUM
+ glass_colour_type = /datum/client_colour/glass_colour/green
/obj/item/clothing/glasses/eyepatch
name = "eyepatch"
@@ -85,6 +90,7 @@
item_state = "glasses"
origin_tech = "magnets=3;engineering=3"
vision_flags = SEE_OBJS
+ glass_colour_type = /datum/client_colour/glass_colour/lightblue
/obj/item/clothing/glasses/material/mining
name = "Optical Material Scanner"
@@ -105,6 +111,7 @@
attack_verb = list("sliced")
hitsound = 'sound/weapons/bladeslice.ogg'
sharpness = IS_SHARP
+ glass_colour_type = /datum/client_colour/glass_colour/lightgreen
/obj/item/clothing/glasses/regular
name = "Prescription Glasses"
@@ -133,7 +140,7 @@
darkness_view = 1
flash_protect = 1
tint = 1
-
+ glass_colour_type = /datum/client_colour/glass_colour/gray
dog_fashion = /datum/dog_fashion/head
/obj/item/clothing/glasses/sunglasses/reagent
@@ -173,6 +180,7 @@
attack_verb = list("sliced")
hitsound = 'sound/weapons/bladeslice.ogg'
sharpness = IS_SHARP
+ glass_colour_type = /datum/client_colour/glass_colour/orange
/obj/item/clothing/glasses/sunglasses/gar/supergar
desc = "We evolve past the person we were a minute before. Little by little we advance with each turn. That's how a drill works!"
@@ -181,6 +189,7 @@
item_state = "gar"
force = 12
throwforce = 12
+ glass_colour_type = /datum/client_colour/glass_colour/red
/obj/item/clothing/glasses/welding
name = "welding goggles"
@@ -193,6 +202,7 @@
tint = 2
flags_cover = GLASSESCOVERSEYES
visor_flags_inv = HIDEEYES
+ glass_colour_type = /datum/client_colour/glass_colour/gray
/obj/item/clothing/glasses/welding/attack_self()
@@ -230,6 +240,7 @@
vision_flags = SEE_MOBS
invis_view = 2
flash_protect = 0
+ glass_colour_type = /datum/client_colour/glass_colour/red
/obj/item/clothing/glasses/thermal/emp_act(severity)
thermal_overload()
@@ -273,12 +284,14 @@
desc = "A sweet pair of orange shades."
icon_state = "orangeglasses"
item_state = "orangeglasses"
+ glass_colour_type = /datum/client_colour/glass_colour/lightorange
/obj/item/clothing/glasses/red
name = "red glasses"
desc = "A sweet pair of red shades."
icon_state = "redglasses"
item_state = "redglasses"
+ glass_colour_type = /datum/client_colour/glass_colour/red
/obj/item/clothing/glasses/godeye
name = "eye of god"
@@ -356,3 +369,35 @@
icon_state = "gar"
item_state = "gar"
+
+/obj/item/clothing/glasses/AltClick(mob/user)
+ if(glass_colour_type && ishuman(user))
+ var/mob/living/carbon/human/H = user
+ if(H.client)
+ if(H.client.prefs)
+ if(src == H.glasses)
+ H.client.prefs.uses_glasses_colour = !H.client.prefs.uses_glasses_colour
+ if(H.client.prefs.uses_glasses_colour)
+ H << "You will now see glasses colors."
+ else
+ H << "You will no longer see glasses colors."
+ H.update_glasses_color(src, 1)
+ else
+ return ..()
+
+/obj/item/clothing/glasses/proc/change_glass_color(mob/living/carbon/human/H, datum/client_colour/glass_colour/new_color_type)
+ var/old_colour_type = glass_colour_type
+ if(!new_color_type || ispath(new_color_type)) //the new glass colour type must be null or a path.
+ glass_colour_type = new_color_type
+ if(H && H.glasses == src)
+ if(old_colour_type)
+ H.remove_client_colour(old_colour_type)
+ if(glass_colour_type)
+ H.update_glasses_color(src, 1)
+
+
+/mob/living/carbon/human/proc/update_glasses_color(obj/item/clothing/glasses/G, glasses_equipped)
+ if(client && client.prefs.uses_glasses_colour && glasses_equipped)
+ add_client_colour(G.glass_colour_type)
+ else
+ remove_client_colour(G.glass_colour_type)
diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm
index ba07bdd1aba..847208a09f4 100644
--- a/code/modules/clothing/glasses/hud.dm
+++ b/code/modules/clothing/glasses/hud.dm
@@ -6,6 +6,7 @@
var/hud_type = null
/obj/item/clothing/glasses/hud/equipped(mob/living/carbon/human/user, slot)
+ ..()
if(hud_type && slot == slot_glasses)
var/datum/atom_hud/H = huds[hud_type]
H.add_hud_to(user)
@@ -33,6 +34,7 @@
icon_state = "healthhud"
origin_tech = "magnets=3;biotech=2"
hud_type = DATA_HUD_MEDICAL_ADVANCED
+ glass_colour_type = /datum/client_colour/glass_colour/lightblue
/obj/item/clothing/glasses/hud/health/night
name = "Night Vision Health Scanner HUD"
@@ -42,6 +44,7 @@
origin_tech = "magnets=4;biotech=4;plasmatech=4;engineering=5"
darkness_view = 8
invis_view = SEE_INVISIBLE_MINIMUM
+ glass_colour_type = /datum/client_colour/glass_colour/green
/obj/item/clothing/glasses/hud/diagnostic
name = "Diagnostic HUD"
@@ -49,6 +52,7 @@
icon_state = "diagnostichud"
origin_tech = "magnets=2;engineering=2"
hud_type = DATA_HUD_DIAGNOSTIC
+ glass_colour_type = /datum/client_colour/glass_colour/lightorange
/obj/item/clothing/glasses/hud/diagnostic/night
name = "Night Vision Diagnostic HUD"
@@ -58,6 +62,7 @@
origin_tech = "magnets=4;powerstorage=4;plasmatech=4;engineering=5"
darkness_view = 8
invis_view = SEE_INVISIBLE_MINIMUM
+ glass_colour_type = /datum/client_colour/glass_colour/green
/obj/item/clothing/glasses/hud/security
name = "Security HUD"
@@ -65,6 +70,7 @@
icon_state = "securityhud"
origin_tech = "magnets=3;combat=2"
hud_type = DATA_HUD_SECURITY_ADVANCED
+ glass_colour_type = /datum/client_colour/glass_colour/red
/obj/item/clothing/glasses/hud/security/chameleon
name = "Chamleon Security HUD"
@@ -88,6 +94,7 @@
darkness_view = 1
flash_protect = 1
tint = 1
+ glass_colour_type = /datum/client_colour/glass_colour/darkred
/obj/item/clothing/glasses/hud/security/night
name = "Night Vision Security HUD"
@@ -96,6 +103,7 @@
origin_tech = "magnets=4;combat=4;plasmatech=4;engineering=5"
darkness_view = 8
invis_view = SEE_INVISIBLE_MINIMUM
+ glass_colour_type = /datum/client_colour/glass_colour/green
/obj/item/clothing/glasses/hud/security/sunglasses/gars
name = "HUD gar glasses"
@@ -151,16 +159,20 @@
hud_type = DATA_HUD_SECURITY_ADVANCED
vision_flags = SEE_MOBS
invis_view = 2
+ glass_colour_type = /datum/client_colour/glass_colour/red
/obj/item/clothing/glasses/hud/toggle/thermal/attack_self(mob/user)
..()
switch (hud_type)
if (DATA_HUD_MEDICAL_ADVANCED)
icon_state = "meson"
+ change_glass_color(user, /datum/client_colour/glass_colour/green)
if (DATA_HUD_SECURITY_ADVANCED)
icon_state = "thermal"
+ change_glass_color(user, /datum/client_colour/glass_colour/red)
else
icon_state = "purple"
+ change_glass_color(user, /datum/client_colour/glass_colour/purple)
user.update_inv_glasses()
/obj/item/clothing/glasses/hud/toggle/thermal/emp_act(severity)
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index f17cb08415b..11e77d18c1f 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -85,6 +85,10 @@
jetpack = new jetpack(src)
..()
+/obj/item/clothing/suit/space/hardsuit/attack_self(mob/user)
+ user.changeNext_move(CLICK_CD_MELEE)
+ ..()
+
/obj/item/clothing/suit/space/hardsuit/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/tank/jetpack/suit))
if(jetpack)
@@ -486,6 +490,28 @@
armor = list(melee = 45, bullet = 25, laser = 30, energy = 10, bomb = 25, bio = 100, rad = 50)
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/security/hos
+ //Captain
+/obj/item/clothing/head/helmet/space/hardsuit/captain
+ name = "captain's hardsuit helmet"
+ icon_state = "capspace"
+ item_state = "capspacehelmet"
+ desc = "A special hardsuit helmet designed for only the most fashionable of military figureheads."
+ armor = list(melee = 40, bullet = 50, laser = 50, energy = 25, bomb = 50, bio = 100, rad = 50)
+ actions_types = list()
+ flags_inv = HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR //we want to see the mask
+
+/obj/item/clothing/head/helmet/space/hardsuit/captain/attack_self()
+ return //Sprites required for flashlight
+
+/obj/item/clothing/suit/space/hardsuit/captain
+ name = "captain's hardsuit"
+ desc = "A bulky, heavy-duty piece of exclusive Nanotrasen hardsuit armor. YOU are in charge!"
+ icon_state = "caparmor"
+ item_state = "capspacesuit"
+ allowed = list(/obj/item/weapon/tank/internals, /obj/item/device/flashlight,/obj/item/weapon/gun/energy, /obj/item/weapon/gun/projectile, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs)
+ armor = list(melee = 40, bullet = 50, laser = 50, energy = 25, bomb = 50, bio = 100, rad = 50)
+ helmettype = /obj/item/clothing/head/helmet/space/hardsuit/captain
+
//Clown
/obj/item/clothing/head/helmet/space/hardsuit/clown
name = "cosmohonk hardsuit helmet"
diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm
index 1b902d27fe4..10bdf923bbb 100644
--- a/code/modules/clothing/spacesuits/miscellaneous.dm
+++ b/code/modules/clothing/spacesuits/miscellaneous.dm
@@ -14,26 +14,6 @@ Contains:
- Carp hardsuit
*/
- //Captain's space suit, not hardsuits because no flashlight!
-/obj/item/clothing/head/helmet/space/captain
- name = "captain's space helmet"
- icon_state = "capspace"
- item_state = "capspacehelmet"
- desc = "A special helmet designed for only the most fashionable of military figureheads."
- flags_inv = HIDEFACE|HIDEEARS|HIDEHAIR
- permeability_coefficient = 0.01
- armor = list(melee = 40, bullet = 50, laser = 50, energy = 25, bomb = 50, bio = 100, rad = 50)
-
-/obj/item/clothing/suit/space/captain
- name = "captain's space suit"
- desc = "A bulky, heavy-duty piece of exclusive Nanotrasen armor. YOU are in charge!"
- icon_state = "caparmor"
- item_state = "capspacesuit"
- w_class = 4
- allowed = list(/obj/item/weapon/tank/internals, /obj/item/device/flashlight,/obj/item/weapon/gun/energy, /obj/item/weapon/gun/projectile, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs)
- armor = list(melee = 40, bullet = 50, laser = 50, energy = 25, bomb = 50, bio = 100, rad = 50)
-
-
//Death squad armored space suits, not hardsuits!
/obj/item/clothing/head/helmet/space/hardsuit/deathsquad
name = "deathsquad helmet"
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index 1531c6780a0..5a77d9f2f7f 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -279,7 +279,7 @@
for(var/mob/living/M in view(6, owner))
if(M == owner)
continue
- owner.Beam(M,icon_state="lightning[rand(1, 12)]",icon='icons/effects/effects.dmi',time=5)
+ owner.Beam(M,icon_state="lightning[rand(1, 12)]",time=5)
M.adjustFireLoss(25)
playsound(M, 'sound/machines/defib_zap.ogg', 50, 1, -1)
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
diff --git a/code/modules/food_and_drinks/food/snacks/meat.dm b/code/modules/food_and_drinks/food/snacks/meat.dm
index d006bfb6ee7..ae777bcbcd1 100644
--- a/code/modules/food_and_drinks/food/snacks/meat.dm
+++ b/code/modules/food_and_drinks/food/snacks/meat.dm
@@ -190,6 +190,22 @@
icon_state = "meatwheat_clump"
bitesize = 4
+/obj/item/weapon/reagent_containers/food/snacks/meat/rawbacon
+ name = "raw piece of bacon"
+ desc = "A raw piece of bacon."
+ icon_state = "bacon"
+ cooked_type = /obj/item/weapon/reagent_containers/food/snacks/meat/bacon
+ bitesize = 2
+ list_reagents = list("nutriment" = 1)
+ filling_color = "#B22222"
+
+/obj/item/weapon/reagent_containers/food/snacks/meat/bacon
+ name = "piece of bacon"
+ desc = "A delicious piece of bacon."
+ icon_state = "baconcooked"
+ list_reagents = list("nutriment" = 2)
+ bonus_reagents = list("nutriment" = 1, "vitamin" = 1)
+
////////////////////////////////////// MEAT STEAKS ///////////////////////////////////////////////////////////
@@ -272,7 +288,6 @@
name = "raw spider cutlet"
cooked_type = /obj/item/weapon/reagent_containers/food/snacks/meat/cutlet/spider
-
//Cooked cutlets
/obj/item/weapon/reagent_containers/food/snacks/meat/cutlet
@@ -298,5 +313,4 @@
name = "xeno cutlet"
/obj/item/weapon/reagent_containers/food/snacks/meat/cutlet/spider
- name = "spider cutlet"
-
+ name = "spider cutlet"
\ No newline at end of file
diff --git a/code/modules/food_and_drinks/food/snacks_burgers.dm b/code/modules/food_and_drinks/food/snacks_burgers.dm
index 4cab54e9891..77e04689317 100644
--- a/code/modules/food_and_drinks/food/snacks_burgers.dm
+++ b/code/modules/food_and_drinks/food/snacks_burgers.dm
@@ -203,3 +203,9 @@
desc = "It's still warm. The steam coming off of it looks like baseball."
icon_state = "baseball"
bonus_reagents = list("nutriment" = 1, "vitamin" = 1)
+
+/obj/item/weapon/reagent_containers/food/snacks/burger/baconburger
+ name = "bacon burger"
+ desc = "The perfect combination of all things American."
+ icon_state = "baconburger"
+ bonus_reagents = list("nutriment" = 8, "vitamin" = 1)
diff --git a/code/modules/food_and_drinks/kitchen_machinery/processor.dm b/code/modules/food_and_drinks/kitchen_machinery/processor.dm
index ebbe4b1e4d2..41b3b987986 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/processor.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/processor.dm
@@ -3,7 +3,7 @@
name = "food processor"
desc = "An industrial grinder used to process meat and other foods. Keep hands clear of intake area while operating."
icon = 'icons/obj/kitchen.dmi'
- icon_state = "processor"
+ icon_state = "processor1"
layer = BELOW_OBJ_LAYER
density = 1
anchored = 1
@@ -90,6 +90,10 @@
input = /obj/item/weapon/reagent_containers/food/snacks/meat/slab
output = /obj/item/weapon/reagent_containers/food/snacks/faggot
+/datum/food_processor_process/bacon
+ input = /obj/item/weapon/reagent_containers/food/snacks/meat/rawcutlet
+ output = /obj/item/weapon/reagent_containers/food/snacks/meat/rawbacon
+
/datum/food_processor_process/sweetpotato
input = /obj/item/weapon/reagent_containers/food/snacks/grown/potato/sweet
output = /obj/item/weapon/reagent_containers/food/snacks/yakiimo
@@ -185,7 +189,7 @@
if(src.processing)
user << "The processor is in the process of processing!"
return 1
- if(default_deconstruction_screwdriver(user, "processor1", "processor", O))
+ if(default_deconstruction_screwdriver(user, "processor", "processor1", O))
return
if(exchange_parts(user, O))
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm
index 94b40722664..573574f4e9c 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm
@@ -262,3 +262,14 @@
)
result = /obj/item/weapon/reagent_containers/food/snacks/burger/baseball
category = CAT_BURGER
+
+/datum/crafting_recipe/food/baconburger
+ name = "Bacon Burger"
+ reqs = list(
+ /obj/item/weapon/reagent_containers/food/snacks/meat/bacon = 3,
+ /obj/item/weapon/reagent_containers/food/snacks/cheesewedge = 1,
+ /obj/item/weapon/reagent_containers/food/snacks/bun = 1
+ )
+
+ result = /obj/item/weapon/reagent_containers/food/snacks/burger/baconburger
+ category = CAT_BURGER
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_cake.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_cake.dm
index 8229391e50e..439db2986b0 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_cake.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_cake.dm
@@ -111,7 +111,7 @@
/obj/item/weapon/reagent_containers/food/snacks/meat/slab = 3,
/datum/reagent/blood = 30,
/datum/reagent/consumable/sprinkles = 5,
- /datum/reagent/toxin/teslium = 1 //To shock the whole thing into life
+ /datum/reagent/teslium = 1 //To shock the whole thing into life
)
result = /mob/living/simple_animal/pet/cat/cak
category = CAT_CAKE //Cat! Haha, get it? CAT? GET IT???
diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm
index 0fcfa4992c1..afcf5b0e83d 100644
--- a/code/modules/hydroponics/hydroponics.dm
+++ b/code/modules/hydroponics/hydroponics.dm
@@ -857,6 +857,10 @@
user.visible_message("[user] digs out the plants in [src]!", "You dig out all of [src]'s plants!")
playsound(src, 'sound/effects/shovel_dig.ogg', 50, 1)
if(myseed) //Could be that they're just using it as a de-weeder
+ age = 0
+ health = 0
+ if(harvest)
+ harvest = FALSE //To make sure they can't just put in another seed and insta-harvest it
qdel(myseed)
myseed = null
weedlevel = 0 //Has a side effect of cleaning up those nasty weeds
diff --git a/code/modules/jobs/job_types/cargo_service.dm b/code/modules/jobs/job_types/cargo_service.dm
index 460d9da5299..a5590867607 100644
--- a/code/modules/jobs/job_types/cargo_service.dm
+++ b/code/modules/jobs/job_types/cargo_service.dm
@@ -152,6 +152,7 @@ Cook
uniform = /obj/item/clothing/under/rank/chef
suit = /obj/item/clothing/suit/toggle/chef
head = /obj/item/clothing/head/chefhat
+ backpack_contents = list(/obj/item/weapon/sharpener = 1)
/datum/outfit/job/cook/pre_equip(mob/living/carbon/human/H)
..()
diff --git a/code/modules/mining/abandoned_crates.dm b/code/modules/mining/abandoned_crates.dm
index 40c2a19addb..9109ddefc76 100644
--- a/code/modules/mining/abandoned_crates.dm
+++ b/code/modules/mining/abandoned_crates.dm
@@ -11,12 +11,12 @@
/obj/structure/closet/crate/secure/loot/New()
..()
- var/list/digits = list("1", "2", "3", "4", "5", "6", "7", "8", "9", "z")
+ var/list/digits = list("1", "2", "3", "4", "5", "6", "7", "8", "9", "0")
code = ""
for(var/i = 0, i < codelen, i++)
var/dig = pick(digits)
code += dig
- digits -= dig //Player can enter codes with matching digits, but there are never matching digits in the answer
+ digits -= dig //there are never matching digits in the answer
var/loot = rand(1,100) //100 different crates with varying chances of spawning
switch(loot)
@@ -153,18 +153,26 @@
/obj/structure/closet/crate/secure/loot/attack_hand(mob/user)
if(locked)
user << "The crate is locked with a Deca-code lock."
- var/input = input(usr, "Enter [codelen] digits.", "Deca-Code Lock", "") as text
+ var/input = input(usr, "Enter [codelen] digits. All digits must be unique.", "Deca-Code Lock", "") as text
if(user.canUseTopic(src, 1))
+ var/list/sanitised = list()
+ var/sanitycheck = 1
+ for(var/i=1,i<=length(input),i++) //put the guess into a list
+ sanitised += text2num(copytext(input,i,i+1))
+ for(var/i=1,i<=(length(input)-1),i++) //compare each digit in the guess to all those following it
+ for(var/j=(i+1),j<=length(input),j++)
+ if(sanitised[i] == sanitised[j])
+ sanitycheck = null //if a digit is repeated, reject the input
if (input == code)
user << "The crate unlocks!"
locked = 0
cut_overlays()
add_overlay("securecrateg")
- else if (input == null || length(input) != codelen)
+ else if (input == null || sanitycheck == null || length(input) != codelen)
user << "You leave the crate alone."
else
user << "A red light flashes."
- lastattempt = replacetext(input, 0, "z")
+ lastattempt = input
attempts--
if(attempts == 0)
boom(user)
@@ -192,19 +200,21 @@
user << "* Anti-Tamper Bomb will activate after [src.attempts] failed access attempts."
if(lastattempt != null)
var/list/guess = list()
+ var/list/answer = list()
var/bulls = 0
var/cows = 0
- for(var/i = 1, i < codelen + 1, i++)
- var/a = copytext(lastattempt, i, i+1) //Stuff the code into the list
- guess += a
- guess[a] = i
- for(var/i in guess) //Go through list and count matches
- var/a = findtext(code, i)
- if(a == guess[i])
- ++bulls
- else if(a)
+ for(var/i=1,i<=length(lastattempt),i++)
+ guess += text2num(copytext(lastattempt,i,i+1))
+ for(var/i=1,i<=length(lastattempt),i++)
+ answer += text2num(copytext(code,i,i+1))
+ for(var/i = 1, i < codelen + 1, i++) // Go through list and count matches
+ if( answer.Find(guess[i],1,codelen+1))
++cows
- user << "Last code attempt had [bulls] correct digits at correct positions and [cows] correct digits at incorrect positions."
+ if( answer[i] == guess[i])
+ ++bulls
+ --cows
+
+ user << "Last code attempt, [lastattempt], had [bulls] correct digits at correct positions and [cows] correct digits at incorrect positions."
return
return ..()
diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index b18314e6e78..a26df35f156 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -48,7 +48,7 @@
if(16)
new /obj/item/weapon/guardiancreator(src)
if(17)
- new /obj/item/borg/upgrade/modkit/aoe/mobs(src)
+ new /obj/item/borg/upgrade/modkit/aoe/turfs/andmobs(src)
if(18)
new /obj/item/device/warp_cube/red(src)
if(19)
@@ -195,7 +195,7 @@
/obj/item/projectile/hook/fire(setAngle)
if(firer)
- chain = Beam(firer, icon_state = "chain", icon = 'icons/obj/lavaland/artefacts.dmi', time = INFINITY, maxdistance = INFINITY)
+ chain = firer.Beam(src, icon_state = "chain", time = INFINITY, maxdistance = INFINITY)
..()
/obj/item/projectile/hook/on_hit(atom/target)
@@ -704,15 +704,13 @@
/obj/structure/closet/crate/necropolis/bubblegum/New()
..()
- var/loot = rand(1,4)
+ var/loot = rand(1,3)
switch(loot)
if(1)
- new /obj/item/weapon/antag_spawner/slaughter_demon(src)
- if(2)
new /obj/item/mayhem(src)
- if(3)
+ if(2)
new /obj/item/blood_contract(src)
- if(4)
+ if(3)
new /obj/item/weapon/gun/magic/staff/spellblade(src)
/obj/item/blood_contract
diff --git a/code/modules/mining/machine_vending.dm b/code/modules/mining/machine_vending.dm
index fdb907cac4b..6c9143d943e 100644
--- a/code/modules/mining/machine_vending.dm
+++ b/code/modules/mining/machine_vending.dm
@@ -38,13 +38,14 @@
new /datum/data/mining_equipment("Mining Hardsuit", /obj/item/clothing/suit/space/hardsuit/mining, 2000),
new /datum/data/mining_equipment("Diamond Pickaxe", /obj/item/weapon/pickaxe/diamond, 2000),
new /datum/data/mining_equipment("Super Resonator", /obj/item/weapon/resonator/upgraded, 2500),
- new /datum/data/mining_equipment("KA White Tracer Rounds", /obj/item/borg/upgrade/modkit/tracer, 200),
- new /datum/data/mining_equipment("KA Adjustable Tracer Rounds", /obj/item/borg/upgrade/modkit/tracer/adjustable, 300),
- new /datum/data/mining_equipment("KA Super Chassis", /obj/item/borg/upgrade/modkit/chassis_mod, 400),
- new /datum/data/mining_equipment("KA Hyper Chassis", /obj/item/borg/upgrade/modkit/chassis_mod/orange, 500),
+ new /datum/data/mining_equipment("KA White Tracer Rounds", /obj/item/borg/upgrade/modkit/tracer, 100),
+ new /datum/data/mining_equipment("KA Adjustable Tracer Rounds", /obj/item/borg/upgrade/modkit/tracer/adjustable, 150),
+ new /datum/data/mining_equipment("KA Super Chassis", /obj/item/borg/upgrade/modkit/chassis_mod, 250),
+ new /datum/data/mining_equipment("KA Hyper Chassis", /obj/item/borg/upgrade/modkit/chassis_mod/orange, 300),
new /datum/data/mining_equipment("KA Range Increase", /obj/item/borg/upgrade/modkit/range, 1000),
new /datum/data/mining_equipment("KA Damage Increase", /obj/item/borg/upgrade/modkit/damage, 1000),
new /datum/data/mining_equipment("KA Cooldown Decrease",/obj/item/borg/upgrade/modkit/cooldown, 1000),
+ new /datum/data/mining_equipment("KA AoE Damage", /obj/item/borg/upgrade/modkit/aoe/mobs, 2000),
new /datum/data/mining_equipment("Point Transfer Card", /obj/item/weapon/card/mining_point_card, 500),
new /datum/data/mining_equipment("Mining Drone", /mob/living/simple_animal/hostile/mining_drone, 800),
new /datum/data/mining_equipment("Drone Melee Upgrade", /obj/item/device/mine_bot_ugprade, 400),
diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm
index bf154f66071..1bd06bab451 100644
--- a/code/modules/mining/mine_items.dm
+++ b/code/modules/mining/mine_items.dm
@@ -313,7 +313,6 @@
desc = "An easily-compressable wall used for temporary shelter."
icon = 'icons/turf/walls/survival_pod_walls.dmi'
icon_state = "smooth"
- walltype = "shuttle"
smooth = SMOOTH_MORE|SMOOTH_DIAGONAL
canSmoothWith = list(/turf/closed/wall/shuttle/survival, /obj/machinery/door/airlock/survival_pod, /obj/structure/window/shuttle/survival_pod, /obj/structure/shuttle/engine)
diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm
index ecaf9f1c75f..377d8ac3b15 100644
--- a/code/modules/mob/inventory.dm
+++ b/code/modules/mob/inventory.dm
@@ -266,6 +266,7 @@
if(client)
client.screen -= I
I.layer = initial(I.layer)
+ I.appearance_flags &= ~NO_CLIENT_COLOR
I.forceMove(loc)
I.dropped(src)
return TRUE
diff --git a/code/modules/mob/living/carbon/alien/larva/life.dm b/code/modules/mob/living/carbon/alien/larva/life.dm
index 0f4de4b6890..0ff617d7532 100644
--- a/code/modules/mob/living/carbon/alien/larva/life.dm
+++ b/code/modules/mob/living/carbon/alien/larva/life.dm
@@ -6,7 +6,7 @@
if (notransform)
return
- if(..())
+ if(..()) //not dead
// GROW!
if(amount_grown < max_grown)
amount_grown++
diff --git a/code/modules/mob/living/carbon/alien/special/facehugger.dm b/code/modules/mob/living/carbon/alien/special/facehugger.dm
index 95387d85691..58551f671e1 100644
--- a/code/modules/mob/living/carbon/alien/special/facehugger.dm
+++ b/code/modules/mob/living/carbon/alien/special/facehugger.dm
@@ -91,7 +91,7 @@ var/const/MAX_ACTIVE_TIME = 400
return Attach(AM)
return 0
-/obj/item/clothing/mask/facehugger/throw_at(atom/target, range, speed, mob/thrower, spin)
+/obj/item/clothing/mask/facehugger/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0)
if(!..())
return
if(stat == CONSCIOUS)
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 0198c4a1cf8..94ee29b74b0 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -672,7 +672,8 @@
if(B)
B.damaged_brain = 0
for(var/datum/disease/D in viruses)
- D.cure(0)
+ if (D.severity != NONTHREAT)
+ D.cure(0)
if(admin_revive)
regenerate_limbs()
handcuffed = initial(handcuffed)
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 6aae26c14c5..7b71530d27f 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -191,18 +191,26 @@
for(var/obj/item/I in BP.embedded_objects)
msg += "[t_He] [t_has] \a \icon[I] [I] embedded in [t_his] [BP.name]!\n"
- //stores how many left limbs are missing
+ //stores missing limbs
var/l_limbs_missing = 0
+ var/r_limbs_missing = 0
for(var/t in missing)
if(t=="head")
msg += "[capitalize(t_his)] [parse_zone(t)] is missing!\n"
continue
if(t == "l_arm" || t == "l_leg")
l_limbs_missing++
+ else if(t == "r_arm" || t == "r_leg")
+ r_limbs_missing++
+
msg += "[capitalize(t_his)] [parse_zone(t)] is missing!\n"
- if(l_limbs_missing >= 2)
+ if(l_limbs_missing >= 2 && r_limbs_missing == 0)
msg += "[t_He] looks all right now.\n"
+ else if(l_limbs_missing == 0 && r_limbs_missing >= 2)
+ msg += "[t_He] really keeps to the left.\n"
+ else if(l_limbs_missing >= 2 && r_limbs_missing >= 2)
+ msg += "[t_He] doesn't seem all there.\n"
if(temp)
if(temp < 30)
diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm
index 98d53ef104f..3bb4c433f4c 100644
--- a/code/modules/mob/living/carbon/human/human_movement.dm
+++ b/code/modules/mob/living/carbon/human/human_movement.dm
@@ -15,7 +15,7 @@
return 0
return ..()
-/mob/living/carbon/human/has_gravity()
+/mob/living/carbon/human/mob_has_gravity()
. = ..()
if(!.)
if(mob_negates_gravity())
diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm
index 3283e04d22e..7a0cb8e246a 100644
--- a/code/modules/mob/living/carbon/human/inventory.dm
+++ b/code/modules/mob/living/carbon/human/inventory.dm
@@ -69,6 +69,8 @@
if(slot_glasses)
glasses = I
var/obj/item/clothing/glasses/G = I
+ if(G.glass_colour_type)
+ update_glasses_color(G, 1)
if(G.tint)
update_tint()
if(G.vision_correction)
@@ -144,6 +146,8 @@
else if(I == glasses)
glasses = null
var/obj/item/clothing/glasses/G = I
+ if(G.glass_colour_type)
+ update_glasses_color(G, 0)
if(G.tint)
update_tint()
if(G.vision_correction)
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 0c3b27ba8d1..5d7003106aa 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -29,20 +29,26 @@
if (notransform)
return
- if(..())
+ if(..()) //not dead
for(var/datum/mutation/human/HM in dna.mutations)
HM.on_life(src)
+ if(stat != DEAD)
//heart attack stuff
handle_heart()
+ if(stat != DEAD)
//Stuff jammed in your limbs hurts
handle_embedded_objects()
+
//Update our name based on whether our face is obscured/disfigured
name = get_visible_name()
dna.species.spec_life(src) // for mutantraces
+ if(stat != DEAD)
+ return 1
+
/mob/living/carbon/human/calculate_affecting_pressure(pressure)
if((wear_suit && (wear_suit.flags & STOPSPRESSUREDMAGE)) && (head && (head.flags & STOPSPRESSUREDMAGE)))
diff --git a/code/modules/mob/living/carbon/human/species_types.dm b/code/modules/mob/living/carbon/human/species_types.dm
index 3369741b53c..97d1a2dd8ab 100644
--- a/code/modules/mob/living/carbon/human/species_types.dm
+++ b/code/modules/mob/living/carbon/human/species_types.dm
@@ -172,6 +172,34 @@
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/shadow
specflags = list(NOBREATH,NOBLOOD,RADIMMUNE,VIRUSIMMUNE)
dangerous_existence = 1
+ var/datum/action/innate/shadow/darkvision/vision_toggle
+
+/datum/action/innate/shadow/darkvision //Darkvision toggle so shadowpeople can actually see where darkness is
+ name = "Toggle Darkvision"
+ check_flags = AB_CHECK_CONSCIOUS
+ background_icon_state = "bg_default"
+ button_icon_state = "blind"
+
+/datum/action/innate/shadow/darkvision/Activate()
+ var/mob/living/carbon/human/H = owner
+ if(H.see_in_dark < 8)
+ H.see_in_dark = 8
+ H.see_invisible = SEE_INVISIBLE_MINIMUM
+ H << "You adjust your vision to pierce the darkness."
+ else
+ H.see_in_dark = 2
+ H.see_invisible = SEE_INVISIBLE_LIVING
+ H << "You adjust your vision to recognize the shadows."
+
+/datum/species/shadow/on_species_gain(mob/living/carbon/C, datum/species/old_species)
+ . = ..()
+ vision_toggle = new
+ vision_toggle.Grant(C)
+
+/datum/species/shadow/on_species_loss(mob/living/carbon/C)
+ . = ..()
+ if(vision_toggle)
+ vision_toggle.Remove(C)
/datum/species/shadow/spec_life(mob/living/carbon/human/H)
var/light_amount = 0
diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm
index e44a4bad371..e399110909f 100644
--- a/code/modules/mob/living/carbon/inventory.dm
+++ b/code/modules/mob/living/carbon/inventory.dm
@@ -37,6 +37,7 @@
observe.client.screen -= I
I.loc = src
I.layer = ABOVE_HUD_LAYER
+ I.appearance_flags |= NO_CLIENT_COLOR
var/not_handled = FALSE
switch(slot)
if(slot_back)
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index aa701d7f1b3..aa898296f9a 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -9,11 +9,10 @@
damageoverlaytemp = 0
update_damage_hud()
- if(..())
- . = 1
-
+ if(..()) //not dead
handle_blood()
+ if(stat != DEAD)
for(var/X in internal_organs)
var/obj/item/organ/O = X
O.on_life()
@@ -21,6 +20,9 @@
//Updates the number of stored chemicals for powers
handle_changeling()
+ if(stat != DEAD)
+ return 1
+
///////////////
// BREATHING //
///////////////
diff --git a/code/modules/mob/living/carbon/monkey/punpun.dm b/code/modules/mob/living/carbon/monkey/punpun.dm
index d892512aecb..995c30f6fed 100644
--- a/code/modules/mob/living/carbon/monkey/punpun.dm
+++ b/code/modules/mob/living/carbon/monkey/punpun.dm
@@ -11,10 +11,6 @@
/mob/living/carbon/monkey/punpun/New()
Read_Memory()
- if(relic_hat)
- equip_to_slot_or_del(new relic_hat, slot_head)
- if(relic_mask)
- equip_to_slot_or_del(new relic_mask, slot_wear_mask)
if(ancestor_name)
name = ancestor_name
if(ancestor_chain > 1)
@@ -27,6 +23,14 @@
gender = pick(MALE, FEMALE)
..()
+ //These have to be after the parent new to ensure that the monkey
+ //bodyparts are actually created before we try to equip things to
+ //those slots
+ if(relic_hat)
+ equip_to_slot_or_del(new relic_hat, slot_head)
+ if(relic_mask)
+ equip_to_slot_or_del(new relic_mask, slot_wear_mask)
+
/mob/living/carbon/monkey/punpun/Life()
if(ticker.current_state == GAME_STATE_FINISHED && !memory_saved)
Write_Memory(0)
diff --git a/code/modules/mob/living/carbon/say.dm b/code/modules/mob/living/carbon/say.dm
index 0b6c2cae108..8b1e3b65298 100644
--- a/code/modules/mob/living/carbon/say.dm
+++ b/code/modules/mob/living/carbon/say.dm
@@ -24,3 +24,7 @@
var/obj/item/organ/tongue/T = getorganslot("tongue")
if(T)
. |= T.get_spans()
+
+ var/obj/item/I = get_active_held_item()
+ if(I)
+ . |= I.get_held_item_speechspans(src)
diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm
index 10c9a2a50f8..6695c4a1271 100644
--- a/code/modules/mob/living/death.dm
+++ b/code/modules/mob/living/death.dm
@@ -3,13 +3,9 @@
if(stat != DEAD)
death(1)
- if(buckled)
- buckled.unbuckle_mob(src,force=1) //to update alien nest overlay, forced because we don't exist anymore
-
if(!prev_lying)
gib_animation()
-
spill_organs(no_brain, no_organs, no_bodyparts)
if(!no_bodyparts)
@@ -64,8 +60,6 @@
living_mob_list -= src
if(!gibbed)
dead_mob_list += src
- else if(buckled)
- buckled.unbuckle_mob(src,force=1)
paralysis = 0
stunned = 0
weakened = 0
diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm
index 052328ac563..19cca48a15b 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -19,21 +19,18 @@
var/datum/gas_mixture/environment = loc.return_air()
if(stat != DEAD)
-
//Breathing, if applicable
handle_breathing()
-
+ if(stat != DEAD)
//Mutations and radiation
handle_mutations_and_radiation()
-
+ if(stat != DEAD)
//Chemicals in the body
handle_chemicals_in_body()
-
+ if(stat != DEAD)
//Random events (vomiting etc)
handle_random_events()
- . = 1
-
//Handle temperature/pressure differences between body and environment
if(environment)
handle_environment(environment)
@@ -43,16 +40,19 @@
//stuff in the stomach
handle_stomach()
- update_gravity(has_gravity())
+ update_gravity(mob_has_gravity())
if(machine)
machine.check_eye(src)
-
if(stat != DEAD)
handle_disabilities() // eye, ear, brain damages
+ if(stat != DEAD)
handle_status_effects() //all special effects, stunned, weakened, jitteryness, hallucination, sleeping, etc
+ if(stat != DEAD)
+ return 1
+
/mob/living/proc/handle_breathing()
return
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index b06fef840ca..74a24079251 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -29,6 +29,9 @@
/mob/living/Destroy()
..()
+ if(buckled)
+ buckled.unbuckle_mob(src,force=1)
+
for(var/mob/living/simple_animal/drone/D in player_list)
for(var/image/I in staticOverlays)
D.staticOverlays.Remove(I)
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index 06e5ad4ff7f..59ab34a98eb 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -92,11 +92,12 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
if(message_mode != MODE_WHISPER) //whisper() calls treat_message(); double process results in "hisspering"
message = treat_message(message)
- spans += get_spans()
if(!message)
return
+ spans += get_spans()
+
//Log of what we've said, plain message, no spans or junk
say_log += message
diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm
index 0c3b45c2d5c..c4a68499d21 100644
--- a/code/modules/mob/living/silicon/ai/life.dm
+++ b/code/modules/mob/living/silicon/ai/life.dm
@@ -4,12 +4,12 @@
#define POWER_RESTORATION_APC_FOUND 3
/mob/living/silicon/ai/Life()
- if (src.stat == DEAD)
+ if (stat == DEAD)
return
else //I'm not removing that shitton of tabs, unneeded as they are. -- Urist
//Being dead doesn't mean your temperature never changes
- update_gravity(has_gravity())
+ update_gravity(mob_has_gravity())
if(malfhack && malfhack.aidisabled)
deltimer(malfhacking)
diff --git a/code/modules/mob/living/silicon/login.dm b/code/modules/mob/living/silicon/login.dm
index 87e348dd92c..e0c6708d564 100644
--- a/code/modules/mob/living/silicon/login.dm
+++ b/code/modules/mob/living/silicon/login.dm
@@ -3,5 +3,4 @@
ticker.mode.remove_cultist(mind, 0, 0)
ticker.mode.remove_revolutionary(mind, 0)
ticker.mode.remove_gangster(mind, remove_bosses=1)
- ticker.mode.remove_hog_follower(mind,0)
..()
diff --git a/code/modules/mob/living/silicon/pai/life.dm b/code/modules/mob/living/silicon/pai/life.dm
index 191f28d7c37..f934a959316 100644
--- a/code/modules/mob/living/silicon/pai/life.dm
+++ b/code/modules/mob/living/silicon/pai/life.dm
@@ -1,7 +1,7 @@
/mob/living/silicon/pai/Life()
- if (src.stat == DEAD)
+ if(stat == DEAD)
return
- if(src.cable)
+ if(cable)
if(get_dist(src, src.cable) > 1)
var/turf/T = get_turf(src.loc)
T.visible_message("[src.cable] rapidly retracts back into its spool.", "You hear a click and the sound of wire spooling rapidly.")
diff --git a/code/modules/mob/living/silicon/robot/login.dm b/code/modules/mob/living/silicon/robot/login.dm
index 30712e68b42..59bcff4fa60 100644
--- a/code/modules/mob/living/silicon/robot/login.dm
+++ b/code/modules/mob/living/silicon/robot/login.dm
@@ -6,4 +6,3 @@
if(mind)
ticker.mode.remove_revolutionary(mind)
ticker.mode.remove_gangster(mind,1,remove_bosses=1)
- ticker.mode.remove_hog_follower(mind, 0)
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 76f8e90ef6e..6f56ca375b9 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -785,9 +785,8 @@
if(isturf(tile))
tile.clean_blood()
for(var/A in tile)
- if(istype(A, /obj/effect))
- if(is_cleanable(A))
- qdel(A)
+ if(is_cleanable(A))
+ qdel(A)
else if(istype(A, /obj/item))
var/obj/item/cleaned_item = A
cleaned_item.clean_blood()
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index 34017a7c64e..7658a71c484 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -402,4 +402,4 @@
/datum/robot_energy_storage/medical
max_energy = 2500
recharge_rate = 250
- name = "Medical Synthesizer"
+ name = "Medical Synthesizer"
diff --git a/code/modules/mob/living/silicon/robot/robot_movement.dm b/code/modules/mob/living/silicon/robot/robot_movement.dm
index 695ea3e4978..63d76801c78 100644
--- a/code/modules/mob/living/silicon/robot/robot_movement.dm
+++ b/code/modules/mob/living/silicon/robot/robot_movement.dm
@@ -11,7 +11,7 @@
/mob/living/silicon/robot/mob_negates_gravity()
return magpulse
-/mob/living/silicon/robot/has_gravity()
+/mob/living/silicon/robot/mob_has_gravity()
return ..() || mob_negates_gravity()
/mob/living/silicon/robot/experience_pressure_difference(pressure_difference, direction)
diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm
index a26f78cecf2..af34d8a989f 100644
--- a/code/modules/mob/living/simple_animal/constructs.dm
+++ b/code/modules/mob/living/simple_animal/constructs.dm
@@ -55,7 +55,7 @@
if(health < maxHealth)
adjustHealth(-5)
if(src != M)
- Beam(M,icon_state="sendbeam",icon='icons/effects/effects.dmi',time=4)
+ Beam(M,icon_state="sendbeam",time=4)
M.visible_message("[M] repairs some of \the [src]'s dents.", \
"You repair some of [src]'s dents, leaving [src] at [health]/[maxHealth] health.")
else
diff --git a/code/modules/mob/living/simple_animal/friendly/cockroach.dm b/code/modules/mob/living/simple_animal/friendly/cockroach.dm
index 9d6a9ab7f64..fc4045ae569 100644
--- a/code/modules/mob/living/simple_animal/friendly/cockroach.dm
+++ b/code/modules/mob/living/simple_animal/friendly/cockroach.dm
@@ -53,4 +53,3 @@
icon = 'icons/effects/blood.dmi'
icon_state = "xfloor1"
random_icon_states = list("xfloor1", "xfloor2", "xfloor3", "xfloor4", "xfloor5", "xfloor6", "xfloor7")
- layer = ABOVE_OPEN_TURF_LAYER
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
index 2d22e293753..fb94224fbbf 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
@@ -46,7 +46,7 @@
staticOverlays = list()
hud_possible = list(DIAG_STAT_HUD, DIAG_HUD, ANTAG_HUD)
unique_name = TRUE
- faction = list("silicon")
+ faction = list("neutral","silicon")
dextrous = TRUE
dextrous_hud_type = /datum/hud/dextrous/drone
var/staticChoice = "static"
@@ -245,7 +245,7 @@
/mob/living/simple_animal/drone/mob_negates_gravity()
return 1
-/mob/living/simple_animal/drone/has_gravity()
+/mob/living/simple_animal/drone/mob_has_gravity()
return ..() || mob_negates_gravity()
/mob/living/simple_animal/drone/experience_pressure_difference(pressure_difference, direction)
diff --git a/code/modules/mob/living/simple_animal/guardian/types/lightning.dm b/code/modules/mob/living/simple_animal/guardian/types/lightning.dm
index 38a03707ef2..a37b4788297 100644
--- a/code/modules/mob/living/simple_animal/guardian/types/lightning.dm
+++ b/code/modules/mob/living/simple_animal/guardian/types/lightning.dm
@@ -30,7 +30,7 @@
var/datum/beam/C = pick(enemychains)
qdel(C)
enemychains -= C
- enemychains += Beam(target,"lightning[rand(1,12)]",'icons/effects/effects.dmi',70, 7,/obj/effect/ebeam/chain)
+ enemychains += Beam(target, "lightning[rand(1,12)]", time=70, maxdistance=7, beam_type=/obj/effect/ebeam/chain)
/mob/living/simple_animal/hostile/guardian/beam/Destroy()
removechains()
@@ -39,7 +39,7 @@
/mob/living/simple_animal/hostile/guardian/beam/Manifest()
if(..())
if(summoner)
- summonerchain = Beam(summoner,"lightning[rand(1,12)]",'icons/effects/effects.dmi',INFINITY, INFINITY,/obj/effect/ebeam/chain)
+ summonerchain = Beam(summoner, "lightning[rand(1,12)]", time=INFINITY, maxdistance=INFINITY, beam_type=/obj/effect/ebeam/chain)
while(loc != summoner)
if(successfulshocks > 5)
successfulshocks = 0
@@ -57,7 +57,7 @@
if(summonerchain && !qdeleted(summonerchain))
. += chainshock(summonerchain)
else
- summonerchain = Beam(summoner,"lightning[rand(1,12)]",'icons/effects/effects.dmi',INFINITY, INFINITY,/obj/effect/ebeam/chain)
+ summonerchain = Beam(summoner, "lightning[rand(1,12)]", time=INFINITY, maxdistance=INFINITY, beam_type=/obj/effect/ebeam/chain)
if(enemychains.len)
for(var/chain in enemychains)
if(!qdeleted(chain))
diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm
index 2f75310ff25..f5c9269c0d9 100644
--- a/code/modules/mob/living/simple_animal/hostile/hostile.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm
@@ -27,6 +27,7 @@
var/ranged_message = "fires" //Fluff text for ranged mobs
var/ranged_cooldown = 0 //What the current cooldown on ranged attacks is, generally world.time + ranged_cooldown_time
var/ranged_cooldown_time = 30 //How long, in deciseconds, the cooldown of ranged attacks is
+ var/ranged_ignores_vision = FALSE //if it'll fire ranged attacks even if it lacks vision on its target, only works with environment smash
var/check_friendly_fire = 0 // Should the ranged mob check for friendlies when shooting
var/retreat_distance = null //If our mob runs from players when they're too close, set in tile distance. By default, mobs do not retreat.
var/minimum_distance = 1 //Minimum approach distance, so ranged mobs chase targets down, but still keep their distance set in tiles to the target, set higher to make mobs keep distance
@@ -53,6 +54,10 @@
environment_target_typecache = typecacheof(environment_target_typecache)
+/mob/living/simple_animal/hostile/Destroy()
+ targets_from = null
+ return ..()
+
/mob/living/simple_animal/hostile/Life()
. = ..()
if(!.) //dead
@@ -225,12 +230,14 @@
else
Goto(target,move_to_delay,minimum_distance)
if(target)
- if(isturf(targets_from.loc) && target.Adjacent(targets_from)) //If they're next to us, attack
+ if(targets_from && isturf(targets_from.loc) && target.Adjacent(targets_from)) //If they're next to us, attack
AttackingTarget()
return 1
return 0
if(environment_smash)
if(target.loc != null && get_dist(targets_from, target.loc) <= vision_range) //We can't see our target, but he's in our vision range still
+ if(ranged_ignores_vision && ranged_cooldown <= world.time) //we can't see our target... but we can fire at them!
+ OpenFire(target)
if(environment_smash >= 2) //If we're capable of smashing through walls, forget about vision completely after finding our target
Goto(target,move_to_delay,minimum_distance)
FindHidden()
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
index c3a657616f8..b64463f3b7c 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
@@ -9,15 +9,15 @@ Bubblegum's footsteps are heralded by shaking booms, proving its tremendous size
It acts as a melee creature, chasing down and attacking its target while also using different attacks to augment its power that increase as it takes damage.
-It often charges, dealing massive damage to anything unfortunate enough to be standing where it's aiming.
-Whenever it isn't chasing something down, it will sink into nearby blood pools (if possible) and springs out of the closest one to its target.
-To make this possible, it sprays streams of blood at random.
-From these blood pools Bubblegum may summon slaughterlings - weak, low-damage minions designed to impede the target's progress.
+It tries to strike at its target through any bloodpools under them; if it fails to do that, it will spray blood and then attempt to warp to a bloodpool near the target.
+If it fails to warp to a target, it may summon up to 6 slaughterlings from the blood around it.
+If it does not summon all 6 slaughterlings, it will instead charge at its target, dealing massive damage to anything it hits and spraying a stream of blood.
+At half health, it will either charge three times or warp, then charge, instead of doing a single charge.
When Bubblegum dies, it leaves behind a chest that can contain three things:
- 1. A slaughter demon spawner
- 2. A bottle that, when activated, drives everyone nearby into a frenzy
- 3. A contract that marks for death the chosen target
+ 1. A bottle that, when activated, drives everyone nearby into a frenzy
+ 2. A contract that marks for death the chosen target
+ 3. A spellblade that can slice off limbs at range
Difficulty: Hard
@@ -45,6 +45,7 @@ Difficulty: Hard
pixel_x = -32
del_on_death = 1
loot = list(/obj/structure/closet/crate/necropolis/bubblegum)
+ blood_volume = BLOOD_VOLUME_MAXIMUM //BLEED FOR ME
var/charging = 0
medal_type = MEDAL_PREFIX
score_type = BUBBLEGUM_SCORE
@@ -57,6 +58,12 @@ Difficulty: Hard
desc = "You're not quite sure how a signal can be bloody."
invisibility = 100
+/mob/living/simple_animal/hostile/megafauna/bubblegum/adjustBruteLoss(amount)
+ if(amount > 0 && prob(33))
+ var/obj/effect/decal/cleanable/blood/B = new /obj/effect/decal/cleanable/blood(loc)
+ B.bloodiness = 20
+ . = ..()
+
/mob/living/simple_animal/hostile/megafauna/bubblegum/Life()
..()
move_to_delay = Clamp(round((health/maxHealth) * 10), 5, 10)
@@ -67,18 +74,21 @@ Difficulty: Hard
return
ranged_cooldown = world.time + ranged_cooldown_time
- blood_warp()
-
- if(prob(25))
+ var/warped = FALSE
+ if(!try_bloodattack())
addtimer(src, "blood_spray", 0)
+ warped = blood_warp()
+ if(warped && prob(100 - anger_modifier))
+ return
- else if(prob(5+anger_modifier/2))
- slaughterlings()
- else
- if(health > maxHealth/2 && !client)
+ if(prob(90 - anger_modifier) || slaughterlings())
+ if(health > maxHealth * 0.5 || client)
addtimer(src, "charge", 0)
else
- addtimer(src, "triple_charge", 0)
+ if(prob(70) || warped)
+ addtimer(src, "triple_charge", 0)
+ else
+ addtimer(src, "warp_charge", 0)
/mob/living/simple_animal/hostile/megafauna/bubblegum/New()
@@ -109,20 +119,22 @@ Difficulty: Hard
..()
/mob/living/simple_animal/hostile/megafauna/bubblegum/Move()
- if(!stat)
- playsound(src.loc, 'sound/effects/meteorimpact.ogg', 200, 1, 2, 1)
if(charging)
PoolOrNew(/obj/effect/overlay/temp/decoy/fading, list(loc,src))
DestroySurroundings()
. = ..()
+ if(!stat && .)
+ playsound(src, 'sound/effects/meteorimpact.ogg', 200, 1, 2, 1)
if(charging)
DestroySurroundings()
+/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/warp_charge()
+ blood_warp()
+ charge()
+
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/triple_charge()
charge()
- sleep(10)
charge()
- sleep(10)
charge()
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/charge()
@@ -135,11 +147,11 @@ Difficulty: Hard
walk(src, 0)
setDir(get_dir(src, T))
var/obj/effect/overlay/temp/decoy/D = PoolOrNew(/obj/effect/overlay/temp/decoy, list(loc,src))
- D.color = "#FF0000"
- animate(D, alpha = 0, color = initial(D.color), transform = matrix()*2, time = 5)
+ animate(D, alpha = 0, color = "#FF0000", transform = matrix()*2, time = 5)
sleep(5)
throw_at(T, get_dist(src, T), 1, src, 0)
charging = 0
+ try_bloodattack()
Goto(target, move_to_delay, minimum_distance)
@@ -167,17 +179,132 @@ Difficulty: Hard
charging = 0
+/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/get_mobs_on_blood()
+ var/list/targets = ListTargets()
+ . = list()
+ for(var/mob/living/L in targets)
+ var/list/bloodpool = get_pools(get_turf(L), 0)
+ if(bloodpool.len && !faction_check(L))
+ . += L
+
+/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/try_bloodattack()
+ var/list/targets = get_mobs_on_blood()
+ if(targets.len)
+ addtimer(src, "bloodattack", 0, FALSE, targets)
+
+ return TRUE
+ return FALSE
+
+/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/bloodattack(list/targets)
+ var/mob/living/target_one = pick_n_take(targets)
+ var/turf/target_one_turf = get_turf(target_one)
+ var/mob/living/target_two
+ if(targets.len)
+ target_two = pick_n_take(targets)
+ var/turf/target_two_turf = get_turf(target_two)
+ if(target_two.stat != CONSCIOUS || prob(10))
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/rightpaw, target_two_turf)
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/rightthumb, target_two_turf)
+ bloodgrab(target_two_turf)
+ else
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/rightsmack, target_two_turf)
+ bloodsmack(target_two_turf)
+
+ var/list/pools = get_pools(get_turf(target_one), 0)
+ if(pools.len)
+ target_one_turf = get_turf(target_one)
+ if(target_one.stat != CONSCIOUS || prob(10))
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/leftpaw, target_one_turf)
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/leftthumb, target_one_turf)
+ bloodgrab(target_one_turf)
+ else
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/leftsmack, target_one_turf)
+ bloodsmack(target_one_turf)
+
+ if(!target_two && target_one)
+ pools = get_pools(get_turf(target_one), 0)
+ if(pools.len)
+ target_one_turf = get_turf(target_one)
+ if(target_one.stat != CONSCIOUS || prob(10))
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/rightpaw, target_one_turf)
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/rightthumb, target_one_turf)
+ bloodgrab(target_one_turf)
+ else
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/rightsmack, target_one_turf)
+ bloodsmack(target_one_turf)
+
+/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/bloodsmack(turf/T)
+ sleep(2.5)
+ for(var/mob/living/L in T)
+ if(!faction_check(L))
+ L << "[src] rends you!"
+ playsound(T, attack_sound, 100, 1, -1)
+ var/limb_to_hit = L.get_bodypart(pick("head", "chest", "r_arm", "l_arm", "r_leg", "l_leg"))
+ L.apply_damage(25, BRUTE, limb_to_hit, L.run_armor_check(limb_to_hit, "melee", null, null, armour_penetration))
+ sleep(3)
+
+/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/bloodgrab(turf/T)
+ sleep(6)
+ for(var/mob/living/L in T)
+ if(!faction_check(L))
+ L << "[src] drags you through the blood!"
+ playsound(T, 'sound/magic/enter_blood.ogg', 100, 1, -1)
+ var/turf/targetturf = get_step(src, dir)
+ L.forceMove(targetturf)
+ playsound(targetturf, 'sound/magic/exit_blood.ogg', 100, 1, -1)
+ if(L.stat != CONSCIOUS)
+ addtimer(src, "devour", 2, FALSE, L)
+ sleep(1)
+
+/obj/effect/overlay/temp/bubblegum_hands
+ icon = 'icons/effects/bubblegum.dmi'
+ duration = 9
+
+/obj/effect/overlay/temp/bubblegum_hands/rightthumb
+ icon_state = "rightthumbgrab"
+
+/obj/effect/overlay/temp/bubblegum_hands/leftthumb
+ icon_state = "leftthumbgrab"
+
+/obj/effect/overlay/temp/bubblegum_hands/rightpaw
+ icon_state = "rightpawgrab"
+ layer = BELOW_MOB_LAYER
+
+/obj/effect/overlay/temp/bubblegum_hands/leftpaw
+ icon_state = "leftpawgrab"
+ layer = BELOW_MOB_LAYER
+
+/obj/effect/overlay/temp/bubblegum_hands/rightsmack
+ icon_state = "rightsmack"
+
+/obj/effect/overlay/temp/bubblegum_hands/leftsmack
+ icon_state = "leftsmack"
+
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/blood_warp()
+ if(Adjacent(target))
+ return FALSE
+ var/list/can_jaunt = get_pools(get_turf(src), 1)
+ if(!can_jaunt.len)
+ return FALSE
+
+ var/list/pools = get_pools(get_turf(target), 2)
+ var/list/pools_to_remove = get_pools(get_turf(target), 1)
+ pools -= pools_to_remove
+ if(!pools.len)
+ return FALSE
+
+ var/obj/effect/overlay/temp/decoy/DA = PoolOrNew(/obj/effect/overlay/temp/decoy, list(loc,src))
+ DA.color = "#FF0000"
+ var/oldtransform = DA.transform
+ DA.transform = matrix()*2
+ animate(DA, alpha = 255, color = initial(DA.color), transform = oldtransform, time = 5)
+ sleep(5)
+ qdel(DA)
+
var/obj/effect/decal/cleanable/blood/found_bloodpool
- var/list/pools = list()
- var/can_jaunt = FALSE
- for(var/obj/effect/decal/cleanable/blood/nearby in view(src,2))
- can_jaunt = TRUE
- break
- if(!can_jaunt)
- return
- for(var/obj/effect/decal/cleanable/blood/nearby in view(get_turf(target),2))
- pools += nearby
+ pools = get_pools(get_turf(target), 2)
+ pools_to_remove = get_pools(get_turf(target), 1)
+ pools -= pools_to_remove
if(pools.len)
shuffle(pools)
found_bloodpool = pick(pools)
@@ -187,35 +314,56 @@ Difficulty: Hard
forceMove(get_turf(found_bloodpool))
playsound(get_turf(src), 'sound/magic/exit_blood.ogg', 100, 1, -1)
visible_message("And springs back out!")
+ return TRUE
+ return FALSE
+/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/get_pools(turf/T, range)
+ . = list()
+ for(var/obj/effect/decal/cleanable/blood/nearby in view(T, range))
+ . += nearby
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/blood_spray()
visible_message("[src] sprays a stream of gore!")
- var/turf/E = get_edge_target_turf(src, src.dir)
- var/range = 10
+ var/range = 6 + round(anger_modifier * 0.4)
var/turf/previousturf = get_turf(src)
- for(var/turf/J in getline(src,E))
- if(!range)
+ var/turf/J = previousturf
+ var/targetdir = get_dir(src, target)
+ if(target.loc == loc)
+ targetdir = dir
+ face_atom(target)
+ new /obj/effect/decal/cleanable/blood(J)
+ for(var/i in 1 to range)
+ J = get_step(previousturf, targetdir)
+ PoolOrNew(/obj/effect/overlay/temp/dir_setting/bloodsplatter, list(previousturf, get_dir(previousturf, J)))
+ playsound(previousturf,'sound/effects/splat.ogg', 100, 1, -1)
+ if(!J || !previousturf.CanAtmosPass(J))
break
- PoolOrNew(/obj/effect/overlay/temp/bloodsplatter, list(previousturf, get_dir(previousturf, J)))
- if(!previousturf.CanAtmosPass(J))
- break
- playsound(J,'sound/effects/splat.ogg', 100, 1, -1)
- new /obj/effect/decal/cleanable/blood(J)
- range--
+ var/obj/effect/decal/cleanable/blood/B = new /obj/effect/decal/cleanable/blood(J)
+ B.bloodiness = 0
previousturf = J
sleep(1)
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/slaughterlings()
visible_message("[src] summons a shoal of slaughterlings!")
- for(var/obj/effect/decal/cleanable/blood/H in range(src, 10))
- if(prob(25))
- new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/slaughter(H.loc)
+ var/max_amount = 6
+ for(var/H in get_pools(get_turf(src), 1))
+ if(!max_amount)
+ break
+ max_amount--
+ var/obj/effect/decal/cleanable/blood/B = H
+ new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/slaughter(B.loc)
+ return max_amount
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/slaughter
name = "slaughterling"
desc = "Though not yet strong enough to create a true physical form, it's nonetheless determined to murder you."
- faction = list("mining")
+ density = 0
+ faction = list("mining", "boss")
weather_immunities = list("lava","ash")
+/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/slaughter/CanPass(atom/movable/mover, turf/target, height = 0)
+ if(istype(mover, /mob/living/simple_animal/hostile/megafauna/bubblegum))
+ return 1
+ return 0
+
#undef MEDAL_PREFIX
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
index bedb33e3d4a..7ebbdad514e 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
@@ -220,7 +220,8 @@ Difficulty: Very Hard
/mob/living/simple_animal/hostile/megafauna/colossus/proc/blast()
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 200, 1, 2)
- for(var/turf/turf in range(1, target))
+ var/turf/T = get_turf(target)
+ for(var/turf/turf in range(1, T))
shoot_projectile(turf)
/mob/living/simple_animal/hostile/megafauna/colossus/proc/dir_shots(list/dirs)
@@ -381,7 +382,7 @@ Difficulty: Very Hard
var/activation_sound = 'sound/effects/break_stone.ogg'
/obj/machinery/anomalous_crystal/New()
- activation_method = pick("touch","laser","bullet","energy","magic","mob_bump","heat","weapon","speech")
+ activation_method = pick("touch","laser","bullet","energy","bomb","mob_bump","heat","weapon","speech")
..()
/obj/machinery/anomalous_crystal/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans)
@@ -423,8 +424,11 @@ Difficulty: Very Hard
if(ismob(AM))
ActivationReaction(AM,"mob_bump")
+/obj/machinery/anomalous_crystal/ex_act()
+ ActivationReaction(null,"bomb")
+
/obj/machinery/anomalous_crystal/random/New()//Just a random crysal spawner for loot
- var/random_crystal = pick(typesof(/obj/machinery/anomalous_crystal) - /obj/machinery/anomalous_crystal/random)
+ var/random_crystal = pick(typesof(/obj/machinery/anomalous_crystal) - /obj/machinery/anomalous_crystal/random - /obj/machinery/anomalous_crystal)
new random_crystal(loc)
qdel(src)
@@ -472,13 +476,14 @@ Difficulty: Very Hard
NewTerrainChairs = /obj/structure/chair/wood/normal
NewTerrainTables = /obj/structure/table/glass
NewFlora = list(/obj/structure/flora/grass/green, /obj/structure/flora/grass/brown, /obj/structure/flora/grass/both)
- if("jungle") //Beneficial due to actually having breathable air. Plus, monkeys.
+ if("jungle") //Beneficial due to actually having breathable air. Plus, monkeys and bows and arrows.
NewTerrainFloors = /turf/open/floor/grass
NewTerrainWalls = /turf/closed/wall/mineral/sandstone
NewTerrainChairs = /obj/structure/chair/wood
NewTerrainTables = /obj/structure/table/wood
NewFlora = list(/obj/structure/flora/ausbushes/sparsegrass, /obj/structure/flora/ausbushes/fernybush, /obj/structure/flora/ausbushes/leafybush,
- /obj/structure/flora/ausbushes/grassybush, /obj/structure/flora/ausbushes/sunnybush, /obj/structure/flora/tree/palm, /mob/living/carbon/monkey)
+ /obj/structure/flora/ausbushes/grassybush, /obj/structure/flora/ausbushes/sunnybush, /obj/structure/flora/tree/palm, /mob/living/carbon/monkey,
+ /obj/item/weapon/gun/projectile/bow, /obj/item/weapon/storage/backpack/quiver/full)
florachance = 20
if("ayy lmao") //Beneficial, turns stuff into alien alloy which is useful to cargo and research. Also repairs atmos.
NewTerrainFloors = /turf/open/floor/plating/abductor
@@ -523,8 +528,8 @@ Difficulty: Very Hard
/obj/machinery/anomalous_crystal/emitter/New()
..()
- generated_projectile = pick(/obj/item/projectile/beam/emitter,/obj/item/projectile/magic/fireball/infernal,/obj/item/projectile/magic/spellblade,
- /obj/item/projectile/energy/net, /obj/item/projectile/bullet/meteorshot, /obj/item/projectile/beam/xray)
+ generated_projectile = pick(/obj/item/projectile/magic/fireball/infernal,/obj/item/projectile/magic/spellblade,
+ /obj/item/projectile/bullet/meteorshot, /obj/item/projectile/beam/xray, /obj/item/projectile/colossus)
/obj/machinery/anomalous_crystal/emitter/ActivationReaction(mob/user, method)
if(..())
@@ -545,17 +550,23 @@ Difficulty: Very Hard
P.xo = 0
P.fire()
-/obj/machinery/anomalous_crystal/dark_reprise //Revives anyone nearby, but turns them into shadowpeople. Cannot revive shadowpeople, so this is a one time thing.
+/obj/machinery/anomalous_crystal/dark_reprise //Revives anyone nearby, but turns them into shadowpeople and renders them uncloneable, so the crystal is your only hope of getting up again if you go down.
activation_method = "touch"
+ activation_sound = 'sound/hallucinations/growl1.ogg'
/obj/machinery/anomalous_crystal/dark_reprise/ActivationReaction(mob/user, method)
if(..())
for(var/i in range(1, src))
+ if(isturf(i))
+ PoolOrNew(/obj/effect/overlay/temp/cult/sparks, i)
+ continue
if(ishuman(i))
var/mob/living/carbon/human/H = i
- if(H.stat == DEAD && !isshadowperson(H))
+ if(H.stat == DEAD)
H.set_species(/datum/species/shadow, 1)
H.revive(1,0)
+ H.disabilities |= NOCLONE //Free revives, but significantly limits your options for reviving except via the crystal
+ H.grab_ghost(force = TRUE)
/obj/machinery/anomalous_crystal/helpers //Lets ghost spawn as helpful creatures that can only heal people slightly. Incredibly fragile and they can't converse with humans
activation_method = "touch"
@@ -564,17 +575,23 @@ Difficulty: Very Hard
/obj/machinery/anomalous_crystal/helpers/ActivationReaction(mob/user, method)
if(..() && !ready_to_deploy)
ready_to_deploy = 1
- notify_ghosts("An anomalous crystal has been activated in [get_area(src)]!", enter_link = "(Click to enter)", source = src, action = NOTIFY_ATTACK)
+ notify_ghosts("An anomalous crystal has been activated in [get_area(src)]! This crystal can always be used by ghosts hereafter.", enter_link = "(Click to enter)", source = src, action = NOTIFY_ATTACK)
/obj/machinery/anomalous_crystal/helpers/attack_ghost(mob/dead/observer/user)
..()
if(ready_to_deploy)
var/be_helper = alert("Become a Lightgeist? (Warning, You can no longer be cloned!)",,"Yes","No")
- if(!be_helper == "No")
+ if(be_helper == "No")
return
var/mob/living/simple_animal/hostile/lightgeist/W = new /mob/living/simple_animal/hostile/lightgeist(get_turf(loc))
W.key = user.key
+/obj/machinery/anomalous_crystal/helpers/Topic(href, href_list)
+ if(href_list["ghostjoin"])
+ var/mob/dead/observer/ghost = usr
+ if(istype(ghost))
+ attack_ghost(ghost)
+
/mob/living/simple_animal/hostile/lightgeist
name = "lightgeist"
desc = "This small floating creature is a completely unknown form of life... being near it fills you with a sense of tranquility."
@@ -603,19 +620,24 @@ Difficulty: Very Hard
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
luminosity = 4
faction = list("neutral")
- languages_spoken = 0
+ languages_spoken = SLIME
languages_understood = ALL
del_on_death = 1
unsuitable_atmos_damage = 0
flying = 1
minbodytemp = 0
maxbodytemp = 1500
+ environment_smash = 0
+ AIStatus = AI_OFF
+ stop_automated_movement = 1
var/heal_power = 5
/mob/living/simple_animal/hostile/lightgeist/New()
..()
verbs -= /mob/living/verb/pulled
verbs -= /mob/verb/me_verb
+ var/datum/atom_hud/medsensor = huds[DATA_HUD_MEDICAL_ADVANCED]
+ medsensor.add_hud_to(src)
/mob/living/simple_animal/hostile/lightgeist/AttackingTarget()
..()
@@ -625,29 +647,35 @@ Difficulty: Very Hard
L.heal_overall_damage(heal_power, heal_power)
PoolOrNew(/obj/effect/overlay/temp/heal, list(get_turf(target), "#80F5FF"))
-/mob/living/simple_animal/hostile/lightgeist/Life()
- if(!ckey)
+/mob/living/simple_animal/hostile/lightgeist/ghostize()
+ if(..())
death()
- ..()
-/obj/machinery/anomalous_crystal/refresher //Deletes and recreates a copy of the item, "refreshing" it. Only works once per item.
+/obj/machinery/anomalous_crystal/refresher //Deletes and recreates a copy of the item, "refreshing" it.
activation_method = "touch"
cooldown_add = 50
+ activation_sound = 'sound/magic/TIMEPARADOX2.ogg'
+ var/list/banned_items_typecache = list(/obj/item/weapon/storage, /obj/item/weapon/implant, /obj/item/weapon/implanter, /obj/item/weapon/disk/nuclear, /obj/item/projectile, /obj/item/weapon/spellbook)
+
+/obj/machinery/anomalous_crystal/refresher/New()
+ ..()
+ banned_items_typecache = typecacheof(banned_items_typecache)
+
/obj/machinery/anomalous_crystal/refresher/ActivationReaction(mob/user, method)
if(..())
- var/list/L
+ var/list/L = list()
var/turf/T = get_step(src, dir)
+ PoolOrNew(/obj/effect/overlay/temp/emp/pulse,T)
for(var/i in T)
- if(istype(i, /obj/item) && !istype(i, /obj/item/weapon/storage) && !(i in affected_targets) && !istype(i, /obj/item/weapon/implant) && !istype(i, /obj/item/weapon/implanter) && !istype(i, /obj/item/weapon/disk/nuclear))
+ if(istype(i, /obj/item) && !is_type_in_typecache(i, banned_items_typecache))
var/obj/item/W = i
if(!W.admin_spawned)
L += W
- var/obj/item/CHOSEN = pick(L)
- if(CHOSEN)
- var/A = new CHOSEN.type(T)
- affected_targets += A
+ if(L.len)
+ var/obj/item/CHOSEN = pick(L)
+ new CHOSEN.type(T)
qdel(CHOSEN)
/obj/machinery/anomalous_crystal/possessor //Allows you to bodyjack small animals, then exit them at your leisure, but you can only do this once per activation. Because they blow up. Also, if the bodyjacked animal dies, SO DO YOU.
@@ -665,7 +693,7 @@ Difficulty: Very Hard
mobcheck = 1
break
if(!mobcheck)
- new /mob/living/simple_animal/cockroach(loc) //Just in case there aren't any animals on the station, this will leave you with a terrible option to possess if you feel like it
+ new /mob/living/simple_animal/cockroach(get_step(src,dir)) //Just in case there aren't any animals on the station, this will leave you with a terrible option to possess if you feel like it
/obj/structure/closet/stasis
name = "quantum entanglement stasis warp field"
@@ -673,17 +701,15 @@ Difficulty: Very Hard
icon_state = null //This shouldn't even be visible, so if it DOES show up, at least nobody will notice
density = 1
anchored = 1
- health = 0
+ health = 999
var/mob/living/simple_animal/holder_animal
/obj/structure/closet/stasis/process()
- if(!isanimal(loc))
- dump_contents(1)
- return
if(holder_animal)
- if(holder_animal.stat == DEAD)
- dump_contents(1)
+ if(holder_animal.stat == DEAD && !qdeleted(holder_animal))
+ dump_contents()
holder_animal.gib()
+ return
/obj/structure/closet/stasis/New()
..()
@@ -702,14 +728,15 @@ Difficulty: Very Hard
holder_animal.mind.AddSpell(P)
holder_animal.verbs -= /mob/living/verb/pulled
-/obj/structure/closet/stasis/dump_contents(var/kill = 0)
+/obj/structure/closet/stasis/dump_contents(var/kill = 1)
STOP_PROCESSING(SSobj, src)
for(var/mob/living/L in src)
L.disabilities &= ~MUTE
L.status_flags &= ~GODMODE
L.notransform = 0
- holder_animal.mind.transfer_to(L)
- L.mind.RemoveSpell(/obj/effect/proc_holder/spell/targeted/exit_possession)
+ if(holder_animal && !qdeleted(holder_animal))
+ holder_animal.mind.transfer_to(L)
+ L.mind.RemoveSpell(/obj/effect/proc_holder/spell/targeted/exit_possession)
if(kill || !isanimal(loc))
L.death(0)
..()
@@ -717,6 +744,9 @@ Difficulty: Very Hard
/obj/structure/closet/stasis/emp_act()
return
+/obj/structure/closet/stasis/ex_act()
+ return
+
/obj/effect/proc_holder/spell/targeted/exit_possession
name = "Exit Possession"
desc = "Exits the body you are possessing"
@@ -737,7 +767,7 @@ Difficulty: Very Hard
for(var/i in user)
if(istype(i, /obj/structure/closet/stasis))
var/obj/structure/closet/stasis/S = i
- S.dump_contents()
+ S.dump_contents(0)
qdel(S)
break
user.gib()
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm
index 67b784fff9a..ff9e3ab67ca 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm
@@ -166,6 +166,7 @@ Difficulty: Medium
addtimer(src, "fire_wall", 0, FALSE, d)
/mob/living/simple_animal/hostile/megafauna/dragon/proc/fire_wall(dir)
+ var/list/hit_things = list(src)
var/turf/E = get_edge_target_turf(src, dir)
var/range = 10
var/turf/previousturf = get_turf(src)
@@ -175,10 +176,10 @@ Difficulty: Medium
range--
PoolOrNew(/obj/effect/hotspot,J)
J.hotspot_expose(700,50,1)
- for(var/mob/living/L in J)
- if(L != src)
- L.adjustFireLoss(20)
- L << "You're hit by the drake's fire breath!"
+ for(var/mob/living/L in J.contents - hit_things)
+ L.adjustFireLoss(20)
+ L << "You're hit by the drake's fire breath!"
+ hit_things += L
previousturf = J
sleep(1)
@@ -257,6 +258,7 @@ Difficulty: Medium
name = "lesser ash drake"
maxHealth = 300
health = 300
+ faction = list("neutral")
melee_damage_upper = 30
melee_damage_lower = 30
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
index ee7e70bdcf2..37aa5575a9b 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
@@ -87,7 +87,7 @@ Difficulty: Hard
did_reset = TRUE
//visible_message("\"Vixyvrmrk xs fewi...\"")
blink(spawned_rune)
- adjustHealth(max((health - maxHealth) * 0.5, 25)) //heal for 50% of our missing health
+ adjustHealth(min((health - maxHealth) * 0.5, -50)) //heal for 50% of our missing health
wander = FALSE
/*if(health > maxHealth * 0.9)
visible_message("\"Vitemvw gsqtpixi. Stivexmrk ex qebmqyq ijjmgmirgc.\"")
@@ -279,6 +279,8 @@ Difficulty: Hard
/mob/living/simple_animal/hostile/megafauna/hierophant/proc/diagonal_blasts(mob/victim) //fire diagonal cross blasts with a delay
var/turf/T = get_turf(victim)
+ if(!T)
+ return
PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph/diagonal, list(T, src))
playsound(T,'sound/magic/blink.ogg', 200, 1)
//playsound(T,'sound/effects/bin_close.ogg', 200, 1)
@@ -289,6 +291,8 @@ Difficulty: Hard
/mob/living/simple_animal/hostile/megafauna/hierophant/proc/cardinal_blasts(mob/victim) //fire cardinal cross blasts with a delay
var/turf/T = get_turf(victim)
+ if(!T)
+ return
PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph/cardinal, list(T, src))
playsound(T,'sound/magic/blink.ogg', 200, 1)
//playsound(T,'sound/effects/bin_close.ogg', 200, 1)
@@ -299,6 +303,8 @@ Difficulty: Hard
/mob/living/simple_animal/hostile/megafauna/hierophant/proc/alldir_blasts(mob/victim) //fire alldir cross blasts with a delay
var/turf/T = get_turf(victim)
+ if(!T)
+ return
PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph, list(T, src))
playsound(T,'sound/magic/blink.ogg', 200, 1)
//playsound(T,'sound/effects/bin_close.ogg', 200, 1)
@@ -396,6 +402,7 @@ Difficulty: Hard
/obj/effect/overlay/temp/hierophant/chaser //a hierophant's chaser. follows target around, moving and producing a blast every speed deciseconds.
duration = 98
var/mob/living/target //what it's following
+ var/turf/targetturf //what turf the target is actually on
var/moving_dir //what dir it's moving in
var/previous_moving_dir //what dir it was moving in before that
var/more_previouser_moving_dir //what dir it was moving in before THAT
@@ -415,7 +422,7 @@ Difficulty: Hard
addtimer(src, "seek_target", 1)
/obj/effect/overlay/temp/hierophant/chaser/proc/get_target_dir()
- . = get_cardinal_dir(src, target)
+ . = get_cardinal_dir(src, targetturf)
if((. != previous_moving_dir && . == more_previouser_moving_dir) || . == 0) //we're alternating, recalculate
var/list/cardinal_copy = cardinal.Copy()
cardinal_copy -= more_previouser_moving_dir
@@ -424,12 +431,13 @@ Difficulty: Hard
/obj/effect/overlay/temp/hierophant/chaser/proc/seek_target()
if(!currently_seeking)
currently_seeking = TRUE
- while(target && src && !qdeleted(src) && currently_seeking && x && y && target.x && target.y) //can this target actually be sook out
+ targetturf = get_turf(target)
+ while(target && src && !qdeleted(src) && currently_seeking && x && y && targetturf) //can this target actually be sook out
if(!moving) //we're out of tiles to move, find more and where the target is!
more_previouser_moving_dir = previous_moving_dir
previous_moving_dir = moving_dir
moving_dir = get_target_dir()
- var/standard_target_dir = get_cardinal_dir(src, target)
+ var/standard_target_dir = get_cardinal_dir(src, targetturf)
if((standard_target_dir != previous_moving_dir && standard_target_dir == more_previouser_moving_dir) || standard_target_dir == 0)
moving = 1 //we would be repeating, only move a tile before checking
else
@@ -446,6 +454,7 @@ Difficulty: Hard
make_blast() //make a blast, too
moving--
sleep(speed)
+ targetturf = get_turf(target)
/obj/effect/overlay/temp/hierophant/chaser/proc/make_blast()
PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(loc, caster, friendly_fire_check))
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
index 948f01e56eb..b63b421ae83 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
@@ -15,6 +15,7 @@
weather_immunities = list("lava","ash")
flying = 1
robust_searching = 1
+ ranged_ignores_vision = TRUE
stat_attack = 2
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
damage_coeff = list(BRUTE = 1, BURN = 0.5, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm
index df5897d9f65..de6056ca76e 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm
@@ -833,7 +833,7 @@
desc = "[src] has become inert, it crackles no more and is useless for \
healing injuries."
-/obj/item/organ/hivelord_core/legion/preserved()
+/obj/item/organ/hivelord_core/legion/preserved(implanted = 0)
..()
desc = "[src] has been stabilized. It no longer crackles with power, but it's healing properties are preserved indefinitely."
diff --git a/code/modules/mob/living/simple_animal/hostile/skeleton.dm b/code/modules/mob/living/simple_animal/hostile/skeleton.dm
index ad20e68458e..4664a41082c 100644
--- a/code/modules/mob/living/simple_animal/hostile/skeleton.dm
+++ b/code/modules/mob/living/simple_animal/hostile/skeleton.dm
@@ -70,7 +70,7 @@
loot = list(/obj/effect/decal/remains/human,
/obj/item/clothing/suit/armor/riot/knight/templar,
/obj/item/clothing/head/helmet/knight/templar,
- /obj/item/weapon/claymore/hog{name = "holy sword"})
+ /obj/item/weapon/claymore/weak{name = "holy sword"})
/mob/living/simple_animal/hostile/skeleton/ice
name = "ice skeleton"
diff --git a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm
index 7dc5c54bd33..14aeb265158 100644
--- a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm
+++ b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm
@@ -21,7 +21,7 @@
anchors += locate(x+2,y-2,z)
for(var/turf/T in anchors)
- var/datum/beam/B = Beam(T,"vine",'icons/effects/spacevines.dmi',INFINITY, 5,/obj/effect/ebeam/vine)
+ var/datum/beam/B = Beam(T, "vine", time=INFINITY, maxdistance=5, beam_type=/obj/effect/ebeam/vine)
B.sleep_time = 10 //these shouldn't move, so let's slow down updates to 1 second (any slower and the deletion of the vines would be too slow)
addtimer(src, "bear_fruit", growth_time)
@@ -98,15 +98,15 @@
if(A.density && A != L)
continue grasping
if(prob(grasp_chance))
- L << "\the [src] has you entangled!"
- grasping[L] = Beam(L,"vine",'icons/effects/spacevines.dmi',INFINITY, 5,/obj/effect/ebeam/vine)
+ L << "\The [src] has you entangled!"
+ grasping[L] = Beam(L, "vine", time=INFINITY, maxdistance=5, beam_type=/obj/effect/ebeam/vine)
break //only take 1 new victim per cycle
/mob/living/simple_animal/hostile/venus_human_trap/OpenFire(atom/the_target)
var/dist = get_dist(src,the_target)
- Beam(the_target,"vine",'icons/effects/spacevines.dmi',dist*2, dist+2,/obj/effect/ebeam/vine)
+ Beam(the_target, "vine", time=dist*2, maxdistance=dist+2, beam_type=/obj/effect/ebeam/vine)
the_target.attack_animal(src)
diff --git a/code/modules/mob/living/simple_animal/shade.dm b/code/modules/mob/living/simple_animal/shade.dm
index 939c1d57ffc..a6387667c7a 100644
--- a/code/modules/mob/living/simple_animal/shade.dm
+++ b/code/modules/mob/living/simple_animal/shade.dm
@@ -43,7 +43,7 @@
if(istype(M, /mob/living/simple_animal/hostile/construct/builder))
if(health < maxHealth)
adjustHealth(-25)
- Beam(M,icon_state="sendbeam",icon='icons/effects/effects.dmi',time=4)
+ Beam(M,icon_state="sendbeam",time=4)
M.visible_message("[M] heals \the [src].", \
"You heal [src], leaving [src] at [health]/[maxHealth] health.")
else
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index edca0beac1d..8de22d32685 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -104,10 +104,14 @@
/mob/living/simple_animal/Life()
if(..()) //alive
if(!ckey)
- handle_automated_movement()
- handle_automated_action()
- handle_automated_speech()
- return 1
+ if(stat != DEAD)
+ handle_automated_movement()
+ if(stat != DEAD)
+ handle_automated_action()
+ if(stat != DEAD)
+ handle_automated_speech()
+ if(stat != DEAD)
+ return 1
/mob/living/simple_animal/updatehealth()
..()
@@ -301,7 +305,11 @@
if(del_on_death)
ghostize()
stat = DEAD
+ //Prevent infinite loops if the mob Destroy() is overriden in such
+ //a manner as to cause a call to death() again
+ del_on_death = FALSE
qdel(src)
+ return
else
health = 0
icon_state = icon_dead
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 4744180d207..1b1808518f8 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -499,8 +499,8 @@ var/next_mob_id = 0
return
var/mob/mob_eye = creatures[eye_name]
-
- if(client && mob_eye)
+ //Istype so we filter out points of interest that are not mobs
+ if(client && mob_eye && istype(mob_eye))
client.eye = mob_eye
if(isobserver(src))
src.client.screen = list()
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 40d23ea638d..e59f4708e90 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -465,3 +465,15 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
M << "There were no ghosts willing to take control."
message_admins("No ghosts were willing to take control of [key_name_admin(M)])")
return FALSE
+
+//toggles the talk wheel
+/mob/verb/toggle_talk_wheel()
+ set name = "talk-wheel"
+ set hidden = 1
+
+ if(isliving(src))
+ var/mob/living/L = src
+ if(L.hud_used)
+ for(var/obj/screen/wheel/talk/TW in L.hud_used.wheels)
+ TW.Click()
+
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index 919e995bca8..25df31320da 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -236,14 +236,12 @@
L.loc = locate(locx,locy,mobloc.z)
var/limit = 2//For only two trailing shadows.
for(var/turf/T in getline(mobloc, L.loc))
- spawn(0)
- anim(T,L,'icons/mob/mob.dmi',,"shadow",,L.dir)
+ PoolOrNew(/obj/effect/overlay/temp/dir_setting/ninja/shadow, list(T, L.dir))
limit--
if(limit<=0)
break
else
- spawn(0)
- anim(mobloc,mob,'icons/mob/mob.dmi',,"shadow",,L.dir)
+ PoolOrNew(/obj/effect/overlay/temp/dir_setting/ninja/shadow, list(mobloc, L.dir))
L.loc = get_step(L, direct)
L.setDir(direct)
if(3) //Incorporeal move, but blocked by holy-watered tiles and salt piles.
@@ -303,6 +301,9 @@
break
. = dense_object_backup
+/mob/proc/mob_has_gravity()
+ return has_gravity()
+
/mob/proc/mob_negates_gravity()
return 0
diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm
index 3c2c95fbbf8..e947d24c1a7 100644
--- a/code/modules/mob/new_player/new_player.dm
+++ b/code/modules/mob/new_player/new_player.dm
@@ -332,6 +332,9 @@
data_core.manifest_inject(humanc)
AnnounceArrival(humanc, rank)
AddEmploymentContract(humanc)
+ if(highlander)
+ humanc << "THERE CAN BE ONLY ONE!!!"
+ humanc.make_scottish()
joined_player_list += character.ckey
diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm
index fcae203a523..6f662412c65 100644
--- a/code/modules/mob/transform_procs.dm
+++ b/code/modules/mob/transform_procs.dm
@@ -41,14 +41,9 @@
cut_overlays()
invisibility = INVISIBILITY_MAXIMUM
- var/atom/movable/overlay/animation = new( loc )
- animation.icon_state = "blank"
- animation.icon = 'icons/mob/mob.dmi'
- animation.master = src
- flick("h2monkey", animation)
+ PoolOrNew(/obj/effect/overlay/temp/monkeyify, get_turf(src))
sleep(22)
var/mob/living/carbon/monkey/O = new /mob/living/carbon/monkey( loc )
- qdel(animation)
// hash the original name?
if(tr_flags & TR_HASHNAME)
@@ -188,16 +183,11 @@
icon = null
cut_overlays()
invisibility = INVISIBILITY_MAXIMUM
- var/atom/movable/overlay/animation = new( loc )
- animation.icon_state = "blank"
- animation.icon = 'icons/mob/mob.dmi'
- animation.master = src
- flick("monkey2h", animation)
+ PoolOrNew(/obj/effect/overlay/temp/monkeyify/humanify, get_turf(src))
sleep(22)
var/mob/living/carbon/human/O = new( loc )
for(var/obj/item/C in O.loc)
O.equip_to_appropriate_slot(C)
- qdel(animation)
dna.transfer_identity(O)
O.updateappearance(mutcolor_update=1)
@@ -496,23 +486,6 @@
qdel(src)
-/mob/proc/become_god(var/side_colour)
- var/mob/camera/god/G = new /mob/camera/god(loc)
- G.side = side_colour
- if(mind)
- mind.transfer_to(G)
- else
- G.key = key
-
- G.job = "Deity"
- G.rename_self("deity")
- G.update_icons()
-
- . = G
- qdel(src)
-
-
-
/mob/living/carbon/human/proc/corgize()
if (notransform)
return
diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm
index 516293bfc27..942a114dc56 100644
--- a/code/modules/modular_computers/computers/item/computer.dm
+++ b/code/modules/modular_computers/computers/item/computer.dm
@@ -36,22 +36,12 @@
var/max_damage = 100 // Damage level at which the computer breaks apart.
// Important hardware (must be installed for computer to work)
- var/obj/item/weapon/computer_hardware/processor_unit/processor_unit // CPU. Without it the computer won't run. Better CPUs can run more programs at once.
- var/obj/item/weapon/computer_hardware/hard_drive/hard_drive // Hard Drive component of this computer. Stores programs and files.
-
- var/obj/item/weapon/computer_hardware/battery/battery_module // Power cell connector. Power cell can be recharged.
- // OR
- var/obj/item/weapon/computer_hardware/recharger/recharger // Recharger. Can be used to recharge power cell or power the PC without it.
// Optional hardware (improves functionality, but is not critical for computer to work)
- var/obj/item/weapon/computer_hardware/network_card/network_card // Network Card component of this computer. Allows connection to NTNet.
- var/obj/item/weapon/computer_hardware/card_slot/card_slot // ID Card slot component of this computer.
- var/obj/item/weapon/computer_hardware/printer/printer // Printer component of this computer, for your everyday paperwork needs.
- var/obj/item/weapon/computer_hardware/hard_drive/portable/portable_drive // Portable data storage
- var/list/all_components = list()
+ var/list/all_components // List of "connection ports" in this computer and the components with which they are plugged
- var/list/idle_threads = list() // Idle programs on background. They still receive process calls but can't be interacted with.
+ var/list/idle_threads // Idle programs on background. They still receive process calls but can't be interacted with.
var/obj/physical = null // Object that represents our computer. It's used for Adjacent() and UI visibility checks.
@@ -63,30 +53,48 @@
physical = src
..()
+ all_components = list()
+ idle_threads = list()
+
/obj/item/device/modular_computer/Destroy()
kill_program(forced = TRUE)
STOP_PROCESSING(SSobj, src)
for(var/H in all_components)
- var/obj/item/weapon/computer_hardware/CH = H
+ var/obj/item/weapon/computer_hardware/CH = all_components[H]
if(CH.holder == src)
CH.holder = null
qdel(CH)
return ..()
+
+/obj/item/device/modular_computer/proc/add_verb(var/path)
+ switch(path)
+ if(MC_CARD)
+ verbs += /obj/item/device/modular_computer/proc/eject_id
+ if(MC_SDD)
+ verbs += /obj/item/device/modular_computer/proc/eject_disk
+
+/obj/item/device/modular_computer/proc/remove_verb(path)
+ switch(path)
+ if(MC_CARD)
+ verbs -= /obj/item/device/modular_computer/proc/eject_id
+ if(MC_SDD)
+ verbs -= /obj/item/device/modular_computer/proc/eject_disk
+
// Eject ID card from computer, if it has ID slot with card inside.
-/obj/item/device/modular_computer/verb/eject_id()
+/obj/item/device/modular_computer/proc/eject_id()
set name = "Eject ID"
set category = "Object"
set src in view(1)
if(issilicon(usr))
return
-
- if (usr.canUseTopic(src))
- proc_eject_id(usr)
+ var/obj/item/weapon/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
+ if(usr.canUseTopic(src))
+ card_slot.try_eject(, usr)
// Eject ID card from computer, if it has ID slot with card inside.
-/obj/item/device/modular_computer/verb/eject_disk()
+/obj/item/device/modular_computer/proc/eject_disk()
set name = "Eject Data Disk"
set category = "Object"
set src in view(1)
@@ -94,30 +102,10 @@
if(issilicon(usr))
return
- if (usr.canUseTopic(src))
- proc_eject_disk(usr)
-
-/obj/item/device/modular_computer/proc/proc_eject_id(mob/user, slot)
- if(!user)
- user = usr
-
- if(!card_slot)
- user << "\The [src] does not have an ID card slot!"
- return
-
- card_slot.try_eject(slot, user)
-
-/obj/item/device/modular_computer/proc/proc_eject_disk(mob/user)
- if(!user)
- user = usr
-
- if(!portable_drive)
- user << "There is no data disk in \the [src]!"
- return
-
- var/obj/item/I = portable_drive
- if(uninstall_component(portable_drive, user))
- I.verb_pickup()
+ if(usr.canUseTopic(src))
+ var/obj/item/weapon/computer_hardware/hard_drive/portable/portable_drive = all_components[MC_SDD]
+ if(uninstall_component(portable_drive, usr))
+ portable_drive.verb_pickup()
/obj/item/device/modular_computer/AltClick(mob/user)
..()
@@ -125,19 +113,24 @@
return
if(user.canUseTopic(src))
+ var/obj/item/weapon/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
+ var/obj/item/weapon/computer_hardware/hard_drive/portable/portable_drive = all_components[MC_SDD]
if(portable_drive)
- proc_eject_disk(user)
+ if(uninstall_component(portable_drive, user))
+ portable_drive.verb_pickup()
else if(card_slot)
- proc_eject_id(user)
+ card_slot.try_eject(, user)
// Gets IDs/access levels from card slot. Would be useful when/if PDAs would become modular PCs.
/obj/item/device/modular_computer/GetAccess()
+ var/obj/item/weapon/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
if(card_slot)
return card_slot.GetAccess()
return ..()
/obj/item/device/modular_computer/GetID()
+ var/obj/item/weapon/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
if(card_slot)
return card_slot.GetID()
return ..()
@@ -208,10 +201,11 @@
return
// If we have a recharger, enable it automatically. Lets computer without a battery work.
+ var/obj/item/weapon/computer_hardware/recharger/recharger = all_components[MC_CHARGE]
if(recharger)
recharger.enabled = 1
- if(processor_unit && use_power()) // use_power() checks if the PC is powered
+ if(all_components[MC_CPU] && use_power()) // use_power() checks if the PC is powered
if(issynth)
user << "You send an activation signal to \the [src], turning it on."
else
@@ -265,6 +259,9 @@
/obj/item/device/modular_computer/proc/get_header_data()
var/list/data = list()
+ var/obj/item/weapon/computer_hardware/battery/battery_module = all_components[MC_CELL]
+ var/obj/item/weapon/computer_hardware/recharger/recharger = all_components[MC_CHARGE]
+
if(battery_module && battery_module.battery)
switch(battery_module.battery.percent())
if(80 to 200) // 100 should be maximal but just in case..
@@ -328,6 +325,7 @@
// Returns 0 for No Signal, 1 for Low Signal and 2 for Good Signal. 3 is for wired connection (always-on)
/obj/item/device/modular_computer/proc/get_ntnet_status(specific_action = 0)
+ var/obj/item/weapon/computer_hardware/network_card/network_card = all_components[MC_NET]
if(network_card)
return network_card.get_signal(specific_action)
else
@@ -336,6 +334,7 @@
/obj/item/device/modular_computer/proc/add_log(text)
if(!get_ntnet_status())
return FALSE
+ var/obj/item/weapon/computer_hardware/network_card/network_card = all_components[MC_NET]
return ntnet_global.add_log(text, network_card)
/obj/item/device/modular_computer/proc/shutdown_computer(loud = 1)
@@ -352,7 +351,7 @@
/obj/item/device/modular_computer/attackby(obj/item/weapon/W as obj, mob/user as mob)
// Insert items into the components
for(var/h in all_components)
- var/obj/item/weapon/computer_hardware/H = h
+ var/obj/item/weapon/computer_hardware/H = all_components[h]
if(H.try_insert(W, user))
return
diff --git a/code/modules/modular_computers/computers/item/computer_components.dm b/code/modules/modular_computers/computers/item/computer_components.dm
index 3a5b68579e1..0f27580a27f 100644
--- a/code/modules/modular_computers/computers/item/computer_components.dm
+++ b/code/modules/modular_computers/computers/item/computer_components.dm
@@ -6,32 +6,8 @@
user << "This component is too large for \the [src]!"
return FALSE
- if(istype(H, /obj/item/weapon/computer_hardware/hard_drive/portable) && portable_drive)
- user << "This computer's FDD is already occupied by \the [portable_drive]."
- return FALSE
-
- else if(istype(H, /obj/item/weapon/computer_hardware/processor_unit) && processor_unit)
- user << "This computer's CPU slot is already occupied by \the [processor_unit]."
- return FALSE
- else if(istype(H, /obj/item/weapon/computer_hardware/hard_drive) && hard_drive)
- user << "This computer's data port is already occupied by \the [hard_drive]."
- return FALSE
-
- else if(istype(H, /obj/item/weapon/computer_hardware/battery) && battery_module)
- user << "This computer's power converter slot is already occupied by \the [battery_module]."
- return FALSE
- else if(istype(H, /obj/item/weapon/computer_hardware/recharger) && recharger)
- user << "This computer's recharger slot is already occupied by \the [recharger]."
- return FALSE
-
- else if(istype(H, /obj/item/weapon/computer_hardware/card_slot) && card_slot)
- user << "This computer's card reader slot is already occupied by \the [card_slot]."
- return FALSE
- else if(istype(H, /obj/item/weapon/computer_hardware/network_card) && network_card)
- user << "This computer's network card is already occupied by \the [network_card]."
- return FALSE
- else if(istype(H, /obj/item/weapon/computer_hardware/printer) && printer)
- user << "This computer's printer slot is already occupied by \the [printer]."
+ if(all_components[H.device_type])
+ user << "This computer's hardware slot is already occupied by \the [all_components[H.device_type]]."
return FALSE
return TRUE
@@ -44,32 +20,12 @@
if(user && !user.unEquip(H))
return FALSE
- if(istype(H, /obj/item/weapon/computer_hardware/hard_drive/portable))
- portable_drive = H
-
- else if(istype(H, /obj/item/weapon/computer_hardware/processor_unit))
- processor_unit = H
- else if(istype(H, /obj/item/weapon/computer_hardware/hard_drive))
- hard_drive = H
-
- else if(istype(H, /obj/item/weapon/computer_hardware/battery))
- battery_module = H
- else if(istype(H, /obj/item/weapon/computer_hardware/recharger))
- recharger = H
-
- else if(istype(H, /obj/item/weapon/computer_hardware/card_slot))
- card_slot = H
- else if(istype(H, /obj/item/weapon/computer_hardware/network_card))
- network_card = H
- else if(istype(H, /obj/item/weapon/computer_hardware/printer))
- printer = H
+ all_components[H.device_type] = H
user << "You install \the [H] into \the [src]."
H.forceMove(src)
H.holder = src
- all_components |= H
H.on_install(src, user)
- return TRUE
// Uninstalls component.
@@ -77,41 +33,22 @@
if(H.holder != src) // Not our component at all.
return FALSE
- if(processor_unit == H)
- processor_unit = null
- if(hard_drive == H)
- hard_drive = null
-
- if(battery_module == H)
- battery_module = null
- if(recharger == H)
- recharger = null
-
- if(card_slot == H)
- card_slot = null
- if(network_card == H)
- network_card = null
- if(printer == H)
- printer = null
- if(portable_drive == H)
- portable_drive = null
+ all_components.Remove(H.device_type)
user << "You remove \the [H] from \the [src]."
H.forceMove(get_turf(src))
H.holder = null
- all_components -= H
H.on_remove(src, user)
- if(enabled && (!processor_unit || !hard_drive || !use_power()))
+ if(enabled && !use_power())
shutdown_computer()
update_icon()
- return TRUE
// Checks all hardware pieces to determine if name matches, if yes, returns the hardware piece, otherwise returns null
/obj/item/device/modular_computer/proc/find_hardware_by_name(name)
for(var/i in all_components)
- var/obj/O = i
+ var/obj/O = all_components[i]
if(O.name == name)
return O
return null
diff --git a/code/modules/modular_computers/computers/item/computer_damage.dm b/code/modules/modular_computers/computers/item/computer_damage.dm
index 8214840bc2b..d27ec0a750f 100644
--- a/code/modules/modular_computers/computers/item/computer_damage.dm
+++ b/code/modules/modular_computers/computers/item/computer_damage.dm
@@ -9,7 +9,7 @@
if(component_probability)
for(var/I in all_components)
- var/obj/item/weapon/computer_hardware/H = I
+ var/obj/item/weapon/computer_hardware/H = all_components[I]
if(prob(component_probability))
H.take_damage(round(amount / 2))
@@ -40,7 +40,7 @@
var/turf/newloc = get_turf(src)
new /obj/item/stack/sheet/metal(newloc, round(steel_sheet_cost/2))
for(var/C in all_components)
- var/obj/item/weapon/computer_hardware/H = C
+ var/obj/item/weapon/computer_hardware/H = all_components[C]
uninstall_component(H)
H.forceMove(newloc)
if(prob(25))
diff --git a/code/modules/modular_computers/computers/item/computer_power.dm b/code/modules/modular_computers/computers/item/computer_power.dm
index f6196477000..c5aab99ce57 100644
--- a/code/modules/modular_computers/computers/item/computer_power.dm
+++ b/code/modules/modular_computers/computers/item/computer_power.dm
@@ -3,10 +3,14 @@
if(check_power_override())
return TRUE
+ var/obj/item/weapon/computer_hardware/recharger/recharger = all_components[MC_CHARGE]
+
if(recharger && recharger.check_functionality())
if(recharger.use_power(amount))
return TRUE
+ var/obj/item/weapon/computer_hardware/battery/battery_module = all_components[MC_CELL]
+
if(battery_module && battery_module.battery && battery_module.battery.charge)
var/obj/item/weapon/stock_parts/cell/cell = battery_module.battery
if(cell.use(amount * CELLRATE))
@@ -17,6 +21,7 @@
return FALSE
/obj/item/device/modular_computer/proc/give_power(amount)
+ var/obj/item/weapon/computer_hardware/battery/battery_module = all_components[MC_CELL]
if(battery_module && battery_module.battery)
return battery_module.battery.give(amount)
return 0
@@ -34,6 +39,7 @@
// Handles power-related things, such as battery interaction, recharging, shutdown when it's discharged
/obj/item/device/modular_computer/proc/handle_power()
+ var/obj/item/weapon/computer_hardware/recharger/recharger = all_components[MC_CHARGE]
if(recharger)
recharger.process()
diff --git a/code/modules/modular_computers/computers/item/computer_ui.dm b/code/modules/modular_computers/computers/item/computer_ui.dm
index a89e84b31f4..b551b98ede7 100644
--- a/code/modules/modular_computers/computers/item/computer_ui.dm
+++ b/code/modules/modular_computers/computers/item/computer_ui.dm
@@ -24,6 +24,7 @@
// We are still here, that means there is no program loaded. Load the BIOS/ROM/OS/whatever you want to call it.
// This screen simply lists available programs and user may select them.
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = all_components[MC_HDD]
if(!hard_drive || !hard_drive.stored_files || !hard_drive.stored_files.len)
physical.visible_message("\The [src] beeps three times, it's screen displaying \"DISK ERROR\" warning.")
return // No HDD, No HDD files list or no stored files. Something is very broken.
@@ -41,6 +42,7 @@
/obj/item/device/modular_computer/ui_data(mob/user)
var/list/data = get_header_data()
data["programs"] = list()
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = all_components[MC_HDD]
for(var/datum/computer_file/program/P in hard_drive.stored_files)
var/running = 0
if(P in idle_threads)
@@ -55,6 +57,7 @@
/obj/item/device/modular_computer/ui_act(action, params)
if(..())
return
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = all_components[MC_HDD]
switch(action)
if("PC_exit")
kill_program()
@@ -64,7 +67,7 @@
return 1
if("PC_minimize")
var/mob/user = usr
- if(!active_program || !processor_unit)
+ if(!active_program || !all_components[MC_CPU])
return
idle_threads.Add(active_program)
@@ -112,7 +115,9 @@
update_icon()
return
- if(idle_threads.len >= processor_unit.max_idle_programs+1)
+ var/obj/item/weapon/computer_hardware/processor_unit/PU = all_components[MC_CPU]
+
+ if(idle_threads.len > PU.max_idle_programs)
user << "\The [src] displays a \"Maximal CPU load reached. Unable to run another program.\" error."
return
diff --git a/code/modules/modular_computers/computers/item/processor.dm b/code/modules/modular_computers/computers/item/processor.dm
index 65712546ef6..d50b9f9fd30 100644
--- a/code/modules/modular_computers/computers/item/processor.dm
+++ b/code/modules/modular_computers/computers/item/processor.dm
@@ -23,6 +23,8 @@
CRASH("Inapropriate type passed to obj/item/device/modular_computer/processor/New()! Aborting.")
return
// Obtain reference to machinery computer
+ all_components = list()
+ idle_threads = list()
machinery_computer = comp
machinery_computer.cpu = src
hardware_flag = machinery_computer.hardware_flag
@@ -53,3 +55,17 @@
..()
machinery_computer.update_icon()
return
+
+/obj/item/device/modular_computer/processor/add_verb(path)
+ switch(path)
+ if(MC_CARD)
+ machinery_computer.verbs += /obj/machinery/modular_computer/proc/eject_id
+ if(MC_SDD)
+ machinery_computer.verbs += /obj/machinery/modular_computer/proc/eject_disk
+
+/obj/item/device/modular_computer/processor/remove_verb(path)
+ switch(path)
+ if(MC_CARD)
+ machinery_computer.verbs -= /obj/machinery/modular_computer/proc/eject_id
+ if(MC_SDD)
+ machinery_computer.verbs -= /obj/machinery/modular_computer/proc/eject_disk
\ No newline at end of file
diff --git a/code/modules/modular_computers/computers/item/tablet.dm b/code/modules/modular_computers/computers/item/tablet.dm
index 0c8cad838de..54e27ea1d15 100644
--- a/code/modules/modular_computers/computers/item/tablet.dm
+++ b/code/modules/modular_computers/computers/item/tablet.dm
@@ -1,4 +1,4 @@
-/obj/item/device/modular_computer/tablet
+/obj/item/device/modular_computer/tablet //Its called tablet for theme of 90ies but actually its a "big smartphone" sized
name = "tablet computer"
icon = 'icons/obj/modular_tablet.dmi'
icon_state = "tablet"
@@ -9,3 +9,4 @@
max_hardware_size = 1
w_class = 2
steel_sheet_cost = 1
+ slot_flags = SLOT_ID | SLOT_BELT
\ No newline at end of file
diff --git a/code/modules/modular_computers/computers/machinery/console_presets.dm b/code/modules/modular_computers/computers/machinery/console_presets.dm
index a4741b16745..7f16199f53f 100644
--- a/code/modules/modular_computers/computers/machinery/console_presets.dm
+++ b/code/modules/modular_computers/computers/machinery/console_presets.dm
@@ -30,8 +30,9 @@
desc = "A stationary computer. This one comes preloaded with engineering programs."
/obj/machinery/modular_computer/console/preset/engineering/install_programs()
- cpu.hard_drive.store_file(new/datum/computer_file/program/power_monitor())
- cpu.hard_drive.store_file(new/datum/computer_file/program/alarm_monitor())
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = cpu.all_components[MC_HDD]
+ hard_drive.store_file(new/datum/computer_file/program/power_monitor())
+ hard_drive.store_file(new/datum/computer_file/program/alarm_monitor())
// ===== RESEARCH CONSOLE =====
/obj/machinery/modular_computer/console/preset/research
@@ -39,9 +40,10 @@
desc = "A stationary computer. This one comes preloaded with research programs."
/obj/machinery/modular_computer/console/preset/research/install_programs()
- cpu.hard_drive.store_file(new/datum/computer_file/program/ntnetmonitor())
- cpu.hard_drive.store_file(new/datum/computer_file/program/nttransfer())
- cpu.hard_drive.store_file(new/datum/computer_file/program/chatclient())
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = cpu.all_components[MC_HDD]
+ hard_drive.store_file(new/datum/computer_file/program/ntnetmonitor())
+ hard_drive.store_file(new/datum/computer_file/program/nttransfer())
+ hard_drive.store_file(new/datum/computer_file/program/chatclient())
// ===== COMMAND CONSOLE =====
@@ -52,8 +54,9 @@
_has_printer = 1
/obj/machinery/modular_computer/console/preset/command/install_programs()
- cpu.hard_drive.store_file(new/datum/computer_file/program/chatclient())
- cpu.hard_drive.store_file(new/datum/computer_file/program/card_mod())
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = cpu.all_components[MC_HDD]
+ hard_drive.store_file(new/datum/computer_file/program/chatclient())
+ hard_drive.store_file(new/datum/computer_file/program/card_mod())
// ===== CIVILIAN CONSOLE =====
/obj/machinery/modular_computer/console/preset/civilian
@@ -61,6 +64,6 @@
desc = "A stationary computer. This one comes preloaded with generic programs."
/obj/machinery/modular_computer/console/preset/civilian/install_programs()
- cpu.hard_drive.store_file(new/datum/computer_file/program/chatclient())
- cpu.hard_drive.store_file(new/datum/computer_file/program/nttransfer())
-
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = cpu.all_components[MC_HDD]
+ hard_drive.store_file(new/datum/computer_file/program/chatclient())
+ hard_drive.store_file(new/datum/computer_file/program/nttransfer())
\ No newline at end of file
diff --git a/code/modules/modular_computers/computers/machinery/modular_computer.dm b/code/modules/modular_computers/computers/machinery/modular_computer.dm
index 2aada0b5860..e04bc0cee73 100644
--- a/code/modules/modular_computers/computers/machinery/modular_computer.dm
+++ b/code/modules/modular_computers/computers/machinery/modular_computer.dm
@@ -74,7 +74,7 @@ var/list/global_modular_computers = list()
add_overlay("broken")
// Eject ID card from computer, if it has ID slot with card inside.
-/obj/machinery/modular_computer/verb/eject_id()
+/obj/machinery/modular_computer/proc/eject_id()
set name = "Eject ID"
set category = "Object"
set src in view(1)
@@ -83,7 +83,7 @@ var/list/global_modular_computers = list()
cpu.eject_id()
// Eject ID card from computer, if it has ID slot with card inside.
-/obj/machinery/modular_computer/verb/eject_disk()
+/obj/machinery/modular_computer/proc/eject_disk()
set name = "Eject Data Disk"
set category = "Object"
set src in view(1)
@@ -109,8 +109,9 @@ var/list/global_modular_computers = list()
// Used in following function to reduce copypaste
/obj/machinery/modular_computer/proc/power_failure(malfunction = 0)
+ var/obj/item/weapon/computer_hardware/battery/battery_module = cpu.all_components[MC_CELL]
if(cpu && cpu.enabled) // Shut down the computer
- visible_message("\The [src]'s screen flickers [cpu.battery_module ? "\"BATTERY [malfunction ? "MALFUNCTION" : "CRITICAL"]\"" : "\"EXTERNAL POWER LOSS\""] warning as it shuts down unexpectedly.")
+ visible_message("\The [src]'s screen flickers [battery_module ? "\"BATTERY [malfunction ? "MALFUNCTION" : "CRITICAL"]\"" : "\"EXTERNAL POWER LOSS\""] warning as it shuts down unexpectedly.")
if(cpu)
cpu.shutdown_computer(0)
stat |= NOPOWER
@@ -119,7 +120,7 @@ var/list/global_modular_computers = list()
// Modular computers can have battery in them, we handle power in previous proc, so prevent this from messing it up for us.
/obj/machinery/modular_computer/power_change()
- if(cpu && cpu.use_power()) // If "CPU" still has a power source, PC wouldn't go offline.
+ if(cpu && cpu.use_power()) // If MC_CPU still has a power source, PC wouldn't go offline.
stat &= ~NOPOWER
update_icon()
return
diff --git a/code/modules/modular_computers/computers/machinery/modular_console.dm b/code/modules/modular_computers/computers/machinery/modular_console.dm
index b5b6fe7b143..cebb1f4d715 100644
--- a/code/modules/modular_computers/computers/machinery/modular_console.dm
+++ b/code/modules/modular_computers/computers/machinery/modular_console.dm
@@ -22,29 +22,35 @@
/obj/machinery/modular_computer/console/buildable/New()
..()
// User-built consoles start as empty frames.
- qdel(cpu.recharger)
- qdel(cpu.network_card)
- qdel(cpu.hard_drive)
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = cpu.all_components[MC_HDD]
+ var/obj/item/weapon/computer_hardware/hard_drive/network_card = cpu.all_components[MC_NET]
+ var/obj/item/weapon/computer_hardware/hard_drive/recharger = cpu.all_components[MC_CHARGE]
+ qdel(recharger)
+ qdel(network_card)
+ qdel(hard_drive)
/obj/machinery/modular_computer/console/New()
..()
- if(cpu.battery_module)
- qdel(cpu.battery_module)
+ var/obj/item/weapon/computer_hardware/battery/battery_module = cpu.all_components[MC_CELL]
+ if(battery_module)
+ qdel(battery_module)
- cpu.install_component(new /obj/item/weapon/computer_hardware/network_card/wired)
+ var/obj/item/weapon/computer_hardware/network_card/wired/network_card = new()
+
+ cpu.install_component(network_card)
cpu.install_component(new /obj/item/weapon/computer_hardware/recharger/APC)
cpu.install_component(new /obj/item/weapon/computer_hardware/hard_drive/super) // Consoles generally have better HDDs due to lower space limitations
var/area/A = get_area(src)
// Attempts to set this console's tag according to our area. Since some areas have stuff like "XX - YY" in their names we try to remove that too.
if(A && console_department)
- cpu.network_card.identification_string = replacetext(replacetext(replacetext("[A.name] [console_department] Console", " ", "_"), "-", ""), "__", "_") // Replace spaces with "_"
+ network_card.identification_string = replacetext(replacetext(replacetext("[A.name] [console_department] Console", " ", "_"), "-", ""), "__", "_") // Replace spaces with "_"
else if(A)
- cpu.network_card.identification_string = replacetext(replacetext(replacetext("[A.name] Console", " ", "_"), "-", ""), "__", "_")
+ network_card.identification_string = replacetext(replacetext(replacetext("[A.name] Console", " ", "_"), "-", ""), "__", "_")
else if(console_department)
- cpu.network_card.identification_string = replacetext(replacetext(replacetext("[console_department] Console", " ", "_"), "-", ""), "__", "_")
+ network_card.identification_string = replacetext(replacetext(replacetext("[console_department] Console", " ", "_"), "-", ""), "__", "_")
else
- cpu.network_card.identification_string = "Unknown Console"
+ network_card.identification_string = "Unknown Console"
if(cpu)
cpu.screen_on = 1
update_icon()
\ No newline at end of file
diff --git a/code/modules/modular_computers/documentation.dm b/code/modules/modular_computers/documentation.dm
deleted file mode 100644
index 94e02f8125c..00000000000
--- a/code/modules/modular_computers/documentation.dm
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-
-Ok. so a quick rundown on how to make a program. This is kind of a shitty documentation, but oh well I was asked to.
-
-
-This is how the base program is setup. the rest is mostly tgui stuff. I'll use the ntnetmonitor as a base
-
-/datum/computer_file/program/ntnetmonitor
- filename = "ntmonitor" <- This is obviously the name of the file itself. not much to be said
- filedesc = "NTNet Diagnostics and Monitoring" <- This sort of the official name. it's what shows up on the main menu
- program_icon_state = "comm_monitor" <- This is what the screen will look like when the program is active
- extended_desc = "This program is a dummy. <- This is a sort of description, visible when looking on the ntnet
- size = 12 <- size of the program. Big programs need more hard drive space. Don't make it too big though.
- requires_ntnet = 1 <- if this is set, the program will not run and will close if ntnet connection is lost. mainly for primarily online programs.
- required_access = access_network <- This is access required to run the program itself. ONLY SET THIS FOR SUPER SECURE SHIT. This also acts as transfer_access as well.
- transfer_access = access_change_ids <- this is the access needed to download from ntnet or host on the ptp program. This is what you want to use most of the time.
- available_on_ntnet = 1 <- If it's available to download on ntnet. pretty self explanatory.
- available_on_syndinet = 0 <- ditto but on emagged syndie net. Use this for antag programs
- usage_flags = PROGRAM_ALL // Bitflags (PROGRAM_CONSOLE, PROGRAM_LAPTOP, PROGRAM_TABLET combination) or PROGRAM_ALL
- ^^- The comment above sorta explains it. Use this to limit what kind of machines can run the program. For example, comms program should be limited to consoles and laptops.
- var/ui_header = "downloader_finished.gif" <- this one is kinda cool. If you have the program minimized, this will show up in the header of the computer screen.
- you can even have the program change what the header is based on the situation! see alarm.dm for an example.
-
-
-Now. for pre-installing stuff.
-
-Primarily done for consoles, there's an install_programs() proc in the console presets file in the machines folder.
-
-for example, the command console one.
-
-/obj/machinery/modular_computer/console/preset/command/install_programs()
- cpu.hard_drive.store_file(new/datum/computer_file/program/chatclient())
- cpu.hard_drive.store_file(new/datum/computer_file/program/card_mod())
-
-Basically, you want to do cpu.hard_drive.store_file(new/*program path here*()) and put it in the subtype's install_programs().
-Probably pretty self explanatory, but just in case.
-
-Will probably be expanded when new features come around or I get asked to mention something.
-
-*/
\ No newline at end of file
diff --git a/code/modules/modular_computers/documentation.md b/code/modules/modular_computers/documentation.md
new file mode 100644
index 00000000000..88d8602729d
--- /dev/null
+++ b/code/modules/modular_computers/documentation.md
@@ -0,0 +1,45 @@
+
+
+#Modular computer programs
+Ok. so a quick rundown on how to make a program. This is kind of a shitty documentation, but oh well I was asked to.
+
+
+## Base setup
+This is how the base program is setup. the rest is mostly tgui stuff. I'll use the ntnetmonitor as a base
+
+
+```DM
+/datum/computer_file/program/ntnetmonitor
+ filename = "ntmonitor" //This is obviously the name of the file itself. not much to be said
+ filedesc = "NTNet Diagnostics and Monitoring" // This is sort of the official name. it's what shows up on the main menu
+ program_icon_state = "comm_monitor" // This is what the screen will look like when the program is active
+ extended_desc = "This program is a dummy. // This is a sort of a description, visible when looking on the ntnet
+ size = 12 // size of the program. Big programs need more hard drive space. Don't make it too big though.
+ requires_ntnet = 1 // If this is set, the program will not run without an ntnet connection, and will close if the connection is lost. Mainly for primarily online programs.
+ required_access = access_network //This is access required to run the program itself. ONLY SET THIS FOR SUPER SECURE SHIT. This also acts as transfer_access as well.
+ transfer_access = access_change_ids // This is the access needed to download from ntnet or host on the ptp program. This is what you want to use most of the time.
+ available_on_ntnet = 1 //If it's available to download on ntnet. pretty self explanatory.
+ available_on_syndinet = 0 // ditto but on emagged syndie net. Use this for antag programs
+ usage_flags = PROGRAM_ALL // Bitflags (PROGRAM_CONSOLE, PROGRAM_LAPTOP, PROGRAM_TABLET combination) or PROGRAM_ALL
+ //^^- The comment above sorta explains it. Use this to limit what kind of machines can run the program. For example, comms program should be limited to consoles and laptops.
+ var/ui_header = "downloader_finished.gif" //This one is kinda cool. If you have the program minimized, this will show up in the header of the computer screen.
+ //you can even have the program change what the header is based on the situation! see alarm.dm for an example.
+```
+
+##Preinstalls
+Now. for pre-installing stuff.
+
+Primarily done for consoles, there's an install_programs() proc in the console presets file in the machines folder.
+
+for example, the command console one.
+
+```DM
+/obj/machinery/modular_computer/console/preset/command/install_programs()
+ cpu.hard_drive.store_file(new/datum/computer_file/program/chatclient())
+ cpu.hard_drive.store_file(new/datum/computer_file/program/card_mod())
+```
+Basically, you want to do cpu.hard_drive.store_file(new/*program path here*()) and put it in the subtype's install_programs().
+Probably pretty self explanatory, but just in case.
+
+Will probably be expanded when new features come around or I get asked to mention something.
+
diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm
index 8ddff02fb64..46a9ea8ebc8 100644
--- a/code/modules/modular_computers/file_system/program.dm
+++ b/code/modules/modular_computers/file_system/program.dm
@@ -87,6 +87,11 @@
return 1
if(ishuman(user))
+ var/obj/item/weapon/card/id/D
+ var/obj/item/weapon/computer_hardware/card_slot/card_slot
+ if(computer && card_slot)
+ card_slot = computer.all_components[MC_CARD]
+ D = card_slot.GetID()
var/mob/living/carbon/human/h = user
var/obj/item/weapon/card/id/I = h.get_idcard()
var/obj/item/weapon/card/id/C = h.get_active_held_item()
@@ -95,7 +100,7 @@
if(!(C && istype(C)))
C = null
- if(!I && !C)
+ if(!I && !C && !D)
if(loud)
user << "\The [computer] flashes an \"RFID Error - Unable to scan ID\" warning."
return 0
@@ -106,6 +111,9 @@
else if(C)
if(access_to_check in C.GetAccess())
return 1
+ else if(D)
+ if(access_to_check in D.GetAccess())
+ return 1
if(loud)
user << "\The [computer] flashes an \"Access Denied\" warning."
return 0
@@ -162,7 +170,7 @@
return 1
if("PC_minimize")
var/mob/user = usr
- if(!computer.active_program || !computer.processor_unit)
+ if(!computer.active_program || !computer.all_components[MC_CPU])
return
computer.idle_threads.Add(computer.active_program)
diff --git a/code/modules/modular_computers/file_system/programs/antagonist/dos.dm b/code/modules/modular_computers/file_system/programs/antagonist/dos.dm
index d14bb885bfe..3d54938ba11 100644
--- a/code/modules/modular_computers/file_system/programs/antagonist/dos.dm
+++ b/code/modules/modular_computers/file_system/programs/antagonist/dos.dm
@@ -69,7 +69,8 @@
executed = 1
target.dos_sources.Add(src)
if(ntnet_global.intrusion_detection_enabled)
- ntnet_global.add_log("IDS WARNING - Excess traffic flood targeting relay [target.uid] detected from device: [computer.network_card.get_network_tag()]")
+ var/obj/item/weapon/computer_hardware/network_card/network_card = computer.all_components[MC_NET]
+ ntnet_global.add_log("IDS WARNING - Excess traffic flood targeting relay [target.uid] detected from device: [network_card.get_network_tag()]")
ntnet_global.intrusion_detection_alarm = 1
return 1
diff --git a/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm b/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm
index f5ae0766f74..89040ca7ae7 100644
--- a/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm
+++ b/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm
@@ -19,16 +19,19 @@
computer.visible_message("\The [computer]'s screen brightly flashes and loud electrical buzzing is heard.")
computer.enabled = 0
computer.update_icon()
- qdel(computer.hard_drive)
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = computer.all_components[MC_HDD]
+ var/obj/item/weapon/computer_hardware/battery/battery_module = computer.all_components[MC_CELL]
+ var/obj/item/weapon/computer_hardware/recharger/recharger = computer.all_components[MC_CHARGE]
+ qdel(hard_drive)
computer.take_damage(25, 10, 1, 1)
- if(computer.battery_module && prob(25))
- qdel(computer.battery_module)
+ if(battery_module && prob(25))
+ qdel(battery_module)
computer.visible_message("\The [computer]'s battery explodes in rain of sparks.")
var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread
spark_system.start()
- if(computer.recharger && prob(50))
- qdel(computer.recharger)
+ if(recharger && prob(50))
+ qdel(recharger)
computer.visible_message("\The [computer]'s recharger explodes in rain of sparks.")
var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread
spark_system.start()
diff --git a/code/modules/modular_computers/file_system/programs/card.dm b/code/modules/modular_computers/file_system/programs/card.dm
index 780045d8b73..0f1b03f4b38 100644
--- a/code/modules/modular_computers/file_system/programs/card.dm
+++ b/code/modules/modular_computers/file_system/programs/card.dm
@@ -88,7 +88,8 @@
/datum/computer_file/program/card_mod/proc/format_jobs(list/jobs)
- var/obj/item/weapon/card/id/id_card = computer.card_slot.stored_card
+ var/obj/item/weapon/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD]
+ var/obj/item/weapon/card/id/id_card = card_slot.stored_card
var/list/formatted = list()
for(var/job in jobs)
formatted.Add(list(list(
@@ -102,11 +103,19 @@
if(..())
return 1
+ var/obj/item/weapon/computer_hardware/card_slot/card_slot
+ var/obj/item/weapon/computer_hardware/printer/printer
+ if(computer)
+ card_slot = computer.all_components[MC_CARD]
+ printer = computer.all_components[MC_PRINT]
+ if(!card_slot)
+ return
+
var/obj/item/weapon/card/id/user_id_card = null
var/mob/user = usr
- var/obj/item/weapon/card/id/id_card = computer.card_slot.stored_card
- var/obj/item/weapon/card/id/auth_card = computer.card_slot.stored_card2
+ var/obj/item/weapon/card/id/id_card = card_slot.stored_card
+ var/obj/item/weapon/card/id/auth_card = card_slot.stored_card2
if(auth_card)
user_id_card = auth_card
@@ -129,7 +138,7 @@
else
show_assignments = 1
if("PRG_print")
- if(computer && computer.printer) //This option should never be called if there is no printer
+ if(computer && printer) //This option should never be called if there is no printer
if(mod_mode)
if(authorized())
var/contents = {"Access Report
@@ -145,7 +154,7 @@
if(A in known_access_rights)
contents += " [get_access_desc(A)]"
- if(!computer.printer.print_text(contents,"access report"))
+ if(!printer.print_text(contents,"access report"))
usr << "Hardware error: Printer was unable to print the file. It may be out of paper."
return
else
@@ -155,26 +164,26 @@
[data_core ? data_core.get_manifest(0) : ""]
"}
- if(!computer.printer.print_text(contents,text("crew manifest ([])", worldtime2text())))
+ if(!printer.print_text(contents,text("crew manifest ([])", worldtime2text())))
usr << "Hardware error: Printer was unable to print the file. It may be out of paper."
return
else
computer.visible_message("\The [computer] prints out paper.")
if("PRG_eject")
- if(computer && computer.card_slot)
+ if(computer && card_slot)
var/select = params["target"]
switch(select)
if("id")
if(id_card)
data_core.manifest_modify(id_card.registered_name, id_card.assignment)
- computer.proc_eject_id(user, 1)
+ card_slot.try_eject(, user)
else
var/obj/item/I = usr.get_active_held_item()
if (istype(I, /obj/item/weapon/card/id))
if(!usr.drop_item())
return
I.forceMove(computer)
- computer.card_slot.stored_card = I
+ card_slot.stored_card = I
if("auth")
if(auth_card)
if(id_card)
@@ -183,14 +192,14 @@
region_access = null
authenticated = 0
minor = 0
- computer.proc_eject_id(user, 2)
+ card_slot.try_eject(, user)
else
var/obj/item/I = usr.get_active_held_item()
if (istype(I, /obj/item/weapon/card/id))
if(!usr.drop_item())
return
I.forceMove(computer)
- computer.card_slot.stored_card2 = I
+ card_slot.stored_card2 = I
if("PRG_terminate")
if(computer && ((id_card.assignment in head_subordinates) || id_card.assignment == "Assistant"))
id_card.assignment = "Unassigned"
@@ -292,13 +301,21 @@
var/list/data = get_header_data()
+ var/obj/item/weapon/computer_hardware/card_slot/card_slot
+ var/obj/item/weapon/computer_hardware/printer/printer
+
+ if(computer)
+ card_slot = computer.all_components[MC_CARD]
+ printer = computer.all_components[MC_PRINT]
+
data["mmode"] = mod_mode
var/authed = 0
- if(computer && computer.card_slot)
- var/obj/item/weapon/card/id/auth_card = computer.card_slot.stored_card2
- data["auth_name"] = auth_card ? strip_html_simple(auth_card.name) : "-----"
- authed = authorized()
+ if(computer)
+ if(card_slot)
+ var/obj/item/weapon/card/id/auth_card = card_slot.stored_card2
+ data["auth_name"] = auth_card ? strip_html_simple(auth_card.name) : "-----"
+ authed = authorized()
if(mod_mode == 2)
@@ -336,9 +353,9 @@
data["manifest"] = crew
data["assignments"] = show_assignments
if(computer)
- data["have_id_slot"] = !!computer.card_slot
- data["have_printer"] = !!computer.printer
- if(!computer.card_slot && mod_mode == 1)
+ data["have_id_slot"] = !!card_slot
+ data["have_printer"] = !!printer
+ if(!card_slot && mod_mode == 1)
mod_mode = 0 //We can't modify IDs when there is no card reader
else
data["have_id_slot"] = 0
@@ -350,10 +367,9 @@
data["authenticated"] = authed
- if(mod_mode == 1)
-
- if(computer && computer.card_slot)
- var/obj/item/weapon/card/id/id_card = computer.card_slot.stored_card
+ if(mod_mode == 1 && computer)
+ if(card_slot)
+ var/obj/item/weapon/card/id/id_card = card_slot.stored_card
data["has_id"] = !!id_card
data["id_rank"] = id_card && id_card.assignment ? html_encode(id_card.assignment) : "Unassigned"
@@ -370,8 +386,8 @@
data["centcom_jobs"] = format_jobs(get_all_centcom_jobs())
- if(computer.card_slot.stored_card)
- var/obj/item/weapon/card/id/id_card = computer.card_slot.stored_card
+ if(card_slot.stored_card)
+ var/obj/item/weapon/card/id/id_card = card_slot.stored_card
if(is_centcom)
var/list/all_centcom_access = list()
for(var/access in get_all_centcom_access())
@@ -431,9 +447,10 @@
/datum/computer_file/program/card_mod/proc/authorized()
- if(!authenticated)
- if(computer && computer.card_slot)
- var/obj/item/weapon/card/id/auth_card = computer.card_slot.stored_card2
+ if(!authenticated && computer)
+ var/obj/item/weapon/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD]
+ if(card_slot)
+ var/obj/item/weapon/card/id/auth_card = card_slot.stored_card2
if(auth_card)
region_access = list()
if(transfer_access in auth_card.GetAccess())
diff --git a/code/modules/modular_computers/file_system/programs/configurator.dm b/code/modules/modular_computers/file_system/programs/configurator.dm
index 6b77cbbd4e6..57348d27441 100644
--- a/code/modules/modular_computers/file_system/programs/configurator.dm
+++ b/code/modules/modular_computers/file_system/programs/configurator.dm
@@ -29,6 +29,8 @@
/datum/computer_file/program/computerconfig/ui_data(mob/user)
movable = computer
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = movable.all_components[MC_HDD]
+ var/obj/item/weapon/computer_hardware/battery/battery_module = movable.all_components[MC_CELL]
if(!istype(movable))
movable = null
@@ -38,20 +40,20 @@
var/list/data = get_header_data()
- data["disk_size"] = movable.hard_drive.max_capacity
- data["disk_used"] = movable.hard_drive.used_capacity
+ data["disk_size"] = hard_drive.max_capacity
+ data["disk_used"] = hard_drive.used_capacity
data["power_usage"] = movable.last_power_usage
- data["battery_exists"] = movable.battery_module ? 1 : 0
- if(movable.battery_module && movable.battery_module.battery)
- data["battery_rating"] = movable.battery_module.battery.maxcharge
- data["battery_percent"] = round(movable.battery_module.battery.percent())
+ data["battery_exists"] = battery_module ? 1 : 0
+ if(battery_module && battery_module.battery)
+ data["battery_rating"] = battery_module.battery.maxcharge
+ data["battery_percent"] = round(battery_module.battery.percent())
- if(movable.battery_module && movable.battery_module.battery)
- data["battery"] = list("max" = movable.battery_module.battery.maxcharge, "charge" = round(movable.battery_module.battery.charge))
+ if(battery_module && battery_module.battery)
+ data["battery"] = list("max" = battery_module.battery.maxcharge, "charge" = round(battery_module.battery.charge))
var/list/all_entries[0]
for(var/I in movable.all_components)
- var/obj/item/weapon/computer_hardware/H = I
+ var/obj/item/weapon/computer_hardware/H = movable.all_components[I]
all_entries.Add(list(list(
"name" = H.name,
"desc" = H.desc,
diff --git a/code/modules/modular_computers/file_system/programs/file_browser.dm b/code/modules/modular_computers/file_system/programs/file_browser.dm
index 254f09b694a..50a07014e5c 100644
--- a/code/modules/modular_computers/file_system/programs/file_browser.dm
+++ b/code/modules/modular_computers/file_system/programs/file_browser.dm
@@ -14,8 +14,9 @@
if(..())
return 1
- var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive
- var/obj/item/weapon/computer_hardware/hard_drive/RHDD = computer.portable_drive
+ var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.all_components[MC_HDD]
+ var/obj/item/weapon/computer_hardware/hard_drive/RHDD = computer.all_components[MC_HDD]
+ var/obj/item/weapon/computer_hardware/printer/printer = computer.all_components[MC_PRINT]
switch(action)
if("PRG_openfile")
@@ -106,10 +107,10 @@
var/datum/computer_file/data/F = HDD.find_file_by_name(open_file)
if(!F || !istype(F))
return 1
- if(!computer.printer)
+ if(!printer)
error = "Missing Hardware: Your computer does not have required hardware to complete this operation."
return 1
- if(!computer.printer.print_text(parse_tags(F.stored_data)))
+ if(!printer.print_text(parse_tags(F.stored_data)))
error = "Hardware error: Printer was unable to print the file. It may be out of paper."
return 1
if("PRG_copytousb")
@@ -185,17 +186,16 @@
/datum/computer_file/program/filemanager/ui_data(mob/user)
var/list/data = get_header_data()
- var/obj/item/weapon/computer_hardware/hard_drive/HDD
- var/obj/item/weapon/computer_hardware/hard_drive/portable/RHDD
+ var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.all_components[MC_HDD]
+ var/obj/item/weapon/computer_hardware/hard_drive/portable/RHDD = computer.all_components[MC_SDD]
if(error)
data["error"] = error
if(open_file)
var/datum/computer_file/data/file
- if(!computer || !computer.hard_drive)
+ if(!computer || !HDD)
data["error"] = "I/O ERROR: Unable to access hard drive."
else
- HDD = computer.hard_drive
file = HDD.find_file_by_name(open_file)
if(!istype(file))
data["error"] = "I/O ERROR: Unable to open file."
@@ -203,11 +203,9 @@
data["filedata"] = parse_tags(file.stored_data)
data["filename"] = "[file.filename].[file.filetype]"
else
- if(!computer || !computer.hard_drive)
+ if(!computer || !HDD)
data["error"] = "I/O ERROR: Unable to access hard drive."
else
- HDD = computer.hard_drive
- RHDD = computer.portable_drive
var/list/files[0]
for(var/datum/computer_file/F in HDD.stored_files)
files.Add(list(list(
diff --git a/code/modules/modular_computers/file_system/programs/ntdownloader.dm b/code/modules/modular_computers/file_system/programs/ntdownloader.dm
index 32d8d2eba13..c15bcd1fce2 100644
--- a/code/modules/modular_computers/file_system/programs/ntdownloader.dm
+++ b/code/modules/modular_computers/file_system/programs/ntdownloader.dm
@@ -30,7 +30,9 @@
if(PRG.available_on_syndinet && !computer.emagged)
return 0
- if(!computer || !computer.hard_drive || !computer.hard_drive.can_store_file(PRG))
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = computer.all_components[MC_HDD]
+
+ if(!computer || !hard_drive || !hard_drive.can_store_file(PRG))
return 0
ui_header = "downloader_running.gif"
@@ -59,7 +61,8 @@
if(!downloaded_file)
return
generate_network_log("Completed download of file [hacked_download ? "**ENCRYPTED**" : "[downloaded_file.filename].[downloaded_file.filetype]"].")
- if(!computer || !computer.hard_drive || !computer.hard_drive.store_file(downloaded_file))
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = computer.all_components[MC_HDD]
+ if(!computer || !hard_drive || !hard_drive.store_file(downloaded_file))
// The download failed
downloaderror = "I/O ERROR - Unable to save file. Check whether you have enough free space on your hard drive and whether your hard drive is properly connected. If the issue persists contact your system administrator for assistance."
downloaded_file = null
@@ -129,8 +132,9 @@
data["downloadspeed"] = download_netspeed
data["downloadcompletion"] = round(download_completion, 0.1)
else // No download running, pick file.
- data["disk_size"] = my_computer.hard_drive.max_capacity
- data["disk_used"] = my_computer.hard_drive.used_capacity
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = my_computer.all_components[MC_HDD]
+ data["disk_size"] = hard_drive.max_capacity
+ data["disk_used"] = hard_drive.used_capacity
var/list/all_entries[0]
for(var/A in ntnet_global.available_station_software)
var/datum/computer_file/program/P = A
@@ -160,3 +164,7 @@
data["downloadable_programs"] = all_entries
return data
+
+/datum/computer_file/program/ntnetdownload/kill_program(forced)
+ abort_file_download()
+ return ..(forced)
\ No newline at end of file
diff --git a/code/modules/modular_computers/file_system/programs/ntnrc_client.dm b/code/modules/modular_computers/file_system/programs/ntnrc_client.dm
index b559e9d161f..1b8ff887673 100644
--- a/code/modules/modular_computers/file_system/programs/ntnrc_client.dm
+++ b/code/modules/modular_computers/file_system/programs/ntnrc_client.dm
@@ -28,7 +28,7 @@
if(!channel)
return 1
var/mob/living/user = usr
- var/message = sanitize(input(user, "Enter message or leave blank to cancel: "))
+ var/message = reject_bad_text(input(user, "Enter message or leave blank to cancel: "))
if(!message || !channel)
return
channel.add_message(message, username)
@@ -51,7 +51,7 @@
if(C.password)
var/mob/living/user = usr
- var/password = sanitize(input(user,"Access Denied. Enter password:"))
+ var/password = reject_bad_text(input(user,"Access Denied. Enter password:"))
if(C && (password == C.password))
C.add_client(src)
channel = C
@@ -66,7 +66,7 @@
if("PRG_newchannel")
. = 1
var/mob/living/user = usr
- var/channel_title = sanitize(input(user,"Enter channel name or leave blank to cancel:"))
+ var/channel_title = reject_bad_text(input(user,"Enter channel name or leave blank to cancel:"))
if(!channel_title)
return
var/datum/ntnet_conversation/C = new/datum/ntnet_conversation()
@@ -119,12 +119,13 @@
logfile.stored_data += "[logstring]\[BR\]"
logfile.stored_data += "\[b\]Logfile dump completed.\[/b\]"
logfile.calculate_size()
- if(!computer || !computer.hard_drive || !computer.hard_drive.store_file(logfile))
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = computer.all_components[MC_HDD]
+ if(!computer || !hard_drive || !hard_drive.store_file(logfile))
if(!computer)
// This program shouldn't even be runnable without computer.
CRASH("Var computer is null!")
return 1
- if(!computer.hard_drive)
+ if(!hard_drive)
computer.visible_message("\The [computer] shows an \"I/O Error - Hard drive connection error\" warning.")
else // In 99.9% cases this will mean our HDD is full
computer.visible_message("\The [computer] shows an \"I/O Error - Hard drive may be full. Please free some space and try again. Required space: [logfile.size]GQ\" warning.")
@@ -133,7 +134,7 @@
if(!operator_mode || !channel)
return 1
var/mob/living/user = usr
- var/newname = sanitize(input(user, "Enter new channel name or leave blank to cancel:"))
+ var/newname = reject_bad_text(input(user, "Enter new channel name or leave blank to cancel:"))
if(!newname || !channel)
return
channel.add_status_message("Channel renamed from [channel.title] to [newname] by operator.")
diff --git a/code/modules/modular_computers/file_system/programs/nttransfer.dm b/code/modules/modular_computers/file_system/programs/nttransfer.dm
index ffc4653221e..4e20bbf9ea5 100644
--- a/code/modules/modular_computers/file_system/programs/nttransfer.dm
+++ b/code/modules/modular_computers/file_system/programs/nttransfer.dm
@@ -66,7 +66,8 @@ var/global/nttransfer_uid = 0
// Finishes download and attempts to store the file on HDD
/datum/computer_file/program/nttransfer/proc/finish_download()
- if(!computer || !computer.hard_drive || !computer.hard_drive.store_file(downloaded_file))
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = computer.all_components[MC_HDD]
+ if(!computer || !hard_drive || !hard_drive.store_file(downloaded_file))
error = "I/O Error: Unable to save file. Check your hard drive and try again."
finalize_download()
@@ -109,7 +110,7 @@ var/global/nttransfer_uid = 0
if(!remote || !remote.provided_file)
return
if(remote.server_password)
- var/pass = sanitize(input(usr, "Code 401 Unauthorized. Please enter password:", "Password required"))
+ var/pass = reject_bad_text(input(usr, "Code 401 Unauthorized. Please enter password:", "Password required"))
if(pass != remote.server_password)
error = "Incorrect Password"
return
@@ -127,7 +128,7 @@ var/global/nttransfer_uid = 0
provided_file = null
return 1
if("PRG_setpassword")
- var/pass = sanitize(input(usr, "Enter new server password. Leave blank to cancel, input 'none' to disable password.", "Server security", "none"))
+ var/pass = reject_bad_text(input(usr, "Enter new server password. Leave blank to cancel, input 'none' to disable password.", "Server security", "none"))
if(!pass)
return
if(pass == "none")
@@ -136,7 +137,8 @@ var/global/nttransfer_uid = 0
server_password = pass
return 1
if("PRG_uploadfile")
- for(var/datum/computer_file/F in computer.hard_drive.stored_files)
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = computer.all_components[MC_HDD]
+ for(var/datum/computer_file/F in hard_drive.stored_files)
if("[F.uid]" == params["id"])
if(F.unsendable)
error = "I/O Error: File locked."
@@ -174,7 +176,8 @@ var/global/nttransfer_uid = 0
data["upload_filename"] = "[provided_file.filename].[provided_file.filetype]"
else if (upload_menu)
var/list/all_files[0]
- for(var/datum/computer_file/F in computer.hard_drive.stored_files)
+ var/obj/item/weapon/computer_hardware/hard_drive/hard_drive = computer.all_components[MC_HDD]
+ for(var/datum/computer_file/F in hard_drive.stored_files)
all_files.Add(list(list(
"uid" = F.uid,
"filename" = "[F.filename].[F.filetype]",
diff --git a/code/modules/modular_computers/hardware/CPU.dm b/code/modules/modular_computers/hardware/CPU.dm
index e78f02d85cc..d212df22028 100644
--- a/code/modules/modular_computers/hardware/CPU.dm
+++ b/code/modules/modular_computers/hardware/CPU.dm
@@ -11,6 +11,10 @@
malfunction_probability = 1
origin_tech = "programming=3;engineering=2"
var/max_idle_programs = 2 // 2 idle, + 1 active = 3 as said in description.
+ device_type = MC_CPU
+
+/obj/item/weapon/computer_hardware/processor_unit/on_remove(obj/item/device/modular_computer/MC, mob/user)
+ MC.shutdown_computer()
/obj/item/weapon/computer_hardware/processor_unit/small
name = "microprocessor"
diff --git a/code/modules/modular_computers/hardware/_hardware.dm b/code/modules/modular_computers/hardware/_hardware.dm
index ebbef88c2d0..81f61671555 100644
--- a/code/modules/modular_computers/hardware/_hardware.dm
+++ b/code/modules/modular_computers/hardware/_hardware.dm
@@ -18,6 +18,7 @@
var/damage_malfunction = 20 // "Malfunction" threshold. When damage exceeds this value the hardware piece will semi-randomly fail and do !!FUN!! things
var/damage_failure = 50 // "Failure" threshold. When damage exceeds this value the hardware piece will not work at all.
var/malfunction_probability = 10// Chance of malfunction when the component is damaged
+ var/device_type
/obj/item/weapon/computer_hardware/New(var/obj/L)
..()
diff --git a/code/modules/modular_computers/hardware/battery_module.dm b/code/modules/modular_computers/hardware/battery_module.dm
index 824cd03bf21..7c4e9d169a1 100644
--- a/code/modules/modular_computers/hardware/battery_module.dm
+++ b/code/modules/modular_computers/hardware/battery_module.dm
@@ -6,6 +6,7 @@
malfunction_probability = 1
origin_tech = "powerstorage=1;engineering=1"
var/obj/item/weapon/stock_parts/cell/battery = null
+ device_type = MC_CELL
/obj/item/weapon/computer_hardware/battery/New(loc, battery_type = null)
if(battery_type)
diff --git a/code/modules/modular_computers/hardware/card_slot.dm b/code/modules/modular_computers/hardware/card_slot.dm
index f0fb2cd20c2..7648d74f54b 100644
--- a/code/modules/modular_computers/hardware/card_slot.dm
+++ b/code/modules/modular_computers/hardware/card_slot.dm
@@ -5,6 +5,7 @@
icon_state = "card_mini"
w_class = 1
origin_tech = "programming=2"
+ device_type = MC_CARD
var/obj/item/weapon/card/id/stored_card = null
var/obj/item/weapon/card/id/stored_card2 = null
@@ -29,6 +30,12 @@
return stored_card2
return ..()
+/obj/item/weapon/computer_hardware/card_slot/on_install(obj/item/device/modular_computer/M, mob/living/user = null)
+ M.add_verb(device_type)
+
+/obj/item/weapon/computer_hardware/card_slot/on_remove(obj/item/device/modular_computer/M, mob/living/user = null)
+ M.remove_verb(device_type)
+
/obj/item/weapon/computer_hardware/card_slot/try_insert(obj/item/I, mob/living/user = null)
if(!holder)
return FALSE
diff --git a/code/modules/modular_computers/hardware/hard_drive.dm b/code/modules/modular_computers/hardware/hard_drive.dm
index e5e43f57283..62c02e0a07a 100644
--- a/code/modules/modular_computers/hardware/hard_drive.dm
+++ b/code/modules/modular_computers/hardware/hard_drive.dm
@@ -6,10 +6,14 @@
critical = 1
w_class = 1
origin_tech = "programming=1;engineering=1"
+ device_type = MC_HDD
var/max_capacity = 128
var/used_capacity = 0
var/list/stored_files = list() // List of stored files on this drive. DO NOT MODIFY DIRECTLY!
+/obj/item/weapon/computer_hardware/hard_drive/on_remove(obj/item/device/modular_computer/MC, mob/user)
+ MC.shutdown_computer()
+
/obj/item/weapon/computer_hardware/hard_drive/proc/install_default_programs()
store_file(new/datum/computer_file/program/computerconfig(src)) // Computer configuration utility, allows hardware control and displays more info than status bar
store_file(new/datum/computer_file/program/ntnetdownload(src)) // NTNet Downloader Utility, allows users to download more software from NTNet repository
diff --git a/code/modules/modular_computers/hardware/network_card.dm b/code/modules/modular_computers/hardware/network_card.dm
index 681dbd503da..8370ad4e384 100644
--- a/code/modules/modular_computers/hardware/network_card.dm
+++ b/code/modules/modular_computers/hardware/network_card.dm
@@ -11,6 +11,7 @@ var/global/ntnet_card_uid = 1
var/long_range = 0
var/ethernet = 0 // Hard-wired, therefore always on, ignores NTNet wireless checks.
malfunction_probability = 1
+ device_type = MC_NET
/obj/item/weapon/computer_hardware/network_card/diagnostics(var/mob/user)
..()
diff --git a/code/modules/modular_computers/hardware/portable_disk.dm b/code/modules/modular_computers/hardware/portable_disk.dm
index 4878e530150..b7392d531f9 100644
--- a/code/modules/modular_computers/hardware/portable_disk.dm
+++ b/code/modules/modular_computers/hardware/portable_disk.dm
@@ -7,6 +7,14 @@
critical = 0
max_capacity = 16
origin_tech = "programming=1"
+ device_type = MC_SDD
+
+/obj/item/weapon/computer_hardware/hard_drive/portable/on_install(obj/item/device/modular_computer/M, mob/living/user = null)
+ M.add_verb(device_type)
+
+/obj/item/weapon/computer_hardware/hard_drive/portable/on_remove(obj/item/device/modular_computer/M, mob/living/user = null)
+ ..()
+ M.remove_verb(device_type)
/obj/item/weapon/computer_hardware/hard_drive/portable/install_default_programs()
return // Empty by default
diff --git a/code/modules/modular_computers/hardware/printer.dm b/code/modules/modular_computers/hardware/printer.dm
index c23905bf119..a93fdd20309 100644
--- a/code/modules/modular_computers/hardware/printer.dm
+++ b/code/modules/modular_computers/hardware/printer.dm
@@ -5,6 +5,7 @@
origin_tech = "programming=2;engineering=2"
icon_state = "printer"
w_class = 3
+ device_type = MC_PRINT
var/stored_paper = 20
var/max_paper = 30
diff --git a/code/modules/modular_computers/hardware/recharger.dm b/code/modules/modular_computers/hardware/recharger.dm
index fc3469fd3aa..0b83714ec42 100644
--- a/code/modules/modular_computers/hardware/recharger.dm
+++ b/code/modules/modular_computers/hardware/recharger.dm
@@ -2,6 +2,7 @@
critical = 1
enabled = 1
var/charge_rate = 100
+ device_type = MC_CHARGE
/obj/item/weapon/computer_hardware/recharger/proc/use_power(amount, charging=0)
if(charging)
@@ -10,10 +11,11 @@
/obj/item/weapon/computer_hardware/recharger/process()
..()
- if(!holder || !holder.battery_module || !holder.battery_module.battery)
+ var/obj/item/weapon/computer_hardware/battery/battery_module = holder.all_components[MC_CELL]
+ if(!holder || !battery_module || !battery_module.battery)
return
- var/obj/item/weapon/stock_parts/cell/cell = holder.battery_module.battery
+ var/obj/item/weapon/stock_parts/cell/cell = battery_module.battery
if(cell.charge >= cell.maxcharge)
return
diff --git a/code/modules/modular_computers/laptop_vendor.dm b/code/modules/modular_computers/laptop_vendor.dm
index 8cb1805f7f6..82ca666360a 100644
--- a/code/modules/modular_computers/laptop_vendor.dm
+++ b/code/modules/modular_computers/laptop_vendor.dm
@@ -54,6 +54,7 @@
fabricated_laptop = new /obj/item/device/modular_computer/laptop/buildable(src)
fabricated_laptop.install_component(new /obj/item/weapon/computer_hardware/battery)
total_price = 99
+ var/obj/item/weapon/computer_hardware/battery/battery_module = fabricated_laptop.all_components[MC_CELL]
switch(dev_cpu)
if(1)
if(fabricate)
@@ -65,14 +66,14 @@
switch(dev_battery)
if(1) // Basic(750C)
if(fabricate)
- fabricated_laptop.battery_module.try_insert(new /obj/item/weapon/stock_parts/cell/computer)
+ battery_module.try_insert(new /obj/item/weapon/stock_parts/cell/computer)
if(2) // Upgraded(1100C)
if(fabricate)
- fabricated_laptop.battery_module.try_insert(new /obj/item/weapon/stock_parts/cell/computer/advanced)
+ battery_module.try_insert(new /obj/item/weapon/stock_parts/cell/computer/advanced)
total_price += 199
if(3) // Advanced(1500C)
if(fabricate)
- fabricated_laptop.battery_module.try_insert(new /obj/item/weapon/stock_parts/cell/computer/super)
+ battery_module.try_insert(new /obj/item/weapon/stock_parts/cell/computer/super)
total_price += 499
switch(dev_disk)
if(1) // Basic(128GQ)
@@ -115,17 +116,18 @@
fabricated_tablet.install_component(new /obj/item/weapon/computer_hardware/battery)
fabricated_tablet.install_component(new /obj/item/weapon/computer_hardware/processor_unit/small)
total_price = 199
+ var/obj/item/weapon/computer_hardware/battery/battery_module = fabricated_tablet.all_components[MC_CELL]
switch(dev_battery)
if(1) // Basic(300C)
if(fabricate)
- fabricated_tablet.battery_module.try_insert(new /obj/item/weapon/stock_parts/cell/computer/nano)
+ battery_module.try_insert(new /obj/item/weapon/stock_parts/cell/computer/nano)
if(2) // Upgraded(500C)
if(fabricate)
- fabricated_tablet.battery_module.try_insert(new /obj/item/weapon/stock_parts/cell/computer/micro)
+ battery_module.try_insert(new /obj/item/weapon/stock_parts/cell/computer/micro)
total_price += 199
if(3) // Advanced(750C)
if(fabricate)
- fabricated_tablet.battery_module.try_insert(new /obj/item/weapon/stock_parts/cell/computer)
+ battery_module.try_insert(new /obj/item/weapon/stock_parts/cell/computer)
total_price += 499
switch(dev_disk)
if(1) // Basic(32GQ)
diff --git a/code/modules/ninja/suit/n_suit_verbs/energy_net_nets.dm b/code/modules/ninja/suit/n_suit_verbs/energy_net_nets.dm
index 04c0c796f23..56457b02ba5 100644
--- a/code/modules/ninja/suit/n_suit_verbs/energy_net_nets.dm
+++ b/code/modules/ninja/suit/n_suit_verbs/energy_net_nets.dm
@@ -76,28 +76,23 @@ It is possible to destroy the net by the occupant or someone else.
continue
M.unEquip(W)
- spawn(0)
- playsound(M.loc, 'sound/effects/sparks4.ogg', 50, 1)
- anim(M.loc,M,'icons/mob/mob.dmi',,"phaseout",,M.dir)
+ playsound(M.loc, 'sound/effects/sparks4.ogg', 50, 1)
+ PoolOrNew(/obj/effect/overlay/temp/dir_setting/ninja/phase/out, list(get_turf(M), M.dir))
- M.loc = pick(holdingfacility)//Throw mob in to the holding facility.
+ visible_message("[M] suddenly vanishes!")
+ M.forceMove(pick(holdingfacility)) //Throw mob in to the holding facility.
M << "You appear in a strange place!"
- spawn(0)
- var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread()
- spark_system.set_up(5, 0, M.loc)
- spark_system.start()
- playsound(M.loc, 'sound/effects/phasein.ogg', 25, 1)
- playsound(M.loc, 'sound/effects/sparks2.ogg', 50, 1)
- anim(M.loc,M,'icons/mob/mob.dmi',,"phasein",,M.dir)
- qdel(src)//Wait for everything to finish, delete the net. Else it will stop everything once net is deleted, including the spawn(0).
-
- for(var/mob/O in viewers(src, 3))
- O.show_message("[M] vanishes!", 1, "You hear sparks flying!", 2)
-
if(!isnull(master))//As long as they still exist.
master << "SUCCESS: transport procedure of \the [affecting] complete."
M.notransform = 0
+ var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread()
+ spark_system.set_up(5, 0, M.loc)
+ spark_system.start()
+ playsound(M.loc, 'sound/effects/phasein.ogg', 25, 1)
+ playsound(M.loc, 'sound/effects/sparks2.ogg', 50, 1)
+ PoolOrNew(/obj/effect/overlay/temp/dir_setting/ninja/phase, list(get_turf(M), M.dir))
+ qdel(src)
else//And they are free.
M << "You are free of the net!"
diff --git a/code/modules/ninja/suit/n_suit_verbs/ninja_net.dm b/code/modules/ninja/suit/n_suit_verbs/ninja_net.dm
index 34d47d7e469..a8d6931a951 100644
--- a/code/modules/ninja/suit/n_suit_verbs/ninja_net.dm
+++ b/code/modules/ninja/suit/n_suit_verbs/ninja_net.dm
@@ -15,7 +15,7 @@
H << "You may not use an energy net through solid obstacles!"
return
spawn(0)
- H.Beam(C,"n_beam",,15)
+ H.Beam(C,"n_beam",time=15)
H.say("Get over here!")
var/obj/effect/energy_net/E = new /obj/effect/energy_net(C.loc)
H.visible_message("[H] caught [C] with an energy net!","You caught [C] with an energy net!")
diff --git a/code/modules/ninja/suit/n_suit_verbs/ninja_teleporting.dm b/code/modules/ninja/suit/n_suit_verbs/ninja_teleporting.dm
index d8a8b642777..50fdd52b241 100644
--- a/code/modules/ninja/suit/n_suit_verbs/ninja_teleporting.dm
+++ b/code/modules/ninja/suit/n_suit_verbs/ninja_teleporting.dm
@@ -31,22 +31,19 @@ Contents:
var/turf/destination = get_teleport_loc(H.loc,H,9,1,3,1,0,1)
var/turf/mobloc = get_turf(H.loc)//Safety
- if(destination&&istype(mobloc, /turf))//So we don't teleport out of containers
- spawn(0)
- playsound(H.loc, "sparks", 50, 1)
- anim(mobloc,src,'icons/mob/mob.dmi',,"phaseout",,H.dir)
+ if(destination && isturf(mobloc))//So we don't teleport out of containers
+ playsound(H.loc, "sparks", 50, 1)
+ PoolOrNew(/obj/effect/overlay/temp/dir_setting/ninja/phase/out, list(get_turf(H), H.dir))
handle_teleport_grab(destination, H)
H.loc = destination
- spawn(0)
- spark_system.start()
- playsound(H.loc, 'sound/effects/phasein.ogg', 25, 1)
- playsound(H.loc, "sparks", 50, 1)
- anim(H.loc,H,'icons/mob/mob.dmi',,"phasein",,H.dir)
+ spark_system.start()
+ playsound(H.loc, 'sound/effects/phasein.ogg', 25, 1)
+ playsound(H.loc, "sparks", 50, 1)
+ PoolOrNew(/obj/effect/overlay/temp/dir_setting/ninja/phase, list(get_turf(H), H.dir))
- spawn(0)
- destination.phase_damage_creatures(20,H)//Paralyse and damage mobs and mechas on the turf
+ destination.phase_damage_creatures(20,H)//Paralyse and damage mobs and mechas on the turf
s_coold = 1
else
H << "The VOID-shift device is malfunctioning, teleportation failed."
@@ -63,22 +60,19 @@ Contents:
if(!ninjacost(200,N_STEALTH_CANCEL))
var/mob/living/carbon/human/H = affecting
var/turf/mobloc = get_turf(H.loc)//To make sure that certain things work properly below.
- if((!T.density)&&istype(mobloc, /turf))
- spawn(0)
- playsound(H.loc, 'sound/effects/sparks4.ogg', 50, 1)
- anim(mobloc,src,'icons/mob/mob.dmi',,"phaseout",,H.dir)
+ if(T.density && isturf(mobloc))
+ playsound(H.loc, "sparks", 50, 1)
+ PoolOrNew(/obj/effect/overlay/temp/dir_setting/ninja/phase/out, list(get_turf(H), H.dir))
handle_teleport_grab(T, H)
H.loc = T
- spawn(0)
- spark_system.start()
- playsound(H.loc, 'sound/effects/phasein.ogg', 25, 1)
- playsound(H.loc, 'sound/effects/sparks2.ogg', 50, 1)
- anim(H.loc,H,'icons/mob/mob.dmi',,"phasein",,H.dir)
+ spark_system.start()
+ playsound(H.loc, 'sound/effects/phasein.ogg', 25, 1)
+ playsound(H.loc, "sparks", 50, 1)
+ PoolOrNew(/obj/effect/overlay/temp/dir_setting/ninja/phase, list(get_turf(H), H.dir))
- spawn(0)//Any living mobs in teleport area are gibbed.
- T.phase_damage_creatures(20,H)//Paralyse and damage mobs and mechas on the turf
+ T.phase_damage_creatures(20,H)//Paralyse and damage mobs and mechas on the turf
s_coold = 1
else
H << "You cannot teleport into solid walls or from solid matter"
diff --git a/code/modules/paperwork/paperplane.dm b/code/modules/paperwork/paperplane.dm
index 78c045f555c..dab3ef6cdb1 100644
--- a/code/modules/paperwork/paperplane.dm
+++ b/code/modules/paperwork/paperplane.dm
@@ -87,7 +87,7 @@
add_fingerprint(user)
-/obj/item/weapon/paperplane/throw_at(atom/target, range, speed, mob/thrower, spin=0) //prevent the paper plane from spinning
+/obj/item/weapon/paperplane/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0) //prevent the paper plane from spinning
if(!..())
return
diff --git a/code/modules/power/gravitygenerator.dm b/code/modules/power/gravitygenerator.dm
index 5ec232ea1ed..80b96c18152 100644
--- a/code/modules/power/gravitygenerator.dm
+++ b/code/modules/power/gravitygenerator.dm
@@ -372,7 +372,7 @@ var/const/GRAV_NEEDS_WRENCH = 3
for(var/mob/M in mob_list)
if(M.z != z)
continue
- M.update_gravity(M.has_gravity())
+ M.update_gravity(M.mob_has_gravity())
if(M.client)
shake_camera(M, 15, 1)
M.playsound_local(T, 'sound/effects/alert.ogg', 100, 1, 0.5)
diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm
index 41e77f5f886..6dd8f092ea1 100644
--- a/code/modules/power/lighting.dm
+++ b/code/modules/power/lighting.dm
@@ -534,8 +534,9 @@
else
flicker()
-/obj/machinery/light/tesla_act(var/power)
- explosion(src.loc,0,0,0,flame_range = 5, adminlog = 0)
+/obj/machinery/light/tesla_act(power, explosive = FALSE)
+ if(explosive)
+ explosion(src.loc,0,0,0,flame_range = 5, adminlog = 0)
qdel(src)
// called when area power state changes
diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm
index c0c108ffe41..a6f99c390a8 100644
--- a/code/modules/power/supermatter/supermatter.dm
+++ b/code/modules/power/supermatter/supermatter.dm
@@ -236,8 +236,9 @@
message_admins("Singularity has consumed a supermatter shard and can now become stage six.")
visible_message("[src] is consumed by the singularity!")
for(var/mob/M in mob_list)
- M << 'sound/effects/supermatter.ogg' //everyone goan know bout this
- M << "A horrible screeching fills your ears, and a wave of dread washes over you..."
+ if(M.z == z)
+ M << 'sound/effects/supermatter.ogg' //everyone goan know bout this
+ M << "A horrible screeching fills your ears, and a wave of dread washes over you..."
qdel(src)
return(gain)
diff --git a/code/modules/power/tesla/coil.dm b/code/modules/power/tesla/coil.dm
index 3ee76344e49..dc7717c3701 100644
--- a/code/modules/power/tesla/coil.dm
+++ b/code/modules/power/tesla/coil.dm
@@ -49,7 +49,9 @@
/obj/machinery/power/tesla_coil/tesla_act(var/power)
being_shocked = 1
- var/power_produced = power / power_loss
+ //don't lose arc power when it's not connected to anything
+ //please place tesla coils all around the station to maximize effectiveness
+ var/power_produced = powernet ? power / power_loss : power
add_avail(power_produced*input_power_multiplier)
flick("coilhit", src)
playsound(src.loc, 'sound/magic/LightningShock.ogg', 100, 1, extrarange = 5)
diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm
index 6af4d863856..4b7399cad3e 100644
--- a/code/modules/power/tesla/energy_ball.dm
+++ b/code/modules/power/tesla/energy_ball.dm
@@ -65,13 +65,13 @@ var/list/blacklisted_tesla_types = typecacheof(list(/obj/machinery/atmospherics,
pixel_x = 0
pixel_y = 0
- setDir(tesla_zap(src, 7, TESLA_DEFAULT_POWER))
+ setDir(tesla_zap(src, 7, TESLA_DEFAULT_POWER, TRUE))
pixel_x = -32
pixel_y = -32
for (var/ball in orbiting_balls)
var/range = rand(1, Clamp(orbiting_balls.len, 3, 7))
- tesla_zap(ball, range, TESLA_MINI_POWER/7*range)
+ tesla_zap(ball, range, TESLA_MINI_POWER/7*range, TRUE)
else
energy = 0 // ensure we dont have miniballs of miniballs
@@ -152,7 +152,7 @@ var/list/blacklisted_tesla_types = typecacheof(list(/obj/machinery/atmospherics,
var/mob/living/carbon/C = A
C.dust()
-/proc/tesla_zap(var/atom/source, zap_range = 3, power)
+/proc/tesla_zap(atom/source, zap_range = 3, power, explosive = FALSE)
. = source.dir
if(power < 1000)
return
@@ -236,17 +236,17 @@ var/list/blacklisted_tesla_types = typecacheof(list(/obj/machinery/atmospherics,
//Alright, we've done our loop, now lets see if was anything interesting in range
if(closest_atom)
//common stuff
- source.Beam(closest_atom, icon_state="lightning[rand(1,12)]", icon='icons/effects/effects.dmi', time=5)
+ source.Beam(closest_atom, icon_state="lightning[rand(1,12)]", time=5)
var/zapdir = get_dir(source, closest_atom)
if(zapdir)
. = zapdir
//per type stuff:
if(closest_tesla_coil)
- closest_tesla_coil.tesla_act(power)
+ closest_tesla_coil.tesla_act(power, explosive)
else if(closest_grounding_rod)
- closest_grounding_rod.tesla_act(power)
+ closest_grounding_rod.tesla_act(power, explosive)
else if(closest_mob)
var/shock_damage = Clamp(round(power/400), 10, 90) + rand(-5, 5)
@@ -259,10 +259,10 @@ var/list/blacklisted_tesla_types = typecacheof(list(/obj/machinery/atmospherics,
tesla_zap(closest_mob, 5, power / 1.5)
else if(closest_machine)
- closest_machine.tesla_act(power)
+ closest_machine.tesla_act(power, explosive)
else if(closest_blob)
- closest_blob.tesla_act(power)
+ closest_blob.tesla_act(power, explosive)
else if(closest_structure)
- closest_structure.tesla_act(power)
+ closest_structure.tesla_act(power, explosive)
diff --git a/code/modules/projectiles/ammunition.dm b/code/modules/projectiles/ammunition.dm
index 40fe0f36a46..e401a5dae8b 100644
--- a/code/modules/projectiles/ammunition.dm
+++ b/code/modules/projectiles/ammunition.dm
@@ -16,6 +16,8 @@
var/randomspread = 0 //Randomspread for automatics
var/delay = 0 //Delay for energy weapons
var/click_cooldown_override = 0 //Override this to make your gun have a faster fire rate, in tenths of a second. 4 is the default gun cooldown.
+ var/firing_effect_type = /obj/effect/overlay/temp/dir_setting/firing_effect //the visual effect appearing when the ammo is fired.
+
/obj/item/ammo_casing/New()
..()
diff --git a/code/modules/projectiles/ammunition/ammo_casings.dm b/code/modules/projectiles/ammunition/ammo_casings.dm
index 20f59b6404f..a3653f0717c 100644
--- a/code/modules/projectiles/ammunition/ammo_casings.dm
+++ b/code/modules/projectiles/ammunition/ammo_casings.dm
@@ -309,6 +309,7 @@
/obj/item/ammo_casing/caseless
desc = "A caseless bullet casing."
+ firing_effect_type = null
/obj/item/ammo_casing/caseless/fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, params, distro, quiet)
@@ -345,6 +346,7 @@
icon_state = "s-casing-live"
projectile_type = /obj/item/projectile/beam
fire_sound = 'sound/weapons/Laser.ogg'
+ firing_effect_type = /obj/effect/overlay/temp/dir_setting/firing_effect/energy
/obj/item/ammo_casing/caseless/laser/gatling
projectile_type = /obj/item/projectile/beam/weak
diff --git a/code/modules/projectiles/ammunition/energy.dm b/code/modules/projectiles/ammunition/energy.dm
index abe46e6732d..d2c414b131c 100644
--- a/code/modules/projectiles/ammunition/energy.dm
+++ b/code/modules/projectiles/ammunition/energy.dm
@@ -6,6 +6,7 @@
var/e_cost = 100 //The amount of energy a cell needs to expend to create this shot.
var/select_name = "energy"
fire_sound = 'sound/weapons/Laser.ogg'
+ firing_effect_type = /obj/effect/overlay/temp/dir_setting/firing_effect/energy
/obj/item/ammo_casing/energy/laser
projectile_type = /obj/item/projectile/beam/laser
@@ -209,4 +210,12 @@ obj/item/ammo_casing/energy/net
var/obj/item/weapon/gun/energy/gravity_gun/gun = null
/obj/item/ammo_casing/energy/gravitychaos/New(var/obj/item/weapon/gun/energy/gravity_gun/G)
- gun = G
\ No newline at end of file
+ gun = G
+
+/obj/item/ammo_casing/energy/plasma
+ projectile_type = /obj/item/projectile/plasma
+ select_name = "plasma burst"
+ fire_sound = 'sound/weapons/pulse.ogg'
+
+/obj/item/ammo_casing/energy/plasma/adv
+ projectile_type = /obj/item/projectile/plasma/adv
diff --git a/code/modules/projectiles/ammunition/special.dm b/code/modules/projectiles/ammunition/special.dm
index 9a720b84138..181333af1a1 100644
--- a/code/modules/projectiles/ammunition/special.dm
+++ b/code/modules/projectiles/ammunition/special.dm
@@ -2,6 +2,7 @@
name = "magic casing"
desc = "I didn't even know magic needed ammo..."
projectile_type = /obj/item/projectile/magic
+ firing_effect_type = /obj/effect/overlay/temp/dir_setting/firing_effect/magic
/obj/item/ammo_casing/magic/change
projectile_type = /obj/item/projectile/magic/change
@@ -41,9 +42,11 @@
name = "syringe gun spring"
desc = "A high-power spring that throws syringes."
projectile_type = null
+ firing_effect_type = null
/obj/item/ammo_casing/energy/c3dbullet
projectile_type = /obj/item/projectile/bullet/midbullet3
select_name = "spraydown"
fire_sound = 'sound/weapons/gunshot_smg.ogg'
e_cost = 20
+ firing_effect_type = /obj/effect/overlay/temp/dir_setting/firing_effect
diff --git a/code/modules/projectiles/firing.dm b/code/modules/projectiles/firing.dm
index d25e65891cf..d293520cb89 100644
--- a/code/modules/projectiles/firing.dm
+++ b/code/modules/projectiles/firing.dm
@@ -40,6 +40,13 @@
if (!istype(targloc) || !istype(curloc) || !BB)
return 0
BB.ammo_casing = src
+
+ var/firing_dir
+ if(BB.firer)
+ firing_dir = BB.firer.dir
+ if(!BB.suppressed && firing_effect_type)
+ PoolOrNew(firing_effect_type, list(get_turf(src), firing_dir))
+
if(targloc == curloc)
if(target) //if the target is right on our location we go straight to bullet_act()
target.bullet_act(BB, BB.def_zone)
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 9311a0e0e42..b1ec4893a43 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -14,6 +14,7 @@
force = 5
origin_tech = "combat=1"
needs_permit = 1
+ unique_rename = 0
attack_verb = list("struck", "hit", "bashed")
var/fire_sound = "gunshot"
@@ -31,11 +32,8 @@
var/firing_burst = 0 //Prevent the weapon from firing again while already firing
var/semicd = 0 //cooldown handler
var/weapon_weight = WEAPON_LIGHT
-
var/spread = 0 //Spread induced by the gun itself.
var/randomspread = 1 //Set to 0 for shotguns. This is used for weapons that don't fire all their bullets at once.
-
- var/unique_rename = 0 //allows renaming with a pen
var/unique_reskin = 0 //allows one-time reskinning
var/current_skin = null //the skin choice if we had a reskin
var/list/options = list()
@@ -90,8 +88,6 @@
user << "It doesn't have a firing pin installed, and won't fire."
if(unique_reskin && !current_skin)
user << "Alt-click it to reskin it."
- if(unique_rename)
- user << "Use a pen on it to rename it."
/obj/item/weapon/gun/proc/process_chamber()
@@ -302,10 +298,7 @@ obj/item/weapon/gun/proc/newshot()
for(var/datum/action/item_action/toggle_gunlight/TGL in actions)
qdel(TGL)
- if(unique_rename)
- if(istype(I, /obj/item/weapon/pen))
- rename_gun(user)
- ..()
+
/obj/item/weapon/gun/proc/toggle_gunlight()
set name = "Toggle Gunlight"
@@ -386,13 +379,6 @@ obj/item/weapon/gun/proc/newshot()
update_icon()
-/obj/item/weapon/gun/proc/rename_gun(mob/M)
- var/input = stripped_input(M,"What do you want to name the gun?", ,"", MAX_NAME_LEN)
-
- if(src && input && !M.stat && in_range(M,src) && !M.restrained() && M.canmove)
- name = input
- M << "You name the gun [input]. Say hello to your new friend."
- return
/obj/item/weapon/gun/proc/handle_suicide(mob/living/carbon/human/user, mob/living/carbon/human/target, params)
diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
index 34ac3eb6407..bb586419f9b 100644
--- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
+++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
@@ -243,18 +243,19 @@
if(number_of_denied >= maximum_of_type)
. = FALSE
break
- if(.)
- if(KA.get_remaining_mod_capacity() >= cost)
+ if(KA.get_remaining_mod_capacity() >= cost)
+ if(.)
user << "You install the modkit."
playsound(loc, 'sound/items/Screwdriver.ogg', 100, 1)
user.unEquip(src)
forceMove(KA)
KA.modkits += src
else
- user << "You don't have room([KA.get_remaining_mod_capacity()]% remaining, [cost]% needed) to install this modkit. Use a crowbar to remove existing modkits."
- . = FALSE
+ user << "The modkit you're trying to install would conflict with an already installed modkit. Use a crowbar to remove existing modkits."
else
- user << "The modkit you're trying to install would conflict with an already installed modkit. Use a crowbar to remove existing modkits."
+ user << "You don't have room([KA.get_remaining_mod_capacity()]% remaining, [cost]% needed) to install this modkit. Use a crowbar to remove existing modkits."
+ . = FALSE
+
/obj/item/borg/upgrade/modkit/proc/uninstall(obj/item/weapon/gun/energy/kinetic_accelerator/KA)
@@ -301,27 +302,34 @@
//AoE blasts
+/obj/item/borg/upgrade/modkit/aoe
+ modifier = 0
+
/obj/item/borg/upgrade/modkit/aoe/modify_projectile(obj/item/projectile/kinetic/K)
K.name = "kinetic explosion"
if(!K.turf_aoe && !K.mob_aoe)
K.hit_overlays += /obj/effect/overlay/temp/explosion/fast
+ K.mob_aoe += modifier
/obj/item/borg/upgrade/modkit/aoe/turfs
name = "mining explosion"
desc = "Causes the kinetic accelerator to destroy rock in an AoE."
+ denied_type = /obj/item/borg/upgrade/modkit/aoe/turfs
/obj/item/borg/upgrade/modkit/aoe/turfs/modify_projectile(obj/item/projectile/kinetic/K)
..()
K.turf_aoe = TRUE
+/obj/item/borg/upgrade/modkit/aoe/turfs/andmobs
+ name = "offensive mining explosion"
+ desc = "Causes the kinetic accelerator to destroy rock and damage mobs in an AoE."
+ maximum_of_type = 3
+ modifier = 0.25
+
/obj/item/borg/upgrade/modkit/aoe/mobs
name = "offensive explosion"
desc = "Causes the kinetic accelerator to damage mobs in an AoE."
- modifier = 0.25
-
-/obj/item/borg/upgrade/modkit/aoe/mobs/modify_projectile(obj/item/projectile/kinetic/K)
- ..()
- K.mob_aoe += modifier
+ modifier = 0.2
//Indoors
diff --git a/code/modules/projectiles/guns/projectile/bow.dm b/code/modules/projectiles/guns/projectile/bow.dm
index 4ed0fac5829..ff16125d8a7 100644
--- a/code/modules/projectiles/guns/projectile/bow.dm
+++ b/code/modules/projectiles/guns/projectile/bow.dm
@@ -74,6 +74,7 @@
/obj/item/ammo_casing/caseless/arrow
name = "arrow"
+ desc = "Stab, stab, stab."
icon_state = "arrow"
force = 10
sharpness = IS_SHARP
@@ -94,4 +95,4 @@
/obj/item/weapon/storage/backpack/quiver/full/New()
..()
for(var/i in 1 to storage_slots)
- new /obj/item/ammo_casing/caseless/arrow(src)
\ No newline at end of file
+ new /obj/item/ammo_casing/caseless/arrow(src)
diff --git a/code/modules/projectiles/guns/projectile/revolver.dm b/code/modules/projectiles/guns/projectile/revolver.dm
index d0f8baa82ff..fdd8b765f67 100644
--- a/code/modules/projectiles/guns/projectile/revolver.dm
+++ b/code/modules/projectiles/guns/projectile/revolver.dm
@@ -37,7 +37,7 @@
if(unique_rename)
if(istype(A, /obj/item/weapon/pen))
- rename_gun(user)
+ rename_weapon(user)
/obj/item/weapon/gun/projectile/revolver/attack_self(mob/living/user)
var/num_unloaded = 0
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 910fe2cc89a..74320f6c062 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -50,6 +50,7 @@
var/jitter = 0
var/forcedodge = 0 //to pass through everything
var/dismemberment = 0 //The higher the number, the greater the bonus to dismembering. 0 will not dismember at all.
+ var/impact_effect_type //what type of impact effect to show when hitting something
/obj/item/projectile/New()
permutated = list()
@@ -75,10 +76,23 @@
return "chest"
/obj/item/projectile/proc/on_hit(atom/target, blocked = 0)
+ var/turf/target_loca = get_turf(target)
if(!isliving(target))
+ if(impact_effect_type)
+ PoolOrNew(impact_effect_type, list(target_loca, target, src))
return 0
var/mob/living/L = target
if(blocked != 100) // not completely blocked
+ if(damage && L.blood_volume && damage_type == BRUTE)
+ if(isalien(L))
+ PoolOrNew(/obj/effect/overlay/temp/dir_setting/bloodsplatter/xenosplatter, list(target_loca, dir))
+ else
+ PoolOrNew(/obj/effect/overlay/temp/dir_setting/bloodsplatter, list(target_loca, dir))
+ if(prob(33))
+ L.add_splatter_floor(target_loca)
+ else if(impact_effect_type)
+ PoolOrNew(impact_effect_type, list(target_loca, target, src))
+
var/organ_hit_text = ""
var/limb_hit = L.check_limb_hit(def_zone)//to get the correct message info.
if(limb_hit)
diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm
index 0dc198bc33a..28902c019dc 100644
--- a/code/modules/projectiles/projectile/beams.dm
+++ b/code/modules/projectiles/projectile/beams.dm
@@ -9,6 +9,7 @@
hitsound_wall = 'sound/weapons/effects/searwall.ogg'
flag = "laser"
eyeblur = 2
+ impact_effect_type = /obj/effect/overlay/temp/impact_effect/red_laser
/obj/item/projectile/beam/laser
@@ -44,6 +45,7 @@
irradiate = 30
range = 15
forcedodge = 1
+ impact_effect_type = /obj/effect/overlay/temp/impact_effect/green_laser
/obj/item/projectile/beam/disabler
name = "disabler beam"
@@ -53,12 +55,14 @@
flag = "energy"
hitsound = 'sound/weapons/tap.ogg'
eyeblur = 0
+ impact_effect_type = /obj/effect/overlay/temp/impact_effect/blue_laser
/obj/item/projectile/beam/pulse
name = "pulse"
icon_state = "u_laser"
damage = 50
luminosity = 2
+ impact_effect_type = /obj/effect/overlay/temp/impact_effect/blue_laser
/obj/item/projectile/beam/pulse/on_hit(atom/target, blocked = 0)
. = ..()
@@ -86,6 +90,7 @@
legacy = 1
luminosity = 2
animate_movement = SLIDE_STEPS
+ impact_effect_type = /obj/effect/overlay/temp/impact_effect/green_laser
/obj/item/projectile/beam/emitter/singularity_pull()
return //don't want the emitters to miss
@@ -102,6 +107,7 @@
damage_type = STAMINA
flag = "laser"
var/suit_types = list(/obj/item/clothing/suit/redtag, /obj/item/clothing/suit/bluetag)
+ impact_effect_type = /obj/effect/overlay/temp/impact_effect/blue_laser
/obj/item/projectile/beam/lasertag/on_hit(atom/target, blocked = 0)
. = ..()
@@ -114,6 +120,7 @@
/obj/item/projectile/beam/lasertag/redtag
icon_state = "laser"
suit_types = list(/obj/item/clothing/suit/bluetag)
+ impact_effect_type = /obj/effect/overlay/temp/impact_effect/red_laser
/obj/item/projectile/beam/lasertag/bluetag
icon_state = "bluelaser"
@@ -124,12 +131,15 @@
icon_state = "purple_laser"
damage = 200
damage_type = BURN
+ impact_effect_type = /obj/effect/overlay/temp/impact_effect/purple_laser
/obj/item/projectile/beam/instakill/blue
icon_state = "blue_laser"
+ impact_effect_type = /obj/effect/overlay/temp/impact_effect/blue_laser
/obj/item/projectile/beam/instakill/red
icon_state = "red_laser"
+ impact_effect_type = /obj/effect/overlay/temp/impact_effect/red_laser
/obj/item/projectile/beam/instakill/on_hit(atom/target)
. = ..()
diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm
index 4a3b66ba108..ab287338cc9 100644
--- a/code/modules/projectiles/projectile/bullets.dm
+++ b/code/modules/projectiles/projectile/bullets.dm
@@ -6,6 +6,7 @@
nodamage = 0
flag = "bullet"
hitsound_wall = "ricochet"
+ impact_effect_type = /obj/effect/overlay/temp/impact_effect
/obj/item/projectile/bullet/weakbullet //beanbag, heavy stamina damage
damage = 5
diff --git a/code/modules/projectiles/projectile/energy.dm b/code/modules/projectiles/projectile/energy.dm
index 6c41ca751d7..a4830b7c28d 100644
--- a/code/modules/projectiles/projectile/energy.dm
+++ b/code/modules/projectiles/projectile/energy.dm
@@ -143,6 +143,7 @@
damage = 20
damage_type = CLONE
irradiate = 10
+ impact_effect_type = /obj/effect/overlay/temp/impact_effect/green_laser
/obj/item/projectile/energy/dart //ninja throwing dart
name = "dart"
@@ -164,22 +165,15 @@
/obj/item/projectile/energy/bolt/large
damage = 20
-/obj/item/ammo_casing/energy/plasma
- projectile_type = /obj/item/projectile/plasma
- select_name = "plasma burst"
- fire_sound = 'sound/weapons/pulse.ogg'
-
-/obj/item/ammo_casing/energy/plasma/adv
- projectile_type = /obj/item/projectile/plasma/adv
-
/obj/item/projectile/energy/shock_revolver
name = "shock bolt"
icon_state = "purple_laser"
+ impact_effect_type = /obj/effect/overlay/temp/impact_effect/purple_laser
var/chain
/obj/item/projectile/energy/shock_revolver/fire(setAngle)
if(firer)
- chain = Beam(firer, icon_state = "lightning[rand(1, 12)]", icon = 'icons/effects/effects.dmi', time = INFINITY, maxdistance = INFINITY)
+ chain = firer.Beam(src, icon_state = "lightning[rand(1, 12)]", time = INFINITY, maxdistance = INFINITY)
..()
/obj/item/projectile/energy/shock_revolver/on_hit(atom/target)
@@ -189,3 +183,4 @@
/obj/item/projectile/energy/shock_revolver/Destroy()
qdel(chain)
+ return ..()
diff --git a/code/modules/projectiles/projectile/reusable.dm b/code/modules/projectiles/projectile/reusable.dm
index f253655e3f6..6d6b086f63b 100644
--- a/code/modules/projectiles/projectile/reusable.dm
+++ b/code/modules/projectiles/projectile/reusable.dm
@@ -3,6 +3,7 @@
desc = "How do you even reuse a bullet?"
var/ammo_type = /obj/item/ammo_casing/caseless/
var/dropped = 0
+ impact_effect_type = null
/obj/item/projectile/bullet/reusable/on_hit(atom/target, blocked = 0)
. = ..()
diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm
index d0f9d4bc511..6a991950ff0 100644
--- a/code/modules/projectiles/projectile/special.dm
+++ b/code/modules/projectiles/projectile/special.dm
@@ -5,6 +5,7 @@
damage_type = BURN
nodamage = 1
flag = "energy"
+ impact_effect_type = /obj/effect/overlay/temp/impact_effect/ion
/obj/item/projectile/ion/on_hit(atom/target, blocked = 0)
@@ -166,6 +167,7 @@
damage = 5
range = 3.5 //works as 4, but doubles to 7
dismemberment = 20
+ impact_effect_type = /obj/effect/overlay/temp/impact_effect/purple_laser
/obj/item/projectile/plasma/New()
var/turf/proj_turf = get_turf(src)
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 7c311d980b3..c38d9023457 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -188,11 +188,9 @@
if("emote")
M.visible_message("[M] [pick("whimpers quietly", "shivers as though cold", "glances around in paranoia")].")
if(data >= 75) // 30 units, 135 seconds
- if(iscultist(M) || is_handofgod_cultist(M) || is_handofgod_prophet(M) || is_servant_of_ratvar(M))
+ if(iscultist(M) || is_servant_of_ratvar(M))
if(iscultist(M))
ticker.mode.remove_cultist(M.mind, 1, 1)
- else if(is_handofgod_cultist(M) || is_handofgod_prophet(M))
- ticker.mode.remove_hog_follower(M.mind)
else if(is_servant_of_ratvar(M))
remove_servant_of_ratvar(M)
holder.remove_reagent(id, volume) // maybe this is a little too perfect and a max() cap on the statuses would be better??
diff --git a/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm b/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm
index 22d718e0b76..d2958b475da 100644
--- a/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm
@@ -164,7 +164,7 @@
/datum/reagent/cryostylane
name = "Cryostylane"
id = "cryostylane"
- description = "Comes into existence at 20K. As long as there is sufficient oxygen for it to react with, Cryostylane slowly cools all other reagents in the mob down to 0K."
+ description = "Comes into existence at 20K. As long as there is sufficient oxygen for it to react with, Cryostylane slowly cools all other reagents in the container 0K."
color = "#0000DC"
metabolization_rate = 0.5 * REAGENTS_METABOLISM
@@ -190,7 +190,7 @@
/datum/reagent/pyrosium
name = "Pyrosium"
id = "pyrosium"
- description = "Comes into existence at 20K. As long as there is sufficient oxygen for it to react with, Pyrosium slowly cools all other reagents in the mob down to 0K."
+ description = "Comes into existence at 20K. As long as there is sufficient oxygen for it to react with, Pyrosium slowly heats all other reagents in the container."
color = "#64FAC8"
metabolization_rate = 0.5 * REAGENTS_METABOLISM
@@ -206,3 +206,21 @@
holder.chem_temp += 10
holder.handle_reactions()
..()
+
+/datum/reagent/teslium //Teslium. Causes periodic shocks, and makes shocks against the target much more effective.
+ name = "Teslium"
+ id = "teslium"
+ description = "An unstable, electrically-charged metallic slurry. Periodically electrocutes its victim, and makes electrocutions against them more deadly. Excessively heating teslium results in dangerous destabilization. Do not allow to come into contact with water."
+ reagent_state = LIQUID
+ color = "#20324D" //RGB: 32, 50, 77
+ metabolization_rate = 0.5 * REAGENTS_METABOLISM
+ var/shock_timer = 0
+
+/datum/reagent/teslium/on_mob_life(mob/living/M)
+ shock_timer++
+ if(shock_timer >= rand(5,30)) //Random shocks are wildly unpredictable
+ shock_timer = 0
+ M.electrocute_act(rand(5,20), "Teslium in their body", 1, 1) //Override because it's caused from INSIDE of you
+ playsound(M, "sparks", 50, 1)
+ ..()
+
diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
index 7f6c1c4cbb4..2d344c1276e 100644
--- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
@@ -657,24 +657,6 @@
. = 1
return ..() || .
-/datum/reagent/toxin/teslium //Teslium. Causes periodic shocks, and makes shocks against the target much more effective.
- name = "Teslium"
- id = "teslium"
- description = "An unstable, electrically-charged metallic slurry. Periodically electrocutes its victim, and makes electrocutions against them more deadly."
- reagent_state = LIQUID
- color = "#20324D" //RGB: 32, 50, 77
- metabolization_rate = 0.5 * REAGENTS_METABOLISM
- toxpwr = 0
- var/shock_timer = 0
-
-/datum/reagent/toxin/teslium/on_mob_life(mob/living/M)
- shock_timer++
- if(shock_timer >= rand(5,30)) //Random shocks are wildly unpredictable
- shock_timer = 0
- M.electrocute_act(rand(5,20), "Teslium in their body", 1, 1) //Override because it's caused from INSIDE of you
- playsound(M, "sparks", 50, 1)
- ..()
-
//ACID
diff --git a/code/modules/reagents/chemistry/recipes.dm b/code/modules/reagents/chemistry/recipes.dm
index b475c752c67..a7bfedb2145 100644
--- a/code/modules/reagents/chemistry/recipes.dm
+++ b/code/modules/reagents/chemistry/recipes.dm
@@ -57,9 +57,9 @@ var/list/chemical_mob_spawn_nicecritters = list() // and possible friendly mobs
chosen = pick(chemical_mob_spawn_nicecritters)
else
chosen = pick(chemical_mob_spawn_meancritters)
- var/mob/living/simple_animal/C = new chosen
+ var/spawnloc = get_turf(holder.my_atom)
+ var/mob/living/simple_animal/C = new chosen(spawnloc)
C.faction |= mob_faction
- C.loc = get_turf(holder.my_atom)
if(prob(50))
for(var/j = 1, j <= rand(1, 3), j++)
step(C, pick(NORTH,SOUTH,EAST,WEST))
diff --git a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm
index 6cb48f90552..ec261d12045 100644
--- a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm
+++ b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm
@@ -69,7 +69,7 @@
R.adjustHealth(50)
sleep(20)
for(var/mob/living/carbon/C in get_hearers_in_view(round(created_volume/48,1),get_turf(holder.my_atom)))
- if(iscultist(C) || is_handofgod_cultist(C))
+ if(iscultist(C))
C << "The divine explosion sears you!"
C.Weaken(2)
C.adjust_fire_stacks(5)
@@ -352,3 +352,44 @@
/datum/chemical_reaction/pyrosium/on_reaction(datum/reagents/holder, created_volume)
holder.chem_temp = 20 // also cools the fuck down
return
+
+/datum/chemical_reaction/teslium
+ name = "Teslium"
+ id = "teslium"
+ results = list("teslium" = 3)
+ required_reagents = list("stable_plasma" = 1, "silver" = 1, "blackpowder" = 1)
+ mix_message = "A jet of sparks flies from the mixture as it merges into a flickering slurry."
+ required_temp = 400
+
+/datum/chemical_reaction/reagent_explosion/teslium_lightning
+ name = "Teslium Destabilization"
+ id = "teslium_lightning"
+ required_reagents = list("teslium" = 1, "water" = 1)
+ results = list("destabilized_teslium" = 1)
+ strengthdiv = 100
+ modifier = -100
+ mix_message = "The teslium starts to spark as electricity arcs away from it!"
+ mix_sound = 'sound/machines/defib_zap.ogg'
+
+/datum/chemical_reaction/reagent_explosion/teslium_lightning/on_reaction(datum/reagents/holder, created_volume)
+ var/T1 = created_volume * 20 //100 units : Zap 3 times, with powers 2000/5000/12000. Tesla revolvers have a power of 10000 for comparison.
+ var/T2 = created_volume * 50
+ var/T3 = created_volume * 120
+ sleep(10)
+ if(created_volume >= 75) //10 units minimum for lightning, 40 units for secondary blast, 75 units for tertiary blast.
+ tesla_zap(holder.my_atom, 7, T1)
+ playsound(holder.my_atom, 'sound/machines/defib_zap.ogg', 50, 1)
+ sleep(10)
+ if(created_volume >= 40)
+ tesla_zap(holder.my_atom, 7, T2)
+ playsound(holder.my_atom, 'sound/machines/defib_zap.ogg', 50, 1)
+ sleep(10)
+ if(created_volume >= 10)
+ tesla_zap(holder.my_atom, 7, T3)
+ playsound(holder.my_atom, 'sound/machines/defib_zap.ogg', 50, 1)
+ ..()
+
+/datum/chemical_reaction/reagent_explosion/teslium_lightning/heat
+ id = "teslium_lightning2"
+ required_temp = 474
+ required_reagents = list("teslium" = 1)
diff --git a/code/modules/reagents/chemistry/recipes/toxins.dm b/code/modules/reagents/chemistry/recipes/toxins.dm
index 5d4fd3ba501..53fcb2bc473 100644
--- a/code/modules/reagents/chemistry/recipes/toxins.dm
+++ b/code/modules/reagents/chemistry/recipes/toxins.dm
@@ -81,14 +81,6 @@
results = list("mindbreaker" = 5)
required_reagents = list("silicon" = 1, "hydrogen" = 1, "charcoal" = 1)
-/datum/chemical_reaction/teslium
- name = "Teslium"
- id = "teslium"
- results = list("teslium" = 3)
- required_reagents = list("plasma" = 1, "silver" = 1, "blackpowder" = 1)
- mix_message = "A jet of sparks flies from the mixture as it merges into a flickering slurry."
- required_temp = 400
-
/datum/chemical_reaction/heparin
name = "Heparin"
id = "Heparin"
diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm
index 1676c8339e0..469be2bbbb2 100644
--- a/code/modules/reagents/reagent_containers/glass.dm
+++ b/code/modules/reagents/reagent_containers/glass.dm
@@ -212,6 +212,9 @@
/obj/item/weapon/reagent_containers/glass/beaker/large/epinephrine
name = "epinephrine reserve tank"
list_reagents = list("epinephrine" = 50)
+
+/obj/item/weapon/reagent_containers/glass/beaker/synthflesh
+ list_reagents = list("synthflesh" = 50)
/obj/item/weapon/reagent_containers/glass/bucket
name = "bucket"
diff --git a/code/modules/research/designs/limbgrower_designs.dm b/code/modules/research/designs/limbgrower_designs.dm
new file mode 100644
index 00000000000..591888bfd9d
--- /dev/null
+++ b/code/modules/research/designs/limbgrower_designs.dm
@@ -0,0 +1,43 @@
+/////////////////////////////////////
+//////////Limb Grower Designs ///////
+/////////////////////////////////////
+
+/datum/design/leftarm
+ name = "Left Arm"
+ id = "leftarm"
+ build_type = LIMBGROWER
+ reagents = list("synthflesh" = 25)
+ build_path = /obj/item/bodypart/l_arm
+ category = list("initial","human","lizard","plasmaman")
+
+/datum/design/rightarm
+ name = "Right Arm"
+ id = "rightarm"
+ build_type = LIMBGROWER
+ reagents = list("synthflesh" = 25)
+ build_path = /obj/item/bodypart/r_arm
+ category = list("initial","human","lizard","plasmaman")
+
+/datum/design/leftleg
+ name = "Left Leg"
+ id = "leftleg"
+ build_type = LIMBGROWER
+ reagents = list("synthflesh" = 25)
+ build_path = /obj/item/bodypart/l_leg
+ category = list("initial","human","lizard","plasmaman")
+
+/datum/design/rightleg
+ name = "Right Leg"
+ id = "rightleg"
+ build_type = LIMBGROWER
+ reagents = list("synthflesh" = 25)
+ build_path = /obj/item/bodypart/r_leg
+ category = list("initial","human","lizard","plasmaman")
+
+/datum/design/armblade
+ name = "Arm Blade"
+ id = "armblade"
+ build_type = LIMBGROWER
+ reagents = list("synthflesh" = 75)
+ build_path = /obj/item/weapon/melee/synthetic_arm_blade
+ category = list("special")
\ No newline at end of file
diff --git a/code/modules/research/research.dm b/code/modules/research/research.dm
index 94bc846e530..6d1cabc38b8 100644
--- a/code/modules/research/research.dm
+++ b/code/modules/research/research.dm
@@ -143,6 +143,16 @@ research holder datum.
if((D.build_type & AUTOLATHE) && ("initial" in D.category)) //autolathe starts without hacked designs
AddDesign2Known(D)
+//Limb Grower files
+/datum/research/limbgrower/New()
+ for(var/T in (subtypesof(/datum/tech)))
+ possible_tech += new T(src)
+ for(var/path in subtypesof(/datum/design))
+ var/datum/design/D = new path(src)
+ possible_designs += D
+ if((D.build_type & LIMBGROWER) && ("initial" in D.category))
+ AddDesign2Known(D)
+
/datum/research/autolathe/AddDesign2Known(datum/design/D)
if(!(D.build_type & AUTOLATHE))
return
diff --git a/code/modules/research/stock_parts.dm b/code/modules/research/stock_parts.dm
index d21722150e1..d010bfbbc57 100644
--- a/code/modules/research/stock_parts.dm
+++ b/code/modules/research/stock_parts.dm
@@ -25,7 +25,7 @@
if(istype(T))
if(T.component_parts)
T.exchange_parts(user, src)
- user.Beam(T,icon_state="rped_upgrade",icon='icons/effects/effects.dmi',time=5)
+ user.Beam(T,icon_state="rped_upgrade",time=5)
return
/obj/item/weapon/storage/part_replacer/bluespace
@@ -45,7 +45,7 @@
if(get_dist(user, dest_object) < 8)
if(dest_object.storage_contents_dump_act(src, user))
play_rped_sound()
- user.Beam(dest_object,icon_state="rped_upgrade",icon='icons/effects/effects.dmi',time=5)
+ user.Beam(dest_object,icon_state="rped_upgrade",time=5)
return 1
user << "The [src.name] buzzes."
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
diff --git a/code/modules/spells/spell_types/construct_spells.dm b/code/modules/spells/spell_types/construct_spells.dm
index 0142489bc88..47aaa643c88 100644
--- a/code/modules/spells/spell_types/construct_spells.dm
+++ b/code/modules/spells/spell_types/construct_spells.dm
@@ -108,16 +108,9 @@
centcom_cancast = 0 //Stop people from getting to centcom
action_icon_state = "phaseshift"
action_background_icon_state = "bg_demon"
-
-/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/jaunt_disappear(atom/movable/overlay/animation, mob/living/target)
- animation.icon_state = "phase_shift"
- animation.setDir(target.dir)
- flick("phase_shift",animation)
-
-/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/jaunt_reappear(atom/movable/overlay/animation, mob/living/target)
- animation.icon_state = "phase_shift2"
- animation.setDir(target.dir)
- flick("phase_shift2",animation)
+ jaunt_in_time = 12
+ jaunt_in_type = /obj/effect/overlay/temp/dir_setting/wraith
+ jaunt_out_type = /obj/effect/overlay/temp/dir_setting/wraith/out
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/jaunt_steam(mobloc)
return
diff --git a/code/modules/spells/spell_types/ethereal_jaunt.dm b/code/modules/spells/spell_types/ethereal_jaunt.dm
index 71b58883ddb..84cfcc108aa 100644
--- a/code/modules/spells/spell_types/ethereal_jaunt.dm
+++ b/code/modules/spells/spell_types/ethereal_jaunt.dm
@@ -13,70 +13,56 @@
centcom_cancast = 0 //Prevent people from getting to centcom
nonabstract_req = 1
var/jaunt_duration = 50 //in deciseconds
+ var/jaunt_in_time = 5
+ var/jaunt_in_type = /obj/effect/overlay/temp/wizard
+ var/jaunt_out_type = /obj/effect/overlay/temp/wizard/out
action_icon_state = "jaunt"
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/cast(list/targets,mob/user = usr) //magnets, so mostly hardcoded
playsound(get_turf(user), 'sound/magic/Ethereal_Enter.ogg', 50, 1, -1)
for(var/mob/living/target in targets)
- target.notransform = 1 //protects the mob from being transformed (replaced) midjaunt and getting stuck in bluespace
- spawn(0)
- var/turf/mobloc = get_turf(target.loc)
- var/obj/effect/dummy/spell_jaunt/holder = new /obj/effect/dummy/spell_jaunt( mobloc )
- var/atom/movable/overlay/animation = new /atom/movable/overlay( mobloc )
- animation.name = "water"
- animation.density = 0
- animation.anchored = 1
- animation.icon = 'icons/mob/mob.dmi'
- animation.layer = FLY_LAYER
- animation.master = holder
- target.ExtinguishMob()
- if(target.buckled)
- target.buckled.unbuckle_mob(target,force=1)
- if(target.pulledby)
- target.pulledby.stop_pulling()
- target.stop_pulling()
- if(target.has_buckled_mobs())
- target.unbuckle_all_mobs(force=1)
- jaunt_disappear(animation, target)
- target.loc = holder
- target.reset_perspective(holder)
- target.notransform=0 //mob is safely inside holder now, no need for protection.
- jaunt_steam(mobloc)
+ addtimer(src, "do_jaunt", 0, FALSE, target)
- sleep(jaunt_duration)
+/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/proc/do_jaunt(mob/living/target)
+ target.notransform = 1
+ var/turf/mobloc = get_turf(target)
+ var/obj/effect/dummy/spell_jaunt/holder = new /obj/effect/dummy/spell_jaunt(mobloc)
+ PoolOrNew(jaunt_out_type, list(mobloc, holder.dir))
+ target.ExtinguishMob()
+ if(target.buckled)
+ target.buckled.unbuckle_mob(target,force=1)
+ if(target.pulledby)
+ target.pulledby.stop_pulling()
+ target.stop_pulling()
+ if(target.has_buckled_mobs())
+ target.unbuckle_all_mobs(force=1)
+ target.loc = holder
+ target.reset_perspective(holder)
+ target.notransform=0 //mob is safely inside holder now, no need for protection.
+ jaunt_steam(mobloc)
- if(target.loc != holder) //mob warped out of the warp
- qdel(holder)
- return
- mobloc = get_turf(target.loc)
- animation.loc = mobloc
- jaunt_steam(mobloc)
- target.canmove = 0
- holder.reappearing = 1
- playsound(get_turf(user), 'sound/magic/Ethereal_Exit.ogg', 50, 1, -1)
- sleep(20)
- if(!qdeleted(target))
- jaunt_reappear(animation, target)
- sleep(5)
- qdel(animation)
- qdel(holder)
- if(!qdeleted(target))
- if(mobloc.density)
- for(var/direction in list(1,2,4,8,5,6,9,10))
- var/turf/T = get_step(mobloc, direction)
- if(T)
- if(target.Move(T))
- break
- target.canmove = 1
-
-/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/proc/jaunt_disappear(atom/movable/overlay/animation, mob/living/target)
- animation.icon_state = "liquify"
- flick("liquify",animation)
-
-
-/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/proc/jaunt_reappear(atom/movable/overlay/animation, mob/living/target)
- flick("reappear",animation)
+ sleep(jaunt_duration)
+ if(target.loc != holder) //mob warped out of the warp
+ qdel(holder)
+ return
+ mobloc = get_turf(target.loc)
+ jaunt_steam(mobloc)
+ target.canmove = 0
+ holder.reappearing = 1
+ playsound(get_turf(target), 'sound/magic/Ethereal_Exit.ogg', 50, 1, -1)
+ sleep(25 - jaunt_in_time)
+ PoolOrNew(jaunt_in_type, list(mobloc, holder.dir))
+ sleep(jaunt_in_time)
+ qdel(holder)
+ if(!qdeleted(target))
+ if(mobloc.density)
+ for(var/direction in alldirs)
+ var/turf/T = get_step(mobloc, direction)
+ if(T)
+ if(target.Move(T))
+ break
+ target.canmove = 1
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/proc/jaunt_steam(mobloc)
var/datum/effect_system/steam_spread/steam = new /datum/effect_system/steam_spread()
@@ -103,6 +89,7 @@
/obj/effect/dummy/spell_jaunt/relaymove(var/mob/user, direction)
if (!src.canmove || reappearing || !direction) return
var/turf/newLoc = get_step(src,direction)
+ setDir(direction)
if(!(newLoc.flags & NOJAUNT))
loc = newLoc
else
diff --git a/code/modules/spells/spell_types/lichdom.dm b/code/modules/spells/spell_types/lichdom.dm
index 728555db52e..1cf58b7fd9b 100644
--- a/code/modules/spells/spell_types/lichdom.dm
+++ b/code/modules/spells/spell_types/lichdom.dm
@@ -99,7 +99,7 @@
var/wheres_wizdo = dir2text(get_dir(body_turf, item_turf))
if(wheres_wizdo)
old_body.visible_message("Suddenly [old_body.name]'s corpse falls to pieces! You see a strange energy rise from the remains, and speed off towards the [wheres_wizdo]!")
- body_turf.Beam(item_turf,icon_state="lichbeam",icon='icons/effects/effects.dmi',time=10+10*resurrections,maxdistance=INFINITY)
+ body_turf.Beam(item_turf,icon_state="lichbeam",time=10+10*resurrections,maxdistance=INFINITY)
old_body.dust()
if(!marked_item) //linking item to the spell
diff --git a/code/modules/spells/spell_types/lightning.dm b/code/modules/spells/spell_types/lightning.dm
index 4fac684f72c..73e958926ca 100644
--- a/code/modules/spells/spell_types/lightning.dm
+++ b/code/modules/spells/spell_types/lightning.dm
@@ -58,13 +58,13 @@
return
playsound(get_turf(user), 'sound/magic/lightningbolt.ogg', 50, 1)
- user.Beam(target,icon_state="lightning[rand(1,12)]",icon='icons/effects/effects.dmi',time=5)
+ user.Beam(target,icon_state="lightning[rand(1,12)]",time=5)
Bolt(user,target,30,5,user)
Reset(user)
/obj/effect/proc_holder/spell/targeted/lightning/proc/Bolt(mob/origin,mob/target,bolt_energy,bounces,mob/user = usr)
- origin.Beam(target,icon_state="lightning[rand(1,12)]",icon='icons/effects/effects.dmi',time=5)
+ origin.Beam(target,icon_state="lightning[rand(1,12)]",time=5)
var/mob/living/carbon/current = target
if(bounces < 1)
current.electrocute_act(bolt_energy,"Lightning Bolt",safety=1)
diff --git a/code/modules/station_goals/bsa.dm b/code/modules/station_goals/bsa.dm
index 77e69582ef0..fdc5247f4aa 100644
--- a/code/modules/station_goals/bsa.dm
+++ b/code/modules/station_goals/bsa.dm
@@ -7,7 +7,7 @@
/datum/station_goal/bluespace_cannon/get_report()
return {"Our military presence is inadequate in your sector.
- We need you to construct BSA-[rand(0-99)] Artillery position aboard your station.
+ We need you to construct BSA-[rand(1,99)] Artillery position aboard your station.
Base parts should be availible for shipping by your cargo shuttle.
-Nanotrasen Naval Command"}
@@ -60,7 +60,7 @@
name = "Bluespace Artillery Fusor"
desc = "Contents classifed by Nanotrasen Naval Command. Needs to be linked with the other BSA parts using multitool."
icon_state = "fuel_chamber"
- var/obj/machinery/bsa/back/back
+ var/obj/machinery/bsa/back/back
var/obj/machinery/bsa/front/front
/obj/machinery/bsa/middle/attackby(obj/item/weapon/W, mob/user, params)
@@ -169,7 +169,7 @@
var/turf/point = get_front_turf()
for(var/turf/T in getline(get_step(point,dir),get_target_turf()))
T.ex_act(1)
- point.Beam(get_target_turf(),icon_state="bsa_beam",icon='icons/effects/beam.dmi',time=50,maxdistance = world.maxx) //ZZZAP
+ point.Beam(get_target_turf(),icon_state="bsa_beam",time=50,maxdistance = world.maxx) //ZZZAP
/obj/structure/filler
@@ -218,7 +218,7 @@
var/notice
var/target
use_power = 0
- circuit = /obj/machinery/computer/bsa_control
+ circuit = /obj/item/weapon/circuitboard/machine/computer/bsa_control
icon = 'icons/obj/machines/particle_accelerator.dmi'
icon_state = "control_boxp"
var/area_aim = FALSE //should also show areas for targeting
diff --git a/code/modules/station_goals/dna_vault.dm b/code/modules/station_goals/dna_vault.dm
index 6de3312238f..7f831986f2a 100644
--- a/code/modules/station_goals/dna_vault.dm
+++ b/code/modules/station_goals/dna_vault.dm
@@ -7,7 +7,7 @@
#define VAULT_NOBREATH "Lung Enhancement"
#define VAULT_FIREPROOF "Thermal Regulation"
#define VAULT_STUNTIME "Neural Repathing"
-#define VAULT_ARMOUR "Bone Reinforcment"
+#define VAULT_ARMOUR "Bone Reinforcement"
/datum/station_goal/dna_vault
name = "DNA Vault"
@@ -20,7 +20,7 @@
animal_count = rand(15,20) //might be too few given ~15 roundstart stationside ones
human_count = rand(round(0.75 * ticker.totalPlayersReady) , ticker.totalPlayersReady) // 75%+ roundstart population.
var/non_standard_plants = non_standard_plants_count()
- plant_count = rand(round(0.7 * non_standard_plants),round(0.9 * non_standard_plants))
+ plant_count = rand(round(0.5 * non_standard_plants),round(0.7 * non_standard_plants))
/datum/station_goal/dna_vault/proc/non_standard_plants_count()
. = 0
@@ -52,7 +52,7 @@
if(..())
return TRUE
for(var/obj/machinery/dna_vault/V in machines)
- if(V.animals.len >= animal_count && V.plants.len >= plant_count && V.dna >= human_count)
+ if(V.animals.len >= animal_count && V.plants.len >= plant_count && V.dna.len >= human_count)
return TRUE
return FALSE
diff --git a/code/modules/station_goals/shield.dm b/code/modules/station_goals/shield.dm
index 357cc426e15..20f5a76f6d4 100644
--- a/code/modules/station_goals/shield.dm
+++ b/code/modules/station_goals/shield.dm
@@ -14,7 +14,7 @@
/datum/station_goal/station_shield/on_report()
- //Unlock
+ //Unlock
var/datum/supply_pack/P = SSshuttle.supply_packs[/datum/supply_pack/misc/shield_sat]
P.special_enabled = TRUE
@@ -69,7 +69,7 @@
/obj/machinery/computer/sat_control/ui_data()
var/list/data = list()
-
+
data["satellites"] = list()
for(var/obj/machinery/satellite/S in machines)
data["satellites"] += list(list(
@@ -78,8 +78,8 @@
"mode" = S.mode
))
data["notice"] = notice
-
-
+
+
var/datum/station_goal/station_shield/G = locate() in ticker.mode.station_goals
if(G)
data["meteor_shield"] = 1
@@ -116,7 +116,7 @@
active = !active
if(active)
animate(src, pixel_y = 2, time = 10, loop = -1)
- anchored = 1
+ anchored = 1
else
animate(src, pixel_y = 0, time = 10)
anchored = 0
@@ -136,7 +136,7 @@
desc = "Meteor Point Defense Satellite"
mode = "M-SHIELD"
var/kill_range = 10
-
+
/obj/machinery/satellite/meteor_shield/proc/space_los(meteor)
for(var/turf/T in getline(src,meteor))
if(!istype(T, /turf/open/space))
@@ -152,7 +152,7 @@
if(get_dist(M,src) > kill_range)
continue
if(!emagged && space_los(M))
- Beam(get_turf(M),time=5,maxdistance=kill_range)
+ Beam(get_turf(M),icon_state="sat_beam",time=5,maxdistance=kill_range)
qdel(M)
/obj/machinery/satellite/meteor_shield/toggle(user)
diff --git a/code/modules/stock_market/computer.dm b/code/modules/stock_market/computer.dm
index ced8a43f179..97a2bc983b1 100644
--- a/code/modules/stock_market/computer.dm
+++ b/code/modules/stock_market/computer.dm
@@ -83,25 +83,6 @@ a.updated {
dat += "Prominent products:
"
for (var/prod in S.products)
dat += "[prod]
"
- dat += "
Borrow options:
"
- if (S.borrow_brokers.len)
- for (var/datum/borrow/B in S.borrow_brokers)
- dat += "[B.broker] offers [B.share_amount] shares for borrowing, for a deposit of [B.deposit * 100]% of the shares' value.
"
- dat += "The broker expects the return of the shares after [B.lease_time / 600] minutes, with a grace period of [B.grace_time / 600] minute(s).
"
- dat += "This offer expires in [(B.offer_expires - world.time) / 600] minutes.
"
- dat += "Note: If you do not return all shares by the end of the grace period, you will lose your deposit and the value of all unreturned shares at current value from your account!
"
- dat += "Note: You cannot withdraw or transfer money off your account while a borrow is active.
"
- dat += "Take offer (Estimated deposit: [B.deposit * S.current_value * B.share_amount] credits)
"
- else
- dat += "No borrow options available
"
- for (var/datum/borrow/B in S.borrows)
- if (B.borrower == logged_in)
- dat += "You are borrowing [B.share_amount] shares from [B.broker].
"
- dat += "Your deposit riding on the deal is [B.deposit] credits.
"
- if (world.time < B.lease_expires)
- dat += "You are expected to return the borrowed shares in [(B.lease_expires - world.time) / 600] minutes.
"
- else
- dat += "The brokering agency is collecting. You still owe them [B.share_debt] shares, which you have [(B.grace_expires - world.time) / 600] minutes to present.
"
var/news = 0
if (logged_in)
var/list/LR = stockExchange.last_read[S]
diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm
index b6218ceaea6..cec2417e876 100644
--- a/code/modules/surgery/bodyparts/dismemberment.dm
+++ b/code/modules/surgery/bodyparts/dismemberment.dm
@@ -263,6 +263,7 @@
break
update_bodypart_damage_state()
+
C.updatehealth()
C.update_body()
C.update_hair()
@@ -270,7 +271,6 @@
C.update_canmove()
-
/obj/item/bodypart/head/attach_limb(mob/living/carbon/C, special)
//Transfer some head appearance vars over
if(brain)
diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm
index 76220ef9ddc..9cfed984f4c 100644
--- a/code/modules/surgery/organs/augments_arms.dm
+++ b/code/modules/surgery/organs/augments_arms.dm
@@ -68,6 +68,10 @@
"[holder] snaps back into your [zone == "r_arm" ? "right" : "left"] arm.",
"You hear a short mechanical noise.")
+ if(istype(holder, /obj/item/device/assembly/flash/armimplant))
+ var/obj/item/device/assembly/flash/F = holder
+ F.SetLuminosity(0)
+
owner.unEquip(holder, 1)
holder.loc = src
holder = null
@@ -85,6 +89,10 @@
holder.w_class = 5
holder.materials = null
+ if(istype(holder, /obj/item/device/assembly/flash/armimplant))
+ var/obj/item/device/assembly/flash/F = holder
+ F.SetLuminosity(7)
+
var/obj/item/arm_item = owner.get_active_held_item()
if(arm_item)
@@ -178,3 +186,45 @@
items_list += new /obj/item/weapon/kitchen/knife/combat/cyborg(src)
return 1
return 0
+
+/obj/item/organ/cyberimp/arm/esword
+ name = "arm-mounted energy blade"
+ desc = "An illegal, and highly dangerous cybernetic implant that can project a deadly blade of concentrated enregy."
+ contents = newlist(/obj/item/weapon/melee/energy/blade)
+
+/obj/item/organ/cyberimp/arm/medibeam
+ name = "integrated medical beamgun"
+ desc = "A cybernetic implant that allows the user to project a healing beam from their hand."
+ contents = newlist(/obj/item/weapon/gun/medbeam)
+
+/obj/item/organ/cyberimp/arm/flash
+ name = "integrated high-intensity photon projector" //Why not
+ desc = "An integrated projector mounted onto a user's arm, that is able to be used as a powerful flash."
+ contents = newlist(/obj/item/device/assembly/flash/armimplant)
+
+/obj/item/organ/cyberimp/arm/flash/New()
+ ..()
+ if(locate(/obj/item/device/assembly/flash/armimplant) in items_list)
+ var/obj/item/device/assembly/flash/armimplant/F = locate(/obj/item/device/assembly/flash/armimplant) in items_list
+ F.I = src
+
+/obj/item/organ/cyberimp/arm/baton
+ name = "arm electrification implant"
+ desc = "An illegal combat implant that allows the user to administer disabling shocks from their arm."
+ contents = newlist(/obj/item/borg/stun)
+
+/obj/item/organ/cyberimp/arm/combat
+ name = "combat cybernetics implant"
+ desc = "A powerful cybernetic implant that contains combat modules built into the user's arm"
+ contents = newlist(/obj/item/weapon/melee/energy/blade, /obj/item/weapon/gun/medbeam, /obj/item/borg/stun, /obj/item/device/assembly/flash/armimplant)
+
+/obj/item/organ/cyberimp/arm/combat/New()
+ ..()
+ if(locate(/obj/item/device/assembly/flash/armimplant) in items_list)
+ var/obj/item/device/assembly/flash/armimplant/F = locate(/obj/item/device/assembly/flash/armimplant) in items_list
+ F.I = src
+
+/obj/item/organ/cyberimp/arm/surgery
+ name = "surgical toolset implant"
+ desc = "A set of surgical tools hidden behind a concealed panel on the user's arm"
+ contents = newlist(/obj/item/weapon/retractor, /obj/item/weapon/hemostat, /obj/item/weapon/cautery, /obj/item/weapon/surgicaldrill, /obj/item/weapon/scalpel, /obj/item/weapon/circular_saw, /obj/item/weapon/surgical_drapes)
diff --git a/code/modules/surgery/organs/augments_chest.dm b/code/modules/surgery/organs/augments_chest.dm
index b977b039dff..5121e955a1b 100644
--- a/code/modules/surgery/organs/augments_chest.dm
+++ b/code/modules/surgery/organs/augments_chest.dm
@@ -197,3 +197,4 @@
toggle(silent=1)
return 0
+
diff --git a/code/modules/vehicles/pimpin_ride.dm b/code/modules/vehicles/pimpin_ride.dm
index c1bfbc020ab..4e001cb1680 100644
--- a/code/modules/vehicles/pimpin_ride.dm
+++ b/code/modules/vehicles/pimpin_ride.dm
@@ -49,6 +49,7 @@
for(var/A in tile)
if(is_cleanable(A))
qdel(A)
+ . = ..()
/obj/vehicle/janicart/examine(mob/user)
diff --git a/config/game_options.txt b/config/game_options.txt
index 9f7e778833d..6a4c773117c 100644
--- a/config/game_options.txt
+++ b/config/game_options.txt
@@ -355,3 +355,6 @@ BOMBCAP 20
# spawn, while the converse is true. Alter this number to affect the amount
# of ruins.
LAVALAND_BUDGET 60
+
+## Space Ruin Budged
+Space_Budget 16
diff --git a/config/tips.txt b/config/tips.txt
index 917443afefa..5af9a6d1938 100644
--- a/config/tips.txt
+++ b/config/tips.txt
@@ -120,7 +120,7 @@ As a Nuclear Operative, you should look into purchasing a syndicate cyborg, as t
As a Nuclear Operative, stick together! While your equipment is robust, your fellow operatives are much better at saving your life: they can drag you away from danger while stunned and provide cover fire.
As a Nuclear Operative, you might end up in a situation where the AI has bolted you into a room. Having some spare C4 in your pocket can save your life.
As a Monkey, you can crawl through air or scrubber vents by alt+left clicking them. You must drop everything you are wearing and holding to do this, however.
-As a Monkey, you can still wear a few human items, like backpacks and gas masks, and still have two free hands. Remember that you cannot use guns!
+As a Monkey, you can still wear a few human items, such as backpacks, gas masks and hats, and still have two free hands.
As a Malfunctioning AI, you can shunt to an APC if the situation gets bad. This can allow the clock to tick down long enough for you to win, but keep in mind the crew's pinpointer will point to you when you do this.
As a Malfunctioning AI, you should either order your cyborgs to dismantle the robotics console or blow it up yourself in order to protect them.
As a Malfunctioning AI, look into flooding the station with plasma fires to kill off large portions of the crew, letting you pick off the remaining few with space suits who escaped.
diff --git a/html/changelog.html b/html/changelog.html
index 9754c9fa064..9cc8dc1941b 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -55,11 +55,169 @@
-->
+
21 September 2016
+
Cyberboss updated:
+
+ - The food processor's sprite's maintenance panel is no longer open while closed and vice/versa
+ - Tesla arcs no longer lose power when passing through a coil that isn't connected to a grid
+
+
MrStonedOne updated:
+
+ - Fixes minimap generation crashes by making parts of it less precise
+
+
+
20 September 2016
+
Ergovisavi updated:
+
+ - fixed "friendly" xenobio mobs and mining drones attacking station drones
+
+
Joan updated:
+
+ - Miners can now buy KA AoE damage mods from the mining vendor for 2000 points per mod.
+ - Combined the Convert and Sacrifice runes into one rune. It'll convert targets that are alive and eligible, and attempt to sacrifice them otherwise. The only changes to mechanics are that: Converting someone will heal them of all brute and burn damage they had, and sacrificing anything will always produce a soulstone(but will still only sometimes fill it)
+ - You can no longer teleport to Teleport runes that have dense objects on top of them.
+ - Wall runes will now activate other nearby wall runes when activated, but will automatically disable after a minute and a half of continuous activity and become unusable for 5 seconds.
+ - The Blood Boil rune no longer does all of its damage instantly or stuns, but if you remain in range for the full duration you will be sent deep into critical.
+ - Bubblegum has been seen reaching through blood. Try not to get hit.
+ - The Raise Dead rune no longer requires a noncultist corpse to revive a cultist; instead, it will draw from the pool of all people sacrificed to power the rune.
+
+
Mekhi updated:
+
+ - Nanotrasen has been experimenting on cybernetics for a while, and rumors are they have a few combat prototypes available...
+ - New arm implants: Energy-blade projector, implanted medical beamgun, stun-arm implant (Like the borg version), flash implant that is automatically-regenerating and doubles as a powerful flashlight. There is also one with all four items in one. Also, a surgery toolkit implant. Adminspawn only for the moment.
+
+
MrStonedOne updated:
+
+ - Fixed space/nograv movement not triggering when atoms moved twice quickly in space/nograv
+
+
Nanotrasen Stress Relief Board updated:
+
+ - Latecomers to highlander can now join in on the fun.
+ - The crew are encouraged to less pacifistic during highlander. Failing to shed blood will result in your soul being devoured. Have a nice day.
+
+
Nicho1010 updated:
+
+ - Fixed lattices appearing after exploding lava
+
+
Screemonster updated:
+
+ - Abandoned crates no longer accept impossible guesses.
+ - Lets players know that all the digits in the code must be unique.
+ - Reads the last guess back on the multitool along with the correct/incorrect guess readout.
+ - multitool output on crates no longer returns nonsense values.
+
+
XDTM updated:
+
+ - Positive viruses are now recognized by medical HUDs with a special icon.
+ - fully_heal no longer removes nonharmful viruses. This affects legion souls, staffs of healing, and changeling's revive.
+ - Canisters of any type of gas are now orderable in cargo. Dangerous experimental gases will require Research Director approval.
+
+
Yackemflam updated:
+
+ - The syndicate has learned on how to give their agents a true syndicate ninja experience.
+
+
chickenboy10 updated:
+
+ - Added a Experimental Limb Grower to the medbay department, now medical stuff can grow synthetic limbs using Synthflesh to help crew that suffer any work related accidents. There may also be a limb that can be grown with a special card...
+
+
feemjmeem updated:
+
+ - You can now disassemble meatspike frames with a welding tool.
+
+
phil235 updated:
+
+ - adds a talk button next to the crafting button. Clicking it makes a "wheel" appear around you with short predetermined messages that you click to say them. This lets you say common responses without having to type in the chat bar. Current messages available are: "Hi", "Bye", "Thanks", "Come", "Help", "Stop", "Get out", "Yes", and "No". The talk button can be activated with the hotkey "H" or "CTRL+H"
+ - Wearing colored glasses colors your vision. This option can be enabled/disabled by alt-clicking any glasses with such feature.
+
+
+
17 September 2016
+
BoxcarRacer41 updated:
+
+ - Added a new food, bacon. Bacon is made by processing raw meat cutlets.
+ - Added a new burger recipe, the Bacon Burger. It is made with one bun, one cheese wedge and three pieces of cooked bacon.
+
+
Ergovisavi updated:
+
+ - Added a nightvision toggle to Shadowpeople
+ - Made several anomalous crystal variants more easily identified/easier to see the effects thereof, and removed the "magic" activation possibility (replaced with the "bomb" flag)
+
+
Gun Hog updated:
+
+ - Nanotrasen Robotics Division is proud to announce slightly less clunky leg servo designs relating to the "Ripley" APLU and "Firefighter" exosuits. Tests show increased mobility in both high and low pressure environments. The previous designer has been fired for incompetence.
+
+
Improves tablets design updated:
+
+ - Brings the tablet icons into the holy light of having depth
+
+
Joan updated:
+
+ - Megafauna will now use ranged attacks even if they don't have direct vision on their target.
+ - Volt Void and Interdiction Lenses will now drain mech cells of energy.
+ - Ocular Wardens do slightly more damage to mechs.
+ - Replicant, Soul Vessel, Cogscarab, and Anima Fragment now take an additional second to recite.
+ - Anima Fragments do slightly less damage in melee.
+ - Mending Motors and Clockwork Obelisks have slightly less health.
+ - Invoking Nezbere now requires 3 invokers.
+ - Clockwork armor no longer has 5% energy resistance.
+ - You can no longer construct clockwork structures on space turfs.
+
+
Papa Bones updated:
+
+ - BZ gas is no longer available on Box and Metastation layouts.
+
+
phil235 updated:
+
+ - You no longer have to click a megaphone to use it, you simply keep it in your active hand and talk normally.
+ - Added new things
+ - added some icons and images
+
+
+
14 September 2016
+
Ergovisavi updated:
+
+ - Fixes lockers, bodybags, etc, giving you ash storm / radiation storm protection
+
+
Erwgd updated:
+
+ - Upgraded sleepers can now inject inacusiate to treat ear damage.
+
+
Joan updated:
+
+ - Added brass, producible by proselytizing rods, metal, or plasteel, or by using Replicant Alloy in-hand, and usable to construct a variety of cult-y brass objects.
+ - Objects constructable with brass include; wall gears, pinion airlocks, brass windoors, brass windows, brass table frames and tables, and brass floor tiles.
+ - Cogscarabs can convert brass sheets into liquified alloy with their proselytizer.
+ - You can use brass sheets on wall gears to produce clockwork walls, or, if the gear is unanchored, false clockwork walls.
+ - Fixed a bug preventing you from converting grilles into ratvar grilles.
+ - Please note that conservation of mass exists.
+
+
Sligneris updated:
+
+ - Captain's space armor has been readapted with modern hardsuit technology.
+
+
oranges updated:
+
+ - Examine code for dismembered humans now has better easter eggs
+
+
12 September 2016
Joan updated:
- Cult structures can once again be constructed with runed metal.
- Cult structures can now take damage and be destroyed. Artificers can repair them if they're damaged.
+ - The Recollection function of the clockwork slab is much more useful and easier to parse.
+ - Tweaked the Recital menus for scripture so the scripture are all in the proper order. This might fuck you up if you were used to the incorrect order, but you'll get used to it.
+
+
Nanotrasen Anti-Cheese Committee updated:
+
+ - A glitch in the hydroponics tray firmware allowed it to retain plant growth even after the plant was removed, resulting in the next planted seed being grown instantaneously. This is no longer possible.
+
+
PKPenguin321 updated:
+
+ - Tesla shocks from grilles will no longer do thousands and thousands of damage. They now properly deal burn damage that is equal to the current power in the powernet divided by 5000.
+
+
Papa Bones updated:
+
+ - You can now rename the captain's sabre by using a pen on it.
RemieRichards updated:
@@ -69,6 +227,7 @@
- The surplus crate and random item will now only contain items allowed by the gamemode
- removes sleeping carp scroll from surplus crates
+ - Minimaps will now try to load from a cache or backup file if minimap generation is disabled.
TheCarlSaganExpress updated:
@@ -972,138 +1131,6 @@
- Clockwork cultists may now have the "Escape" and "Silicon" objectives, requiring a certain amount of servants to escape on the shuttle and all silicons to be converted respectively.
- Ocular wardens are now forced to target bibles rather than the people holding them.
-
- 19 July 2016
- Joan updated:
-
- - Cogscarabs can no longer pass mobs and have slightly less health.
- - The Gateway to the Celestial Derelict can now take damage from bombs.
-
- RemieRichards updated:
-
- - Added VR Sleepers that allow users to enter a virtual body in a virtual world (Currently not mapped in ;_;)
-
- Xhuis updated:
-
- - Added communication intercept texts for gamemodes that were missing them.
- - Changed all intercept texts and improved grammar for a lot of key game code.
- - The shuttle can now leave while a celestial gateway exists.
- - If the shuttle docks at Central Command while a celestial gateway exists, Ratvar's servants will win a minor victory. His arrival will still award a major victory.
- - The celestial gateway can now take damage from explosions.
-
-
- 18 July 2016
- CoreOverload updated:
-
- - Sterilizine now reduces probability of step failure if you apply it after starting surgery. Useful while operating in less-than-perfect conditions.
- - Potent alcohol can be used as replacement for sterilizine.
-
- Joan updated:
-
- - The Vanguard scripture no longer prevents you from using slabs while active, but you cannot reactivate it if it is currently active.
- - It now only lasts 20 seconds, instead of 30.
- - When Vanguard deactivates, it now stuns for half the time of all stuns absorbed, instead of all of them.
- - Invoking Sevtug is less potent at long ranges, and slightly more potent if extremely close.
- - Invoking Sevtug now requires 3 invokers instead of 1.
- - The Clockwork Slab now has action buttons for rapidly invoking Guvax and Vanguard.
- - Belligerent is now chanted more often.
- - Taunting Tirade now weakens nearby nonservants, but is now only invoked once every 6 seconds(1 second chant, 5 second flee time) and is only chanted five times.
-
- lordpidey updated:
-
- - Flyswatters are now included in beekeeping crates, they are great at killing insects and flies of all sizes.
-
-
- 16 July 2016
- Gun Hog and WJohnston updated:
-
- - Aliens (Xenos) now have the ability to sense the direction and rough distance of their queen!
-
- Iamgoofball updated:
-
- - Fixed the lag when opening the foodcrafting menu by splitting everything up into categories.
-
- Joan updated:
-
- - Cogscarabs(and other nonhuman mobs able to hold clockwork slabs) can now check the stats of the clockwork cult by using a clockwork slab. They remain unable to use slabs under normal conditions.
-
- MrStonedOne updated:
-
- - Added a system to detect when stickybans go rogue and revert all recent matches.
-
-
- 15 July 2016
- Cheridan updated:
-
- - Added an aesthetic new space ruin
-
-
- 14 July 2016
- Basilman updated:
-
- - Added a new hairstyle "Boddicker"
-
- Bawhoppen updated:
-
- - Added two new materials, Titanium and plastitanium. Titanium is naturally occuring, and plastitanium is an alloy made of plasma and titanium.
- - These materials can be used to build shuttle walls and floors, though this serves no current purpose.
-
- CoreOverload updated:
-
- - Some clothing has pockets now.
-
- Firecage updated:
-
- - Mechas can no longer pass through Plastic Flaps
-
- Fox McCloud updated:
-
- - Fixes borg stun arm not having a hitsound, bypassing shields, and not doing an attack animation
- - Fixes simple mobs not properly having armor penetration
-
- Joan updated:
-
- - Added dextrous guardians to the code, able to hold and use items and store a single item within themselves.
- - Dextrous guardians do low damage on punches, have medium damage resist, and recalling or leashing will force them to drop any items in their hands.
-
- Kor updated:
-
- - Shuttle travel time has been shortened from 25 seconds to 6 seconds
-
- Lzimann updated:
-
- - Alt clicking a jumpsuit now removes the accessories(if there's any)!
-
- Papa Bones updated:
-
- - Security's lethal injections are actually lethal now.
-
- Xhuis updated:
-
- - Nanotrasen electricians have introduced a software update to all licensed pinpointers. The new pinpointers are more responsive and automatically switch modes based on the current crisis.
- - It should be noted that some of these pinpointers have been reported as missing from their distribution warehouse and are presumed to have been stolen. This is likely nothing to worry about.
-
- lordpidey updated:
-
- - Infernal jaunt now has a cooldown, to prevent trying to jaunt while already jaunting. This should have no practical changes.
- - Infernal jaunt no longer occasionally leaves you permanently on fire.
- - Pitchforks no longer burn devils and soul-sellers, as intended.
-
-
- 12 July 2016
- MMMiracles updated:
-
- - Hotel staff can now actually use their own lockers.
-
- RemieRichards updated:
-
- - fixed Kor's plant disguises
- - fixed some issues with Alternate Appearances not being added/removed
-
- hornygranny updated:
-
- - Attacks will no longer miss missing limbs
-
GoonStation 13 Development Team
diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml
index bfb5b9bc4fb..07339eff261 100644
--- a/html/changelogs/.all_changelog.yml
+++ b/html/changelogs/.all_changelog.yml
@@ -7010,6 +7010,21 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
- rscadd: Cult structures can once again be constructed with runed metal.
- experiment: Cult structures can now take damage and be destroyed. Artificers can
repair them if they're damaged.
+ - tweak: The Recollection function of the clockwork slab is much more useful and
+ easier to parse.
+ - wip: Tweaked the Recital menus for scripture so the scripture are all in the proper
+ order. This might fuck you up if you were used to the incorrect order, but you'll
+ get used to it.
+ Nanotrasen Anti-Cheese Committee:
+ - bugfix: A glitch in the hydroponics tray firmware allowed it to retain plant growth
+ even after the plant was removed, resulting in the next planted seed being grown
+ instantaneously. This is no longer possible.
+ PKPenguin321:
+ - bugfix: Tesla shocks from grilles will no longer do thousands and thousands of
+ damage. They now properly deal burn damage that is equal to the current power
+ in the powernet divided by 5000.
+ Papa Bones:
+ - tweak: You can now rename the captain's sabre by using a pen on it.
RemieRichards:
- rscadd: Added the functionality for mobs to have multiple hands, this might have
broken some things, so please report any weirdness
@@ -7017,6 +7032,8 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
- rscdel: The surplus crate and random item will now only contain items allowed
by the gamemode
- rscdel: removes sleeping carp scroll from surplus crates
+ - experiment: Minimaps will now try to load from a cache or backup file if minimap
+ generation is disabled.
TheCarlSaganExpress:
- rscadd: Crayons, lipstick, cigarettes, and penlights can now be inserted into
PDAs.
@@ -7036,3 +7053,138 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
- bugfix: Alien larva has its own gib and dust animation.
- bugfix: A bodypart that looks wounded still looks bloody when dismembered.
- bugfix: Amputation surgery now works on robotic limbs, and monkeys.
+2016-09-14:
+ Ergovisavi:
+ - bugfix: Fixes lockers, bodybags, etc, giving you ash storm / radiation storm protection
+ Erwgd:
+ - rscadd: Upgraded sleepers can now inject inacusiate to treat ear damage.
+ Joan:
+ - rscadd: Added brass, producible by proselytizing rods, metal, or plasteel, or
+ by using Replicant Alloy in-hand, and usable to construct a variety of cult-y
+ brass objects.
+ - tweak: Objects constructable with brass include; wall gears, pinion airlocks,
+ brass windoors, brass windows, brass table frames and tables, and brass floor
+ tiles.
+ - rscadd: Cogscarabs can convert brass sheets into liquified alloy with their proselytizer.
+ - tweak: You can use brass sheets on wall gears to produce clockwork walls, or,
+ if the gear is unanchored, false clockwork walls.
+ - bugfix: Fixed a bug preventing you from converting grilles into ratvar grilles.
+ - experiment: Please note that conservation of mass exists.
+ Sligneris:
+ - tweak: Captain's space armor has been readapted with modern hardsuit technology.
+ oranges:
+ - tweak: Examine code for dismembered humans now has better easter eggs
+2016-09-17:
+ BoxcarRacer41:
+ - rscadd: Added a new food, bacon. Bacon is made by processing raw meat cutlets.
+ - rscadd: Added a new burger recipe, the Bacon Burger. It is made with one bun,
+ one cheese wedge and three pieces of cooked bacon.
+ Ergovisavi:
+ - rscadd: Added a nightvision toggle to Shadowpeople
+ - tweak: Made several anomalous crystal variants more easily identified/easier to
+ see the effects thereof, and removed the "magic" activation possibility (replaced
+ with the "bomb" flag)
+ Gun Hog:
+ - tweak: Nanotrasen Robotics Division is proud to announce slightly less clunky
+ leg servo designs relating to the "Ripley" APLU and "Firefighter" exosuits.
+ Tests show increased mobility in both high and low pressure environments. The
+ previous designer has been fired for incompetence.
+ Improves tablets design:
+ - imageadd: Brings the tablet icons into the holy light of having depth
+ Joan:
+ - rscadd: Megafauna will now use ranged attacks even if they don't have direct vision
+ on their target.
+ - rscadd: Volt Void and Interdiction Lenses will now drain mech cells of energy.
+ - tweak: Ocular Wardens do slightly more damage to mechs.
+ - experiment: Replicant, Soul Vessel, Cogscarab, and Anima Fragment now take an
+ additional second to recite.
+ - tweak: Anima Fragments do slightly less damage in melee.
+ - tweak: Mending Motors and Clockwork Obelisks have slightly less health.
+ - tweak: Invoking Nezbere now requires 3 invokers.
+ - rscdel: Clockwork armor no longer has 5% energy resistance.
+ - bugfix: You can no longer construct clockwork structures on space turfs.
+ Papa Bones:
+ - tweak: BZ gas is no longer available on Box and Metastation layouts.
+ phil235:
+ - tweak: You no longer have to click a megaphone to use it, you simply keep it in
+ your active hand and talk normally.
+ - rscadd: Added new things
+ - imageadd: added some icons and images
+2016-09-20:
+ Ergovisavi:
+ - bugfix: fixed "friendly" xenobio mobs and mining drones attacking station drones
+ Joan:
+ - rscadd: Miners can now buy KA AoE damage mods from the mining vendor for 2000
+ points per mod.
+ - rscadd: 'Combined the Convert and Sacrifice runes into one rune. It''ll convert
+ targets that are alive and eligible, and attempt to sacrifice them otherwise.
+ The only changes to mechanics are that: Converting someone will heal them of
+ all brute and burn damage they had, and sacrificing anything will always produce
+ a soulstone(but will still only sometimes fill it)'
+ - tweak: You can no longer teleport to Teleport runes that have dense objects on
+ top of them.
+ - experiment: Wall runes will now activate other nearby wall runes when activated,
+ but will automatically disable after a minute and a half of continuous activity
+ and become unusable for 5 seconds.
+ - experiment: The Blood Boil rune no longer does all of its damage instantly or
+ stuns, but if you remain in range for the full duration you will be sent deep
+ into critical.
+ - experiment: Bubblegum has been seen reaching through blood. Try not to get hit.
+ - experiment: The Raise Dead rune no longer requires a noncultist corpse to revive
+ a cultist; instead, it will draw from the pool of all people sacrificed to power
+ the rune.
+ Mekhi:
+ - rscadd: Nanotrasen has been experimenting on cybernetics for a while, and rumors
+ are they have a few combat prototypes available...
+ - experiment: 'New arm implants: Energy-blade projector, implanted medical beamgun,
+ stun-arm implant (Like the borg version), flash implant that is automatically-regenerating
+ and doubles as a powerful flashlight. There is also one with all four items
+ in one. Also, a surgery toolkit implant. Adminspawn only for the moment.'
+ MrStonedOne:
+ - bugfix: Fixed space/nograv movement not triggering when atoms moved twice quickly
+ in space/nograv
+ Nanotrasen Stress Relief Board:
+ - rscadd: Latecomers to highlander can now join in on the fun.
+ - rscadd: The crew are encouraged to less pacifistic during highlander. Failing
+ to shed blood will result in your soul being devoured. Have a nice day.
+ Nicho1010:
+ - bugfix: Fixed lattices appearing after exploding lava
+ Screemonster:
+ - tweak: Abandoned crates no longer accept impossible guesses.
+ - tweak: Lets players know that all the digits in the code must be unique.
+ - tweak: Reads the last guess back on the multitool along with the correct/incorrect
+ guess readout.
+ - bugfix: multitool output on crates no longer returns nonsense values.
+ XDTM:
+ - rscadd: Positive viruses are now recognized by medical HUDs with a special icon.
+ - tweak: fully_heal no longer removes nonharmful viruses. This affects legion souls,
+ staffs of healing, and changeling's revive.
+ - rscadd: Canisters of any type of gas are now orderable in cargo. Dangerous experimental
+ gases will require Research Director approval.
+ Yackemflam:
+ - rscadd: The syndicate has learned on how to give their agents a true syndicate
+ ninja experience.
+ chickenboy10:
+ - rscadd: Added a Experimental Limb Grower to the medbay department, now medical
+ stuff can grow synthetic limbs using Synthflesh to help crew that suffer any
+ work related accidents. There may also be a limb that can be grown with a special
+ card...
+ feemjmeem:
+ - tweak: You can now disassemble meatspike frames with a welding tool.
+ phil235:
+ - experiment: 'adds a talk button next to the crafting button. Clicking it makes
+ a "wheel" appear around you with short predetermined messages that you click
+ to say them. This lets you say common responses without having to type in the
+ chat bar. Current messages available are: "Hi", "Bye", "Thanks", "Come", "Help",
+ "Stop", "Get out", "Yes", and "No". The talk button can be activated with the
+ hotkey "H" or "CTRL+H"'
+ - rscadd: Wearing colored glasses colors your vision. This option can be enabled/disabled
+ by alt-clicking any glasses with such feature.
+2016-09-21:
+ Cyberboss:
+ - bugfix: The food processor's sprite's maintenance panel is no longer open while
+ closed and vice/versa
+ - tweak: Tesla arcs no longer lose power when passing through a coil that isn't
+ connected to a grid
+ MrStonedOne:
+ - bugfix: Fixes minimap generation crashes by making parts of it less precise
diff --git a/icons/effects/beam.dmi b/icons/effects/beam.dmi
index d41b9403fa2..247d6a401f7 100644
Binary files a/icons/effects/beam.dmi and b/icons/effects/beam.dmi differ
diff --git a/icons/effects/blood.dmi b/icons/effects/blood.dmi
index e915cb49e37..5e71e45d4bf 100644
Binary files a/icons/effects/blood.dmi and b/icons/effects/blood.dmi differ
diff --git a/icons/effects/bubblegum.dmi b/icons/effects/bubblegum.dmi
new file mode 100644
index 00000000000..a53dd7d563a
Binary files /dev/null and b/icons/effects/bubblegum.dmi differ
diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi
index 01e00f7163f..adef4345cc9 100644
Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ
diff --git a/icons/minimaps/BirdboatStation_1.png b/icons/minimaps/BirdboatStation_1.png
new file mode 100644
index 00000000000..a6c1a4dd932
Binary files /dev/null and b/icons/minimaps/BirdboatStation_1.png differ
diff --git a/icons/minimaps/Box Station_1.png b/icons/minimaps/Box Station_1.png
new file mode 100644
index 00000000000..d14145b5604
Binary files /dev/null and b/icons/minimaps/Box Station_1.png differ
diff --git a/icons/minimaps/DreamStation_1.png b/icons/minimaps/DreamStation_1.png
new file mode 100644
index 00000000000..75ac12fec85
Binary files /dev/null and b/icons/minimaps/DreamStation_1.png differ
diff --git a/icons/minimaps/Efficiency Station_1.png b/icons/minimaps/Efficiency Station_1.png
new file mode 100644
index 00000000000..3c952a21493
Binary files /dev/null and b/icons/minimaps/Efficiency Station_1.png differ
diff --git a/icons/minimaps/MetaStation_1.png b/icons/minimaps/MetaStation_1.png
new file mode 100644
index 00000000000..bf8a6ed430a
Binary files /dev/null and b/icons/minimaps/MetaStation_1.png differ
diff --git a/icons/minimaps/MiniStation_1.png b/icons/minimaps/MiniStation_1.png
new file mode 100644
index 00000000000..52689a1a576
Binary files /dev/null and b/icons/minimaps/MiniStation_1.png differ
diff --git a/icons/mob/hud.dmi b/icons/mob/hud.dmi
index 2338f667955..0d61c44cbbd 100644
Binary files a/icons/mob/hud.dmi and b/icons/mob/hud.dmi differ
diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi
index 4fd8e88842f..613fdf7e18b 100644
Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ
diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi
index 438f41daca2..fc596866750 100644
Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ
diff --git a/icons/mob/mob.dmi b/icons/mob/mob.dmi
index 413248185ef..486e4e7fb74 100644
Binary files a/icons/mob/mob.dmi and b/icons/mob/mob.dmi differ
diff --git a/icons/mob/screen_gen.dmi b/icons/mob/screen_gen.dmi
index b0a1dbcb168..256bd412b4f 100644
Binary files a/icons/mob/screen_gen.dmi and b/icons/mob/screen_gen.dmi differ
diff --git a/icons/mob/screen_midnight.dmi b/icons/mob/screen_midnight.dmi
index 4de01c73cc8..c25813197fe 100644
Binary files a/icons/mob/screen_midnight.dmi and b/icons/mob/screen_midnight.dmi differ
diff --git a/icons/mob/screen_operative.dmi b/icons/mob/screen_operative.dmi
index e1728959e6a..e6a65052c14 100644
Binary files a/icons/mob/screen_operative.dmi and b/icons/mob/screen_operative.dmi differ
diff --git a/icons/mob/screen_plasmafire.dmi b/icons/mob/screen_plasmafire.dmi
index c40a531d8a6..3d1846b3009 100644
Binary files a/icons/mob/screen_plasmafire.dmi and b/icons/mob/screen_plasmafire.dmi differ
diff --git a/icons/mob/screen_retro.dmi b/icons/mob/screen_retro.dmi
index 9c99dba486b..db87b592169 100644
Binary files a/icons/mob/screen_retro.dmi and b/icons/mob/screen_retro.dmi differ
diff --git a/icons/mob/screen_slimecore.dmi b/icons/mob/screen_slimecore.dmi
index 91e2d73abe2..8575fa037de 100644
Binary files a/icons/mob/screen_slimecore.dmi and b/icons/mob/screen_slimecore.dmi differ
diff --git a/icons/obj/clothing/glasses.dmi b/icons/obj/clothing/glasses.dmi
index 2084597bea4..06c3a0ce8a4 100644
Binary files a/icons/obj/clothing/glasses.dmi and b/icons/obj/clothing/glasses.dmi differ
diff --git a/icons/obj/food/burgerbread.dmi b/icons/obj/food/burgerbread.dmi
index 843a6cd508b..64fac1c3eb7 100644
Binary files a/icons/obj/food/burgerbread.dmi and b/icons/obj/food/burgerbread.dmi differ
diff --git a/icons/obj/food/food.dmi b/icons/obj/food/food.dmi
index 7c0df528dd6..fec63c0a165 100644
Binary files a/icons/obj/food/food.dmi and b/icons/obj/food/food.dmi differ
diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi
index 62f5dd37112..c629012bb16 100644
Binary files a/icons/obj/items.dmi and b/icons/obj/items.dmi differ
diff --git a/icons/obj/machines/limbgrower.dmi b/icons/obj/machines/limbgrower.dmi
new file mode 100644
index 00000000000..7e26a9f7f24
Binary files /dev/null and b/icons/obj/machines/limbgrower.dmi differ
diff --git a/icons/obj/modular_tablet.dmi b/icons/obj/modular_tablet.dmi
index 82f4e1438f6..2438f375f65 100644
Binary files a/icons/obj/modular_tablet.dmi and b/icons/obj/modular_tablet.dmi differ
diff --git a/icons/obj/tiles.dmi b/icons/obj/tiles.dmi
index f6054cca6a7..9347e67f233 100644
Binary files a/icons/obj/tiles.dmi and b/icons/obj/tiles.dmi differ
diff --git a/icons/obj/weapons.dmi b/icons/obj/weapons.dmi
index dcc0ffb5ce8..d0afb945f00 100644
Binary files a/icons/obj/weapons.dmi and b/icons/obj/weapons.dmi differ
diff --git a/icons/turf/walls/clockwork_wall.dmi b/icons/turf/walls/clockwork_wall.dmi
index ae9f2de887a..8263e901d00 100644
Binary files a/icons/turf/walls/clockwork_wall.dmi and b/icons/turf/walls/clockwork_wall.dmi differ
diff --git a/interface/skin.dmf b/interface/skin.dmf
index 335caf26118..27dca90bcc8 100644
--- a/interface/skin.dmf
+++ b/interface/skin.dmf
@@ -77,6 +77,9 @@ macro "default"
elem
name = "CTRL+G"
command = "a-intent right"
+ elem
+ name = "CTRL+H"
+ command = "talk-wheel"
elem
name = "CTRL+Q"
command = ".northwest"
@@ -238,6 +241,12 @@ macro "hotkeys"
elem
name = "CTRL+G"
command = "a-intent right"
+ elem
+ name = "H"
+ command = "talk-wheel"
+ elem
+ name = "CTRL+H"
+ command = "talk-wheel"
elem
name = "M"
command = "me"
diff --git a/tgstation.dme b/tgstation.dme
index 14896210baf..a29bd5bc4da 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -156,6 +156,7 @@
#include "code\controllers\subsystem\radio.dm"
#include "code\controllers\subsystem\server_maintenance.dm"
#include "code\controllers\subsystem\shuttles.dm"
+#include "code\controllers\subsystem\spacedrift.dm"
#include "code\controllers\subsystem\stickyban.dm"
#include "code\controllers\subsystem\sun.dm"
#include "code\controllers\subsystem\tgui.dm"
@@ -336,6 +337,7 @@
#include "code\game\gamemodes\clock_cult\clock_items.dm"
#include "code\game\gamemodes\clock_cult\clock_machines.dm"
#include "code\game\gamemodes\clock_cult\clock_mobs.dm"
+#include "code\game\gamemodes\clock_cult\clock_powerdrain.dm"
#include "code\game\gamemodes\clock_cult\clock_proselytizer.dm"
#include "code\game\gamemodes\clock_cult\clock_ratvar.dm"
#include "code\game\gamemodes\clock_cult\clock_scripture.dm"
@@ -363,14 +365,6 @@
#include "code\game\gamemodes\gang\gang_datum.dm"
#include "code\game\gamemodes\gang\gang_pen.dm"
#include "code\game\gamemodes\gang\recaller.dm"
-#include "code\game\gamemodes\handofgod\_handofgod.dm"
-#include "code\game\gamemodes\handofgod\actions.dm"
-#include "code\game\gamemodes\handofgod\god.dm"
-#include "code\game\gamemodes\handofgod\items.dm"
-#include "code\game\gamemodes\handofgod\objectives.dm"
-#include "code\game\gamemodes\handofgod\powers.dm"
-#include "code\game\gamemodes\handofgod\structures.dm"
-#include "code\game\gamemodes\handofgod\traps.dm"
#include "code\game\gamemodes\malfunction\Malf_Modules.dm"
#include "code\game\gamemodes\meteor\meteor.dm"
#include "code\game\gamemodes\meteor\meteors.dm"
@@ -430,6 +424,7 @@
#include "code\game\machinery\igniter.dm"
#include "code\game\machinery\iv_drip.dm"
#include "code\game\machinery\lightswitch.dm"
+#include "code\game\machinery\limbgrower.dm"
#include "code\game\machinery\machinery.dm"
#include "code\game\machinery\magnet.dm"
#include "code\game\machinery\mass_driver.dm"
@@ -602,6 +597,7 @@
#include "code\game\objects\items\documents.dm"
#include "code\game\objects\items\latexballoon.dm"
#include "code\game\objects\items\nuke_tools.dm"
+#include "code\game\objects\items\religion.dm"
#include "code\game\objects\items\shooting_range.dm"
#include "code\game\objects\items\toys.dm"
#include "code\game\objects\items\trash.dm"
@@ -747,6 +743,7 @@
#include "code\game\objects\structures\bedsheet_bin.dm"
#include "code\game\objects\structures\destructible_structures.dm"
#include "code\game\objects\structures\displaycase.dm"
+#include "code\game\objects\structures\divine.dm"
#include "code\game\objects\structures\door_assembly.dm"
#include "code\game\objects\structures\dresser.dm"
#include "code\game\objects\structures\electricchair.dm"
@@ -782,6 +779,7 @@
#include "code\game\objects\structures\tables_racks.dm"
#include "code\game\objects\structures\tank_dispenser.dm"
#include "code\game\objects\structures\target_stake.dm"
+#include "code\game\objects\structures\traps.dm"
#include "code\game\objects\structures\watercloset.dm"
#include "code\game\objects\structures\windoor_assembly.dm"
#include "code\game\objects\structures\window.dm"
@@ -1766,6 +1764,7 @@
#include "code\modules\research\designs\biogenerator_designs.dm"
#include "code\modules\research\designs\comp_board_designs.dm"
#include "code\modules\research\designs\computer_part_designs.dm"
+#include "code\modules\research\designs\limbgrower_designs.dm"
#include "code\modules\research\designs\machine_designs.dm"
#include "code\modules\research\designs\mecha_designs.dm"
#include "code\modules\research\designs\mechfabricator_designs.dm"