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..3944bb87a79 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" = (
@@ -10943,7 +10943,7 @@ kG
kG
kG
nb
-lG
+md
ju
aa
aa
@@ -11200,7 +11200,7 @@ ln
lI
kG
jc
-kj
+ju
ju
aa
aa
@@ -12999,9 +12999,9 @@ kG
kG
kG
ku
-lG
-lG
-ns
+nr
+nr
+ni
jc
nD
nD
diff --git a/code/__DEFINES/clothing.dm b/code/__DEFINES/clothing.dm
index 93b422cdaa8..3de5a63b40e 100644
--- a/code/__DEFINES/clothing.dm
+++ b/code/__DEFINES/clothing.dm
@@ -122,6 +122,20 @@
#define FEMALE_UNIFORM_FULL 1
#define FEMALE_UNIFORM_TOP 2
+//flags for alternate styles: These are hard sprited so don't set this if you didn't put the effort it
+
+#define NORMAL_STYLE 0
+#define ALT_STYLE 1
+#define DIGITIGRADE_STYLE 2
+
+//flags for outfits that have mutantrace variants (try not to use this): Currently only needed if you're trying to add tight fitting bootyshorts
+
+#define NO_MUTANTRACE_VARIATION 0
+#define MUTANTRACE_VARIATION 1
+
+#define NOT_DIGITIGRADE 0
+#define FULL_DIGITIGRADE 1
+#define SQUISHED_DIGITIGRADE 2
//flags for covering body parts
#define GLASSESCOVERSEYES 1
diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm
index 1554b1e728b..f8f54c991ca 100644
--- a/code/__DEFINES/flags.dm
+++ b/code/__DEFINES/flags.dm
@@ -35,6 +35,7 @@
//turf-only flags
#define NOJAUNT 1
#define UNUSED_TRANSIT_TURF 2
+#define CAN_BE_DIRTY 4 //If a turf can be made dirty at roundstart. This is also used in areas.
/*
These defines are used specifically with the atom/pass_flags bitmask
@@ -72,6 +73,7 @@
#define EASYDISMEMBER 20
#define EASYLIMBATTACHMENT 21
#define TOXINLOVER 22
+#define DIGITIGRADE 23 //Uses weird leg sprites. Optional for Lizards, required for ashwalkers. Don't give it to other races unless you make sprites for this (see human_parts_greyscale.dmi)
#define FLYING 65536
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/__DEFINES/wires.dm b/code/__DEFINES/wires.dm
index 344c9fa23bb..c5954b01f62 100644
--- a/code/__DEFINES/wires.dm
+++ b/code/__DEFINES/wires.dm
@@ -1,44 +1,44 @@
-#define WIRE_ACTIVATE "activate"
-#define WIRE_AI "ai"
-#define WIRE_ALARM "alarm"
-#define WIRE_AVOIDANCE "avoidance"
-#define WIRE_BACKUP1 "backup1"
-#define WIRE_BACKUP2 "backup2"
-#define WIRE_BEACON "beacon"
-#define WIRE_BOLTS "bolts"
-#define WIRE_BOOM "boom"
-#define WIRE_CAMERA "camera"
-#define WIRE_CONTRABAND "contraband"
-#define WIRE_DELAY "delay"
-#define WIRE_DISABLE "disable"
-#define WIRE_DISARM "disarm"
-#define WIRE_ELECTRIFY "electrify"
-#define WIRE_HACK "hack"
-#define WIRE_IDSCAN "idscan"
-#define WIRE_INTERFACE "interface"
-#define WIRE_LAWSYNC "lawsync"
-#define WIRE_LIGHT "light"
-#define WIRE_LIMIT "limit"
-#define WIRE_LOADCHECK "loadcheck"
-#define WIRE_LOCKDOWN "lockdown"
-#define WIRE_MOTOR1 "motor1"
-#define WIRE_MOTOR2 "motor2"
-#define WIRE_OPEN "open"
-#define WIRE_PANIC "panic"
-#define WIRE_POWER "power"
-#define WIRE_POWER1 "power1"
-#define WIRE_POWER2 "power2"
-#define WIRE_PROCEED "proceed"
-#define WIRE_RX "recieve"
-#define WIRE_SAFETY "safety"
-#define WIRE_SHOCK "shock"
-#define WIRE_SIGNAL "signal"
-#define WIRE_SPEAKER "speaker"
-#define WIRE_STRENGTH "strength"
-#define WIRE_THROW "throw"
-#define WIRE_TIMING "timing"
-#define WIRE_TX "transmit"
-#define WIRE_UNBOLT "unbolt"
-#define WIRE_ZAP "zap"
-#define WIRE_ZAP1 "zap1"
-#define WIRE_ZAP2 "zap2"
+#define WIRE_DUD_PREFIX "__dud"
+#define WIRE_ACTIVATE "Activate"
+#define WIRE_AI "AI Connection"
+#define WIRE_ALARM "Alarm"
+#define WIRE_AVOIDANCE "Avoidance"
+#define WIRE_BACKUP1 "Auxillary Power 1"
+#define WIRE_BACKUP2 "Auxillary Power 2"
+#define WIRE_BEACON "Beacon"
+#define WIRE_BOLTS "Bolts"
+#define WIRE_BOOM "Boom"
+#define WIRE_CAMERA "Camera"
+#define WIRE_CONTRABAND "Contraband"
+#define WIRE_DELAY "Delay"
+#define WIRE_DISABLE "Disable"
+#define WIRE_DISARM "Disarm"
+#define WIRE_HACK "Hack"
+#define WIRE_IDSCAN "ID Scan"
+#define WIRE_INTERFACE "Interface"
+#define WIRE_LAWSYNC "AI Law Synchronization"
+#define WIRE_LIGHT "Bolt Lights"
+#define WIRE_LIMIT "Limiter"
+#define WIRE_LOADCHECK "Load Check"
+#define WIRE_LOCKDOWN "Lockdown"
+#define WIRE_MOTOR1 "Motor 1"
+#define WIRE_MOTOR2 "Motor 2"
+#define WIRE_OPEN "Open"
+#define WIRE_PANIC "Panic Siphon"
+#define WIRE_POWER "Power"
+#define WIRE_POWER1 "Main Power 1"
+#define WIRE_POWER2 "Main Power 2"
+#define WIRE_PROCEED "Proceed"
+#define WIRE_RX "Recieve"
+#define WIRE_SAFETY "Safety"
+#define WIRE_SHOCK "High Voltage Ground"
+#define WIRE_SIGNAL "Signal"
+#define WIRE_SPEAKER "Speaker"
+#define WIRE_STRENGTH "Strength"
+#define WIRE_THROW "Throw"
+#define WIRE_TIMING "Timing"
+#define WIRE_TX "Transmit"
+#define WIRE_UNBOLT "Unbolt"
+#define WIRE_ZAP "High Voltage Circuit"
+#define WIRE_ZAP1 "High Voltage Circuit 1"
+#define WIRE_ZAP2 "High Voltage Circuit 2"
diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm
index 65cef4fbc43..c0587d74481 100644
--- a/code/__HELPERS/global_lists.dm
+++ b/code/__HELPERS/global_lists.dm
@@ -27,6 +27,7 @@
init_sprite_accessory_subtypes(/datum/sprite_accessory/frills, frills_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/spines, spines_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/spines_animated, animated_spines_list)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/legs, legs_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/wings, r_wings_list,roundstart = TRUE)
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/mobs.dm b/code/__HELPERS/mobs.dm
index 0fcbb30ef6e..244229615b2 100644
--- a/code/__HELPERS/mobs.dm
+++ b/code/__HELPERS/mobs.dm
@@ -62,13 +62,15 @@
init_sprite_accessory_subtypes(/datum/sprite_accessory/frills, frills_list)
if(!spines_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/spines, spines_list)
+ if(!legs_list.len)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/legs, legs_list)
if(!body_markings_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/body_markings, body_markings_list)
if(!wings_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/wings, wings_list)
//For now we will always return none for tail_human and ears.
- return(list("mcolor" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"), "tail_lizard" = pick(tails_list_lizard), "tail_human" = "None", "wings" = "None", "snout" = pick(snouts_list), "horns" = pick(horns_list), "ears" = "None", "frills" = pick(frills_list), "spines" = pick(spines_list), "body_markings" = pick(body_markings_list)))
+ return(list("mcolor" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"), "tail_lizard" = pick(tails_list_lizard), "tail_human" = "None", "wings" = "None", "snout" = pick(snouts_list), "horns" = pick(horns_list), "ears" = "None", "frills" = pick(frills_list), "spines" = pick(spines_list), "body_markings" = pick(body_markings_list), "legs" = "Normal Legs"))
/proc/random_hair_style(gender)
switch(gender)
@@ -328,6 +330,24 @@ Proc for attack log creation, because really why not
if(H.dna && istype(H.dna.species, species_datum))
. = TRUE
+/proc/spawn_and_random_walk(spawn_type, target, amount, walk_chance=100, max_walk=3, always_max_walk=FALSE, admin_spawn=FALSE)
+ var/turf/T = get_turf(target)
+ var/step_count = 0
+ if(!T)
+ throw EXCEPTION("attempt to spawn atom type: [spawn_type] in nullspace")
+
+ for(var/j in 1 to amount)
+ var/atom/movable/X = new spawn_type(T)
+ X.admin_spawned = admin_spawn
+
+ if(always_max_walk || prob(walk_chance))
+ if(always_max_walk)
+ step_count = max_walk
+ else
+ step_count = rand(1, max_walk)
+
+ for(var/i in 1 to step_count)
+ step(X, pick(NORTH, SOUTH, EAST, WEST))
/proc/deadchat_broadcast(message, mob/follow_target=null, speaker_key=null, message_type=DEADCHAT_REGULAR)
for(var/mob/M in player_list)
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 8f9f98e82fe..d90ae1925bb 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -1006,65 +1006,6 @@ B --><-- A
*/
-//This is just so you can stop an orbit.
-//orbit() can run without it (swap orbiting for A)
-//but then you can never stop it and that's just silly.
-/atom/movable/var/atom/orbiting = null
-
-//A: atom to orbit
-//radius: range to orbit at, radius of the circle formed by orbiting
-//clockwise: whether you orbit clockwise or anti clockwise
-//rotation_speed: how fast to rotate
-//rotation_segments: the resolution of the orbit circle, less = a more block circle, this can be used to produce hexagons (6 segments) triangles (3 segments), and so on, 36 is the best default.
-//pre_rotation: Chooses to rotate src 90 degress towards the orbit dir (clockwise/anticlockwise), useful for things to go "head first" like ghosts
-//lockinorbit: Forces src to always be on A's turf, otherwise the orbit cancels when src gets too far away (eg: ghosts)
-
-/atom/movable/proc/orbit(atom/A, radius = 10, clockwise = FALSE, rotation_speed = 20, rotation_segments = 36, pre_rotation = TRUE, lockinorbit = FALSE)
- if(!istype(A))
- return
-
- if(orbiting)
- stop_orbit()
-
- orbiting = A
- var/matrix/initial_transform = matrix(transform)
- var/lastloc = loc
-
- //Head first!
- if(pre_rotation)
- var/matrix/M = matrix(transform)
- var/pre_rot = 90
- if(!clockwise)
- pre_rot = -90
- M.Turn(pre_rot)
- transform = M
-
- var/matrix/shift = matrix(transform)
- shift.Translate(0,radius)
- transform = shift
-
- SpinAnimation(rotation_speed, -1, clockwise, rotation_segments)
-
- //we stack the orbits up client side, so we can assign this back to normal server side without it breaking the orbit
- transform = initial_transform
- while(orbiting && orbiting == A && A.loc)
- var/targetloc = get_turf(A)
- if(!lockinorbit && loc != lastloc && loc != targetloc)
- break
- loc = targetloc
- lastloc = loc
- stoplag()
-
- if (orbiting == A) //make sure we haven't started orbiting something else.
- orbiting = null
- SpinAnimation(0,0)
-
-
-
-/atom/movable/proc/stop_orbit()
- orbiting = null
-
-
//Center's an image.
//Requires:
//The Image
@@ -1239,6 +1180,8 @@ B --><-- A
/proc/add_to_proximity_list(atom/A, range)
var/turf/T = get_turf(A)
+ if(!T || !A.loc)
+ throw EXCEPTION("Someone adding a prox sensor in nullspace")
var/list/L = block(locate(T.x - range, T.y - range, T.z), locate(T.x + range, T.y + range, T.z))
for(var/B in L)
var/turf/C = B
diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm
index dc4075cd2e3..b2448a401f7 100644
--- a/code/_globalvars/lists/flavor_misc.dm
+++ b/code/_globalvars/lists/flavor_misc.dm
@@ -24,6 +24,7 @@ var/global/list/snouts_list = list()
var/global/list/horns_list = list()
var/global/list/frills_list = list()
var/global/list/spines_list = list()
+var/global/list/legs_list = list()
var/global/list/animated_spines_list = list()
//Mutant Human bits
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/subsystem/minimap.dm b/code/controllers/subsystem/minimap.dm
index 679104bbc62..d651cabd498 100644
--- a/code/controllers/subsystem/minimap.dm
+++ b/code/controllers/subsystem/minimap.dm
@@ -73,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)
@@ -99,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
@@ -116,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)
@@ -137,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/orbit.dm b/code/controllers/subsystem/orbit.dm
new file mode 100644
index 00000000000..a66a575a6dd
--- /dev/null
+++ b/code/controllers/subsystem/orbit.dm
@@ -0,0 +1,50 @@
+var/datum/subsystem/orbit/SSorbit
+
+/datum/subsystem/orbit
+ name = "Orbits"
+ priority = 35
+ wait = 2
+ flags = SS_NO_INIT|SS_TICKER
+
+ var/list/currentrun = list()
+ var/list/processing = list()
+
+/datum/subsystem/orbit/New()
+ NEW_SS_GLOBAL(SSorbit)
+
+
+/datum/subsystem/orbit/stat_entry()
+ ..("P:[processing.len]")
+
+
+/datum/subsystem/orbit/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/datum/orbit/O = currentrun[currentrun.len]
+ currentrun.len--
+ if (!O)
+ processing -= O
+ if (MC_TICK_CHECK)
+ return
+ continue
+ if (!O.orbiter)
+ qdel(O)
+ if (MC_TICK_CHECK)
+ return
+ continue
+ if (O.lastprocess >= world.time) //we already checked recently
+ if (MC_TICK_CHECK)
+ return
+ continue
+ var/targetloc = get_turf(O.orbiting)
+ if (targetloc != O.lastloc || O.orbiter.loc != targetloc)
+ O.Check(targetloc)
+ if (MC_TICK_CHECK)
+ return
+
+
diff --git a/code/controllers/subsystem/spacedrift.dm b/code/controllers/subsystem/spacedrift.dm
index 51b8df01619..856f51ce7ac 100644
--- a/code/controllers/subsystem/spacedrift.dm
+++ b/code/controllers/subsystem/spacedrift.dm
@@ -32,8 +32,15 @@ var/datum/subsystem/spacedrift/SSspacedrift
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
@@ -43,7 +50,10 @@ var/datum/subsystem/spacedrift/SSspacedrift
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
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index cdc90a8bb3f..4294595a0a7 100644
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -221,21 +221,21 @@ var/datum/subsystem/ticker/ticker
//initialise our cinematic screen object
cinematic = new /obj/screen{icon='icons/effects/station_explosion.dmi';icon_state="station_intact";layer=21;mouse_opacity=0;screen_loc="1,0";}(src)
- var/obj/structure/bed/temp_buckle = new(src)
if(station_missed)
for(var/mob/M in mob_list)
- M.buckled = temp_buckle //buckles the mob so it can't do anything
+ M.notransform = TRUE //stop everything moving
if(M.client)
M.client.screen += cinematic //show every client the cinematic
else //nuke kills everyone on z-level 1 to prevent "hurr-durr I survived"
for(var/mob/M in mob_list)
- M.buckled = temp_buckle
if(M.client)
M.client.screen += cinematic
if(M.stat != DEAD)
var/turf/T = get_turf(M)
if(T && T.z==1)
M.death(0) //no mercy
+ else
+ M.notransform=TRUE //no moving for you
//Now animate the cinematic
switch(station_missed)
@@ -299,8 +299,8 @@ var/datum/subsystem/ticker/ticker
if(cinematic)
qdel(cinematic)
cinematic = null
- if(temp_buckle)
- qdel(temp_buckle)
+ for(var/mob/M in mob_list)
+ M.notransform = FALSE
return //Faster exit, since nothing happened
else //Station nuked (nuke,explosion,summary)
flick("intro_nuke",cinematic)
@@ -313,8 +313,8 @@ var/datum/subsystem/ticker/ticker
spawn(300)
if(cinematic)
qdel(cinematic) //end the cinematic
- if(temp_buckle)
- qdel(temp_buckle) //release everybody
+ for(var/mob/M in mob_list)
+ M.notransform = FALSE //gratz you survived
return
diff --git a/code/datums/diseases/advance/advance.dm b/code/datums/diseases/advance/advance.dm
index 8db25732ca9..bab3e068d96 100644
--- a/code/datums/diseases/advance/advance.dm
+++ b/code/datums/diseases/advance/advance.dm
@@ -182,7 +182,7 @@ var/list/advance_cures = list(
CRASH("We did not have any symptoms before generating properties.")
return
- var/list/properties = list("resistance" = 1, "stealth" = 1, "stage_rate" = 1, "transmittable" = 1, "severity" = 0)
+ var/list/properties = list("resistance" = 0, "stealth" = 0, "stage_rate" = 0, "transmittable" = 0, "severity" = 0)
for(var/datum/symptom/S in symptoms)
diff --git a/code/datums/diseases/advance/symptoms/damage_converter.dm b/code/datums/diseases/advance/symptoms/damage_converter.dm
index f9109df17c1..ab79e52eb87 100644
--- a/code/datums/diseases/advance/symptoms/damage_converter.dm
+++ b/code/datums/diseases/advance/symptoms/damage_converter.dm
@@ -46,6 +46,7 @@ Bonus
if(L.heal_damage(heal_amt, heal_amt))
C.update_damage_overlays()
C.adjustToxLoss(heal_amt*parts.len)
+ PoolOrNew(/obj/effect/overlay/temp/heal, list(C), "#FF3399")
return 1
/*
@@ -96,6 +97,7 @@ Bonus
for(var/obj/item/bodypart/L in parts)
L.heal_damage(get_damage, get_damage, 0)
+ PoolOrNew(/obj/effect/overlay/temp/heal, list(get_turf(M), "#FFFF00"))
M.adjustToxLoss(get_damage)
else
@@ -105,5 +107,4 @@ Bonus
M.adjustToxLoss(get_damage)
else
return
-
return 1
\ No newline at end of file
diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm
index 27bccaec3df..7c27837bab2 100644
--- a/code/datums/diseases/advance/symptoms/heal.dm
+++ b/code/datums/diseases/advance/symptoms/heal.dm
@@ -35,6 +35,8 @@ Bonus
/datum/symptom/heal/proc/Heal(mob/living/M, datum/disease/advance/A)
var/get_damage = (sqrt(20+A.totalStageSpeed())*(1+rand()))
+ if(M.toxloss > 0)
+ PoolOrNew(/obj/effect/overlay/temp/heal, list(get_turf(M), "#66FF99"))
M.adjustToxLoss(-get_damage)
return 1
@@ -72,6 +74,8 @@ Bonus
return
/datum/symptom/aptx/proc/Apoptosis(mob/living/M, datum/disease/advance/A)
+ if(M.toxloss > 0)
+ PoolOrNew(/obj/effect/overlay/temp/heal, list(get_turf(M), "#00FF00"))
var/get_damage = (sqrt(20+A.totalStageSpeed())*(2+rand()))
M.adjustToxLoss(-get_damage)
return 1
@@ -155,9 +159,15 @@ Bonus
var/stage_speed = max( 20 + A.totalStageSpeed(), 0)
var/stealth_amount = max( 16 + A.totalStealth(), 0)
var/amt_healed = (sqrt(stage_speed*(3+rand())))-(sqrt(stealth_amount*rand()))
+ if(M.brainloss > 0)
+ PoolOrNew(/obj/effect/overlay/temp/heal, list(M), "#DDDDDD")
M.adjustBrainLoss(-amt_healed)
//Non-power mutations, excluding race, so the virus does not force monkey -> human transformations.
var/list/unclean_mutations = (not_good_mutations|bad_mutations) - mutations_list[RACEMUT]
+ if(unclean_mutations.len)
+ PoolOrNew(/obj/effect/overlay/temp/heal, list(M), "#00FFFF")
M.dna.remove_mutation_group(unclean_mutations)
+ if(M.radiation > 0)
+ PoolOrNew(/obj/effect/overlay/temp/heal, list(M), "#88FFFF")
M.radiation = max(M.radiation - 3, 0)
return 1
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/outfit.dm b/code/datums/outfit.dm
index 96b0a27e834..8478b2bb46a 100644
--- a/code/datums/outfit.dm
+++ b/code/datums/outfit.dm
@@ -72,4 +72,5 @@
post_equip(H, visualsOnly)
+ H.update_body()
return 1
\ No newline at end of file
diff --git a/code/datums/wires/airalarm.dm b/code/datums/wires/airalarm.dm
index e682045cd7a..073b4610d11 100644
--- a/code/datums/wires/airalarm.dm
+++ b/code/datums/wires/airalarm.dm
@@ -1,5 +1,6 @@
/datum/wires/airalarm
holder_type = /obj/machinery/airalarm
+ proper_name = "Air Alarm"
/datum/wires/airalarm/New(atom/holder)
wires = list(
diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm
index f39494cefbc..6209aed807e 100644
--- a/code/datums/wires/airlock.dm
+++ b/code/datums/wires/airlock.dm
@@ -1,5 +1,6 @@
/datum/wires/airlock
holder_type = /obj/machinery/door/airlock
+ proper_name = "Airlock"
/datum/wires/airlock/secure
randomize = TRUE
diff --git a/code/datums/wires/apc.dm b/code/datums/wires/apc.dm
index 860cb37e086..8ef49216487 100644
--- a/code/datums/wires/apc.dm
+++ b/code/datums/wires/apc.dm
@@ -1,5 +1,6 @@
/datum/wires/apc
holder_type = /obj/machinery/power/apc
+ proper_name = "APC"
/datum/wires/apc/New(atom/holder)
wires = list(
diff --git a/code/datums/wires/autolathe.dm b/code/datums/wires/autolathe.dm
index 9aa1f60e6e1..7deba0a4ed1 100644
--- a/code/datums/wires/autolathe.dm
+++ b/code/datums/wires/autolathe.dm
@@ -1,5 +1,6 @@
/datum/wires/autolathe
holder_type = /obj/machinery/autolathe
+ proper_name = "Autolathe"
/datum/wires/autolathe/New(atom/holder)
wires = list(
diff --git a/code/datums/wires/explosive.dm b/code/datums/wires/explosive.dm
index 830aa7805a7..2ab4eb09b9b 100644
--- a/code/datums/wires/explosive.dm
+++ b/code/datums/wires/explosive.dm
@@ -14,6 +14,7 @@
/datum/wires/explosive/c4
holder_type = /obj/item/weapon/c4
+ randomize = TRUE //Same behaviour since no wire actually disarms it
/datum/wires/explosive/c4/interactable(mob/user)
var/obj/item/weapon/c4/P = holder
diff --git a/code/datums/wires/particle_accelerator.dm b/code/datums/wires/particle_accelerator.dm
index 939e93c4917..6c69742f9b1 100644
--- a/code/datums/wires/particle_accelerator.dm
+++ b/code/datums/wires/particle_accelerator.dm
@@ -1,5 +1,6 @@
/datum/wires/particle_accelerator/control_box
holder_type = /obj/machinery/particle_accelerator/control_box
+ proper_name = "Particle Accelerator"
/datum/wires/particle_accelerator/control_box/New(atom/holder)
wires = list(
diff --git a/code/datums/wires/radio.dm b/code/datums/wires/radio.dm
index 3db229b1878..298406c3718 100644
--- a/code/datums/wires/radio.dm
+++ b/code/datums/wires/radio.dm
@@ -1,5 +1,6 @@
/datum/wires/radio
holder_type = /obj/item/device/radio
+ proper_name = "Radio"
/datum/wires/radio/New(atom/holder)
wires = list(
diff --git a/code/datums/wires/suit_storage_unit.dm b/code/datums/wires/suit_storage_unit.dm
index d51e4c850b6..8be1c4be672 100644
--- a/code/datums/wires/suit_storage_unit.dm
+++ b/code/datums/wires/suit_storage_unit.dm
@@ -1,5 +1,6 @@
/datum/wires/suit_storage_unit
holder_type = /obj/machinery/suit_storage_unit
+ proper_name = "Suit Storage Unit"
/datum/wires/suit_storage_unit/New(atom/holder)
wires = list(
diff --git a/code/datums/wires/vending.dm b/code/datums/wires/vending.dm
index a067aa14f90..2e715eaea59 100644
--- a/code/datums/wires/vending.dm
+++ b/code/datums/wires/vending.dm
@@ -1,9 +1,10 @@
/datum/wires/vending
holder_type = /obj/machinery/vending
+ proper_name = "Vending Unit"
/datum/wires/vending/New(atom/holder)
wires = list(
- WIRE_THROW, WIRE_ELECTRIFY, WIRE_SPEAKER,
+ WIRE_THROW, WIRE_SHOCK, WIRE_SPEAKER,
WIRE_CONTRABAND, WIRE_IDSCAN
)
add_duds(1)
@@ -33,7 +34,7 @@
V.shoot_inventory = !V.shoot_inventory
if(WIRE_CONTRABAND)
V.extended_inventory = !V.extended_inventory
- if(WIRE_ELECTRIFY)
+ if(WIRE_SHOCK)
V.seconds_electrified = 30
if(WIRE_IDSCAN)
V.scan_id = !V.scan_id
@@ -47,7 +48,7 @@
V.shoot_inventory = !mend
if(WIRE_CONTRABAND)
V.extended_inventory = FALSE
- if(WIRE_ELECTRIFY)
+ if(WIRE_SHOCK)
if(mend)
V.seconds_electrified = FALSE
else
diff --git a/code/datums/wires/wires.dm b/code/datums/wires/wires.dm
index cf4b1f1e862..c65098f5b5c 100644
--- a/code/datums/wires/wires.dm
+++ b/code/datums/wires/wires.dm
@@ -17,6 +17,7 @@ var/list/wire_colors = list(
"yellow",
)
var/list/wire_color_directory = list()
+var/list/wire_name_directory = list()
/proc/is_wire_tool(obj/item/I)
if(istype(I, /obj/item/device/multitool))
@@ -35,12 +36,14 @@ var/list/wire_color_directory = list()
/datum/wires
var/atom/holder = null // The holder (atom that contains these wires).
var/holder_type = null // The holder's typepath (used to make wire colors common to all holders).
+ var/proper_name = "Unknown" // The display name for the wire set shown in station blueprints. Not used if randomize is true or it's an item NT wouldn't know about (Explosives/Nuke)
var/list/wires = list() // List of wires.
var/list/cut_wires = list() // List of wires that have been cut.
var/list/colors = list() // Dictionary of colors to wire.
var/list/assemblies = list() // List of attached assemblies.
var/randomize = 0 // If every instance of these wires should be random.
+ // Prevents wires from showing up in station blueprints
/datum/wires/New(atom/holder)
..()
@@ -55,6 +58,7 @@ var/list/wire_color_directory = list()
if(!wire_color_directory[holder_type])
randomize()
wire_color_directory[holder_type] = colors
+ wire_name_directory[holder_type] = proper_name
else
colors = wire_color_directory[holder_type]
@@ -65,7 +69,7 @@ var/list/wire_color_directory = list()
/datum/wires/proc/add_duds(duds)
while(duds)
- var/dud = "dud[--duds]"
+ var/dud = WIRE_DUD_PREFIX + "[--duds]"
if(dud in wires)
continue
wires += dud
diff --git a/code/game/area/Space_Station_13_areas.dm b/code/game/area/Space_Station_13_areas.dm
index 717556c6f52..56b43bbce1e 100644
--- a/code/game/area/Space_Station_13_areas.dm
+++ b/code/game/area/Space_Station_13_areas.dm
@@ -187,6 +187,7 @@ var/list/teleportlocs = list()
has_gravity = 1
noteleport = 1
blob_allowed = 0 //Should go without saying, no blobs should take over centcom as a win condition.
+ flags = NONE
/area/centcom/control
name = "Centcom Docks"
@@ -396,6 +397,7 @@ var/list/teleportlocs = list()
/area/atmos
name = "Atmospherics"
icon_state = "atmos"
+ flags = NONE
//Maintenance
/area/maintenance
@@ -617,11 +619,15 @@ var/list/teleportlocs = list()
/area/library
name = "Library"
icon_state = "library"
+ flags = NONE
+
+/area/chapel
+ icon_state = "chapel"
+ ambientsounds = list('sound/ambience/ambicha1.ogg','sound/ambience/ambicha2.ogg','sound/ambience/ambicha3.ogg','sound/ambience/ambicha4.ogg')
+ flags = NONE
/area/chapel/main
name = "Chapel"
- icon_state = "chapel"
- ambientsounds = list('sound/ambience/ambicha1.ogg','sound/ambience/ambicha2.ogg','sound/ambience/ambicha3.ogg','sound/ambience/ambicha4.ogg')
/area/chapel/office
name = "Chapel Office"
@@ -668,6 +674,7 @@ var/list/teleportlocs = list()
lighting_use_dynamic = DYNAMIC_LIGHTING_IFSTARLIGHT
valid_territory = 0
blob_allowed = FALSE
+ flags = NONE
/area/solar/auxport
name = "Fore Port Solar Array"
@@ -784,6 +791,7 @@ var/list/teleportlocs = list()
/area/medical/virology
name = "Virology"
icon_state = "virology"
+ flags = NONE
/area/medical/morgue
name = "Morgue"
@@ -957,6 +965,7 @@ var/list/teleportlocs = list()
/area/janitor/
name = "Custodial Closet"
icon_state = "janitor"
+ flags = NONE
/area/hydroponics
name = "Hydroponics"
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index 3be5b294dcc..83648e92d7a 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -23,6 +23,7 @@
'sound/ambience/ambigen8.ogg','sound/ambience/ambigen9.ogg',\
'sound/ambience/ambigen10.ogg','sound/ambience/ambigen11.ogg',\
'sound/ambience/ambigen12.ogg','sound/ambience/ambigen14.ogg')
+ flags = CAN_BE_DIRTY
/area/New()
icon_state = ""
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 8cb112ca8f8..b4dffaf8f51 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -13,13 +13,19 @@
var/verb_exclaim = "exclaims"
var/verb_yell = "yells"
var/inertia_dir = 0
- var/inertia_last_loc
+ 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
appearance_flags = TILE_BOUND
-
+/atom/movable/New()
+ ..()
+ if(loc)
+ loc.Entered(src)
/atom/movable/Move(atom/newloc, direct = 0)
if(!loc || !newloc) return 0
@@ -71,13 +77,13 @@
last_move = direct
setDir(direct)
-
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_dir)
+ if (!inertia_moving)
+ inertia_next_move = world.time + inertia_move_delay
newtonian_move(Dir)
return 1
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/antag_spawner.dm b/code/game/gamemodes/antag_spawner.dm
index 53f07c8ffd8..a94738c6dc4 100644
--- a/code/game/gamemodes/antag_spawner.dm
+++ b/code/game/gamemodes/antag_spawner.dm
@@ -56,7 +56,7 @@
if (used)
H << "You already used this contract!"
return
- var/list/candidates = get_candidates(ROLE_WIZARD)
+ var/list/candidates = pollCandidates("Do you want to play as a wizard's [href_list["school"]] apprentice?", ROLE_WIZARD, null, ROLE_WIZARD, 150)
if(candidates.len)
src.used = 1
var/client/C = pick(candidates)
@@ -149,8 +149,8 @@
if(!(check_usability(user)))
return
- var/list/nuke_candidates = get_candidates(ROLE_OPERATIVE, 3000, "operative")
- if(nuke_candidates.len > 0)
+ var/list/nuke_candidates = pollCandidates("Do you want to play as a syndicate [borg_to_spawn ? "[lowertext(borg_to_spawn)] cyborg":"operative"]?", ROLE_OPERATIVE, null, ROLE_OPERATIVE, 150)
+ if(nuke_candidates.len)
used = 1
var/client/C = pick(nuke_candidates)
spawn_antag(C, get_turf(src.loc), "syndieborg")
@@ -228,7 +228,7 @@
/obj/item/weapon/antag_spawner/slaughter_demon/attack_self(mob/user)
- var/list/demon_candidates = get_candidates(ROLE_ALIEN)
+ var/list/demon_candidates = pollCandidates("Do you want to play as a [initial(demon_type.name)]?", null, null, ROLE_ALIEN, 50)
if(user.z != 1)
user << "You should probably wait until you reach the station."
return
diff --git a/code/game/gamemodes/blob/blob.dm b/code/game/gamemodes/blob/blob.dm
index 8b0a671a1b4..1c4d8460291 100644
--- a/code/game/gamemodes/blob/blob.dm
+++ b/code/game/gamemodes/blob/blob.dm
@@ -32,7 +32,7 @@ var/list/blobs_legit = list() //used for win-score calculations, contains only b
var/blob_point_rate = 3
var/blob_base_starting_points = 80
- var/blobwincount = 350
+ var/blobwincount = 250
var/messagedelay_low = 2400 //in deciseconds
var/messagedelay_high = 3600 //blob report will be sent after a random value between these (minimum 4 minutes, maximum 6 minutes)
@@ -42,7 +42,8 @@ var/list/blobs_legit = list() //used for win-score calculations, contains only b
/datum/game_mode/blob/pre_setup()
cores_to_spawn = max(round(num_players()/players_per_core, 1), 1)
- blobwincount = initial(blobwincount) * cores_to_spawn
+ var/win_multiplier = 1 + (0.1 * cores_to_spawn)
+ blobwincount = initial(blobwincount) * cores_to_spawn * win_multiplier
for(var/j = 0, j < cores_to_spawn, j++)
if (!antag_candidates.len)
@@ -96,7 +97,7 @@ var/list/blobs_legit = list() //used for win-score calculations, contains only b
message_sent = TRUE
sleep(24000) //40 minutes, plus burst_delay*3(minimum of 6 minutes, maximum of 8)
-
- send_intercept(2) //if the blob has been alive this long, it's time to bomb it
+ if(!replacementmode)
+ send_intercept(2) //if the blob has been alive this long, it's time to bomb it
return ..()
diff --git a/code/game/gamemodes/blob/blobs/core.dm b/code/game/gamemodes/blob/blobs/core.dm
index db52561020b..8e0e4b036a1 100644
--- a/code/game/gamemodes/blob/blobs/core.dm
+++ b/code/game/gamemodes/blob/blobs/core.dm
@@ -62,6 +62,8 @@
overmind.update_health_hud()
/obj/effect/blob/core/Life()
+ if(qdeleted(src))
+ return
if(!overmind)
create_overmind()
else
@@ -91,7 +93,7 @@
var/list/candidates = list()
if(!new_overmind)
- candidates = get_candidates(ROLE_BLOB)
+ candidates = pollCandidatesForMob("Do you want to play as a blob overmind?", ROLE_BLOB, null, ROLE_BLOB, 50, src) //we're technically not a mob but behave similarly
if(candidates.len)
C = pick(candidates)
else
diff --git a/code/game/gamemodes/clock_cult/clock_items.dm b/code/game/gamemodes/clock_cult/clock_items.dm
index 3082e756b88..a69220d5fe5 100644
--- a/code/game/gamemodes/clock_cult/clock_items.dm
+++ b/code/game/gamemodes/clock_cult/clock_items.dm
@@ -568,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)
..()
@@ -599,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)
@@ -638,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))
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..7e733959ff4
--- /dev/null
+++ b/code/game/gamemodes/clock_cult/clock_powerdrain.dm
@@ -0,0 +1,56 @@
+//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
+ else if(prob(50))
+ burn_out()
+
+/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_scripture.dm b/code/game/gamemodes/clock_cult/clock_scripture.dm
index 0156767691a..ad2615e54a1 100644
--- a/code/game/gamemodes/clock_cult/clock_scripture.dm
+++ b/code/game/gamemodes/clock_cult/clock_scripture.dm
@@ -161,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()
..()
@@ -168,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
@@ -196,19 +201,21 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
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"
@@ -227,6 +234,7 @@ 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
@@ -380,7 +388,7 @@ 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."
@@ -435,6 +443,7 @@ 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
@@ -473,6 +482,7 @@ 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()
@@ -501,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
@@ -559,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
@@ -585,6 +556,7 @@ 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
@@ -642,7 +614,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
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]!", \
@@ -701,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
@@ -709,6 +681,7 @@ 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
@@ -718,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
@@ -757,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
@@ -985,6 +958,7 @@ 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()
@@ -1018,6 +992,8 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
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)
diff --git a/code/game/gamemodes/clock_cult/clock_structures.dm b/code/game/gamemodes/clock_cult/clock_structures.dm
index 923b83fe8ba..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)
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 0b69fc9baba..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",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)
@@ -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)
@@ -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 b96e2ee6697..e4311624dc5 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -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]: "
- 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 = "


| [C] | " + dat += "
According to \the [src], you are now in \"[html_encode(A.name)]\".
" - . += "You may make an amendment to the drawing.
" - if(!viewing) - . += "" + if(!legend) + var/area/A = get_area() + if(get_area_type() == AREA_STATION) + . += "According to \the [src], you are now in \"[html_encode(A.name)]\".
" + . += "You may make an amendment to the drawing.
" + . += "" + if(!viewing) + . += "" + else + . += "" + . += "" else - . += "" - . += "" + if(legend == TRUE) + . += "<< Back" + . += view_wire_devices(user); + else + //legend is a wireset + . += "<< Back" + . += view_wire_set(user, legend) var/datum/browser/popup = new(user, "blueprints", "[src]", 700, 500) popup.set_content(.) popup.open() @@ -84,6 +95,12 @@ if(get_area_type()!=AREA_STATION) return edit_area() + if(href_list["exit_legend"]) + legend = FALSE; + if(href_list["view_legend"]) + legend = TRUE; + if(href_list["view_wireset"]) + legend = href_list["view_wireset"]; if(href_list["view_blueprints"]) set_viewer(usr, "You flip the blueprints over to view the complex information diagram.") if(href_list["hide_blueprints"]) @@ -122,6 +139,7 @@ /obj/item/areaeditor/blueprints/dropped(mob/user) ..() clear_viewer() + legend = FALSE /obj/item/areaeditor/proc/get_area() @@ -149,6 +167,26 @@ return AREA_SPECIAL return AREA_STATION +/obj/item/areaeditor/blueprints/proc/view_wire_devices(mob/user) + var/message = "[wire_name_directory[device]]:" + for(var/Col in wire_color_directory[device]) + var/wire_name = wire_color_directory[device][Col] + if(!findtext(wire_name, WIRE_DUD_PREFIX)) //don't show duds + message += "
[Col]: [wire_name]
" + message += "" + return message + return "" + /proc/create_area(mob/living/creator) var/res = detect_room(get_turf(creator)) if(!istype(res,/list)) diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index b7ce1e4a737..91745ffed8e 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -50,6 +50,8 @@ var/global/list/obj/item/device/pda/PDAs = list() var/image/photo = null //Scanned photo + var/list/contained_item = list(/obj/item/weapon/pen, /obj/item/toy/crayon, /obj/item/weapon/lipstick, /obj/item/device/flashlight/pen, /obj/item/clothing/mask/cigarette) + var/obj/item/inserted_item //Used for pen, crayon, and lipstick insertion or removal. Same as above. /obj/item/device/pda/pickup(mob/user) ..() @@ -74,7 +76,7 @@ var/global/list/obj/item/device/pda/PDAs = list() PDAs += src if(default_cartridge) cartridge = new default_cartridge(src) - new /obj/item/weapon/pen(src) + inserted_item = new /obj/item/weapon/pen(src) /obj/item/device/pda/proc/update_label() name = "PDA-[owner] ([ownjob])" //Name generalisation @@ -314,10 +316,8 @@ var/global/list/obj/item/device/pda/PDAs = list() update_label() if("Eject")//Ejects the cart, only done from hub. if (!isnull(cartridge)) - var/turf/T = loc - if(ismob(T)) - T = T.loc - cartridge.loc = T + U.put_in_hands(cartridge) + U << "You remove [cartridge] from [src]." scanmode = 0 if (cartridge.radio) cartridge.radio.hostpda = null @@ -704,18 +704,16 @@ var/global/list/obj/item/device/pda/PDAs = list() return if (usr.canUseTopic(src)) - var/obj/item/weapon/pen/O = locate() in src - if(O) - if (istype(loc, /mob)) + if(inserted_item) + if(ismob(loc)) var/mob/M = loc - if(M.get_active_held_item() == null) - M.put_in_hands(O) - usr << "You remove \the [O] from \the [src]." - return - O.loc = get_turf(src) + M.put_in_hands(inserted_item) + else + inserted_item.forceMove(loc) + usr << "You remove \the [inserted_item] from \the [src]." + inserted_item = null else usr << "This PDA does not have a pen in it!" - /obj/item/device/pda/proc/id_check(mob/user, choice as num)//To check for IDs; 1 for in-pda use, 2 for out of pda use. if(choice == 1) if (id) @@ -775,15 +773,15 @@ var/global/list/obj/item/device/pda/PDAs = list() pai = C user << "You slot \the [C] into [src]." updateUsrDialog() - else if(istype(C, /obj/item/weapon/pen)) - var/obj/item/weapon/pen/O = locate() in src - if(O) - user << "There is already a pen in \the [src]!" + else if(is_type_in_list(C, contained_item)) //Checks if there is a pen + if(inserted_item) + user << "There is already \a [inserted_item] in \the [src]!" else if(!user.unEquip(C)) return - C.loc = src + C.forceMove(src) user << "You slide \the [C] into \the [src]." + inserted_item = C else if(istype(C, /obj/item/weapon/photo)) var/obj/item/weapon/photo/P = C photo = P.img 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/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/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm index 461d4cc2a33..c2615f28d7a 100644 --- a/code/game/objects/items/weapons/cigs_lighters.dm +++ b/code/game/objects/items/weapons/cigs_lighters.dm @@ -573,3 +573,177 @@ CIGARETTE PACKETS ARE IN FANCY.DM user << "You need to dry this first!" else ..() + +/////////////// +//VAPE NATION// +/////////////// +/obj/item/clothing/mask/vape + name = "E-Cigarette" + desc = "A classy and highly sophisticated electronic cigarette, for classy and dignified gentlemen. A warning label reads \"Warning: do not fill with flamable materials\""//<<< i'd vape to that. + icon = 'icons/obj/clothing/masks.dmi' + icon_state = null + item_state = null + var/chem_volume = 100 + var/vapetime = 0 //this so it won't puff out clouds every tick + var/screw = 0 // kinky + var/super = 0 //for the fattest vapes dude. + var/emagged = 0 //LET THE GRIEF BEGIN + +/obj/item/clothing/mask/vape/suicide_act(mob/user) + user.visible_message("[user] is puffin hard on dat vape, they trying to join the vape life on a whole notha plane!")//it doesn't give you cancer, it is cancer + return (TOXLOSS|OXYLOSS) + + +/obj/item/clothing/mask/vape/New(loc, var/param_color = null) + ..() + create_reagents(chem_volume) + reagents.set_reacting(FALSE) // so it doesn't react until you light it + reagents.add_reagent("nicotine", 50) + if(!icon_state) + if(!param_color) + param_color = pick("red","blue","black","white","green","purple","yellow","orange") + icon_state = "[param_color]_vape" + item_state = "[param_color]_vape" + +/obj/item/clothing/mask/vape/attackby(obj/item/O, mob/user, params) + if(istype(O, /obj/item/weapon/reagent_containers/glass)) + if(reagents.total_volume < chem_volume) + if(O.reagents.total_volume > 0) + O.reagents.trans_to(src,25) + user << "You add the contents of [O] to the [src]" + else + user << "The [O] is empty!" + else + user << "[src] can't hold anymore reagents!" + + if(istype(O, /obj/item/weapon/screwdriver)) + if(!screw) + screw = 1 + user << "You open the cap on the [src]" + if(super) + add_overlay(image(icon, "vapeopen_med")) + else + add_overlay(image(icon, "vapeopen_low")) + else + screw = 0 + user << "You close the cap on the [src]" + cut_overlays() + + if(istype(O, /obj/item/device/multitool)) + if(screw && !emagged)//also kinky + if(!super) + cut_overlays() + super = 1 + user << "You increase the voltage in the [src]" + add_overlay(image(icon, "vapeopen_med")) + else + cut_overlays() + super = 0 + user << "You decrease the voltage in the [src]" + add_overlay(image(icon, "vapeopen_low")) + + if(screw && emagged) + user << "The [name] can't be modified!" + + +/obj/item/clothing/mask/vape/emag_act(mob/user)// I WON'T REGRET WRITTING THIS, SURLY. + if(screw) + if(!emagged) + cut_overlays() + emagged = 1 + super = 0 + user << "You maximize the voltage in the [src]" + add_overlay(image(icon, "vapeopen_high")) + var/datum/effect_system/spark_spread/sp = new /datum/effect_system/spark_spread //for effect + sp.set_up(5, 1, src) + sp.start() + else + user << "The [name] is already emagged!" + else + user << "You need to open the cap to do that" + +/obj/item/clothing/mask/vape/attack_self(mob/user) + if(reagents.total_volume > 0) + user << "you empty [src] of all reagents." + reagents.clear_reagents() + return + +/obj/item/clothing/mask/vape/equipped(mob/user, slot) + if(slot == slot_wear_mask) + if(!screw) + user << "You start puffing on that dank vape" + reagents.set_reacting(TRUE) + START_PROCESSING(SSobj, src) + else //it will not start if the vape is opened. + user << "You need to close the cap first!" + +/obj/item/clothing/mask/vape/dropped(mob/user) + var/mob/living/carbon/C = user + if(C.get_item_by_slot(slot_wear_mask) == src) + reagents.set_reacting(FALSE) + STOP_PROCESSING(SSobj, src) + +/obj/item/clothing/mask/vape/proc/hand_reagents()//had to rename to avoid duplicate error + if(reagents.total_volume) + if(iscarbon(loc)) + var/mob/living/carbon/C = loc + if (src == C.wear_mask) // if it's in the human/monkey mouth, transfer reagents to the mob + var/fraction = min(REAGENTS_METABOLISM/reagents.total_volume, 1) //this will react instantly, making them a little more dangerous than cigarettes + reagents.reaction(C, INGEST, fraction) + reagents.trans_to(C, REAGENTS_METABOLISM) + if(reagents.get_reagent_amount("welding_fuel")) + //HOT STUFF + C.fire_stacks = 2 + C.IgniteMob() + + if(reagents.get_reagent_amount("plasma")) // the plasma explodes when exposed to fire + var/datum/effect_system/reagents_explosion/e = new() + e.set_up(round(reagents.get_reagent_amount("plasma") / 2.5, 1), get_turf(src), 0, 0) + e.start() + if(ismob(loc)) + var/mob/M = loc + M.unEquip(src, 1) + qdel(src) + return + reagents.remove_any(REAGENTS_METABOLISM) + +/obj/item/clothing/mask/vape/process() + var/mob/living/M = loc + + if(isliving(loc)) + M.IgniteMob() + + vapetime++ + + if(!reagents.total_volume) + if(ismob(loc)) + M << "The [name] is empty!" + STOP_PROCESSING(SSobj, src) + //it's reusable so it won't unequip when empty + return + //open flame removed because vapes are a closed system, they wont light anything on fire + + if(super && vapetime > 3)//Time to start puffing those fat vapes, yo. + var/datum/effect_system/smoke_spread/chem/s = new + s.set_up(reagents, 1, loc) + s.start() + vapetime = 0 + + if(emagged && vapetime > 3) + var/datum/effect_system/smoke_spread/chem/s = new + s.set_up(reagents, 4, loc) + s.start() + vapetime = 0 + if(prob(5))//small chance for the vape to break and deal damage if it's emagged + playsound(get_turf(src), 'sound/effects/pop_expl.ogg', 50, 0) + M.apply_damage(20, BURN, "head") + M.unEquip(src, 1) + M.Weaken(15, 1, 0) + qdel(src) + var/datum/effect_system/spark_spread/sp = new /datum/effect_system/spark_spread + sp.set_up(5, 1, src) + sp.start() + M << "The [name] suddenly explodes in your mouth!" + + if(reagents && reagents.total_volume) + hand_reagents() 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/grenades/spawnergrenade.dm b/code/game/objects/items/weapons/grenades/spawnergrenade.dm index 76536e7b21d..0af7877d3d7 100644 --- a/code/game/objects/items/weapons/grenades/spawnergrenade.dm +++ b/code/game/objects/items/weapons/grenades/spawnergrenade.dm @@ -17,15 +17,8 @@ for(var/mob/living/carbon/C in viewers(T, null)) C.flash_act() - for(var/i=1, i<=deliveryamt, i++) - var/atom/movable/x = new spawner_type - x.admin_spawned = admin_spawned - x.loc = T - if(prob(50)) - for(var/j = 1, j <= rand(1, 3), j++) - step(x, pick(NORTH,SOUTH,EAST,WEST)) - - // Spawn some hostile syndicate critters + // Spawn some hostile syndicate critters and spread them out + spawn_and_random_walk(spawner_type, T, deliveryamt, walk_chance=50, admin_spawn=admin_spawned) qdel(src) 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 b81a9cf75aa..596ed7b35b6 100644 --- a/code/game/objects/items/weapons/melee/misc.dm +++ b/code/game/objects/items/weapons/melee/misc.dm @@ -21,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" @@ -36,7 +47,7 @@ armour_penetration = 75 sharpness = IS_SHARP origin_tech = "combat=5" - attack_verb = list("lunged at", "stabbed") + attack_verb = list("slashed", "cut") hitsound = 'sound/weapons/rapierhit.ogg' materials = list(MAT_METAL = 1000) 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/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index 46dbaa39b36..0b248912b93 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -431,6 +431,23 @@ /obj/item/weapon/melee/sabre ) +/obj/item/weapon/storage/belt/sabre/examine(mob/user) + ..() + if(contents.len) + user << "Alt-click it to quickly draw the blade." + +/obj/item/weapon/storage/belt/sabre/AltClick(mob/user) + if(!ishuman(user) || !user.canUseTopic(src)) + return + if(contents.len) + var/obj/item/I = contents[1] + user.visible_message("[user] takes [I] out of [src].", "You take [I] out of [src].",\ + ) + user.put_in_hands(I) + update_icon() + else + user << "[src] is empty." + /obj/item/weapon/storage/belt/sabre/update_icon() icon_state = "sheath" item_state = "sheath" @@ -442,6 +459,7 @@ L.regenerate_icons() ..() + /obj/item/weapon/storage/belt/sabre/New() ..() new /obj/item/weapon/melee/sabre(src) 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/tools.dm b/code/game/objects/items/weapons/tools.dm index a48395a2cab..8b3816cc3dd 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -518,6 +518,7 @@ obj/item/weapon/weldingtool/proc/switched_off(mob/user) can_off_process = 1 light_intensity = 1 toolspeed = 2 + var/nextrefueltick = 0 /obj/item/weapon/weldingtool/experimental/brass name = "brass welding tool" @@ -526,20 +527,11 @@ obj/item/weapon/weldingtool/proc/switched_off(mob/user) item_state = "brasswelder" -//Proc to make the experimental welder generate fuel, optimized as fuck -Sieve -//i don't think this is actually used, yaaaaay -Pete -/obj/item/weapon/weldingtool/experimental/proc/fuel_gen() - if(!welding && !last_gen) - last_gen = 1 - reagents.add_reagent("welding_fuel",1) - spawn(10) - last_gen = 0 - /obj/item/weapon/weldingtool/experimental/process() ..() - if(reagents.total_volume < max_fuel) - fuel_gen() - + if(get_fuel() < max_fuel && nextrefueltick < world.time) + nextrefueltick = world.time + 10 + reagents.add_reagent("welding_fuel", 1) /* diff --git a/code/game/objects/items/weapons/vending_items.dm b/code/game/objects/items/weapons/vending_items.dm index 82fa5b64f5d..29b76b0a746 100644 --- a/code/game/objects/items/weapons/vending_items.dm +++ b/code/game/objects/items/weapons/vending_items.dm @@ -57,8 +57,8 @@ /obj/item/weapon/vending_refill/cigarette machine_name = "ShadyCigs Deluxe" icon_state = "refill_smoke" - charges = list(12, 1, 2)// of 36 standard, 3 contraband, 6 premium - init_charges = list(12, 1, 2) + charges = list(12, 3, 2)// of 36 standard, 9 contraband, 6 premium + init_charges = list(12, 3, 2) /obj/item/weapon/vending_refill/autodrobe machine_name = "AutoDrobe" @@ -69,5 +69,5 @@ /obj/item/weapon/vending_refill/clothing machine_name = "ClothesMate" icon_state = "refill_clothes" - charges = list(31, 3, 4)// of 101 standard, 7 contraband, 10 premium(?) - init_charges = list(31, 2, 4) + charges = list(31, 4, 4)// of 101 standard, 12 contraband, 10 premium(?) + init_charges = list(31, 4, 4) diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index 0702a80d30c..07d09d07451 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -82,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() ..() @@ -95,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." @@ -120,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() @@ -138,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() @@ -196,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 22e1473d8c4..89a48c7c22c 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -216,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() diff --git a/code/game/objects/structures/crates_lockers/closets/fitness.dm b/code/game/objects/structures/crates_lockers/closets/fitness.dm index d3e7f0156ea..7c01cb0b18f 100644 --- a/code/game/objects/structures/crates_lockers/closets/fitness.dm +++ b/code/game/objects/structures/crates_lockers/closets/fitness.dm @@ -11,6 +11,8 @@ new /obj/item/clothing/under/shorts/red(src) new /obj/item/clothing/under/shorts/blue(src) new /obj/item/clothing/under/shorts/green(src) + if(prob(3)) + new /obj/item/clothing/under/jabroni(src) /obj/structure/closet/boxinggloves 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/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 c6284f25056..91a840b1e3c 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -264,17 +264,8 @@ var/turf/T = get_turf(src) var/obj/structure/cable/C = T.get_cable_node() if(C) - var/mob/living/closest_mob - for(var/A in oview(src, 3)) - if(istype(A, /mob/living)) - var/dist = get_dist(src, A) - if(dist <= 3) - closest_mob = A - if(closest_mob) - 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) + playsound(src.loc, 'sound/magic/LightningShock.ogg', 100, 1, extrarange = 5) + tesla_zap(src, 3, C.powernet.avail * 0.01) //Zap for 1/100 of the amount of power. At a million watts in the grid, it will be as powerful as a tesla revolver shot. take_damage(tforce) /obj/structure/grille/storage_contents_dump_act(obj/item/weapon/storage/src_object, mob/user) 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/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 1d452fdc76c..9a9e11d2091 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -391,6 +391,7 @@ icon = 'icons/obj/smooth_structures/brass_table.dmi' icon_state = "brass_table" frame = /obj/structure/table_frame/brass + framestack = /obj/item/stack/sheet/brass buildstack = /obj/item/stack/sheet/brass framestackamount = 1 buildstackamount = 1 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 efcc4ec6499..9b076bcd5c2 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -516,19 +516,20 @@ /obj/structure/window/reinforced/clockwork/New(loc, direct) ..() + for(var/obj/item/I in debris) + debris -= I + qdel(I) 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 - for(var/obj/item/I in debris) - debris -= I - qdel(I) - debris += new/obj/item/stack/sheet/brass(src) + debris += new/obj/item/stack/sheet/brass(src, 2) change_construction_value(fulltile ? 3 : 2) /obj/structure/window/reinforced/clockwork/setDir(direct) diff --git a/code/game/turfs/simulated/dirtystation.dm b/code/game/turfs/simulated/dirtystation.dm index 2d65237947c..f3428beef4a 100644 --- a/code/game/turfs/simulated/dirtystation.dm +++ b/code/game/turfs/simulated/dirtystation.dm @@ -3,6 +3,8 @@ //Conspicuously not-recent versions of suspicious cleanables +//This file was made not awful by Xhuis on September 13, 2016 + /obj/effect/decal/cleanable/blood/old name = "dried blood" desc = "Looks like it's been here a while. Eew." @@ -10,7 +12,7 @@ /obj/effect/decal/cleanable/blood/old/New() ..() - icon_state += "-old" + icon_state += "-old" //This IS necessary because the parent /blood type uses icon randomization. blood_DNA["Non-human DNA"] = "A+" /obj/effect/decal/cleanable/blood/gibs/old @@ -20,8 +22,8 @@ /obj/effect/decal/cleanable/blood/gibs/old/New() ..() - icon_state += "-old" setDir(pick(1,2,4,8)) + icon_state += "-old" blood_DNA["Non-human DNA"] = "A+" /obj/effect/decal/cleanable/vomit/old @@ -36,26 +38,25 @@ name = "dusty robot debris" desc = "Looks like nobody has touched this in a while." - //Making the station dirty, one tile at a time. Called by master controller's setup_objects /turf/open/floor/proc/MakeDirty() if(prob(66)) //fastest possible exit 2/3 of the time return - // These look weird if you make them dirty - if(istype(src, /turf/open/floor/carpet) || istype(src, /turf/open/floor/grass) || istype(src, /turf/open/floor/plating/beach) || istype(src, /turf/open/floor/holofloor)|| istype(src, /turf/open/floor/plating/ironsand)) + if(!(flags & CAN_BE_DIRTY)) return if(locate(/obj/structure/grille) in contents) return - var/area/A = loc + var/area/A = get_area(src) - //zero dirt - if(!istype(A) || istype(A, /area/centcom) || istype(A, /area/holodeck) || istype(A, /area/library) || istype(A, /area/janitor) || istype(A, /area/chapel) || istype(A, /area/mine/explored) || istype(A, /area/mine/unexplored) || istype(A, /area/solar) || istype(A, /area/atmos) || istype(A, /area/medical/virology)) + if(A && !(A.flags & CAN_BE_DIRTY)) return + //The code below here isn't exactly optimal, but because of the individual decals that each area uses it's still applicable. + //high dirt - 1/3 if(istype(A, /area/toxins/test_area) || istype(A, /area/mine/production) || istype(A, /area/mine/living_quarters) || istype(A, /area/mine/north_outpost) || istype(A, /area/mine/west_outpost) || istype(A, /area/wreck) || istype(A, /area/derelict) || istype(A, /area/djstation)) new /obj/effect/decal/cleanable/dirt(src) //vanilla, but it works @@ -117,15 +118,16 @@ new /obj/effect/decal/cleanable/blood/gibs/old(src) else new /obj/effect/decal/cleanable/blood/old(src) - else - if(prob(30)) - if(istype(A, /area/medical/morgue)) - new /obj/item/weapon/ectoplasm(src) - else - new /obj/effect/decal/cleanable/vomit/old(src) + else if(prob(30)) + if(istype(A, /area/medical/morgue)) + new /obj/item/weapon/ectoplasm(src) + else + new /obj/effect/decal/cleanable/vomit/old(src) return if(istype(A, /area/toxins)) if(prob(20)) new /obj/effect/decal/cleanable/greenglow(src) //this cleans itself up but it might startle you when you see it. return + + return TRUE diff --git a/code/game/turfs/simulated/floor/fancy_floor.dm b/code/game/turfs/simulated/floor/fancy_floor.dm index edefd3b9f66..f4e9934dd27 100644 --- a/code/game/turfs/simulated/floor/fancy_floor.dm +++ b/code/game/turfs/simulated/floor/fancy_floor.dm @@ -29,9 +29,11 @@ /turf/open/floor/grass name = "grass patch" + desc = "You can't tell if this is real grass or just cheap plastic imitation." icon_state = "grass" floor_tile = /obj/item/stack/tile/grass broken_states = list("sand") + flags = NONE var/ore_type = /obj/item/weapon/ore/glass /turf/open/floor/grass/New() @@ -43,7 +45,8 @@ if(istype(C, /obj/item/weapon/shovel) && params) new ore_type(src) new ore_type(src) //Make some sand if you shovel grass - user << "You shovel [src]." + user.visible_message("[user] digs up [src].", "You uproot [src].") + playsound(src, 'sound/effects/shovel_dig.ogg', 50, 1) make_plating() if(..()) return @@ -83,13 +86,15 @@ /turf/open/floor/carpet - name = "Carpet" + name = "carpet" + desc = "Soft velvet carpeting. Feels good between your toes." icon = 'icons/turf/floors/carpet.dmi' icon_state = "carpet" floor_tile = /obj/item/stack/tile/carpet broken_states = list("damaged") smooth = SMOOTH_TRUE canSmoothWith = null + flags = NONE /turf/open/floor/carpet/New() ..() diff --git a/code/game/turfs/simulated/floor/light_floor.dm b/code/game/turfs/simulated/floor/light_floor.dm index e4895097777..da67666b25d 100644 --- a/code/game/turfs/simulated/floor/light_floor.dm +++ b/code/game/turfs/simulated/floor/light_floor.dm @@ -1,5 +1,6 @@ /turf/open/floor/light - name = "Light floor" + name = "light floor" + desc = "A wired glass tile embedded into the floor." luminosity = 5 icon_state = "light_on" floor_tile = /obj/item/stack/tile/light diff --git a/code/game/turfs/simulated/floor/misc_floor.dm b/code/game/turfs/simulated/floor/misc_floor.dm index 86f5d417620..a1d8ea6dfdf 100644 --- a/code/game/turfs/simulated/floor/misc_floor.dm +++ b/code/game/turfs/simulated/floor/misc_floor.dm @@ -1,5 +1,5 @@ /turf/open/floor/goonplaque - name = "Commemorative Plaque" + name = "commemorative plaque" icon_state = "plaque" desc = "\"This is a plaque in honour of our comrades on the G4407 Stations. Hopefully TG4407 model can live up to your fame and fortune.\" Scratched in beneath that is a crude image of a meteor and a spaceman. The spaceman is laughing. The meteor is exploding." floor_tile = /obj/item/stack/tile/plasteel @@ -27,35 +27,42 @@ floor_tile = /obj/item/stack/tile/plasteel /turf/open/floor/plating/beach - name = "Beach" + name = "beach" icon = 'icons/misc/beach.dmi' + flags = NONE /turf/open/floor/plating/beach/ex_act(severity, target) contents_explosion(severity, target) /turf/open/floor/plating/beach/sand - name = "Sand" + name = "sand" + desc = "Surf's up." icon_state = "sand" baseturf = /turf/open/floor/plating/beach/sand /turf/open/floor/plating/beach/coastline_t - name = "Coastline" + name = "coastline" + desc = "Tide's high tonight. Charge your batons." icon_state = "sandwater_t" baseturf = /turf/open/floor/plating/beach/coastline_t /turf/open/floor/plating/beach/coastline_b - name = "Coastline" + name = "coastline" icon_state = "sandwater_b" baseturf = /turf/open/floor/plating/beach/coastline_b /turf/open/floor/plating/beach/water - name = "Water" + name = "water" + desc = "You get the feeling that nobody's bothered to actually make this water functional..." icon_state = "water" baseturf = /turf/open/floor/plating/beach/water +/turf/open/floor/plating/ironsand + name = "iron sand" + desc = "Like sand, but more metal." + /turf/open/floor/plating/ironsand/New() ..() - name = "Iron Sand" icon_state = "ironsand[rand(1,15)]" /turf/open/floor/plating/ironsand/burn_tile() 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/turf.dm b/code/game/turfs/turf.dm index 4a73e76ba90..2c4c0577749 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -13,7 +13,7 @@ var/PathNode/PNode = null //associated PathNode in the A* algorithm - flags = 0 + flags = CAN_BE_DIRTY var/list/proximity_checkers = list() 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 += "| Red Deity | ||
| Red Deity: [M.real_name][M.client ? "" : " (No Client)"][M.stat == 2 ? " (DEAD)" : ""] | " - dat += "PM | " - dat += "FLW |
| Blue Deity | ||
| Blue Deity: [M.real_name][M.client ? "" : " (No Client)"][M.stat == 2 ? " (DEAD)" : ""] | " - dat += "PM | " - dat += "FLW |
| Red Deity Prophets | ||
| Red Deity Prophet: [M.real_name][M.client ? "" : " (No Client)"][M.stat == 2 ? " (DEAD)" : ""] | " - dat += "PM | " - dat += "FLW |
| Blue Deity Prophets | ||
| Blue Deity Prophet: [M.real_name][M.client ? "" : " (No Client)"][M.stat == 2 ? " (DEAD)" : ""] | " - dat += "PM | " - dat += "FLW |
| Red Deity Followers | ||
| Red Deity Followers: [M.real_name][M.client ? "" : " (No Client)"][M.stat == 2 ? " (DEAD)" : ""] | " - dat += "PM | " - dat += "FLW |
| Blue Deity Followers | ||
| Blue Deity Followers: [M.real_name][M.client ? "" : " (No Client)"][M.stat == 2 ? " (DEAD)" : ""] | " - dat += "PM | " - dat += "FLW |
| Traitors | " + dat += " | "
- dat += "Alien/Mutant Color" + dat += "Mutant Color" dat += " Change" @@ -299,7 +301,14 @@ var/list/preferences_datums = list() dat += "[features["body_markings"]] " dat += " | "
+ if("legs" in pref_species.mutant_bodyparts)
+ dat += ""
+ dat += "Legs" + + dat += "[features["legs"]]" + + dat += " | "
if(config.mutant_humans)
if("tail_human" in pref_species.mutant_bodyparts)
@@ -986,6 +995,12 @@ var/list/preferences_datums = list()
if(new_body_markings)
features["body_markings"] = new_body_markings
+ if("legs")
+ var/new_legs
+ new_legs = input(user, "Choose your character's legs:", "Character Preference") as null|anything in legs_list
+ if(new_legs)
+ features["legs"] = new_legs
+
if("s_tone")
var/new_s_tone = input(user, "Choose your character's skin-tone:", "Character Preference") as null|anything in skin_tones
if(new_s_tone)
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index 5042ae817ba..ee624a6c99f 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -2,7 +2,7 @@
#define SAVEFILE_VERSION_MIN 10
//This is the current version, anything below this will attempt to update (if it's not obsolete)
-#define SAVEFILE_VERSION_MAX 16
+#define SAVEFILE_VERSION_MAX 17
/*
SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn
This proc checks if the current directory of the savefile S needs updating
@@ -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
@@ -123,7 +123,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
joblessrole = BERANDOMJOB
else
joblessrole = BEASSISTANT
-
+ if(current_version < 17)
+ features["legs"] = "Normal Legs"
+
/datum/preferences/proc/load_path(ckey,filename="preferences.sav")
@@ -171,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)
@@ -222,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
@@ -283,6 +287,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["feature_lizard_frills"] >> features["frills"]
S["feature_lizard_spines"] >> features["spines"]
S["feature_lizard_body_markings"] >> features["body_markings"]
+ S["feature_lizard_legs"] >> features["legs"]
if(!config.mutant_humans)
features["tail_human"] = "none"
features["ears"] = "none"
@@ -348,6 +353,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
features["frills"] = sanitize_inlist(features["frills"], frills_list)
features["spines"] = sanitize_inlist(features["spines"], spines_list)
features["body_markings"] = sanitize_inlist(features["body_markings"], body_markings_list)
+ features["feature_lizard_legs"] = sanitize_inlist(features["legs"], legs_list, "Normal Legs")
joblessrole = sanitize_integer(joblessrole, 1, 3, initial(joblessrole))
job_civilian_high = sanitize_integer(job_civilian_high, 0, 65535, initial(job_civilian_high))
@@ -399,6 +405,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["feature_lizard_frills"] << features["frills"]
S["feature_lizard_spines"] << features["spines"]
S["feature_lizard_body_markings"] << features["body_markings"]
+ S["feature_lizard_legs"] << features["legs"]
S["clown_name"] << custom_names["clown"]
S["mime_name"] << custom_names["mime"]
S["ai_name"] << custom_names["ai"]
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index 3a848e8d52a..d347342d22c 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -368,9 +368,10 @@ BLIND // can't see anything
var/random_sensor = 1
var/sensor_mode = 0 /* 1 = Report living/dead, 2 = Report detailed damages, 3 = Report location */
var/can_adjust = 1
- var/adjusted = 0
+ var/adjusted = NORMAL_STYLE
var/alt_covers_chest = 0 // for adjusted/rolled-down jumpsuits, 0 = exposes chest and arms, 1 = exposes arms only
var/obj/item/clothing/tie/hastie = null
+ var/mutantrace_variation = NO_MUTANTRACE_VARIATION //Are there special sprites for specific situations? Don't use this unless you need to.
/obj/item/clothing/under/worn_overlays(var/isinhands = FALSE)
. = list()
@@ -393,9 +394,24 @@ BLIND // can't see anything
if(random_sensor)
//make the sensor mode favor higher levels, except coords.
sensor_mode = pick(0, 1, 1, 2, 2, 2, 3, 3)
- adjusted = 0
+ adjusted = NORMAL_STYLE
..()
+/obj/item/clothing/under/equipped(mob/user, slot)
+ ..()
+ if(adjusted)
+ adjusted = NORMAL_STYLE
+ fitted = initial(fitted)
+ if(!alt_covers_chest)
+ body_parts_covered |= CHEST
+
+ if(mutantrace_variation && ishuman(user))
+ var/mob/living/carbon/human/H = user
+ if(DIGITIGRADE in H.dna.species.specflags)
+ adjusted = DIGITIGRADE_STYLE
+ H.update_inv_w_uniform()
+
+
/obj/item/clothing/under/attackby(obj/item/I, mob/user, params)
if(!attachTie(I, user))
..()
@@ -532,25 +548,29 @@ BLIND // can't see anything
usr << "You adjust the suit to wear it more casually."
else
usr << "You adjust the suit back to normal."
- usr.update_inv_w_uniform()
+ if(ishuman(usr))
+ var/mob/living/carbon/human/H = usr
+ H.update_inv_w_uniform()
+ H.update_body()
/obj/item/clothing/under/proc/toggle_jumpsuit_adjust()
+ if(adjusted == DIGITIGRADE_STYLE)
+ return
adjusted = !adjusted
if(adjusted)
if(fitted != FEMALE_UNIFORM_TOP)
fitted = NO_FEMALE_UNIFORM
- if (alt_covers_chest) // for the special snowflake suits that don't expose the chest when adjusted
- body_parts_covered = CHEST|GROIN|LEGS
- else
- body_parts_covered = GROIN|LEGS
+ if(!alt_covers_chest) // for the special snowflake suits that expose the chest when adjusted
+ body_parts_covered &= ~CHEST
else
fitted = initial(fitted)
- body_parts_covered = CHEST|GROIN|LEGS|ARMS
+ if(!alt_covers_chest)
+ body_parts_covered |= CHEST
return adjusted
/obj/item/clothing/under/examine(mob/user)
..()
- if(src.adjusted)
+ if(src.adjusted == ALT_STYLE)
user << "Alt-click on [src] to wear it normally."
else
user << "Alt-click on [src] to wear it casually."
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 2c60fbb8900..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)
@@ -494,6 +498,7 @@
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
diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm
index 5c65c32af97..98c4e5e2d7d 100644
--- a/code/modules/clothing/suits/miscellaneous.dm
+++ b/code/modules/clothing/suits/miscellaneous.dm
@@ -321,6 +321,12 @@
icon_state = "nerdshirt"
item_state = "nerdshirt"
+/obj/item/clothing/suit/vapeshirt //wearing this is asking to get beat.
+ name = "Vape Naysh shirt"
+ desc = "A cheap white T-shirt with a big tacky \"VN\" on the front, Why would you wear this unironicly?"
+ icon_state = "vapeshirt"
+ item_state = "vapeshirt"
+
/obj/item/clothing/suit/jacket
name = "bomber jacket"
desc = "Aviators not included."
diff --git a/code/modules/clothing/suits/wiz_robe.dm b/code/modules/clothing/suits/wiz_robe.dm
index 4d71d282588..980c9603357 100644
--- a/code/modules/clothing/suits/wiz_robe.dm
+++ b/code/modules/clothing/suits/wiz_robe.dm
@@ -150,7 +150,7 @@
burn_state = FLAMMABLE
/obj/item/clothing/suit/wizrobe/paper
- name = "papier-mâché robe"
+ name = "papier-mâché robe"
desc = "A robe held together by various bits of clear-tape and paste."
icon_state = "wizard-paper"
item_state = "wizrobe"
@@ -199,6 +199,7 @@
max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/wizard
armor = list(melee = 30, bullet = 20, laser = 20, energy = 20, bomb = 20, bio = 20, rad = 20)
+ unacidable = 1
slowdown = 0
/obj/item/clothing/head/helmet/space/hardsuit/shielded/wizard
@@ -209,6 +210,7 @@
min_cold_protection_temperature = ARMOR_MIN_TEMP_PROTECT
max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT
armor = list(melee = 30, bullet = 20, laser = 20, energy = 20, bomb = 20, bio = 20, rad = 20)
+ unacidable = 1
actions_types = null //No inbuilt light
/obj/item/clothing/head/helmet/space/hardsuit/shielded/wizard/attack_self(mob/user)
diff --git a/code/modules/clothing/under/jobs/civilian.dm b/code/modules/clothing/under/jobs/civilian.dm
index 6b6bad92bec..2f23d7a4eff 100644
--- a/code/modules/clothing/under/jobs/civilian.dm
+++ b/code/modules/clothing/under/jobs/civilian.dm
@@ -31,6 +31,8 @@
icon_state = "cargotech"
item_state = "lb_suit"
item_color = "cargo"
+ body_parts_covered = CHEST|GROIN|ARMS
+ mutantrace_variation = MUTANTRACE_VARIATION
/obj/item/clothing/under/rank/chaplain
diff --git a/code/modules/clothing/under/shorts.dm b/code/modules/clothing/under/shorts.dm
index 23e98a040c6..0da22fc678e 100644
--- a/code/modules/clothing/under/shorts.dm
+++ b/code/modules/clothing/under/shorts.dm
@@ -4,6 +4,7 @@
gender = PLURAL
body_parts_covered = GROIN
fitted = NO_FEMALE_UNIFORM
+ mutantrace_variation = MUTANTRACE_VARIATION
can_adjust = 0
/obj/item/clothing/under/shorts/red
diff --git a/code/modules/events/holiday/halloween.dm b/code/modules/events/holiday/halloween.dm
index 107c8f10920..b3f97136cb9 100644
--- a/code/modules/events/holiday/halloween.dm
+++ b/code/modules/events/holiday/halloween.dm
@@ -18,6 +18,9 @@
for(var/mob/living/simple_animal/pet/dog/corgi/Ian/Ian in mob_list)
Ian.place_on_head(new /obj/item/weapon/bedsheet(Ian))
+ for(var/mob/living/simple_animal/parrot/Poly/Poly in mob_list)
+ new /mob/living/simple_animal/parrot/Poly/ghost(Poly.loc)
+ qdel(Poly)
/datum/round_event/spooky/announce()
priority_announce(pick("RATTLE ME BONES!","THE RIDE NEVER ENDS!", "A SKELETON POPS OUT!", "SPOOKY SCARY SKELETONS!", "CREWMEMBERS BEWARE, YOU'RE IN FOR A SCARE!") , "THE CALL IS COMING FROM INSIDE THE HOUSE")
@@ -68,7 +71,7 @@
/obj/item/weapon/storage/spooky
name = "trick-o-treat bag"
- desc = "A Pumpkin shaped bag that holds all sorts of goodies!"
+ desc = "A pumpkin-shaped bag that holds all sorts of goodies!"
icon = 'icons/obj/halloween_items.dmi'
icon_state = "treatbag"
@@ -79,5 +82,7 @@
/obj/item/weapon/reagent_containers/food/snacks/sugarcookie/spookycoffin,
/obj/item/weapon/reagent_containers/food/snacks/candy_corn,
/obj/item/weapon/reagent_containers/food/snacks/candy,
- /obj/item/weapon/reagent_containers/food/snacks/chocolatebar)
+ /obj/item/weapon/reagent_containers/food/snacks/candiedapple,
+ /obj/item/weapon/reagent_containers/food/snacks/chocolatebar,
+ /obj/item/organ/brain ) // OH GOD THIS ISN'T CANDY!
new type(src)
diff --git a/code/modules/events/shuttle_loan.dm b/code/modules/events/shuttle_loan.dm
index 4649f851152..328e8af3268 100644
--- a/code/modules/events/shuttle_loan.dm
+++ b/code/modules/events/shuttle_loan.dm
@@ -3,6 +3,7 @@
#define SPIDER_GIFT 3
#define DEPARTMENT_RESUPPLY 4
#define ANTIDOTE_NEEDED 5
+#define PIZZA_DELIVERY 6
/datum/round_event_control/shuttle_loan
@@ -20,7 +21,7 @@
var/thanks_msg = "The cargo shuttle should return in five minutes. Have some supply points for your trouble."
/datum/round_event/shuttle_loan/start()
- dispatch_type = pick(HIJACK_SYNDIE, RUSKY_PARTY, SPIDER_GIFT, DEPARTMENT_RESUPPLY, ANTIDOTE_NEEDED)
+ dispatch_type = pick(HIJACK_SYNDIE, RUSKY_PARTY, SPIDER_GIFT, DEPARTMENT_RESUPPLY, ANTIDOTE_NEEDED, PIZZA_DELIVERY)
/datum/round_event/shuttle_loan/announce()
SSshuttle.shuttle_loan = src
@@ -37,6 +38,8 @@
bonus_points = 0
if(ANTIDOTE_NEEDED)
priority_announce("Cargo: Your station has been chosen for an epidemiological research project. Send us your cargo shuttle to receive your research samples.", "Centcom Research Initiatives")
+ if (PIZZA_DELIVERY)
+ priority_announce("Cargo: It looks like a neighbouring station accidentally delivered their pizza to you instead", "Centcom Spacepizza Division")
/datum/round_event/shuttle_loan/proc/loan_shuttle()
priority_announce(thanks_msg, "Cargo shuttle commandeered by Centcom.")
@@ -60,6 +63,8 @@
SSshuttle.centcom_message += "Department resupply incoming."
if(ANTIDOTE_NEEDED)
SSshuttle.centcom_message += "Virus samples incoming."
+ if(PIZZA_DELIVERY)
+ SSshuttle.centcom_message += "Pizza delivery for [world.name]"
/datum/round_event/shuttle_loan/tick()
if(dispatched)
@@ -165,6 +170,16 @@
for(var/i in 1 to 5)
var/decal = pick(/obj/effect/decal/cleanable/flour, /obj/effect/decal/cleanable/robot_debris, /obj/effect/decal/cleanable/oil)
new decal(pick_n_take(empty_shuttle_turfs))
+ if(PIZZA_DELIVERY)
+ shuttle_spawns.Add(/obj/item/pizzabox/margherita)
+ shuttle_spawns.Add(/obj/item/pizzabox/margherita)
+ shuttle_spawns.Add(/obj/item/pizzabox/meat)
+ shuttle_spawns.Add(/obj/item/pizzabox/meat)
+ shuttle_spawns.Add(/obj/item/pizzabox/vegetable)
+ if(prob(10))
+ shuttle_spawns.Add(/obj/item/pizzabox/bomb)
+ else
+ shuttle_spawns.Add(/obj/item/pizzabox/margherita)
var/false_positive = 0
while(shuttle_spawns.len && empty_shuttle_turfs.len)
@@ -181,3 +196,4 @@
#undef SPIDER_GIFT
#undef DEPARTMENT_RESUPPLY
#undef ANTIDOTE_NEEDED
+#undef PIZZA_DELIVERY
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/food/snacks_other.dm b/code/modules/food_and_drinks/food/snacks_other.dm
index babef429153..a257234425d 100644
--- a/code/modules/food_and_drinks/food/snacks_other.dm
+++ b/code/modules/food_and_drinks/food/snacks_other.dm
@@ -315,4 +315,14 @@
desc = "The former skull of a damned human, filled with goliath meat. It has a decorative lava pool made of ketchup and hotsauce."
icon_state = "stuffed_legion"
bonus_reagents = list("vitamin" = 3, "capsaicin" = 1, "tricordrazine" = 5)
- list_reagents = list("nutriment" = 5, "vitamin" = 5, "capsaicin" = 2, "tricordrazine" = 10,)
\ No newline at end of file
+ list_reagents = list("nutriment" = 5, "vitamin" = 5, "capsaicin" = 2, "tricordrazine" = 10,)
+
+
+/obj/item/weapon/reagent_containers/food/snacks/powercrepe
+ name = "Powercrepe"
+ desc = "With great power, comes great crepes. It looks like a pancake filled with jelly but packs quite a punch."
+ icon_state = "powercrepe"
+ bonus_reagents = list("nutriment" = 5, "vitamin" = 3, "iron" = 10)
+ list_reagents = list("nutriment" = 10, "vitamin" = 5, "cherryjelly" = 5)
+ force = 15
+ w_class = 4
\ No newline at end of file
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/food_and_drinks/recipes/tablecraft/recipes_misc.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm
index 2127fa29d33..de9861bb80d 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm
@@ -259,7 +259,7 @@
category = CAT_MISCFOOD
-/datum/crafting_recipe/stuffedlegion
+/datum/crafting_recipe/food/stuffedlegion
name = "Stuffed legion"
time = 40
reqs = list(
@@ -271,7 +271,8 @@
result = /obj/item/weapon/reagent_containers/food/snacks/stuffedlegion
category = CAT_MISCFOOD
-/datum/crafting_recipe/lizardwine
+
+/datum/crafting_recipe/food/lizardwine
name = "Lizard wine"
time = 40
reqs = list(
@@ -280,3 +281,17 @@
)
result = /obj/item/weapon/reagent_containers/food/drinks/bottle/lizardwine
category = CAT_MISCFOOD
+
+
+/datum/crafting_recipe/food/powercrepe
+ name = "Powercrepe"
+ time = 40
+ reqs = list(
+ /obj/item/weapon/reagent_containers/food/snacks/flatdough = 1,
+ /datum/reagent/consumable/milk = 1,
+ /datum/reagent/consumable/cherryjelly = 5,
+ /obj/item/weapon/stock_parts/cell/super =1,
+ /obj/item/weapon/melee/sabre = 1
+ )
+ result = /obj/item/weapon/reagent_containers/food/snacks/powercrepe
+ category = CAT_MISCFOOD
diff --git a/code/modules/holodeck/areas.dm b/code/modules/holodeck/areas.dm
index cd6a74581be..3e7f4d2c825 100644
--- a/code/modules/holodeck/areas.dm
+++ b/code/modules/holodeck/areas.dm
@@ -3,6 +3,7 @@
icon_state = "Holodeck"
luminosity = 1
lighting_use_dynamic = 0
+ flags = 0
var/obj/machinery/computer/holodeck/linked
var/restricted = 0 // if true, program goes on emag list
diff --git a/code/modules/holodeck/turfs.dm b/code/modules/holodeck/turfs.dm
index ed2021bc5f4..1a81a053890 100644
--- a/code/modules/holodeck/turfs.dm
+++ b/code/modules/holodeck/turfs.dm
@@ -3,16 +3,17 @@
thermal_conductivity = 0
broken_states = list("engine")
burnt_states = list("engine")
+ flags = NONE
-/turf/open/floor/holofloor/attackby(obj/item/weapon/W as obj, mob/user as mob)
+/turf/open/floor/holofloor/attackby(obj/item/I, mob/living/user)
return // HOLOFLOOR DOES NOT GIVE A FUCK
/turf/open/floor/holofloor/plating
- name = "Holodeck Projector Floor"
+ name = "holodeck projector floor"
icon_state = "engine"
/turf/open/floor/holofloor/plating/burnmix
- name = "Burn-mix Floor"
+ name = "burn-mix floor"
initial_gas_mix = "o2=2500;plasma=5000;TEMP=370"
/turf/open/floor/holofloor/grass
@@ -38,7 +39,7 @@
icon_state = "water"
/turf/open/floor/holofloor/asteroid
- name = "Asteroid"
+ name = "asteroid"
icon_state = "asteroid0"
/turf/open/floor/holofloor/asteroid/New()
@@ -55,7 +56,7 @@
..()
/turf/open/floor/holofloor/hyperspace
- name = "Hyperspace"
+ name = "hyperspace"
icon = 'icons/turf/space.dmi'
icon_state = "speedspace_ew_1"
@@ -68,7 +69,7 @@
icon_state = "speedspace_ns_[(x + 5*y + (y%2+1)*7)%15+1]"
/turf/open/floor/holofloor/carpet
- name = "Carpet"
+ name = "carpet"
desc = "Electrically inviting."
icon = 'icons/turf/floors/carpet.dmi'
icon_state = "carpet"
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 c17e682949e..2545d47892c 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)
@@ -95,7 +95,7 @@
"
if(wisp.orbiting)
- var/atom/A = wisp.orbiting
+ var/atom/A = wisp.orbiting.orbiting
if(istype(A, /mob/living))
var/mob/living/M = A
M.sight &= ~SEE_MOBS
@@ -534,8 +534,15 @@
var/turf/T = get_turf(src)
var/list/contents = T.GetAllContents()
var/mob/dead/observer/current_spirits = list()
- for(var/mob/dead/observer/G in dead_mob_list)
- if(G.orbiting in contents)
+ var/list/orbiters = list()
+ for(var/thing in contents)
+ var/atom/A = thing
+ if (A.orbiters)
+ orbiters += A.orbiters
+
+ for(var/thing in orbiters)
+ if (isobserver(thing))
+ var/mob/dead/observer/G = thing
ghost_counter++
G.invisibility = 0
current_spirits |= G
@@ -579,7 +586,7 @@
switch(random)
if(1)
user << "Your appearence morphs to that of a very small humanoid ash dragon! You get to look like a freak without the cool abilities."
- H.dna.features = list("mcolor" = "A02720", "tail_lizard" = "Dark Tiger", "tail_human" = "None", "snout" = "Sharp", "horns" = "Curled", "ears" = "None", "wings" = "None", "frills" = "None", "spines" = "Long", "body_markings" = "Dark Tiger Body")
+ H.dna.features = list("mcolor" = "A02720", "tail_lizard" = "Dark Tiger", "tail_human" = "None", "snout" = "Sharp", "horns" = "Curled", "ears" = "None", "wings" = "None", "frills" = "None", "spines" = "Long", "body_markings" = "Dark Tiger Body", "legs" = "Digitigrade Legs")
H.eye_color = "fee5a3"
H.set_species(/datum/species/lizard)
if(2)
@@ -704,15 +711,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_areas.dm b/code/modules/mining/mine_areas.dm
index 10dbc16c516..9d133fe1b74 100644
--- a/code/modules/mining/mine_areas.dm
+++ b/code/modules/mining/mine_areas.dm
@@ -16,6 +16,7 @@
power_light = 0
outdoors = 1
ambientsounds = list('sound/ambience/ambimine.ogg')
+ flags = NONE
/area/mine/unexplored
name = "Mine"
@@ -29,12 +30,13 @@
power_light = 0
outdoors = 1
ambientsounds = list('sound/ambience/ambimine.ogg')
+ flags = NONE
/area/mine/lobby
- name = "Mining station"
+ name = "Mining Station"
/area/mine/storage
- name = "Mining station Storage"
+ name = "Mining Station Storage"
/area/mine/production
name = "Mining Station Starboard Wing"
diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm
index 2438bd0b626..db741e5f04c 100644
--- a/code/modules/mining/mine_turfs.dm
+++ b/code/modules/mining/mine_turfs.dm
@@ -662,6 +662,10 @@
return 1
/turf/open/chasm/proc/drop(atom/movable/AM)
+ //Make sure the item is still there after our sleep
+ if(!AM || qdeleted(AM))
+ return
+
var/turf/T = locate(drop_x, drop_y, drop_z)
if(T)
AM.visible_message("[AM] falls into [src]!", "GAH! Ah... where are you?")
@@ -697,6 +701,9 @@
initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
/turf/open/chasm/straight_down/lava_land_surface/drop(atom/movable/AM)
+ //Make sure the item is still there after our sleep
+ if(!AM || qdeleted(AM))
+ return
AM.visible_message("[AM] falls into [src]!", "You stumble and stare into an abyss before you. It stares back, and you fall \
into the enveloping dark.")
if(isliving(AM))
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 8642e27ca31..3f36349ff7f 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -383,7 +383,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
var/orbitsize = (I.Width()+I.Height())*0.5
orbitsize -= (orbitsize/world.icon_size)*(world.icon_size*0.25)
- if(orbiting != target)
+ if(orbiting && orbiting.orbiting != target)
src << "Now orbiting [target]."
var/rot_seg
@@ -403,13 +403,14 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
orbit(target,orbitsize, FALSE, 20, rot_seg)
/mob/dead/observer/orbit()
- setDir(2 )//reset dir so the right directional sprites show up
+ setDir(2)//reset dir so the right directional sprites show up
+ ..()
+
+/mob/dead/observer/stop_orbit()
..()
//restart our floating animation after orbit is done.
- sleep 2 //orbit sets up a 2ds animation when it finishes, so we wait for that to end
- if (!orbiting) //make sure another orbit hasn't started
- pixel_y = 0
- animate(src, pixel_y = 2, time = 10, loop = -1)
+ pixel_y = 0
+ animate(src, pixel_y = 2, time = 10, loop = -1)
/mob/dead/observer/verb/jumptomob() //Moves the ghost instead of just changing the ghosts's eye -Nodrak
set category = "Ghost"
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/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/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index 4de7733bd26..96afa3055f4 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -9,6 +9,14 @@
if(head && (head.flags & HEADBANGPROTECT))
return 1
+//Overridden so we can handle when it hits a limb that doesn't exist
+mob/living/carbon/bullet_act(obj/item/projectile/P, def_zone)
+ var/obj/item/bodypart/affecting = get_bodypart(def_zone)
+ if(!affecting) //that zone is dismembered
+ . = bullet_act(P, "chest")//act on chest instead
+ else
+ . = ..()//Proceed with standard handling
+
/mob/living/carbon/check_projectile_dismemberment(obj/item/projectile/P, def_zone)
var/obj/item/bodypart/affecting = get_bodypart(def_zone)
if(affecting && affecting.dismemberable && affecting.get_damage() >= (affecting.max_damage - P.dismemberment))
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 535f7f39ffb..a3a7413932b 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -3,11 +3,12 @@
var/organnum = 0
if(def_zone)
+ //Can pass in a bodypart or zone, so lets shortcut that handling
if(islimb(def_zone))
return checkarmor(def_zone, type)
- var/obj/item/bodypart/affecting = get_bodypart(ran_zone(def_zone))
+ //Note the check_zone call, this changes UI target values to bodypart zones
+ var/obj/item/bodypart/affecting = get_bodypart(check_zone(def_zone))
return checkarmor(affecting, type)
- //If a specific bodypart is targetted, check how that bodypart is protected and return the value.
//If you don't specify a bodypart, it checks ALL your bodyparts for protection, and averages out the values
for(var/X in bodyparts)
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.dm b/code/modules/mob/living/carbon/human/species.dm
index 852a19fd1ab..f250fa7cb85 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -164,11 +164,16 @@
if(exotic_bloodtype && C.dna.blood_type != exotic_bloodtype)
C.dna.blood_type = exotic_bloodtype
-
+ if(("legs" in C.dna.species.mutant_bodyparts) && C.dna.features["legs"] == "Digitigrade Legs")
+ specflags += DIGITIGRADE
+ if(DIGITIGRADE in specflags)
+ C.Digitigrade_Leg_Swap(FALSE)
/datum/species/proc/on_species_loss(mob/living/carbon/C)
if(C.dna.species.exotic_bloodtype)
C.dna.blood_type = random_blood_type()
+ if(DIGITIGRADE in specflags)
+ C.Digitigrade_Leg_Swap(TRUE)
/datum/species/proc/handle_hair(mob/living/carbon/human/H, forced_colour)
H.remove_overlay(HAIR_LAYER)
@@ -258,8 +263,6 @@
var/list/standing = list()
- handle_mutant_bodyparts(H)
-
var/obj/item/bodypart/head/HD = H.get_bodypart("head")
if(!(H.disabilities & HUSK))
@@ -289,7 +292,7 @@
else
standing += image("icon"=U2.icon, "icon_state"="[U2.icon_state]_s", "layer"=-BODY_LAYER)
- if(H.socks && H.get_num_legs() >= 2)
+ if(H.socks && H.get_num_legs() >= 2 && !(DIGITIGRADE in specflags))
var/datum/sprite_accessory/socks/U3 = socks_list[H.socks]
if(U3)
standing += image("icon"=U3.icon, "icon_state"="[U3.icon_state]_s", "layer"=-BODY_LAYER)
@@ -298,7 +301,7 @@
H.overlays_standing[BODY_LAYER] = standing
H.apply_overlay(BODY_LAYER)
-
+ handle_mutant_bodyparts(H)
/datum/species/proc/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour)
var/list/bodyparts_to_add = mutant_bodyparts.Copy()
@@ -371,6 +374,29 @@
else if ("wings" in mutant_bodyparts)
bodyparts_to_add -= "wings_open"
+ //Digitigrade legs are stuck in the phantom zone between true limbs and mutant bodyparts. Mainly it just needs more agressive updating than most limbs.
+ var/update_needed = FALSE
+ var/not_digitigrade = TRUE
+ for(var/X in H.bodyparts)
+ var/obj/item/bodypart/O = X
+ if(!O.use_digitigrade)
+ continue
+ not_digitigrade = FALSE
+ if(!(DIGITIGRADE in specflags)) //Someone cut off a digitigrade leg and tacked it on
+ specflags += DIGITIGRADE
+ var/should_be_squished = FALSE
+ if(H.wear_suit && ((H.wear_suit.flags_inv & HIDEJUMPSUIT) || (H.wear_suit.body_parts_covered & LEGS)) || (H.w_uniform && (H.w_uniform.body_parts_covered & LEGS)))
+ should_be_squished = TRUE
+ if(O.use_digitigrade == FULL_DIGITIGRADE && should_be_squished)
+ O.use_digitigrade = SQUISHED_DIGITIGRADE
+ update_needed = TRUE
+ else if(O.use_digitigrade == SQUISHED_DIGITIGRADE && !should_be_squished)
+ O.use_digitigrade = FULL_DIGITIGRADE
+ update_needed = TRUE
+ if(update_needed)
+ H.update_body_parts()
+ if(not_digitigrade && (DIGITIGRADE in specflags)) //Curse is lifted
+ specflags -= DIGITIGRADE
if(!bodyparts_to_add)
return
@@ -411,6 +437,8 @@
S = wings_list[H.dna.features["wings"]]
if("wingsopen")
S = wings_open_list[H.dna.features["wings"]]
+ if("legs")
+ S = legs_list[H.dna.features["legs"]]
if(!S || S.icon_state == "none")
continue
@@ -552,6 +580,10 @@
return 0
if(num_legs < 2)
return 0
+ if(DIGITIGRADE in specflags)
+ if(!disable_warning)
+ H << "The footwear around here isn't compatible with your feet!"
+ return 0
return 1
if(slot_belt)
if(H.belt)
@@ -678,7 +710,7 @@
return
/datum/species/proc/after_equip_job(datum/job/J, mob/living/carbon/human/H)
- return
+ H.update_mutant_bodyparts()
/datum/species/proc/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
if(chem.id == exotic_blood)
@@ -1065,13 +1097,15 @@
user.add_mob_blood(H)
switch(hit_area)
- if("head") //Harder to score a stun but if you do it lasts a bit longer
+ if("head")
if(H.stat == CONSCIOUS && armor_block < 50)
if(prob(I.force))
- H.visible_message("[H] has been knocked unconscious!", \
- "[H] has been knocked unconscious!")
- H.apply_effect(20, PARALYZE, armor_block)
- if(prob(I.force + ((100 - H.health)/2)) && H != user && I.damtype == BRUTE)
+ H.visible_message("[H] has been knocked senseless!", \
+ "[H] has been knocked senseless!")
+ H.confused = max(H.confused, 20)
+ H.adjust_blurriness(10)
+
+ if(prob(I.force + ((100 - H.health)/2)) && H != user)
ticker.mode.remove_revolutionary(H.mind)
if(bloody) //Apply blood
@@ -1085,11 +1119,12 @@
H.glasses.add_mob_blood(H)
H.update_inv_glasses()
- if("chest") //Easier to score a stun but lasts less time
- if(H.stat == CONSCIOUS && I.force && prob(I.force + 10))
- H.visible_message("[H] has been knocked down!", \
+ if("chest")
+ if(H.stat == CONSCIOUS && armor_block < 50)
+ if(prob(I.force))
+ H.visible_message("[H] has been knocked down!", \
"[H] has been knocked down!")
- H.apply_effect(5, WEAKEN, armor_block)
+ H.apply_effect(3, WEAKEN, armor_block)
if(bloody)
if(H.wear_suit)
diff --git a/code/modules/mob/living/carbon/human/species_types.dm b/code/modules/mob/living/carbon/human/species_types.dm
index c3e0bc205e1..97d1a2dd8ab 100644
--- a/code/modules/mob/living/carbon/human/species_types.dm
+++ b/code/modules/mob/living/carbon/human/species_types.dm
@@ -54,9 +54,9 @@
say_mod = "hisses"
default_color = "00FF00"
specflags = list(MUTCOLORS,EYECOLOR,LIPS)
- mutant_bodyparts = list("tail_lizard", "snout", "spines", "horns", "frills", "body_markings")
+ mutant_bodyparts = list("tail_lizard", "snout", "spines", "horns", "frills", "body_markings", "legs")
mutant_organs = list(/obj/item/organ/tongue/lizard)
- default_features = list("mcolor" = "0F0", "tail" = "Smooth", "snout" = "Round", "horns" = "None", "frills" = "None", "spines" = "None", "body_markings" = "None")
+ default_features = list("mcolor" = "0F0", "tail" = "Smooth", "snout" = "Round", "horns" = "None", "frills" = "None", "spines" = "None", "body_markings" = "None", "legs" = "Normal Legs")
attack_verb = "slash"
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
@@ -86,7 +86,7 @@
/datum/species/lizard/ashwalker
name = "Ash Walker"
id = "lizard"
- specflags = list(MUTCOLORS,EYECOLOR,LIPS,NOBREATH,NOGUNS)
+ specflags = list(MUTCOLORS,EYECOLOR,LIPS,NOBREATH,NOGUNS,DIGITIGRADE)
/*
PODPEOPLE
*/
@@ -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
@@ -893,6 +921,33 @@ var/global/image/plasmaman_on_fire = image("icon"='icons/mob/OnFire.dmi', "icon_
return ..()
+/datum/species/android
+ name = "Android"
+ id = "android"
+ say_mod = "states"
+ specflags = list(NOBREATH,RESISTTEMP,NOBLOOD,VIRUSIMMUNE,PIERCEIMMUNE,NOHUNGER,EASYLIMBATTACHMENT)
+ safe_oxygen_min = 0
+ safe_toxins_min = 0
+ safe_toxins_max = 0
+ safe_co2_max = 0
+ SA_para_min = 0
+ SA_sleep_min = 0
+ meat = null
+ damage_overlay_type = "synth"
+ limbs_id = "synth"
+
+/datum/species/android/on_species_gain(mob/living/carbon/C)
+ . = ..()
+ for(var/X in C.bodyparts)
+ var/obj/item/bodypart/O = X
+ O.change_bodypart_status(BODYPART_ROBOTIC)
+
+/datum/species/android/on_species_loss(mob/living/carbon/C)
+ . = ..()
+ for(var/X in C.bodyparts)
+ var/obj/item/bodypart/O = X
+ O.change_bodypart_status(BODYPART_ORGANIC)
+
/*
SYNDICATE BLACK OPS
*/
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index 4bbde09513d..1413c6cd2cd 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -117,8 +117,10 @@ There are several things that need to be remembered:
var/t_color = U.item_color
if(!t_color)
t_color = U.icon_state
- if(U.adjusted)
+ if(U.adjusted == ALT_STYLE)
t_color = "[t_color]_d"
+ else if(U.adjusted == DIGITIGRADE_STYLE)
+ t_color = "[t_color]_l"
var/image/standing
@@ -138,6 +140,7 @@ There are several things that need to be remembered:
unEquip(thing)
apply_overlay(UNIFORM_LAYER)
+ update_mutant_bodyparts()
/mob/living/carbon/human/update_inv_wear_id()
@@ -537,13 +540,14 @@ generate/load female uniform sprites matching all previously decided variables
. += "-organic"
else
. += "-robotic"
+ if(BP.use_digitigrade)
+ . += "-digitigrade[BP.use_digitigrade]"
if(disabilities & HUSK)
. += "-husk"
/mob/living/carbon/human/load_limb_from_cache()
..()
- update_mutant_bodyparts()
update_hair()
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/carbon/update_icons.dm b/code/modules/mob/living/carbon/update_icons.dm
index dcd5b1a59b2..85df21c0974 100644
--- a/code/modules/mob/living/carbon/update_icons.dm
+++ b/code/modules/mob/living/carbon/update_icons.dm
@@ -263,6 +263,8 @@ var/global/list/limb_icon_cache = list()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
. += "-[BP.body_zone]"
+ if(BP.use_digitigrade)
+ . += "-digitigrade[BP.use_digitigrade]"
if(BP.animal_origin)
. += "-[BP.animal_origin]"
if(BP.status == BODYPART_ORGANIC)
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 5d2c0c48535..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)
@@ -48,11 +45,14 @@
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 946f2e04900..c4a68499d21 100644
--- a/code/modules/mob/living/silicon/ai/life.dm
+++ b/code/modules/mob/living/silicon/ai/life.dm
@@ -4,7 +4,7 @@
#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
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/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 5dcfcc2b9ed..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"
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 68adb12b3c0..c68cf8a541f 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,24 @@ 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/gibs/bubblegum/B = new /obj/effect/decal/cleanable/blood/gibs/bubblegum(loc)
+ if(prob(33))
+ step(B, pick(cardinal))
+ else
+ B.setDir(pick(cardinal))
+ . = ..()
+
+/obj/effect/decal/cleanable/blood/gibs/bubblegum
+ name = "thick blood"
+ desc = "Thick, splattered blood."
+ random_icon_states = list("gib3", "gib5", "gib6")
+ bloodiness = 20
+
+/obj/effect/decal/cleanable/blood/gibs/bubblegum/can_bloodcrawl_in()
+ return TRUE
+
/mob/living/simple_animal/hostile/megafauna/bubblegum/Life()
..()
move_to_delay = Clamp(round((health/maxHealth) * 10), 5, 10)
@@ -67,18 +86,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 +131,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 +159,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 +191,135 @@ 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.stat == DEAD))
+ . += 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, prob(50))
+
+ return TRUE
+ return FALSE
+
+/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/bloodattack(list/targets, handedness)
+ 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))
+ bloodgrab(target_two_turf, handedness)
+ else
+ bloodsmack(target_two_turf, handedness)
+
+ var/list/pools = get_pools(get_turf(target_one), 0)
+ if(pools.len)
+ target_one_turf = get_turf(target_one)
+ if(target_one_turf)
+ if(target_one.stat != CONSCIOUS || prob(10))
+ bloodgrab(target_one_turf, !handedness)
+ else
+ bloodsmack(target_one_turf, !handedness)
+
+ if(!target_two && target_one)
+ var/list/poolstwo = get_pools(get_turf(target_one), 0)
+ if(poolstwo.len)
+ target_one_turf = get_turf(target_one)
+ if(target_one_turf)
+ if(target_one.stat != CONSCIOUS || prob(10))
+ bloodgrab(target_one_turf, handedness)
+ else
+ bloodsmack(target_one_turf, handedness)
+
+/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/bloodsmack(turf/T, handedness)
+ if(handedness)
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/rightsmack, T)
+ else
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/leftsmack, 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, handedness)
+ if(handedness)
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/rightpaw, T)
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/rightthumb, T)
+ else
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/leftpaw, T)
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/leftthumb, 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 +329,62 @@ 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/nearby in view(T, range))
+ if(nearby.can_bloodcrawl_in())
+ . += 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)
- break
+ 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/bubblegum(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)))
- if(!previousturf.CanAtmosPass(J))
+ playsound(previousturf,'sound/effects/splat.ogg', 100, 1, -1)
+ if(!J || !previousturf.CanAtmosPass(J))
break
- playsound(J,'sound/effects/splat.ogg', 100, 1, -1)
- new /obj/effect/decal/cleanable/blood(J)
- range--
+ new /obj/effect/decal/cleanable/blood/bubblegum(J)
previousturf = J
sleep(1)
+/obj/effect/decal/cleanable/blood/bubblegum
+ bloodiness = 0
+
+/obj/effect/decal/cleanable/blood/bubblegum/can_bloodcrawl_in()
+ return TRUE
+
/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..22719303693 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
@@ -121,13 +121,10 @@ Difficulty: Very Hard
..()
/mob/living/simple_animal/hostile/megafauna/colossus/proc/enrage(mob/living/L)
- var/enraged = FALSE
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(H.martial_art && prob(H.martial_art.deflection_chance))
- enraged = TRUE
-
- return enraged
+ . = TRUE
/mob/living/simple_animal/hostile/megafauna/colossus/proc/alternating_dir_shots()
dir_shots(diagonals)
@@ -188,15 +185,15 @@ Difficulty: Very Hard
else
counter++
if(counter > 16)
- counter = 0
- if(counter < 0)
+ counter = 1
+ if(counter < 1)
counter = 16
shoot_projectile(marker)
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, 1)
sleep(1)
/mob/living/simple_animal/hostile/megafauna/colossus/proc/shoot_projectile(turf/marker)
- if(!marker)
+ if(!marker || marker == loc)
return
var/turf/startloc = get_turf(src)
var/obj/item/projectile/P = new /obj/item/projectile/colossus(startloc)
@@ -220,7 +217,9 @@ 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)
+ newtonian_move(get_dir(T, targets_from))
+ 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 +380,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 +422,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 +474,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 +526,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 +548,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 +573,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 +618,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 +645,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 +691,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 +699,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 +726,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 +742,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 +765,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..cfeb0a19e9d 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)
@@ -228,8 +229,11 @@ Difficulty: Medium
else
L.adjustBruteLoss(75)
if(L && !qdeleted(L)) // Some mobs are deleted on death
- var/throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(L, src)))
- L.throw_at_fast(throwtarget)
+ var/throw_dir = get_dir(src, L)
+ if(L.loc == loc)
+ throw_dir = pick(alldirs)
+ var/throwtarget = get_edge_target_turf(src, throw_dir)
+ L.throw_at_fast(throwtarget, 3)
visible_message("[L] is thrown clear of [src]!")
for(var/mob/M in range(7, src))
@@ -243,7 +247,7 @@ Difficulty: Medium
if(!istype(A))
return
if(swoop_cooldown >= world.time)
- src << "You need to wait 20 seconds between swoop attacks!M/span>"
+ src << "You need to wait 20 seconds between swoop attacks!"
return
swoop_attack(1, A)
@@ -257,6 +261,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/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/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/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/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm
index 054bb354824..9c5a1242b4a 100644
--- a/code/modules/mob/new_player/sprite_accessories.dm
+++ b/code/modules/mob/new_player/sprite_accessories.dm
@@ -1135,29 +1135,15 @@
name = "None"
icon_state = "none"
-/datum/sprite_accessory/body_markings/dstripe
- name = "Dark Stripe"
- icon_state = "dstripe"
-
-/datum/sprite_accessory/body_markings/lstripe
- name = "Light Stripe"
- icon_state = "lstripe"
-
/datum/sprite_accessory/body_markings/dtiger
name = "Dark Tiger Body"
icon_state = "dtiger"
-
-/datum/sprite_accessory/body_markings/dtigerhead
- name = "Dark Tiger Body + Head"
- icon_state = "dtigerhead"
+ gender_specific = 1
/datum/sprite_accessory/body_markings/ltiger
name = "Light Tiger Body"
icon_state = "ltiger"
-
-/datum/sprite_accessory/body_markings/ltigerhead
- name = "Light Tiger Body + Head"
- icon_state = "ltigerhead"
+ gender_specific = 1
/datum/sprite_accessory/body_markings/lbelly
name = "Light Belly"
@@ -1178,30 +1164,6 @@
name = "Smooth"
icon_state = "smooth"
-/datum/sprite_accessory/tails/lizard/light
- name = "Light"
- icon_state = "light"
-
-/datum/sprite_accessory/tails_animated/lizard/light
- name = "Light"
- icon_state = "light"
-
-/datum/sprite_accessory/tails/lizard/dstripe
- name = "Dark Stripe"
- icon_state = "dstripe"
-
-/datum/sprite_accessory/tails_animated/lizard/dstripe
- name = "Dark Stripe"
- icon_state = "dstripe"
-
-/datum/sprite_accessory/tails/lizard/lstripe
- name = "Light Stripe"
- icon_state = "lstripe"
-
-/datum/sprite_accessory/tails_animated/lizard/lstripe
- name = "Light Stripe"
- icon_state = "lstripe"
-
/datum/sprite_accessory/tails/lizard/dtiger
name = "Dark Tiger"
icon_state = "dtiger"
@@ -1218,21 +1180,13 @@
name = "Light Tiger"
icon_state = "ltiger"
-/datum/sprite_accessory/tails/lizard/club
- name = "Club"
- icon_state = "club"
+/datum/sprite_accessory/tails/lizard/spikes
+ name = "Spikes"
+ icon_state = "spikes"
-/datum/sprite_accessory/tails_animated/lizard/club
- name = "Club"
- icon_state = "club"
-
-/datum/sprite_accessory/tails/lizard/aqua
- name = "Aquatic"
- icon_state = "aqua"
-
-/datum/sprite_accessory/tails_animated/lizard/aqua
- name = "Aquatic"
- icon_state = "aqua"
+/datum/sprite_accessory/tails_animated/lizard/spikes
+ name = "Spikes"
+ icon_state = "spikes"
/datum/sprite_accessory/tails/human/none
name = "None"
@@ -1410,3 +1364,12 @@
/datum/sprite_accessory/spines_animated/aqautic
name = "Aquatic"
icon_state = "aqua"
+
+/datum/sprite_accessory/legs //legs are a special case, they aren't actually sprite_accessories but are updated with them.
+ icon = null //These datums exist for selecting legs on preference, and little else
+
+/datum/sprite_accessory/legs/none
+ name = "Normal Legs"
+
+/datum/sprite_accessory/legs/digitigrade_lizard
+ name = "Digitigrade Legs"
diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm
index 9ba2db5975b..6f662412c65 100644
--- a/code/modules/mob/transform_procs.dm
+++ b/code/modules/mob/transform_procs.dm
@@ -486,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 = {"