diff --git a/SQL/paradise_schema.sql b/SQL/paradise_schema.sql
index ed4fb787b8d..1e4692b7e3b 100644
--- a/SQL/paradise_schema.sql
+++ b/SQL/paradise_schema.sql
@@ -269,6 +269,7 @@ CREATE TABLE `player` (
`fuid` bigint(20) NULL DEFAULT NULL,
`fupdate` smallint(4) NULL DEFAULT '0',
`afk_watch` tinyint(1) NOT NULL DEFAULT '0',
+ `parallax` tinyint(1) DEFAULT '8',
PRIMARY KEY (`id`),
UNIQUE KEY `ckey` (`ckey`)
) ENGINE=InnoDB AUTO_INCREMENT=32446 DEFAULT CHARSET=latin1;
diff --git a/SQL/paradise_schema_prefixed.sql b/SQL/paradise_schema_prefixed.sql
index b0f7bbc5c82..aa5d5895e56 100644
--- a/SQL/paradise_schema_prefixed.sql
+++ b/SQL/paradise_schema_prefixed.sql
@@ -268,6 +268,7 @@ CREATE TABLE `SS13_player` (
`fuid` bigint(20) NULL DEFAULT NULL,
`fupdate` smallint(4) NULL DEFAULT '0',
`afk_watch` tinyint(1) NOT NULL DEFAULT '0',
+ `parallax` tinyint(1) DEFAULT '8',
PRIMARY KEY (`id`),
UNIQUE KEY `ckey` (`ckey`)
) ENGINE=InnoDB AUTO_INCREMENT=32446 DEFAULT CHARSET=latin1;
diff --git a/SQL/updates/8-9.sql b/SQL/updates/8-9.sql
new file mode 100644
index 00000000000..d7f0fd19ab3
--- /dev/null
+++ b/SQL/updates/8-9.sql
@@ -0,0 +1,4 @@
+#Updating the SQL from version 8 to version 9. -affectedarc07
+#Adding new column to contain the parallax value.
+ALTER TABLE `player`
+ ADD `parallax` tinyint(1) DEFAULT '8' AFTER `fupdate`;
diff --git a/_maps/map_files/Delta/delta.dmm b/_maps/map_files/Delta/delta.dmm
index 447889d17a1..36a5e25bbfd 100644
--- a/_maps/map_files/Delta/delta.dmm
+++ b/_maps/map_files/Delta/delta.dmm
@@ -31407,6 +31407,7 @@
id_tag = "s_docking_airlock";
req_access_txt = "48"
},
+/obj/structure/fans/tiny,
/turf/simulated/shuttle/floor,
/area/shuttle/mining)
"bgZ" = (
@@ -31431,6 +31432,7 @@
name = "mining shuttle bay";
width = 7
},
+/obj/structure/fans/tiny,
/turf/simulated/shuttle/floor,
/area/shuttle/mining)
"bha" = (
@@ -34038,6 +34040,7 @@
name = "Mining Dock Airlock";
req_access_txt = "48"
},
+/obj/structure/fans/tiny,
/turf/simulated/floor/plasteel,
/area/quartermaster/miningdock)
"blH" = (
@@ -38843,6 +38846,7 @@
name = "Labor Shuttle Airlock";
req_access_txt = "2"
},
+/obj/structure/fans/tiny,
/turf/simulated/shuttle/floor{
icon_state = "floor4"
},
@@ -38864,6 +38868,7 @@
name = "Labor Camp Airlock";
req_access_txt = "2"
},
+/obj/structure/fans/tiny,
/turf/simulated/floor/plasteel,
/area/security/prisonershuttle)
"btT" = (
@@ -41958,6 +41963,7 @@
name = "fore bay 1";
width = 9
},
+/obj/structure/fans/tiny,
/turf/simulated/shuttle/floor,
/area/shuttle/siberia)
"bzg" = (
diff --git a/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm b/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm
index 8bf89da81b2..0a054feb801 100644
--- a/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm
@@ -11722,6 +11722,7 @@
name = "Labor Camp Shuttle Airlock";
req_access_txt = "2"
},
+/obj/structure/fans/tiny,
/turf/simulated/floor/plasteel{
icon_state = "dark"
},
@@ -14760,6 +14761,7 @@
id_tag = "s_docking_airlock";
name = "Labor Shuttle Airlock"
},
+/obj/structure/fans/tiny,
/turf/simulated/shuttle/floor{
icon_state = "floor4"
},
@@ -14769,6 +14771,7 @@
id_tag = "laborcamp_home";
name = "Labor Camp Shuttle Airlock"
},
+/obj/structure/fans/tiny,
/turf/simulated/floor/plasteel{
icon_state = "dark"
},
@@ -15638,6 +15641,7 @@
pixel_y = -25;
req_access_txt = "2"
},
+/obj/structure/fans/tiny,
/turf/simulated/floor/plasteel{
icon_state = "dark"
},
@@ -17546,6 +17550,7 @@
name = "mining shuttle bay";
width = 7
},
+/obj/structure/fans/tiny,
/turf/simulated/shuttle/plating,
/area/shuttle/mining)
"aEJ" = (
@@ -17554,6 +17559,7 @@
req_access = null;
req_access_txt = "0"
},
+/obj/structure/fans/tiny,
/turf/simulated/floor/plating,
/area/quartermaster/miningdock{
name = "\improper Mining Office"
@@ -17568,6 +17574,7 @@
name = "Mining Dock";
req_access_txt = "48"
},
+/obj/structure/fans/tiny,
/turf/simulated/floor/plasteel,
/area/quartermaster/miningdock{
name = "\improper Mining Office"
@@ -17814,6 +17821,7 @@
id_tag = "s_docking_airlock";
name = "Labor Shuttle Airlock"
},
+/obj/structure/fans/tiny,
/turf/simulated/shuttle/floor,
/area/shuttle/siberia)
"aFe" = (
@@ -17821,6 +17829,7 @@
id_tag = "laborcamp_home";
name = "Labor Camp Shuttle Airlock"
},
+/obj/structure/fans/tiny,
/turf/simulated/floor/plasteel{
icon_state = "dark"
},
diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm
index f40f82a6ff3..73a88d1df69 100644
--- a/_maps/map_files/cyberiad/cyberiad.dmm
+++ b/_maps/map_files/cyberiad/cyberiad.dmm
@@ -2225,6 +2225,7 @@
icon_state = "1-2";
pixel_y = 0
},
+/obj/structure/fans/tiny,
/turf/simulated/floor/plating,
/area/security/prisonershuttle)
"aeG" = (
@@ -11418,10 +11419,6 @@
id_tag = "secmaintdorm1";
name = "Room 1"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plating,
/area/maintenance/fsmaint)
"ats" = (
@@ -11429,10 +11426,6 @@
id_tag = "secmaintdorm2";
name = "Room 2"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plating,
/area/maintenance/fsmaint)
"att" = (
@@ -12166,6 +12159,7 @@
name = "Labor Camp Airlock";
req_access_txt = "2"
},
+/obj/structure/fans/tiny,
/turf/simulated/floor/plating,
/area/security/prisonershuttle)
"auz" = (
@@ -12174,6 +12168,7 @@
name = "Labor Shuttle Airlock";
req_access_txt = "2"
},
+/obj/structure/fans/tiny,
/turf/simulated/shuttle/floor{
icon_state = "floor4"
},
@@ -13181,16 +13176,6 @@
},
/turf/simulated/floor/plasteel,
/area/security/lobby)
-"avU" = (
-/obj/machinery/door/airlock/maintenance{
- req_access_txt = "12"
- },
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 4
- },
-/turf/simulated/floor/plating,
-/area/maintenance/fsmaint)
"avV" = (
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 10
@@ -13214,10 +13199,6 @@
dir = 4;
level = 1
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
/turf/simulated/floor/plasteel{
tag = "icon-cult";
icon_state = "cult";
@@ -14352,16 +14333,6 @@
icon_state = "darkredcorners"
},
/area/security/prison/cell_block/A)
-"axN" = (
-/obj/machinery/door/airlock/maintenance{
- req_access_txt = "12"
- },
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
-/turf/simulated/floor/plating,
-/area/maintenance/fsmaint)
"axO" = (
/obj/structure/cable{
d1 = 1;
@@ -14558,6 +14529,7 @@
name = "fore bay 1";
width = 9
},
+/obj/structure/fans/tiny,
/turf/simulated/shuttle/floor,
/area/shuttle/siberia)
"ayi" = (
@@ -17788,10 +17760,6 @@
req_access_txt = "12"
},
/obj/effect/decal/cleanable/dirt,
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 4
- },
/turf/simulated/floor/plasteel{
icon_state = "floorgrime"
},
@@ -19009,13 +18977,6 @@
/obj/item/twohanded/required/kirbyplants,
/turf/simulated/floor/wood,
/area/crew_quarters/courtroom)
-"aGv" = (
-/obj/machinery/door/airlock/maintenance{
- req_access_txt = "12"
- },
-/obj/effect/mapping_helpers/airlock/unres,
-/turf/simulated/floor/plating,
-/area/maintenance/fsmaint)
"aGw" = (
/obj/structure/disposalpipe/junction{
dir = 1;
@@ -20068,10 +20029,6 @@
name = "Magistrate's Office";
req_access_txt = "74"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 4
- },
/turf/simulated/floor/plasteel{
tag = "icon-cult";
icon_state = "cult";
@@ -20160,10 +20117,6 @@
/obj/machinery/door/airlock/maintenance{
req_access_txt = "12"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plating,
/area/maintenance/fsmaint)
"aIZ" = (
@@ -20743,16 +20696,6 @@
},
/turf/simulated/floor/plasteel,
/area/hallway/primary/fore)
-"aKp" = (
-/obj/machinery/door/airlock/maintenance{
- req_access_txt = "12"
- },
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 4
- },
-/turf/simulated/floor/plating,
-/area/maintenance/fsmaint2)
"aKq" = (
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 4
@@ -20826,10 +20769,6 @@
d2 = 2;
icon_state = "1-2"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plasteel{
tag = "icon-cult";
icon_state = "cult";
@@ -21150,10 +21089,6 @@
req_access = null;
req_access_txt = "4"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 4
- },
/turf/simulated/floor/plasteel{
icon_state = "grimy"
},
@@ -21192,10 +21127,6 @@
/obj/machinery/door/airlock/maintenance{
req_access_txt = "12"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 4
- },
/turf/simulated/floor/plating,
/area/maintenance/fpmaint2)
"aLl" = (
@@ -21234,10 +21165,6 @@
req_access_txt = "12"
},
/obj/effect/decal/cleanable/dirt,
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
/turf/simulated/floor/wood{
tag = "icon-wood-broken3";
icon_state = "wood-broken3"
@@ -22079,16 +22006,6 @@
},
/turf/simulated/floor/carpet,
/area/crew_quarters/courtroom)
-"aNe" = (
-/obj/machinery/door/airlock/maintenance{
- req_access_txt = "12"
- },
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
-/turf/simulated/floor/plating,
-/area/maintenance/fsmaint2)
"aNf" = (
/obj/machinery/access_button{
command = "cycle_interior";
@@ -22464,10 +22381,6 @@
name = "Courtroom Privacy Shutters";
opacity = 0
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
/turf/simulated/floor/wood,
/area/crew_quarters/courtroom)
"aNT" = (
@@ -22567,16 +22480,6 @@
icon_state = "barber"
},
/area/civilian/barber)
-"aOa" = (
-/obj/machinery/door/airlock/maintenance{
- req_access_txt = "12"
- },
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
-/turf/simulated/floor/plating,
-/area/maintenance/fsmaint2)
"aOb" = (
/obj/machinery/prize_counter,
/obj/machinery/light{
@@ -22895,10 +22798,6 @@
icon_state = "1-2"
},
/obj/machinery/atmospherics/pipe/simple/visible/purple,
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plating,
/area/maintenance/fpmaint2)
"aOO" = (
@@ -22926,10 +22825,6 @@
name = "Courtroom Privacy Shutters";
opacity = 0
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
/turf/simulated/floor/wood,
/area/crew_quarters/courtroom)
"aOP" = (
@@ -23025,10 +22920,6 @@
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 4
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 4
- },
/turf/simulated/floor/plating,
/area/maintenance/fsmaint)
"aPc" = (
@@ -23105,10 +22996,6 @@
/obj/machinery/atmospherics/pipe/simple/visible/purple{
dir = 4
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 4
- },
/turf/simulated/floor/plating,
/area/maintenance/fpmaint2)
"aPi" = (
@@ -23418,10 +23305,6 @@
d2 = 2;
icon_state = "1-2"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plating,
/area/maintenance/fsmaint)
"aPQ" = (
@@ -23476,10 +23359,6 @@
req_access_txt = "12"
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plating,
/area/maintenance/fsmaint)
"aPV" = (
@@ -25238,10 +25117,6 @@
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 4
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
/turf/simulated/floor/plating,
/area/maintenance/fsmaint2)
"aTt" = (
@@ -26043,7 +25918,6 @@
d2 = 2;
icon_state = "1-2"
},
-/obj/effect/mapping_helpers/airlock/unres,
/turf/simulated/floor/plating,
/area/maintenance/fpmaint)
"aVc" = (
@@ -26512,10 +26386,6 @@
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plating,
/area/maintenance/fpmaint2)
"aVM" = (
@@ -27629,13 +27499,6 @@
/obj/machinery/lapvend,
/turf/simulated/floor/plasteel,
/area/storage/primary)
-"aXT" = (
-/obj/machinery/door/airlock/maintenance{
- req_access_txt = "12"
- },
-/obj/effect/mapping_helpers/airlock/unres,
-/turf/simulated/floor/plating,
-/area/maintenance/fsmaint2)
"aXU" = (
/obj/item/flag/mime,
/obj/machinery/power/apc{
@@ -29496,16 +29359,6 @@
dir = 2
},
/area/crew_quarters/dorms)
-"bbx" = (
-/obj/machinery/door/airlock/maintenance{
- req_access_txt = "12"
- },
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
-/turf/simulated/floor/plating,
-/area/maintenance/fpmaint2)
"bby" = (
/obj/machinery/camera{
c_tag = "Medbay Morgue";
@@ -30068,10 +29921,6 @@
/obj/machinery/door/airlock/maintenance{
req_access_txt = "12"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 4
- },
/turf/simulated/floor/plating,
/area/maintenance/fpmaint)
"bcw" = (
@@ -31210,10 +31059,6 @@
icon_state = "4-8";
tag = ""
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
/turf/simulated/floor/plating,
/area/maintenance/fpmaint)
"bex" = (
@@ -31513,10 +31358,6 @@
name = "Mime's Office";
req_access_txt = "46"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 4
- },
/turf/simulated/floor/plasteel{
icon_state = "tranquillite";
dir = 4;
@@ -31587,10 +31428,6 @@
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plating,
/area/maintenance/fpmaint2)
"bfg" = (
@@ -33844,7 +33681,6 @@
name = "Clown's Office";
req_access_txt = "46"
},
-/obj/effect/mapping_helpers/airlock/unres,
/turf/simulated/floor/wood,
/area/clownoffice)
"bjf" = (
@@ -33858,10 +33694,6 @@
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plating,
/area/maintenance/fsmaint2)
"bjh" = (
@@ -33875,10 +33707,6 @@
},
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plating,
/area/maintenance/fpmaint2)
"bji" = (
@@ -37146,7 +36974,6 @@
/obj/structure/disposalpipe/segment,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
-/obj/effect/mapping_helpers/airlock/unres,
/turf/simulated/floor/plating,
/area/maintenance/fsmaint2)
"bpF" = (
@@ -37426,10 +37253,6 @@
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plating,
/area/maintenance/fsmaint2)
"bqk" = (
@@ -40033,10 +39856,6 @@
name = "Chapel Office";
req_access_txt = "22"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
/turf/simulated/floor/plasteel{
icon_state = "dark"
},
@@ -40313,10 +40132,6 @@
name = "Bar Office";
req_access_txt = "25"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/wood,
/area/crew_quarters/bar)
"bwm" = (
@@ -40719,10 +40534,6 @@
},
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plating,
/area/maintenance/fsmaint2)
"bwY" = (
@@ -41516,10 +41327,6 @@
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plating,
/area/maintenance/fpmaint)
"byt" = (
@@ -43424,10 +43231,6 @@
/obj/machinery/door/airlock/maintenance{
req_access_txt = "12"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plating,
/area/maintenance/fpmaint)
"bCr" = (
@@ -48801,20 +48604,6 @@
icon_state = "brown"
},
/area/quartermaster/office)
-"bMz" = (
-/obj/machinery/door/firedoor,
-/obj/machinery/door/airlock/glass{
- name = "Chapel Office";
- req_access_txt = "22"
- },
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
-/turf/simulated/floor/plasteel{
- icon_state = "dark"
- },
-/area/chapel/office)
"bMA" = (
/obj/machinery/mineral/ore_redemption,
/turf/simulated/floor/plasteel,
@@ -48859,10 +48648,6 @@
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plasteel{
icon_state = "showroomfloor"
},
@@ -49728,7 +49513,6 @@
},
/obj/structure/disposalpipe/segment,
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
-/obj/effect/mapping_helpers/airlock/unres,
/turf/simulated/floor/plating,
/area/maintenance/port)
"bNQ" = (
@@ -50010,7 +49794,6 @@
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
-/obj/effect/mapping_helpers/airlock/unres,
/turf/simulated/floor/plating,
/area/maintenance/port)
"bOo" = (
@@ -50671,7 +50454,6 @@
icon_state = "1-2";
tag = ""
},
-/obj/effect/mapping_helpers/airlock/unres,
/turf/simulated/floor/plating,
/area/storage/emergency2)
"bPs" = (
@@ -50730,10 +50512,6 @@
},
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plating,
/area/maintenance/fsmaint2)
"bPy" = (
@@ -50928,10 +50706,6 @@
name = "Kitchen";
req_access_txt = "28"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 4
- },
/turf/simulated/floor/plasteel{
dir = 2;
icon_state = "cafeteria";
@@ -52146,10 +51920,6 @@
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 4
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 4
- },
/turf/simulated/floor/plating,
/area/maintenance/port)
"bRI" = (
@@ -52632,7 +52402,6 @@
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
-/obj/effect/mapping_helpers/airlock/unres,
/turf/simulated/floor/plasteel{
icon_state = "white"
},
@@ -52658,10 +52427,6 @@
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 4
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
/turf/simulated/floor/plating,
/area/maintenance/port)
"bSB" = (
@@ -54255,10 +54020,6 @@
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 4
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
/turf/simulated/floor/plasteel,
/area/quartermaster/office)
"bVl" = (
@@ -54273,10 +54034,6 @@
icon_state = "4-8";
pixel_x = 0
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
/turf/simulated/floor/plasteel,
/area/quartermaster/storage)
"bVm" = (
@@ -54545,10 +54302,6 @@
name = "Delivery Office";
req_access_txt = "50"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plasteel,
/area/quartermaster/office)
"bVI" = (
@@ -55262,10 +55015,6 @@
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 4
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
/turf/simulated/floor/plasteel,
/area/quartermaster/storage)
"bWP" = (
@@ -55486,7 +55235,6 @@
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
-/obj/effect/mapping_helpers/airlock/unres,
/turf/simulated/floor/plating,
/area/maintenance/asmaint2)
"bXj" = (
@@ -56536,9 +56284,6 @@
/area/server)
"bYV" = (
/obj/structure/table,
-/obj/machinery/photocopier/faxmachine{
- department = "Head of Personnel's Office"
- },
/obj/machinery/firealarm{
dir = 1;
pixel_y = -24
@@ -56551,6 +56296,9 @@
pixel_y = 16;
req_access_txt = "57"
},
+/obj/machinery/photocopier/faxmachine/longrange{
+ department = "Head of Personnel's Office"
+ },
/turf/simulated/floor/plasteel,
/area/crew_quarters/heads)
"bYW" = (
@@ -57305,7 +57053,7 @@
name = "Biohazard Shutter Control";
pixel_x = -4;
pixel_y = 6;
- req_access_txt = "47"
+ req_access_txt = "30"
},
/obj/item/folder/white{
pixel_x = 4
@@ -57321,7 +57069,7 @@
normaldoorcontrol = 1;
pixel_x = -4;
pixel_y = -4;
- req_access_txt = "20"
+ req_access_txt = "30"
},
/turf/simulated/floor/plasteel{
dir = 2;
@@ -58287,10 +58035,6 @@
d2 = 2;
icon_state = "1-2"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plasteel{
tag = "icon-whitebluefull";
icon_state = "whitebluefull"
@@ -58368,10 +58112,6 @@
name = "Medical Supplies";
req_access_txt = "5"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plasteel{
tag = "icon-whitebluefull";
icon_state = "whitebluefull"
@@ -58389,10 +58129,6 @@
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 4
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
/turf/simulated/floor/plasteel,
/area/quartermaster/office)
"cbA" = (
@@ -63286,10 +63022,6 @@
/obj/machinery/door/airlock/maintenance{
req_access_txt = "12"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
/turf/simulated/floor/plating,
/area/maintenance/asmaint2)
"cjB" = (
@@ -63341,7 +63073,6 @@
tag = ""
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
-/obj/effect/mapping_helpers/airlock/unres,
/turf/simulated/floor/plating,
/area/maintenance/apmaint)
"cjE" = (
@@ -63728,6 +63459,7 @@
name = "mining shuttle bay";
width = 7
},
+/obj/structure/fans/tiny,
/turf/simulated/shuttle/floor,
/area/shuttle/mining)
"ckl" = (
@@ -63736,6 +63468,7 @@
name = "Mining Dock Airlock";
req_access_txt = "48"
},
+/obj/structure/fans/tiny,
/turf/simulated/floor/plating,
/area/quartermaster/miningdock)
"ckm" = (
@@ -63744,6 +63477,7 @@
name = "Mining Dock Airlock";
req_access_txt = "48"
},
+/obj/structure/fans/tiny,
/turf/simulated/floor/plasteel,
/area/quartermaster/miningdock)
"ckn" = (
@@ -64006,7 +63740,6 @@
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
-/obj/effect/mapping_helpers/airlock/unres,
/turf/simulated/floor/wood,
/area/blueshield)
"ckJ" = (
@@ -64050,7 +63783,6 @@
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
-/obj/effect/mapping_helpers/airlock/unres,
/turf/simulated/floor/wood,
/area/ntrep)
"ckO" = (
@@ -64066,7 +63798,6 @@
req_access_txt = "26"
},
/obj/structure/disposalpipe/segment,
-/obj/effect/mapping_helpers/airlock/unres,
/turf/simulated/floor/plasteel,
/area/janitor)
"ckQ" = (
@@ -64100,7 +63831,6 @@
},
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
-/obj/effect/mapping_helpers/airlock/unres,
/turf/simulated/floor/plating,
/area/maintenance/asmaint)
"ckU" = (
@@ -64188,7 +63918,6 @@
},
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
-/obj/effect/mapping_helpers/airlock/unres,
/turf/simulated/floor/plating,
/area/maintenance/asmaint2)
"clb" = (
@@ -64964,10 +64693,6 @@
/obj/machinery/door/airlock/maintenance{
req_access_txt = "12"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plating,
/area/maintenance/asmaint)
"cmu" = (
@@ -65387,7 +65112,7 @@
/turf/simulated/wall,
/area/toxins/test_area)
"cnl" = (
-/obj/structure/closet/wardrobe/miner/lavaland,
+/obj/structure/closet/wardrobe/miner,
/turf/simulated/floor/plasteel{
dir = 2;
icon_state = "brown"
@@ -66670,10 +66395,6 @@
/obj/machinery/door/airlock/maintenance{
req_access_txt = "12"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 4
- },
/turf/simulated/floor/plating,
/area/maintenance/asmaint)
"cpl" = (
@@ -67411,10 +67132,6 @@
/obj/machinery/holosign/surgery{
id = "surgery1"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
/turf/simulated/floor/plasteel{
icon_state = "dark"
},
@@ -67598,10 +67315,6 @@
/obj/machinery/holosign/surgery{
id = "surgery2"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 4
- },
/turf/simulated/floor/plasteel{
icon_state = "dark"
},
@@ -67683,7 +67396,6 @@
/obj/machinery/door/airlock/maintenance{
req_access_txt = "12"
},
-/obj/effect/mapping_helpers/airlock/unres,
/turf/simulated/floor/plating,
/area/maintenance/apmaint)
"cqG" = (
@@ -69561,13 +69273,6 @@
/area/medical/research{
name = "Research Division"
})
-"ctD" = (
-/obj/machinery/door/airlock/maintenance{
- req_access_txt = "12"
- },
-/obj/effect/mapping_helpers/airlock/unres,
-/turf/simulated/floor/plating,
-/area/maintenance/asmaint)
"ctE" = (
/obj/machinery/hologram/holopad,
/turf/simulated/floor/plasteel{
@@ -69651,16 +69356,6 @@
/obj/effect/decal/warning_stripes/yellow,
/turf/simulated/floor/plasteel,
/area/engine/controlroom)
-"ctK" = (
-/obj/machinery/door/airlock/maintenance{
- req_access_txt = "12"
- },
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
-/turf/simulated/floor/plating,
-/area/maintenance/apmaint)
"ctL" = (
/obj/machinery/light{
dir = 4;
@@ -71702,10 +71397,6 @@
req_access_txt = "5";
req_one_access_txt = "0"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 4
- },
/turf/simulated/floor/plasteel{
dir = 2;
icon_state = "cafeteria";
@@ -72359,16 +72050,6 @@
},
/turf/simulated/floor/plasteel,
/area/storage/tech)
-"cyu" = (
-/obj/machinery/door/airlock/maintenance{
- req_access_txt = "12"
- },
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 4
- },
-/turf/simulated/floor/plating,
-/area/maintenance/asmaint)
"cyv" = (
/obj/structure/sign/securearea{
desc = "A warning sign which reads 'HIGH VOLTAGE'";
@@ -72505,10 +72186,6 @@
name = "Medbay Maintenance";
req_access_txt = "5"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plating,
/area/maintenance/genetics)
"cyF" = (
@@ -72646,10 +72323,6 @@
/obj/structure/disposalpipe/segment,
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plasteel{
icon_state = "white"
},
@@ -72956,10 +72629,6 @@
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 4
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
/turf/simulated/floor/plating,
/area/maintenance/asmaint)
"czy" = (
@@ -73660,10 +73329,6 @@
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 4
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
/turf/simulated/floor/plating,
/area/maintenance/asmaint2)
"cAH" = (
@@ -74106,10 +73771,6 @@
/obj/machinery/door/airlock/maintenance{
req_access_txt = "12"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 4
- },
/turf/simulated/floor/plating,
/area/maintenance/asmaint2)
"cBy" = (
@@ -74707,16 +74368,6 @@
},
/turf/simulated/floor/plating,
/area/maintenance/apmaint)
-"cCF" = (
-/obj/machinery/door/airlock/maintenance{
- req_access_txt = "12"
- },
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 4
- },
-/turf/simulated/floor/plating,
-/area/maintenance/apmaint)
"cCG" = (
/obj/structure/cable{
d1 = 2;
@@ -74755,10 +74406,6 @@
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 4
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
/turf/simulated/floor/plating,
/area/storage/tech)
"cCJ" = (
@@ -75216,7 +74863,6 @@
/obj/structure/disposalpipe/segment,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
-/obj/effect/mapping_helpers/airlock/unres,
/turf/simulated/floor/plasteel{
icon_state = "white"
},
@@ -76078,10 +75724,6 @@
name = "Alternate Construction Area";
req_access_txt = "12"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
/turf/simulated/floor/plating,
/area/maintenance/apmaint)
"cFf" = (
@@ -76615,10 +76257,6 @@
name = "Alternate Construction Area";
req_access_txt = "12"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
/turf/simulated/floor/plating,
/area/maintenance/consarea)
"cFU" = (
@@ -77116,7 +76754,6 @@
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
/obj/structure/disposalpipe/segment,
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
-/obj/effect/mapping_helpers/airlock/unres,
/turf/simulated/floor/wood,
/area/medical/psych)
"cGM" = (
@@ -77623,10 +77260,6 @@
/obj/machinery/door/airlock/maintenance{
req_access_txt = "12"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plating,
/area/maintenance/apmaint)
"cHF" = (
@@ -77779,10 +77412,6 @@
},
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plating,
/area/maintenance/apmaint)
"cHS" = (
@@ -79008,10 +78637,6 @@
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 4
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
/turf/simulated/floor/plasteel{
icon_state = "dark"
},
@@ -80231,10 +79856,6 @@
/obj/machinery/door/airlock/maintenance{
req_access_txt = "12"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
/turf/simulated/floor/plating,
/area/maintenance/aft)
"cMr" = (
@@ -81304,7 +80925,6 @@
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
-/obj/effect/mapping_helpers/airlock/unres,
/turf/simulated/floor/plating,
/area/maintenance/aft)
"cOt" = (
@@ -84378,10 +83998,6 @@
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 4
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 4
- },
/turf/simulated/floor/plasteel,
/area/engine/break_room)
"cTH" = (
@@ -88573,7 +88189,6 @@
/obj/machinery/door/airlock/maintenance{
req_access_txt = "12"
},
-/obj/effect/mapping_helpers/airlock/unres,
/turf/simulated/floor/plating,
/area/maintenance/aft)
"dbi" = (
@@ -88639,7 +88254,6 @@
tag = ""
},
/obj/structure/disposalpipe/segment,
-/obj/effect/mapping_helpers/airlock/unres,
/turf/simulated/floor/plating,
/area/maintenance/aft)
"dbq" = (
@@ -89110,10 +88724,6 @@
/area/maintenance/asmaint)
"dci" = (
/obj/machinery/door/airlock/maintenance,
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 4
- },
/turf/simulated/floor/plating,
/area/maintenance/genetics)
"dcj" = (
@@ -89450,6 +89060,7 @@
req_access_txt = "0";
req_one_access_txt = "10;24"
},
+/obj/structure/fans/tiny,
/turf/simulated/floor/plating,
/area/maintenance/engi_shuttle)
"dcV" = (
@@ -89966,7 +89577,6 @@
/obj/structure/disposalpipe/segment,
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
-/obj/effect/mapping_helpers/airlock/unres,
/turf/simulated/floor/plating,
/area/maintenance/engi_shuttle)
"ddX" = (
@@ -89982,13 +89592,6 @@
/obj/structure/lattice/catwalk,
/turf/space,
/area/space/nearstation)
-"ddY" = (
-/obj/machinery/door/airlock/maintenance{
- req_access_txt = "12"
- },
-/obj/effect/mapping_helpers/airlock/unres,
-/turf/simulated/floor/plating,
-/area/maintenance/asmaint2)
"ddZ" = (
/obj/structure/reagent_dispensers/watertank,
/obj/structure/cable{
@@ -90162,10 +89765,6 @@
d2 = 8;
icon_state = "4-8"
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
/turf/simulated/floor/plating,
/area/maintenance/asmaint)
"dep" = (
@@ -90176,7 +89775,6 @@
icon_state = "1-2";
tag = ""
},
-/obj/effect/mapping_helpers/airlock/unres,
/turf/simulated/floor/plating,
/area/maintenance/genetics)
"deq" = (
@@ -90578,10 +90176,6 @@
icon_state = "4-8";
pixel_x = 0
},
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
/turf/simulated/floor/plating,
/area/maintenance/asmaint2)
"dfg" = (
@@ -91018,16 +90612,6 @@
"dfV" = (
/turf/simulated/floor/plating,
/area/storage/secure)
-"dfW" = (
-/obj/machinery/door/airlock/maintenance{
- req_access_txt = "12"
- },
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 1
- },
-/turf/simulated/floor/plating,
-/area/maintenance/asmaint2)
"dfX" = (
/turf/space,
/turf/simulated/shuttle/wall{
@@ -91066,6 +90650,7 @@
name = "engineering dock";
width = 7
},
+/obj/structure/fans/tiny,
/turf/simulated/floor/plating,
/area/shuttle/constructionsite)
"dga" = (
@@ -91098,15 +90683,10 @@
req_access_txt = "12"
},
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
-/obj/effect/mapping_helpers/airlock/unres,
/turf/simulated/floor/plating,
/area/maintenance/asmaint)
"dgf" = (
/obj/machinery/door/airlock/maintenance,
-/obj/effect/mapping_helpers/airlock/unres{
- icon_state = "airlock_unres_helper";
- dir = 8
- },
/turf/simulated/floor/plating,
/area/maintenance/asmaint2)
"dgg" = (
@@ -114518,7 +114098,7 @@ aaa
cng
coL
coL
-ctK
+cqF
coL
cvk
cwx
@@ -115239,7 +114819,7 @@ aGn
aGn
aGn
aGn
-bbx
+aLk
aGn
aGn
aUy
@@ -115289,7 +114869,7 @@ aaa
cng
coL
coL
-ctK
+cqF
coL
coL
cwx
@@ -117093,7 +116673,7 @@ ctU
cgQ
cgQ
cgQ
-cCF
+cqF
cgQ
cgQ
cgQ
@@ -118375,7 +117955,7 @@ cam
aab
cgQ
ctU
-ctK
+cqF
coL
coL
coL
@@ -121980,7 +121560,7 @@ czN
cyg
cCH
coL
-ctK
+cqF
cEQ
cGj
cJZ
@@ -126806,7 +126386,7 @@ avq
avq
avq
avq
-axN
+aHp
aRx
aUw
aDN
@@ -128909,7 +128489,7 @@ cPd
cos
cPd
cqY
-ctD
+cmt
csL
csL
cvI
@@ -130710,7 +130290,7 @@ csL
cqD
csL
chf
-cyu
+cmt
chf
chf
chf
@@ -132958,7 +132538,7 @@ aIq
avq
aAc
aBt
-aGv
+aHp
aCh
aEw
aFI
@@ -133723,7 +133303,7 @@ ajb
awl
arR
awl
-avU
+aHp
aqc
aya
awl
@@ -135269,7 +134849,7 @@ avb
aAQ
awF
aye
-axN
+aHp
avq
aAS
atG
@@ -137340,7 +136920,7 @@ aFJ
aPq
aRv
aTb
-aXT
+aMn
aGY
aGY
aGY
@@ -139904,7 +139484,7 @@ aGX
aHc
aIv
aGX
-aOa
+aMn
aGX
aGX
aGX
@@ -140417,10 +139997,10 @@ aCy
aMf
aNf
aGY
-aNe
+aMn
aGY
aGY
-aNe
+aMn
aGY
aGY
aPK
@@ -140933,7 +140513,7 @@ aJI
aGY
aGX
aGX
-aKp
+aMn
aGX
aGX
aGY
@@ -142470,14 +142050,14 @@ aab
aAf
aAf
aAf
-aKp
+aMn
aAf
aHb
aMz
aMz
aIE
aGX
-aKp
+aMn
aMz
aGX
aOG
@@ -143520,7 +143100,7 @@ bcu
ber
bga
bis
-bMz
+bvN
bcD
bld
blw
@@ -147194,7 +146774,7 @@ bGH
bGG
dgy
bGG
-dfW
+cjA
dia
cuQ
djQ
@@ -148470,7 +148050,7 @@ aab
bGH
bGG
bGG
-ddY
+cjA
bGG
dcJ
ddJ
@@ -148735,7 +148315,7 @@ cuQ
dfc
bGG
bGG
-ddY
+cjA
bGG
bGG
bGH
diff --git a/_maps/map_files/cyberiad/z2.dmm b/_maps/map_files/cyberiad/z2.dmm
index d04bf394f26..d3417ba50f3 100644
--- a/_maps/map_files/cyberiad/z2.dmm
+++ b/_maps/map_files/cyberiad/z2.dmm
@@ -12230,6 +12230,12 @@
"FL" = (
/turf/simulated/wall/r_wall,
/area/adminconstruction)
+"Ga" = (
+/obj/machinery/computer/shuttle/ert,
+/turf/unsimulated/floor{
+ icon_state = "dark"
+ },
+/area/centcom/specops)
"GP" = (
/turf/unsimulated/floor{
icon_state = "gcircuit"
@@ -31701,7 +31707,7 @@ pb
uj
uj
uj
-uj
+Ga
sX
we
we
diff --git a/_maps/map_files/cyberiad/z4.dmm b/_maps/map_files/cyberiad/z4.dmm
index 08d56927445..bd20066c0a4 100644
--- a/_maps/map_files/cyberiad/z4.dmm
+++ b/_maps/map_files/cyberiad/z4.dmm
@@ -2571,6 +2571,7 @@
req_access_txt = "0";
req_one_access_txt = "10;24"
},
+/obj/structure/fans/tiny,
/turf/simulated/floor/plating,
/area/engiestation)
"gs" = (
diff --git a/code/__DEFINES/atmospherics.dm b/code/__DEFINES/atmospherics.dm
index 67eea12291a..1ccb0cd0786 100644
--- a/code/__DEFINES/atmospherics.dm
+++ b/code/__DEFINES/atmospherics.dm
@@ -128,3 +128,6 @@
#define ATMOS_ALARM_NONE 0
#define ATMOS_ALARM_WARNING 1
#define ATMOS_ALARM_DANGER 2
+
+//LAVALAND
+#define LAVALAND_EQUIPMENT_EFFECT_PRESSURE 50 //what pressure you have to be under to increase the effect of equipment meant for lavaland
\ No newline at end of file
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 8491c589751..e29e5be1c56 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -57,6 +57,89 @@
#define MAX_STACK_AMOUNT_GLASS 50
#define MAX_STACK_AMOUNT_RODS 60
+//Colors
+#define COLOR_RED "#FF0000"
+#define COLOR_GREEN "#00FF00"
+#define COLOR_BLUE "#0000FF"
+#define COLOR_CYAN "#00FFFF"
+#define COLOR_PINK "#FF00FF"
+#define COLOR_YELLOW "#FFFF00"
+#define COLOR_ORANGE "#FF9900"
+#define COLOR_WHITE "#FFFFFF"
+#define COLOR_GRAY "#808080"
+#define COLOR_BLACK "#000000"
+#define COLOR_NAVY_BLUE "#000080"
+#define COLOR_LIGHT_GREEN "#008000"
+#define COLOR_DARK_GRAY "#404040"
+#define COLOR_MAROON "#800000"
+#define COLOR_PURPLE "#800080"
+#define COLOR_VIOLET "#9933ff"
+#define COLOR_OLIVE "#808000"
+#define COLOR_BROWN_ORANGE "#824b28"
+#define COLOR_DARK_ORANGE "#b95a00"
+#define COLOR_GRAY40 "#666666"
+#define COLOR_GRAY20 "#333333"
+#define COLOR_GRAY15 "#151515"
+#define COLOR_SEDONA "#cc6600"
+#define COLOR_DARK_BROWN "#917448"
+#define COLOR_DEEP_SKY_BLUE "#00e1ff"
+#define COLOR_LIME "#00ff00"
+#define COLOR_TEAL "#33cccc"
+#define COLOR_PALE_PINK "#bf89ba"
+#define COLOR_YELLOW_GRAY "#c9a344"
+#define COLOR_PALE_YELLOW "#c1bb7a"
+#define COLOR_WARM_YELLOW "#b3863c"
+#define COLOR_RED_GRAY "#aa5f61"
+#define COLOR_BROWN "#b19664"
+#define COLOR_GREEN_GRAY "#8daf6a"
+#define COLOR_DARK_GREEN_GRAY "#54654c"
+#define COLOR_BLUE_GRAY "#6a97b0"
+#define COLOR_DARK_BLUE_GRAY "#3e4855"
+#define COLOR_SUN "#ec8b2f"
+#define COLOR_PURPLE_GRAY "#a2819e"
+#define COLOR_BLUE_LIGHT "#33ccff"
+#define COLOR_RED_LIGHT "#ff3333"
+#define COLOR_BEIGE "#ceb689"
+#define COLOR_BABY_BLUE "#89cff0"
+#define COLOR_PALE_GREEN_GRAY "#aed18b"
+#define COLOR_PALE_RED_GRAY "#cc9090"
+#define COLOR_PALE_PURPLE_GRAY "#bda2ba"
+#define COLOR_PALE_BLUE_GRAY "#8bbbd5"
+#define COLOR_LUMINOL "#66ffff"
+#define COLOR_SILVER "#c0c0c0"
+#define COLOR_GRAY80 "#cccccc"
+#define COLOR_OFF_WHITE "#eeeeee"
+#define COLOR_GOLD "#6d6133"
+#define COLOR_NT_RED "#9d2300"
+#define COLOR_BOTTLE_GREEN "#1f6b4f"
+#define COLOR_PALE_BTL_GREEN "#57967f"
+#define COLOR_GUNMETAL "#545c68"
+#define COLOR_WALL_GUNMETAL "#353a42"
+#define COLOR_STEEL "#a8b0b2"
+#define COLOR_MUZZLE_FLASH "#ffffb2"
+#define COLOR_CHESTNUT "#996633"
+#define COLOR_BEASTY_BROWN "#663300"
+#define COLOR_WHEAT "#ffff99"
+#define COLOR_CYAN_BLUE "#3366cc"
+#define COLOR_LIGHT_CYAN "#66ccff"
+#define COLOR_PAKISTAN_GREEN "#006600"
+#define COLOR_HULL "#436b8e"
+#define COLOR_AMBER "#ffbf00"
+#define COLOR_COMMAND_BLUE "#46698c"
+#define COLOR_SKY_BLUE "#5ca1cc"
+#define COLOR_PALE_ORANGE "#b88a3b"
+#define COLOR_CIVIE_GREEN "#b7f27d"
+#define COLOR_TITANIUM "#d1e6e3"
+#define COLOR_DARK_GUNMETAL "#4c535b"
+#define COLOR_BRONZE "#8c7853"
+#define COLOR_BRASS "#b99d71"
+#define COLOR_INDIGO "#4b0082"
+#define COLOR_ALUMINIUM "#bbbbbb"
+#define COLOR_CRYSTAL "#00c8a5"
+#define COLOR_ASTEROID_ROCK "#735555"
+#define COLOR_NULLGLASS "#ff6088"
+#define COLOR_DIAMOND "#d8d4ea"
+
//FONTS:
// Used by Paper and PhotoCopier (and PaperBin once a year).
// Used by PDA's Notekeeper.
@@ -320,7 +403,7 @@
#define INVESTIGATE_BOMB "bombs"
// The SQL version required by this version of the code
-#define SQL_VERSION 8
+#define SQL_VERSION 9
// Vending machine stuff
#define CAT_NORMAL 1
@@ -404,6 +487,12 @@
#define DICE_BASICALLY_RIGGED 2
#define DICE_TOTALLY_RIGGED 3
+// Parallax
+#define PARALLAX_DELAY_DEFAULT world.tick_lag
+#define PARALLAX_DELAY_MED 1
+#define PARALLAX_DELAY_LOW 2
+#define PARALLAX_LOOP_TIME 25
+
// Engine types
#define ENGTYPE_SING "Singularity"
#define ENGTYPE_SM "Supermatter"
diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index 284b0e4d745..608fcfcce20 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -187,6 +187,7 @@
#define isswarmer(A) (istype((A), /mob/living/simple_animal/hostile/swarmer))
#define isguardian(A) (istype((A), /mob/living/simple_animal/hostile/guardian))
#define isnymph(A) (istype((A), /mob/living/simple_animal/diona))
+#define ishostile(A) (istype(A, /mob/living/simple_animal/hostile))
#define issilicon(A) (istype((A), /mob/living/silicon))
#define isAI(A) (istype((A), /mob/living/silicon/ai))
diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm
index 9582fddccfe..a28d68a392b 100644
--- a/code/__DEFINES/preferences.dm
+++ b/code/__DEFINES/preferences.dm
@@ -63,3 +63,12 @@
#define EXP_TYPE_WHITELIST "Whitelist"
#define EXP_DEPT_TYPE_LIST list(EXP_TYPE_SERVICE, EXP_TYPE_MEDICAL, EXP_TYPE_ENGINEERING, EXP_TYPE_SCIENCE, EXP_TYPE_SECURITY, EXP_TYPE_COMMAND, EXP_TYPE_SILICON, EXP_TYPE_SPECIAL)
+
+// Defines just for parallax because its levels make storing it in the regular prefs a pain in the ass
+// These dont need to be bitflags because there isnt going to be more than one at a time of these active
+// But its gonna piss off my OCD if it isnt bitflags, so deal with it, -affected
+#define PARALLAX_DISABLE 1
+#define PARALLAX_LOW 2
+#define PARALLAX_MED 4
+#define PARALLAX_HIGH 8
+#define PARALLAX_INSANE 16
diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm
index e5d5bb723c1..f451a34a8b7 100644
--- a/code/__DEFINES/status_effects.dm
+++ b/code/__DEFINES/status_effects.dm
@@ -26,7 +26,7 @@
//#define STATUS_EFFECT_WISH_GRANTERS_GIFT /datum/status_effect/wish_granters_gift //If you're currently resurrecting with the Wish Granter
-//#define STATUS_EFFECT_BLOODDRUNK /datum/status_effect/blooddrunk //Stun immunity and greatly reduced damage taken
+#define STATUS_EFFECT_BLOODDRUNK /datum/status_effect/blooddrunk //Stun immunity and greatly reduced damage taken
/////////////
// DEBUFFS //
@@ -52,7 +52,7 @@
#define STATUS_EFFECT_SUMMONEDGHOST /datum/status_effect/cultghost //is a cult ghost and can't use manifest runes
-//#define STATUS_EFFECT_CRUSHERMARK /datum/status_effect/crusher_mark //if struck with a proto-kinetic crusher, takes a ton of damage
+#define STATUS_EFFECT_CRUSHERMARK /datum/status_effect/crusher_mark //if struck with a proto-kinetic crusher, takes a ton of damage
#define STATUS_EFFECT_SAWBLEED /datum/status_effect/saw_bleed //if the bleed builds up enough, takes a ton of damage
@@ -74,6 +74,6 @@
//#define STATUS_EFFECT_SIGILMARK /datum/status_effect/sigil_mark
-//#define STATUS_EFFECT_CRUSHERDAMAGETRACKING /datum/status_effect/crusher_damage //tracks total kinetic crusher damage on a target
+#define STATUS_EFFECT_CRUSHERDAMAGETRACKING /datum/status_effect/crusher_damage //tracks total kinetic crusher damage on a target
-//#define STATUS_EFFECT_SYPHONMARK /datum/status_effect/syphon_mark //tracks kills for the KA death syphon module
\ No newline at end of file
+#define STATUS_EFFECT_SYPHONMARK /datum/status_effect/syphon_mark //tracks kills for the KA death syphon module
\ No newline at end of file
diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm
index 27b69284a3d..3bb6b742a04 100644
--- a/code/__HELPERS/game.dm
+++ b/code/__HELPERS/game.dm
@@ -19,6 +19,12 @@
return A
return 0
+/proc/get_location_name(atom/X, format_text = FALSE)
+ var/area/A = isarea(X) ? X : get_area(X)
+ if(!A)
+ return null
+ return format_text ? format_text(A.name) : A.name
+
/proc/get_areas_in_range(dist=0, atom/center=usr)
if(!dist)
var/turf/T = get_turf(center)
@@ -429,6 +435,17 @@
/proc/GetBluePart(const/hexa)
return hex2num(copytext(hexa, 6, 8))
+/proc/lavaland_equipment_pressure_check(turf/T)
+ . = FALSE
+ if(!istype(T))
+ return
+ var/datum/gas_mixture/environment = T.return_air()
+ if(!istype(environment))
+ return
+ var/pressure = environment.return_pressure()
+ if(pressure <= LAVALAND_EQUIPMENT_EFFECT_PRESSURE)
+ . = TRUE
+
/proc/GetHexColors(const/hexa)
return list(
GetRedPart(hexa),
diff --git a/code/__HELPERS/icon_smoothing.dm b/code/__HELPERS/icon_smoothing.dm
index 11c86940b75..acf202f0eee 100644
--- a/code/__HELPERS/icon_smoothing.dm
+++ b/code/__HELPERS/icon_smoothing.dm
@@ -153,29 +153,33 @@
/turf/simulated/wall/diagonal_smooth(adjacencies)
adjacencies = reverse_ndir(..())
if(adjacencies)
- var/list/U = list()
+ var/mutable_appearance/underlay_appearance = mutable_appearance(layer = TURF_LAYER, plane = FLOOR_PLANE)
+ var/list/U = list(underlay_appearance)
if(fixed_underlay)
if(fixed_underlay["space"])
- U += image('icons/turf/space.dmi', SPACE_ICON_STATE, layer=TURF_LAYER)
+ underlay_appearance.icon = 'icons/turf/space.dmi'
+ underlay_appearance.icon_state = SPACE_ICON_STATE
+ underlay_appearance.plane = PLANE_SPACE
else
- U += image(fixed_underlay["icon"], fixed_underlay["icon_state"], layer=TURF_LAYER)
+ underlay_appearance.icon = fixed_underlay["icon"]
+ underlay_appearance.icon_state = fixed_underlay["icon_state"]
else
- var/turf/T = get_step(src, turn(adjacencies, 180))
- if(T && (T.density || T.smooth))
+ var/turned_adjacency = turn(adjacencies, 180)
+ var/turf/T = get_step(src, turned_adjacency)
+ if(!T.get_smooth_underlay_icon(underlay_appearance, src, turned_adjacency))
T = get_step(src, turn(adjacencies, 135))
- if(T && (T.density || T.smooth))
+ if(!T.get_smooth_underlay_icon(underlay_appearance, src, turned_adjacency))
T = get_step(src, turn(adjacencies, 225))
-
- if(istype(T, /turf/space) && !istype(T, /turf/space/transit))
- U += image('icons/turf/space.dmi', SPACE_ICON_STATE, layer=TURF_LAYER)
- else if(T && !T.density && !T.smooth)
- U += T
- else if(baseturf && !initial(baseturf.density) && !initial(baseturf.smooth))
- U += image(initial(baseturf.icon), initial(baseturf.icon_state), layer=TURF_LAYER)
- else
- U += DEFAULT_UNDERLAY_IMAGE
+ //if all else fails, ask our own turf
+ if(!T.get_smooth_underlay_icon(underlay_appearance, src, turned_adjacency) && !get_smooth_underlay_icon(underlay_appearance, src, turned_adjacency))
+ underlay_appearance.icon = DEFAULT_UNDERLAY_ICON
+ underlay_appearance.icon_state = DEFAULT_UNDERLAY_ICON_STATE
underlays = U
+ // Drop posters which were previously placed on this wall.
+ for(var/obj/structure/sign/poster/P in src)
+ P.roll_and_drop(src)
+
/proc/cardinal_smooth(atom/A, adjacencies)
//NW CORNER
var/nw = "1-i"
diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm
index 04d63e0e862..08af11a128c 100644
--- a/code/__HELPERS/text.dm
+++ b/code/__HELPERS/text.dm
@@ -545,6 +545,43 @@ proc/checkhtml(var/t)
text = copytext(text, 1, MAX_PAPER_MESSAGE_LEN)
return text
+/proc/convert_pencode_arg(text, tag, arg)
+ arg = sanitize_simple(html_encode(arg), list("''"="","\""="", "?"=""))
+ // https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#rule-4---css-escape-and-strictly-validate-before-inserting-untrusted-data-into-html-style-property-values
+ var/list/style_attacks = list("javascript:", "expression", "byond:", "file:")
+
+ for(var/style_attack in style_attacks)
+ if(findtext(arg, style_attack))
+ // Do not attempt to render dangerous things
+ return text
+
+ if(tag == "class")
+ return ""
+
+ if(tag == "style")
+ return ""
+
+ if(tag == "img")
+ var/list/img_props = splittext(arg, ";")
+ if(img_props.len == 3)
+ return "
"
+ if(img_props.len == 2)
+ return "
"
+ return "
"
+
+ return text
+
+/proc/admin_pencode_to_html()
+ var/text = pencode_to_html(arglist(args))
+ var/regex/R = new(@"\[(.*?) (.*?)\]", "ge")
+ text = R.Replace(text, /proc/convert_pencode_arg)
+
+ text = replacetext(text, "\[/class\]", "")
+ text = replacetext(text, "\[/style\]", "")
+ text = replacetext(text, "\[/img\]", "")
+
+ return text
+
/proc/html_to_pencode(text)
text = replacetext(text, "
", "\n")
text = replacetext(text, "
", "\[center\]")
diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm
index 22921f5228d..ca8f32f2599 100644
--- a/code/_onclick/ai.dm
+++ b/code/_onclick/ai.dm
@@ -209,11 +209,13 @@
/atom/proc/AIMiddleClick()
return
-/obj/machinery/door/airlock/AIMiddleClick() // Toggles door bolt lights.
- if(!src.lights)
- Topic(src, list("src" = UID(), "command"="lights", "activate" = "1"), 1) // 1 meaning no window (consistency!)
+/obj/machinery/door/airlock/AIMiddleClick() // Toggles door safety.
+ if(safe)
+ Topic(src, list("src" = UID(), "command"="safeties", "activate" = "1"), 1) // 1 meaning no window (consistency!)
+ to_chat(usr, "The door safeties have been overridden.")
else
- Topic(src, list("src" = UID(), "command"="lights", "activate" = "0"), 1)
+ Topic(src, list("src" = UID(), "command"="safeties", "activate" = "0"), 1)
+ to_chat(usr, "The door safeties have been reset.")
return
/obj/machinery/ai_slipper/AICtrlClick() //Turns liquid dispenser on or off
diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm
index e3d423130e5..58e82733abe 100644
--- a/code/_onclick/hud/_defines.dm
+++ b/code/_onclick/hud/_defines.dm
@@ -107,14 +107,20 @@
#define ui_healthdoll "EAST-1:28,CENTER-1:15"
#define ui_health "EAST-1:28,CENTER:17"
#define ui_internal "EAST-1:28,CENTER+1:19"
- //borgs
+
+//borgs
#define ui_borg_health "EAST-1:28,CENTER-1:15" //borgs have the health display where humans have the pressure damage indicator.
+
+//aliens
#define ui_alien_health "EAST-1:28,CENTER-1:15" //aliens have the health display where humans have the pressure damage indicator.
-
+//constructs
#define ui_construct_pull "EAST-1:28,SOUTH+1:10" //above the zone_sel icon
#define ui_construct_health "EAST,CENTER:15" //same height as humans, hugging the right border
+//slimes
+#define ui_slime_health "EAST,CENTER:15" //same as borgs, constructs and humans
+
//Pop-up inventory
#define ui_shoes "WEST+1:8,SOUTH:5"
diff --git a/code/_onclick/hud/action_button.dm b/code/_onclick/hud/action_button.dm
index 15ed4429965..b70c98908f5 100644
--- a/code/_onclick/hud/action_button.dm
+++ b/code/_onclick/hud/action_button.dm
@@ -2,6 +2,25 @@
var/datum/action/linked_action
screen_loc = null
+/obj/screen/movable/action_button/MouseDrop(over_object)
+ if((istype(over_object, /obj/screen/movable/action_button) && !istype(over_object, /obj/screen/movable/action_button/hide_toggle)))
+ if(locked)
+ to_chat(usr, "Action button \"[name]\" is locked, unlock it first.")
+ closeToolTip(usr)
+ return
+ var/obj/screen/movable/action_button/B = over_object
+ var/list/actions = usr.actions
+ actions.Swap(actions.Find(linked_action), actions.Find(B.linked_action))
+ moved = FALSE
+ B.moved = FALSE
+ closeToolTip(usr)
+ usr.update_action_buttons()
+ else if(istype(over_object, /obj/screen/movable/action_button/hide_toggle))
+ closeToolTip(usr)
+ else
+ closeToolTip(usr)
+ return ..()
+
/obj/screen/movable/action_button/Click(location,control,params)
var/list/modifiers = params2list(params)
if(modifiers["shift"])
@@ -29,6 +48,13 @@
icon_state = "bg_default"
var/hidden = 0
+/obj/screen/movable/action_button/hide_toggle/MouseDrop(over_object)
+ if(istype(over_object, /obj/screen/movable/action_button))
+ closeToolTip(usr)
+ else
+ closeToolTip(usr)
+ return ..()
+
/obj/screen/movable/action_button/hide_toggle/Click(location,control,params)
var/list/modifiers = params2list(params)
if(modifiers["shift"])
@@ -83,9 +109,9 @@
var/image/img = image(icon, src, hidden ? "show" : "hide")
overlays += img
-/obj/screen/movable/action_button/MouseEntered(location,control,params)
- openToolTip(usr,src,params,title = name,content = desc)
-
+/obj/screen/movable/action_button/MouseEntered(location, control, params)
+ if(!QDELETED(src))
+ openToolTip(usr, src, params, title = name, content = desc)
/obj/screen/movable/action_button/MouseExited()
closeToolTip(usr)
diff --git a/code/_onclick/hud/ghost.dm b/code/_onclick/hud/ghost.dm
index 4e92395f4cc..600c1105e8e 100644
--- a/code/_onclick/hud/ghost.dm
+++ b/code/_onclick/hud/ghost.dm
@@ -59,3 +59,8 @@
using = new /obj/screen/ghost/teleport()
using.screen_loc = ui_ghost_teleport
static_inventory += using
+
+/datum/hud/ghost/show_hud()
+ mymob.client.screen = list()
+ mymob.client.screen += static_inventory
+ ..()
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index 0063feae9cf..e93b3b121e6 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -99,6 +99,7 @@
/datum/hud/proc/show_hud(version = 0)
if(!ismob(mymob))
return FALSE
+
if(!mymob.client)
return FALSE
@@ -172,6 +173,7 @@
mymob.update_action_buttons(1)
reorganize_alerts()
reload_fullscreen()
+ update_parallax_pref(mymob)
plane_masters_update()
/datum/hud/proc/plane_masters_update()
diff --git a/code/_onclick/hud/parallax.dm b/code/_onclick/hud/parallax.dm
new file mode 100644
index 00000000000..46fe7331dbe
--- /dev/null
+++ b/code/_onclick/hud/parallax.dm
@@ -0,0 +1,311 @@
+/client
+ var/list/parallax_layers
+ var/list/parallax_layers_cached
+ var/static/list/parallax_static_layers_tail = newlist(/obj/screen/parallax_pmaster, /obj/screen/parallax_space_whitifier)
+ var/atom/movable/movingmob
+ var/turf/previous_turf
+ var/dont_animate_parallax //world.time of when we can state animate()ing parallax again
+ var/last_parallax_shift //world.time of last update
+ var/parallax_throttle = 0 //ds between updates
+ var/parallax_movedir = 0
+ var/parallax_layers_max = 3
+ var/parallax_animate_timer
+
+/datum/hud/proc/create_parallax()
+ var/client/C = mymob.client
+ if(!apply_parallax_pref())
+ return
+
+ if(!length(C.parallax_layers_cached))
+ C.parallax_layers_cached = list()
+ C.parallax_layers_cached += new /obj/screen/parallax_layer/layer_1(null, C.view)
+ C.parallax_layers_cached += new /obj/screen/parallax_layer/layer_2(null, C.view)
+ C.parallax_layers_cached += new /obj/screen/parallax_layer/planet(null, C.view)
+
+ C.parallax_layers = C.parallax_layers_cached.Copy()
+
+ if(length(C.parallax_layers) > C.parallax_layers_max)
+ C.parallax_layers.len = C.parallax_layers_max
+
+ C.screen |= (C.parallax_layers + C.parallax_static_layers_tail)
+
+/datum/hud/proc/remove_parallax()
+ var/client/C = mymob.client
+ C.screen -= (C.parallax_layers_cached + C.parallax_static_layers_tail)
+ C.parallax_layers = null
+
+/datum/hud/proc/apply_parallax_pref()
+ var/client/C = mymob.client
+ if(C.prefs)
+ var/pref = C.prefs.parallax
+ if (isnull(pref))
+ pref = PARALLAX_HIGH
+ switch(C.prefs.parallax)
+ if (PARALLAX_INSANE)
+ C.parallax_throttle = FALSE
+ C.parallax_layers_max = 4
+ return TRUE
+
+ if (PARALLAX_MED)
+ C.parallax_throttle = PARALLAX_DELAY_MED
+ C.parallax_layers_max = 2
+ return TRUE
+
+ if (PARALLAX_LOW)
+ C.parallax_throttle = PARALLAX_DELAY_LOW
+ C.parallax_layers_max = 1
+ return TRUE
+
+ if (PARALLAX_DISABLE)
+ return FALSE
+
+ C.parallax_throttle = PARALLAX_DELAY_DEFAULT
+ C.parallax_layers_max = 3
+ return TRUE
+
+/datum/hud/proc/update_parallax_pref()
+ remove_parallax()
+ create_parallax()
+ update_parallax()
+
+// This sets which way the current shuttle is moving (returns true if the shuttle has stopped moving so the caller can append their animation)
+// Well, it would if our shuttle code had dynamic areas
+/datum/hud/proc/set_parallax_movedir(new_parallax_movedir, skip_windups)
+ . = FALSE
+ var/client/C = mymob.client
+ if(new_parallax_movedir == C.parallax_movedir)
+ return
+ var/animatedir = new_parallax_movedir
+ if(new_parallax_movedir == FALSE)
+ var/animate_time = 0
+ for(var/thing in C.parallax_layers)
+ var/obj/screen/parallax_layer/L = thing
+ L.icon_state = initial(L.icon_state)
+ L.update_o(C.view)
+ var/T = PARALLAX_LOOP_TIME / L.speed
+ if(T > animate_time)
+ animate_time = T
+ C.dont_animate_parallax = world.time + min(animate_time, PARALLAX_LOOP_TIME)
+ animatedir = C.parallax_movedir
+
+ var/matrix/newtransform
+ switch(animatedir)
+ if(NORTH)
+ newtransform = matrix(1, 0, 0, 0, 1, 480)
+ if(SOUTH)
+ newtransform = matrix(1, 0, 0, 0, 1,-480)
+ if(EAST)
+ newtransform = matrix(1, 0, 480, 0, 1, 0)
+ if(WEST)
+ newtransform = matrix(1, 0,-480, 0, 1, 0)
+
+ var/shortesttimer
+ for(var/thing in C.parallax_layers)
+ var/obj/screen/parallax_layer/L = thing
+
+ var/T = PARALLAX_LOOP_TIME / L.speed
+ if(isnull(shortesttimer))
+ shortesttimer = T
+ if(T < shortesttimer)
+ shortesttimer = T
+ L.transform = newtransform
+ animate(L, transform = matrix(), time = T, easing = QUAD_EASING | (new_parallax_movedir ? EASE_IN : EASE_OUT), flags = ANIMATION_END_NOW)
+ if(new_parallax_movedir)
+ L.transform = newtransform
+ animate(transform = matrix(), time = T) //queue up another animate so lag doesn't create a shutter
+
+ C.parallax_movedir = new_parallax_movedir
+ if(C.parallax_animate_timer)
+ deltimer(C.parallax_animate_timer)
+ var/datum/callback/CB = CALLBACK(src, .proc/update_parallax_motionblur, C, animatedir, new_parallax_movedir, newtransform)
+ if(skip_windups)
+ CB.Invoke()
+ else
+ C.parallax_animate_timer = addtimer(CB, min(shortesttimer, PARALLAX_LOOP_TIME), TIMER_CLIENT_TIME|TIMER_STOPPABLE)
+
+/datum/hud/proc/update_parallax_motionblur(client/C, animatedir, new_parallax_movedir, matrix/newtransform)
+ C.parallax_animate_timer = FALSE
+ for(var/thing in C.parallax_layers)
+ var/obj/screen/parallax_layer/L = thing
+ if(!new_parallax_movedir)
+ animate(L)
+ continue
+
+ var/newstate = initial(L.icon_state)
+ if(animatedir)
+ if(animatedir == NORTH || animatedir == SOUTH)
+ newstate += "_vertical"
+ else
+ newstate += "_horizontal"
+
+ var/T = PARALLAX_LOOP_TIME / L.speed
+
+ if(newstate in icon_states(L.icon))
+ L.icon_state = newstate
+ L.update_o(C.view)
+
+ L.transform = newtransform
+
+ animate(L, transform = matrix(), time = T, loop = -1, flags = ANIMATION_END_NOW)
+
+/datum/hud/proc/update_parallax()
+ var/client/C = mymob.client
+ var/turf/posobj = get_turf(C.eye)
+ var/area/areaobj = posobj.loc
+
+ // Update the movement direction of the parallax if necessary (for shuttles)
+ var/area/shuttle/SA = areaobj
+ if(!SA || !SA.moving)
+ set_parallax_movedir(0)
+ else
+ set_parallax_movedir(SA.parallax_movedir)
+
+ var/force
+ if(!C.previous_turf || (C.previous_turf.z != posobj.z))
+ C.previous_turf = posobj
+ force = TRUE
+
+ if(!force && world.time < C.last_parallax_shift+C.parallax_throttle)
+ return
+
+ //Doing it this way prevents parallax layers from "jumping" when you change Z-Levels.
+ var/offset_x = posobj.x - C.previous_turf.x
+ var/offset_y = posobj.y - C.previous_turf.y
+
+ if(!offset_x && !offset_y && !force)
+ return
+
+ var/last_delay = world.time - C.last_parallax_shift
+ last_delay = min(last_delay, C.parallax_throttle)
+ C.previous_turf = posobj
+ C.last_parallax_shift = world.time
+
+ for(var/thing in C.parallax_layers)
+ var/obj/screen/parallax_layer/L = thing
+ L.update_status(mymob)
+ if(L.view_sized != C.view)
+ L.update_o(C.view)
+
+ var/change_x
+ var/change_y
+
+ if(L.absolute)
+ L.offset_x = -(posobj.x - SSparallax.planet_x_offset) * L.speed
+ L.offset_y = -(posobj.y - SSparallax.planet_y_offset) * L.speed
+ else
+ change_x = offset_x * L.speed
+ L.offset_x -= change_x
+ change_y = offset_y * L.speed
+ L.offset_y -= change_y
+
+ if(L.offset_x > 240)
+ L.offset_x -= 480
+ if(L.offset_x < -240)
+ L.offset_x += 480
+ if(L.offset_y > 240)
+ L.offset_y -= 480
+ if(L.offset_y < -240)
+ L.offset_y += 480
+
+ if(!(areaobj.parallax_movedir && areaobj.moving) && C.dont_animate_parallax <= world.time && (offset_x || offset_y) && abs(offset_x) <= max(C.parallax_throttle/world.tick_lag+1,1) && abs(offset_y) <= max(C.parallax_throttle/world.tick_lag+1,1) && (round(abs(change_x)) > 1 || round(abs(change_y)) > 1))
+ L.transform = matrix(1, 0, offset_x*L.speed, 0, 1, offset_y*L.speed)
+ animate(L, transform=matrix(), time = last_delay)
+
+ L.screen_loc = "CENTER-7:[round(L.offset_x,1)],CENTER-7:[round(L.offset_y,1)]"
+
+/atom/movable/proc/update_parallax_contents()
+ if(length(client_mobs_in_contents))
+ for(var/thing in client_mobs_in_contents)
+ var/mob/M = thing
+ if(M && M.client && M.hud_used && length(M.client.parallax_layers))
+ M.hud_used.update_parallax()
+
+/obj/screen/parallax_layer
+ icon = 'icons/effects/parallax.dmi'
+ var/speed = 1
+ var/offset_x = 0
+ var/offset_y = 0
+ var/view_sized
+ var/absolute = FALSE
+ blend_mode = BLEND_ADD
+ plane = PLANE_SPACE_PARALLAX
+ screen_loc = "CENTER-7,CENTER-7"
+ mouse_opacity = 0
+
+
+/obj/screen/parallax_layer/New(view)
+ ..()
+ if(!view)
+ view = world.view
+ update_o(view)
+
+/obj/screen/parallax_layer/proc/update_o(view)
+ if(!view)
+ view = world.view
+ var/list/new_overlays = list()
+ var/count = Ceiling(view/(480/world.icon_size))+1
+ for(var/x in -count to count)
+ for(var/y in -count to count)
+ if(x == 0 && y == 0)
+ continue
+ var/mutable_appearance/texture_overlay = mutable_appearance(icon, icon_state)
+ texture_overlay.transform = matrix(1, 0, x*480, 0, 1, y*480)
+ new_overlays += texture_overlay
+
+ overlays = new_overlays
+ view_sized = view
+
+/obj/screen/parallax_layer/proc/update_status(mob/M)
+ return
+
+/obj/screen/parallax_layer/layer_1
+ icon_state = "layer1"
+ speed = 0.6
+ layer = 1
+
+/obj/screen/parallax_layer/layer_2
+ icon_state = "layer2"
+ speed = 1
+ layer = 2
+
+/obj/screen/parallax_layer/planet
+ icon_state = "planet"
+ blend_mode = BLEND_OVERLAY
+ absolute = TRUE //Status of seperation
+ speed = 3
+ layer = 30
+
+/obj/screen/parallax_layer/planet/update_status(mob/M)
+ var/turf/T = get_turf(M)
+ if(is_station_level(T.z))
+ invisibility = 0
+ else
+ invisibility = INVISIBILITY_ABSTRACT
+
+/obj/screen/parallax_layer/planet/update_o()
+ return //Shit wont move
+
+/obj/screen/parallax_pmaster
+ appearance_flags = PLANE_MASTER
+ plane = PLANE_SPACE_PARALLAX
+ blend_mode = BLEND_MULTIPLY
+ mouse_opacity = FALSE
+ screen_loc = "CENTER-7,CENTER-7"
+
+/obj/screen/parallax_space_whitifier
+ appearance_flags = PLANE_MASTER
+ plane = PLANE_SPACE
+ color = list(
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 1, 1, 1, 1,
+ 0, 0, 0, 0
+ )
+ screen_loc = "CENTER-7,CENTER-7"
+
+
+#undef LOOP_NONE
+#undef LOOP_NORMAL
+#undef LOOP_REVERSE
+#undef LOOP_TIME
\ No newline at end of file
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index a0274c30616..8bc65fcf691 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -456,6 +456,12 @@
/obj/screen/healths/corgi
icon = 'icons/mob/screen_corgi.dmi'
+/obj/screen/healths/slime
+ icon = 'icons/mob/screen_slime.dmi'
+ icon_state = "slime_health0"
+ screen_loc = ui_slime_health
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+
/obj/screen/healths/guardian
name = "summoner health"
icon = 'icons/mob/guardian.dmi'
diff --git a/code/_onclick/hud/slime.dm b/code/_onclick/hud/slime.dm
new file mode 100644
index 00000000000..9f5621b75ee
--- /dev/null
+++ b/code/_onclick/hud/slime.dm
@@ -0,0 +1,18 @@
+/mob/living/carbon/slime/create_mob_hud()
+ if(client && !hud_used)
+ hud_used = new /datum/hud/slime(src)
+
+/mob/living/simple_animal/slime/create_mob_hud()
+ if(client && !hud_used)
+ hud_used = new /datum/hud/slime(src)
+
+/datum/hud/slime/New(mob/owner)
+ ..()
+ mymob.healths = new /obj/screen/healths/slime()
+ infodisplay += mymob.healths
+
+ mymob.pullin = new /obj/screen/pull()
+ mymob.pullin.icon = 'icons/mob/screen_slime.dmi'
+ mymob.pullin.update_icon(mymob)
+ mymob.pullin.screen_loc = ui_construct_pull
+ hotkeybuttons += mymob.pullin
diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm
index 797384b8336..a988277012b 100644
--- a/code/_onclick/observer.dm
+++ b/code/_onclick/observer.dm
@@ -17,6 +17,7 @@
else
following = null
forceMove(get_turf(A))
+ update_parallax_contents()
/mob/dead/observer/ClickOn(var/atom/A, var/params)
if(client.click_intercept)
diff --git a/code/controllers/subsystem/parallax.dm b/code/controllers/subsystem/parallax.dm
new file mode 100644
index 00000000000..039b6d2b008
--- /dev/null
+++ b/code/controllers/subsystem/parallax.dm
@@ -0,0 +1,44 @@
+SUBSYSTEM_DEF(parallax)
+ name = "Parallax"
+ wait = 2
+ flags = SS_POST_FIRE_TIMING | SS_BACKGROUND
+ priority = FIRE_PRIORITY_PARALLAX
+ runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
+ var/list/currentrun
+ var/planet_x_offset = 128
+ var/planet_y_offset = 128
+
+/datum/controller/subsystem/parallax/Initialize(timeofday)
+ . = ..()
+ planet_y_offset = rand(100, 160)
+ planet_x_offset = rand(100, 160)
+
+/datum/controller/subsystem/parallax/fire(resumed = 0)
+ if(!resumed)
+ src.currentrun = GLOB.clients.Copy()
+
+ //cache for sanic speed (lists are references anyways)
+ var/list/currentrun = src.currentrun
+
+ while(length(currentrun))
+ var/client/C = currentrun[currentrun.len]
+ currentrun.len--
+ if(!C || !C.eye)
+ if(MC_TICK_CHECK)
+ return
+ continue
+ var/atom/movable/A = C.eye
+ if(!istype(A))
+ continue
+ for (A; isloc(A.loc) && !isturf(A.loc); A = A.loc);
+
+ if(A != C.movingmob)
+ if(C.movingmob != null)
+ C.movingmob.client_mobs_in_contents -= C.mob
+ UNSETEMPTY(C.movingmob.client_mobs_in_contents)
+ LAZYINITLIST(A.client_mobs_in_contents)
+ A.client_mobs_in_contents += C.mob
+ C.movingmob = A
+ if(MC_TICK_CHECK)
+ return
+ currentrun = null
diff --git a/code/datums/components/paintable.dm b/code/datums/components/paintable.dm
new file mode 100644
index 00000000000..ef9a2923cc6
--- /dev/null
+++ b/code/datums/components/paintable.dm
@@ -0,0 +1,31 @@
+/datum/component/spraycan_paintable
+ var/current_paint
+
+/datum/component/spraycan_paintable/Initialize()
+ RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/Repaint)
+
+/datum/component/spraycan_paintable/Destroy()
+ RemoveCurrentCoat()
+ return ..()
+
+/datum/component/spraycan_paintable/proc/RemoveCurrentCoat()
+ var/atom/A = parent
+ A.remove_atom_colour(FIXED_COLOUR_PRIORITY, current_paint)
+
+/datum/component/spraycan_paintable/proc/Repaint(datum/source, obj/item/toy/crayon/spraycan/spraycan, mob/living/user)
+ if(!istype(spraycan) || user.a_intent == INTENT_HARM)
+ return
+ . = COMPONENT_NO_AFTERATTACK
+ if(spraycan.capped)
+ to_chat(user, "Take the cap off first!")
+ return
+ if(spraycan.uses < 2)
+ to_chat(user, "There is not enough paint in the can!")
+ return
+ RemoveCurrentCoat()
+ var/colour = spraycan.colour
+ current_paint = colour
+ var/atom/A = parent
+ A.add_atom_colour(colour, FIXED_COLOUR_PRIORITY)
+ playsound(spraycan, 'sound/effects/spray.ogg', 5, 1, 5)
+ to_chat(user, "You spray [spraycan] on [A], painting it.")
diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm
index 387cc70f992..fb336192b38 100644
--- a/code/datums/status_effects/buffs.dm
+++ b/code/datums/status_effects/buffs.dm
@@ -40,6 +40,132 @@
playsound(owner, 'sound/weapons/bite.ogg', 50, 1)
owner.adjustBruteLoss(3)
+/datum/status_effect/blooddrunk
+ id = "blooddrunk"
+ duration = 10
+ tick_interval = 0
+ alert_type = /obj/screen/alert/status_effect/blooddrunk
+ var/last_health = 0
+ var/last_bruteloss = 0
+ var/last_fireloss = 0
+ var/last_toxloss = 0
+ var/last_oxyloss = 0
+ var/last_cloneloss = 0
+ var/last_staminaloss = 0
+
+/obj/screen/alert/status_effect/blooddrunk
+ name = "Blood-Drunk"
+ desc = "You are drunk on blood! Your pulse thunders in your ears! Nothing can harm you!" //not true, and the item description mentions its actual effect
+ icon_state = "blooddrunk"
+
+/datum/status_effect/blooddrunk/on_apply()
+ . = ..()
+ if(.)
+ owner.maxHealth *= 10
+ owner.bruteloss *= 10
+ owner.fireloss *= 10
+ if(ishuman(owner))
+ var/mob/living/carbon/human/H = owner
+ for(var/X in H.bodyparts)
+ var/obj/item/organ/external/BP = X
+ BP.max_damage *= 10
+ BP.min_broken_damage *= 10
+ BP.brute_dam *= 10
+ BP.burn_dam *= 10
+ owner.toxloss *= 10
+ owner.oxyloss *= 10
+ owner.cloneloss *= 10
+ owner.staminaloss *= 10
+ owner.updatehealth()
+ last_health = owner.health
+ last_bruteloss = owner.getBruteLoss()
+ last_fireloss = owner.getFireLoss()
+ last_toxloss = owner.getToxLoss()
+ last_oxyloss = owner.getOxyLoss()
+ last_cloneloss = owner.getCloneLoss()
+ last_staminaloss = owner.getStaminaLoss()
+ add_attack_logs(owner, owner, "gained blood-drunk stun immunity")
+ var/status = CANSTUN | CANWEAKEN | CANPARALYSE | IGNORESLOWDOWN
+ owner.status_flags &= ~status
+ owner.playsound_local(get_turf(owner), 'sound/effects/singlebeat.ogg', 40, 1)
+
+/datum/status_effect/blooddrunk/tick() //multiply the effect of healing by 10
+ if(owner.health > last_health)
+ var/needs_health_update = FALSE
+ var/new_bruteloss = owner.getBruteLoss()
+ if(new_bruteloss < last_bruteloss)
+ var/heal_amount = (new_bruteloss - last_bruteloss) * 10
+ owner.adjustBruteLoss(heal_amount, updating_health = FALSE)
+ new_bruteloss = owner.getBruteLoss()
+ needs_health_update = TRUE
+ last_bruteloss = new_bruteloss
+
+ var/new_fireloss = owner.getFireLoss()
+ if(new_fireloss < last_fireloss)
+ var/heal_amount = (new_fireloss - last_fireloss) * 10
+ owner.adjustFireLoss(heal_amount, updating_health = FALSE)
+ new_fireloss = owner.getFireLoss()
+ needs_health_update = TRUE
+ last_fireloss = new_fireloss
+
+ var/new_toxloss = owner.getToxLoss()
+ if(new_toxloss < last_toxloss)
+ var/heal_amount = (new_toxloss - last_toxloss) * 10
+ owner.adjustToxLoss(heal_amount, updating_health = FALSE)
+ new_toxloss = owner.getToxLoss()
+ needs_health_update = TRUE
+ last_toxloss = new_toxloss
+
+ var/new_oxyloss = owner.getOxyLoss()
+ if(new_oxyloss < last_oxyloss)
+ var/heal_amount = (new_oxyloss - last_oxyloss) * 10
+ owner.adjustOxyLoss(heal_amount, updating_health = FALSE)
+ new_oxyloss = owner.getOxyLoss()
+ needs_health_update = TRUE
+ last_oxyloss = new_oxyloss
+
+ var/new_cloneloss = owner.getCloneLoss()
+ if(new_cloneloss < last_cloneloss)
+ var/heal_amount = (new_cloneloss - last_cloneloss) * 10
+ owner.adjustCloneLoss(heal_amount, updating_health = FALSE)
+ new_cloneloss = owner.getCloneLoss()
+ needs_health_update = TRUE
+ last_cloneloss = new_cloneloss
+
+ var/new_staminaloss = owner.getStaminaLoss()
+ if(new_staminaloss < last_staminaloss)
+ var/heal_amount = (new_staminaloss - last_staminaloss) * 10
+ owner.adjustStaminaLoss(heal_amount, updating_health = FALSE)
+ new_staminaloss = owner.getStaminaLoss()
+ needs_health_update = TRUE
+ last_staminaloss = new_staminaloss
+
+ if(needs_health_update)
+ owner.updatehealth()
+ owner.playsound_local(get_turf(owner), 'sound/effects/singlebeat.ogg', 40, 1)
+ last_health = owner.health
+
+/datum/status_effect/blooddrunk/on_remove()
+ tick()
+ owner.maxHealth *= 0.1
+ owner.bruteloss *= 0.1
+ owner.fireloss *= 0.1
+ if(ishuman(owner))
+ var/mob/living/carbon/human/H = owner
+ for(var/X in H.bodyparts)
+ var/obj/item/organ/external/BP = X
+ BP.brute_dam *= 0.1
+ BP.burn_dam *= 0.1
+ BP.max_damage /= 10
+ BP.min_broken_damage /= 10
+ owner.toxloss *= 0.1
+ owner.oxyloss *= 0.1
+ owner.cloneloss *= 0.1
+ owner.staminaloss *= 0.1
+ owner.updatehealth()
+ add_attack_logs(owner, owner, "lost blood-drunk stun immunity")
+ owner.status_flags |= CANSTUN | CANWEAKEN | CANPARALYSE | IGNORESLOWDOWN
+
/datum/status_effect/exercised
id = "Exercised"
duration = 1200
diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm
index 6e809b32606..3ce68f85250 100644
--- a/code/datums/status_effects/debuffs.dm
+++ b/code/datums/status_effects/debuffs.dm
@@ -9,6 +9,39 @@
if(owner.reagents)
owner.reagents.del_reagent("holywater") //can't be deconverted
+/datum/status_effect/crusher_mark
+ id = "crusher_mark"
+ duration = 300 //if you leave for 30 seconds you lose the mark, deal with it
+ status_type = STATUS_EFFECT_REPLACE
+ alert_type = null
+ var/mutable_appearance/marked_underlay
+ var/obj/item/twohanded/kinetic_crusher/hammer_synced
+
+/datum/status_effect/crusher_mark/on_creation(mob/living/new_owner, obj/item/twohanded/kinetic_crusher/new_hammer_synced)
+ . = ..()
+ if(.)
+ hammer_synced = new_hammer_synced
+
+/datum/status_effect/crusher_mark/on_apply()
+ if(owner.mob_size >= MOB_SIZE_LARGE)
+ marked_underlay = mutable_appearance('icons/effects/effects.dmi', "shield2")
+ marked_underlay.pixel_x = -owner.pixel_x
+ marked_underlay.pixel_y = -owner.pixel_y
+ owner.underlays += marked_underlay
+ return TRUE
+ return FALSE
+
+/datum/status_effect/crusher_mark/Destroy()
+ hammer_synced = null
+ if(owner)
+ owner.underlays -= marked_underlay
+ QDEL_NULL(marked_underlay)
+ return ..()
+
+/datum/status_effect/crusher_mark/be_replaced()
+ owner.underlays -= marked_underlay //if this is being called, we should have an owner at this point.
+ ..()
+
/datum/status_effect/saw_bleed
id = "saw_bleed"
duration = -1 //removed under specific conditions
diff --git a/code/datums/status_effects/neutral.dm b/code/datums/status_effects/neutral.dm
index eaa14c4d0b0..8f5023e4a74 100644
--- a/code/datums/status_effects/neutral.dm
+++ b/code/datums/status_effects/neutral.dm
@@ -1,5 +1,43 @@
//entirely neutral or internal status effects go here
+/datum/status_effect/crusher_damage //tracks the damage dealt to this mob by kinetic crushers
+ id = "crusher_damage"
+ duration = -1
+ status_type = STATUS_EFFECT_UNIQUE
+ alert_type = null
+ var/total_damage = 0
+
+/datum/status_effect/syphon_mark
+ id = "syphon_mark"
+ duration = 50
+ status_type = STATUS_EFFECT_MULTIPLE
+ alert_type = null
+ on_remove_on_mob_delete = TRUE
+ var/obj/item/borg/upgrade/modkit/bounty/reward_target
+
+/datum/status_effect/syphon_mark/on_creation(mob/living/new_owner, obj/item/borg/upgrade/modkit/bounty/new_reward_target)
+ . = ..()
+ if(.)
+ reward_target = new_reward_target
+
+/datum/status_effect/syphon_mark/on_apply()
+ if(owner.stat == DEAD)
+ return FALSE
+ return ..()
+
+/datum/status_effect/syphon_mark/proc/get_kill()
+ if(!QDELETED(reward_target))
+ reward_target.get_kill(owner)
+
+/datum/status_effect/syphon_mark/tick()
+ if(owner.stat == DEAD)
+ get_kill()
+ qdel(src)
+
+/datum/status_effect/syphon_mark/on_remove()
+ get_kill()
+ . = ..()
+
/datum/status_effect/high_five
id = "high_five"
duration = 40
diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm
index 4c1fb437046..f0ba75d5e10 100644
--- a/code/datums/uplink_item.dm
+++ b/code/datums/uplink_item.dm
@@ -207,6 +207,14 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 10
job = list("Mime")
+/datum/uplink_item/jobspecific/pressure_mod
+ name = "Kinetic Accelerator Pressure Mod"
+ desc = "A modification kit which allows Kinetic Accelerators to do greatly increased damage while indoors. Occupies 35% mod capacity."
+ reference = "KPM"
+ item = /obj/item/borg/upgrade/modkit/indoors
+ cost = 5 //you need two for full damage, so total of 10 for maximum damage
+ job = list("Shaft Miner")
+
//Chef
/datum/uplink_item/jobspecific/specialsauce
name = "Chef Excellence's Special Sauce"
diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm
index d5b4faef17c..d6a531950c5 100644
--- a/code/game/area/Space Station 13 areas.dm
+++ b/code/game/area/Space Station 13 areas.dm
@@ -100,9 +100,11 @@ var/list/ghostteleportlocs = list()
requires_power = FALSE
valid_territory = FALSE
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
+ parallax_movedir = NORTH
/area/shuttle/arrival
name = "\improper Arrival Shuttle"
+ parallax_movedir = EAST
/area/shuttle/arrival/pre_game
icon_state = "shuttle2"
@@ -136,12 +138,14 @@ var/list/ghostteleportlocs = list()
music = "music/escape.ogg"
icon_state = "shuttle"
nad_allowed = TRUE
+ parallax_movedir = EAST
/area/shuttle/pod_4
name = "\improper Escape Pod Four"
music = "music/escape.ogg"
icon_state = "shuttle"
nad_allowed = TRUE
+ parallax_movedir = EAST
/area/shuttle/escape_pod1
name = "\improper Escape Pod One"
@@ -207,6 +211,7 @@ var/list/ghostteleportlocs = list()
/area/shuttle/transport
icon_state = "shuttle"
name = "\improper Transport Shuttle"
+ parallax_movedir = EAST
/area/shuttle/transport1
icon_state = "shuttle"
@@ -247,6 +252,7 @@ var/list/ghostteleportlocs = list()
/area/shuttle/specops
name = "\improper Special Ops Shuttle"
icon_state = "shuttlered"
+ parallax_movedir = EAST
/area/shuttle/specops/centcom
name = "\improper Special Ops Shuttle"
@@ -260,6 +266,7 @@ var/list/ghostteleportlocs = list()
name = "\improper Syndicate Elite Shuttle"
icon_state = "shuttlered"
nad_allowed = TRUE
+ parallax_movedir = SOUTH
/area/shuttle/syndicate_elite/mothership
name = "\improper Syndicate Elite Shuttle"
@@ -273,6 +280,7 @@ var/list/ghostteleportlocs = list()
name = "\improper Syndicate SIT Shuttle"
icon_state = "shuttlered"
nad_allowed = TRUE
+ parallax_movedir = SOUTH
/area/shuttle/assault_pod
name = "Steel Rain"
@@ -281,6 +289,7 @@ var/list/ghostteleportlocs = list()
/area/shuttle/administration
name = "\improper Nanotrasen Vessel"
icon_state = "shuttlered"
+ parallax_movedir = EAST
/area/shuttle/administration/centcom
name = "\improper Nanotrasen Vessel Centcom"
@@ -380,6 +389,7 @@ var/list/ghostteleportlocs = list()
/area/shuttle/salvage/abandoned_ship
name = "\improper Abandoned Ship"
icon_state = "yellow"
+ parallax_movedir = WEST
/area/shuttle/salvage/clown_asteroid
name = "\improper Clown Asteroid"
@@ -412,6 +422,7 @@ var/list/ghostteleportlocs = list()
/area/shuttle/trade/sol
name = "Sol Freighter"
+ parallax_movedir = EAST
/area/shuttle/freegolem
name = "Free Golem Ship"
@@ -1859,6 +1870,7 @@ var/list/ghostteleportlocs = list()
/area/shuttle/constructionsite
name = "\improper Construction Site Shuttle"
icon_state = "yellow"
+ parallax_movedir = EAST
/area/shuttle/constructionsite/station
name = "\improper Construction Site Shuttle"
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index 2e7448ec5c8..26dc6ddbf56 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -67,6 +67,9 @@
var/can_get_auto_cryod = TRUE
var/hide_attacklogs = FALSE // For areas such as thunderdome, lavaland syndiebase, etc which generate a lot of spammy attacklogs. Reduces log priority.
+ var/parallax_movedir = 0
+ var/moving = FALSE
+
/area/Initialize(mapload)
GLOB.all_areas += src
icon_state = ""
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 1a23dc71070..0a22c19770b 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -26,7 +26,7 @@
var/inertia_move_delay = 5
var/moving_diagonally = 0 //0: not doing a diagonal move. 1 and 2: doing the first/second step of the diagonal move
-
+ var/list/client_mobs_in_contents
var/area/areaMaster
/atom/movable/New()
@@ -215,6 +215,8 @@
if(!inertia_moving)
inertia_next_move = world.time + inertia_move_delay
newtonian_move(Dir)
+ if(length(client_mobs_in_contents))
+ update_parallax_contents()
return TRUE
// Previously known as HasEntered()
diff --git a/code/game/gamemodes/blob/powers.dm b/code/game/gamemodes/blob/powers.dm
index e7751ffcd8a..d6d4a91cf19 100644
--- a/code/game/gamemodes/blob/powers.dm
+++ b/code/game/gamemodes/blob/powers.dm
@@ -25,7 +25,8 @@
if(blob_nodes.len)
var/list/nodes = list()
for(var/i = 1; i <= blob_nodes.len; i++)
- nodes["Blob Node #[i]"] = blob_nodes[i]
+ var/obj/structure/blob/node/B = blob_nodes[i]
+ nodes["Blob Node #[i] ([get_location_name(B)])"] = B
var/node_name = input(src, "Choose a node to jump to.", "Node Jump") in nodes
var/obj/structure/blob/node/chosen_node = nodes[node_name]
if(chosen_node)
diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm
index 021eb7461f5..9442c319dcb 100644
--- a/code/game/gamemodes/cult/cult.dm
+++ b/code/game/gamemodes/cult/cult.dm
@@ -29,7 +29,7 @@ var/global/list/all_cults = list()
return 1
/proc/is_sacrifice_target(datum/mind/mind)
- if(istype(SSticker.mode.name, "cult"))
+ if(SSticker.mode.name == "cult")
var/datum/game_mode/cult/cult_mode = SSticker.mode
if(mind == cult_mode.sacrifice_target)
return 1
diff --git a/code/game/gamemodes/cult/cult_objectives.dm b/code/game/gamemodes/cult/cult_objectives.dm
index da4e190cb7f..c31ebaf9b84 100644
--- a/code/game/gamemodes/cult/cult_objectives.dm
+++ b/code/game/gamemodes/cult/cult_objectives.dm
@@ -163,6 +163,16 @@
possible_sac_targets += player.mind
return possible_sac_targets
+// Handles the updating of sacrifice objectives after the sacrifice target goes to cryo and ghosts
+/datum/game_mode/cult/proc/update_sac_objective(previous_target, previous_role)
+ for(var/datum/mind/cult_mind in cult)
+ if(cult_mind)
+ var/updated_memory = cult_mind.memory
+ updated_memory = replacetext("[cult_mind.memory]", "[previous_target]", "[sacrifice_target]")
+ updated_memory = replacetext("[updated_memory]", "[previous_role]", "[sacrifice_target.assigned_role]")
+ cult_mind.memory = updated_memory
+
+
/datum/game_mode/cult/proc/pick_objective()
var/list/possible_objectives = list()
diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm
index 92fc09490ec..08633ef92f4 100644
--- a/code/game/gamemodes/cult/talisman.dm
+++ b/code/game/gamemodes/cult/talisman.dm
@@ -1,4 +1,5 @@
/obj/item/paper/talisman
+ icon = 'icons/obj/paper.dmi'
icon_state = "paper_talisman"
var/cultist_name = "talisman"
var/cultist_desc = "A basic talisman. It serves no purpose."
@@ -7,6 +8,9 @@
var/uses = 1
var/health_cost = 0 //The amount of health taken from the user when invoking the talisman
+/obj/item/paper/talisman/update_icon()//overriding this so the update_icon doesn't turn them into normal looking paper
+ SEND_SIGNAL(src, COMSIG_OBJ_UPDATE_ICON)
+
/obj/item/paper/talisman/examine(mob/user)
if(iscultist(user) || user.stat == DEAD)
to_chat(user, "Name: [cultist_name]")
@@ -49,6 +53,7 @@
//Supply Talisman: Has a few unique effects. Granted only to starter cultists.
/obj/item/paper/talisman/supply
cultist_name = "Supply Talisman"
+ icon_state = "supply"
cultist_desc = "A multi-use talisman that can create various objects. Intended to increase the cult's strength early on."
invocation = null
uses = 3
@@ -117,6 +122,7 @@
//Rite of Translocation: Same as rune
/obj/item/paper/talisman/teleport
cultist_name = "Talisman of Teleportation"
+ icon_state = "teleport"
cultist_desc = "A single-use talisman that will teleport a user to a random rune of the same keyword."
invocation = "Sas'so c'arta forbici!"
health_cost = 5
@@ -159,6 +165,7 @@
/obj/item/paper/talisman/summon_tome
cultist_name = "Talisman of Tome Summoning"
+ icon_state = "tome"
cultist_desc = "A one-use talisman that will call an untranslated tome from the archives of a cult."
invocation = "N'ath reth sh'yro eth d'raggathnor!"
health_cost = 1
@@ -173,6 +180,7 @@
/obj/item/paper/talisman/true_sight
cultist_name = "Talisman of Veiling"
+ icon_state = "veil"
cultist_desc = "A multi-use talisman that hides nearby runes. On its second use, will reveal nearby runes."
invocation = "Kla'atu barada nikt'o!"
health_cost = 1
@@ -197,6 +205,7 @@
//Rite of False Truths: Same as rune
/obj/item/paper/talisman/make_runes_fake
cultist_name = "Talisman of Disguising"
+ icon_state = "disguising"
cultist_desc = "A talisman that will make nearby runes appear fake."
invocation = "By'o nar'nar!"
@@ -212,6 +221,7 @@
//Rite of Disruption: Weaker than rune
/obj/item/paper/talisman/emp
cultist_name = "Talisman of Electromagnetic Pulse"
+ icon_state = "emp"
cultist_desc = "A talisman that will cause a moderately-sized electromagnetic pulse."
invocation = "Ta'gh fara'qha fel d'amar det!"
health_cost = 5
@@ -226,6 +236,7 @@
//Rite of Disorientation: Stuns and inhibit speech on a single target for quite some time
/obj/item/paper/talisman/stun
cultist_name = "Talisman of Stunning"
+ icon_state = "stunning"
cultist_desc = "A talisman that will stun and inhibit speech on a single target. To use, attack target directly."
invocation = "Dream sign:Evil sealing talisman!"
health_cost = 10
@@ -271,6 +282,7 @@
//Rite of Arming: Equips cultist armor on the user, where available
/obj/item/paper/talisman/armor
cultist_name = "Talisman of Arming"
+ icon_state = "arming"
cultist_desc = "A talisman that will equip the invoker with cultist equipment if there is a slot to equip it to."
invocation = "N'ath reth sh'yro eth draggathnor!"
@@ -301,6 +313,7 @@
//Talisman of Horrors: Breaks the mind of the victim with nightmarish hallucinations
/obj/item/paper/talisman/horror
cultist_name = "Talisman of Horrors"
+ icon_state = "horror"
cultist_desc = "A talisman that will break the mind of the victim with nightmarish hallucinations."
invocation = "Lo'Nab Na'Dm!"
@@ -316,6 +329,7 @@
//Talisman of Fabrication: Creates a construct shell out of 25 metal sheets.
/obj/item/paper/talisman/construction
cultist_name = "Talisman of Construction"
+ icon_state = "construction"
cultist_desc = "Use this talisman on at least twenty-five metal sheets to create an empty construct shell or on plasteel to make runed metal"
invocation = "Ethra p'ni dedol!"
uses = 25
@@ -360,6 +374,7 @@
//Talisman of Shackling: Applies special cuffs directly from the talisman
/obj/item/paper/talisman/shackle
cultist_name = "Talisman of Shackling"
+ icon_state = "shackling"
cultist_desc = "Use this talisman on a victim to handcuff them with dark bindings."
invocation = "In'totum Lig'abis!"
uses = 4
diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm
index 5ac62401d23..131afd84fff 100644
--- a/code/game/gamemodes/wizard/wizard.dm
+++ b/code/game/gamemodes/wizard/wizard.dm
@@ -7,7 +7,8 @@
required_players = 20
required_enemies = 1
recommended_enemies = 1
- var/use_huds = 0
+ var/use_huds = 1
+
var/finished = 0
var/but_wait_theres_more = 0
@@ -157,22 +158,30 @@
wizard_mob.gene_stability += DEFAULT_GENE_STABILITY //magic
return 1
+// Checks if the game should end due to all wizards and apprentices being dead, or MMI'd/Borged
/datum/game_mode/wizard/check_finished()
var/wizards_alive = 0
var/traitors_alive = 0
+
+ // Wizards
for(var/datum/mind/wizard in wizards)
if(!istype(wizard.current,/mob/living/carbon))
continue
if(wizard.current.stat==DEAD)
continue
+ if(istype(wizard.current, /obj/item/mmi)) // wizard is in an MMI, don't count them as alive
+ continue
wizards_alive++
+ // Apprentices - classified as "traitors"
if(!wizards_alive)
for(var/datum/mind/traitor in traitors)
if(!istype(traitor.current,/mob/living/carbon))
continue
if(traitor.current.stat==DEAD)
continue
+ if(istype(traitor.current, /obj/item/mmi)) // apprentice is in an MMI, don't count them as alive
+ continue
traitors_alive++
if(wizards_alive || traitors_alive || but_wait_theres_more)
diff --git a/code/game/jobs/job/support.dm b/code/game/jobs/job/support.dm
index 22c2d47e3b9..aac1c291355 100644
--- a/code/game/jobs/job/support.dm
+++ b/code/game/jobs/job/support.dm
@@ -175,23 +175,24 @@
name = "Shaft Miner"
jobtype = /datum/job/mining
- uniform = /obj/item/clothing/under/rank/miner/lavaland
- gloves = /obj/item/clothing/gloves/color/black
- shoes = /obj/item/clothing/shoes/workboots/mining
l_ear = /obj/item/radio/headset/headset_cargo/mining
- id = /obj/item/card/id/supply
+ shoes = /obj/item/clothing/shoes/workboots/mining
+ gloves = /obj/item/clothing/gloves/color/black
+ uniform = /obj/item/clothing/under/rank/miner/lavaland
l_pocket = /obj/item/reagent_containers/hypospray/autoinjector/survival
- r_pocket = /obj/item/flashlight/seclite
+ r_pocket = /obj/item/storage/bag/ore
+ id = /obj/item/card/id/supply
pda = /obj/item/pda/shaftminer
backpack_contents = list(
- /obj/item/storage/bag/ore=1,\
+ /obj/item/flashlight/seclite=1,\
/obj/item/kitchen/knife/combat/survival=1,\
/obj/item/mining_voucher=1,\
/obj/item/stack/marker_beacon/ten=1
)
-
+
backpack = /obj/item/storage/backpack/explorer
- satchel = /obj/item/storage/backpack/explorer
+ satchel = /obj/item/storage/backpack/satchel/explorer
+ box = /obj/item/storage/box/survival_mining
/datum/outfit/job/mining/equipped
name = "Shaft Miner"
@@ -210,9 +211,6 @@
/obj/item/stack/marker_beacon/ten=1
)
- backpack = /obj/item/storage/backpack/explorer
- satchel = /obj/item/storage/backpack/explorer
-
/datum/outfit/job/miner/equipped/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
..()
if(visualsOnly)
diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm
index 9e91e254950..411a2d68d84 100644
--- a/code/game/machinery/constructable_frame.dm
+++ b/code/game/machinery/constructable_frame.dm
@@ -591,6 +591,16 @@ to destroy them and players will be able to make replacements.
/obj/item/stock_parts/micro_laser = 1,
/obj/item/stock_parts/console_screen = 1)
+/obj/item/circuitboard/reagentgrinder
+ name = "circuit board (All-In-One Grinder)"
+ build_path = /obj/machinery/reagentgrinder/empty
+ board_type = "machine"
+ origin_tech = "materials=2;engineering=2;biotech=2"
+ frame_desc = "Requires 2 Manipulators and 1 Matter Bin."
+ req_components = list(
+ /obj/item/stock_parts/manipulator = 2,
+ /obj/item/stock_parts/matter_bin = 1)
+
//Almost the same recipe as destructive analyzer to give people choices.
/obj/item/circuitboard/experimentor
name = "circuit board (E.X.P.E.R.I-MENTOR)"
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index 17965c12f4c..f9d708a6200 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -371,6 +371,8 @@
for(var/datum/mind/H in SSticker.mode.cult)
if(H.current)
to_chat(H.current, "[SSticker.cultdat.entity_name] murmurs, [occupant] is beyond your reach. Sacrifice [cult_mode.sacrifice_target.current] instead...")
+ H.current << 'sound/ambience/alarm4.ogg'
+ cult_mode.update_sac_objective(occupant.mind, occupant.mind.assigned_role)
else
cult_mode.bypass_phase()
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 17b6f9e55c8..b8c0f3d02f4 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -181,12 +181,6 @@ About the new airlock wires panel:
/obj/machinery/door/airlock/bumpopen(mob/living/simple_animal/user)
..(user)
-/obj/machinery/door/airlock/autoclose()
- autoclose_timer = 0
- if(!QDELETED(src) && !density && !operating && !locked && !welded && autoclose)
- close()
- return
-
/obj/machinery/door/airlock/proc/isElectrified()
if(electrified_until != 0)
return 1
@@ -645,7 +639,7 @@ About the new airlock wires panel:
add_overlay(I)
else
set_light(0)
-
+
/obj/machinery/door/airlock/CanPass(atom/movable/mover, turf/target, height=0)
if(isElectrified() && density && istype(mover, /obj/item))
var/obj/item/I = mover
@@ -1103,6 +1097,10 @@ About the new airlock wires panel:
playsound(loc, doorOpen, 30, 1)
if(closeOther != null && istype(closeOther, /obj/machinery/door/airlock/) && !closeOther.density)
closeOther.close()
+
+ if(autoclose)
+ autoclose_in(normalspeed ? auto_close_time : auto_close_time_dangerous)
+
if(!density)
return TRUE
operating = TRUE
@@ -1117,10 +1115,6 @@ About the new airlock wires panel:
layer = OPEN_DOOR_LAYER
update_icon(AIRLOCK_OPEN, 1)
operating = FALSE
-
- // The `addtimer` system has the advantage of being cancelable
- if(autoclose)
- autoclose_timer = addtimer(CALLBACK(src, .proc/autoclose), normalspeed ? auto_close_time : auto_close_time_dangerous, TIMER_UNIQUE | TIMER_STOPPABLE)
return TRUE
/obj/machinery/door/airlock/close(forced=0, override = 0)
@@ -1137,7 +1131,8 @@ About the new airlock wires panel:
for(var/turf/turf in locs)
for(var/atom/movable/M in turf)
if(M.density && M != src) //something is blocking the door
- addtimer(CALLBACK(src, .proc/autoclose), 60)
+ autoclose_in(60)
+ return
use_power(360) //360 W seems much more appropriate for an actuator moving an industrial door capable of crushing people
if(forced)
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index fdfaae71477..ca9639319e3 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -14,7 +14,6 @@
var/visible = 1
var/operating = FALSE
var/autoclose = 0
- var/autoclose_timer
var/safe = TRUE //whether the door detects things and mobs in its way and reopen or crushes them.
var/locked = FALSE //whether the door is bolted or not.
var/glass = FALSE
@@ -77,9 +76,6 @@
air_update_turf(1)
update_freelook_sight()
GLOB.airlocks -= src
- if(autoclose_timer)
- deltimer(autoclose_timer)
- autoclose_timer = 0
QDEL_NULL(spark_system)
return ..()
@@ -187,7 +183,7 @@
/obj/machinery/door/proc/unrestricted_side(mob/M) //Allows for specific side of airlocks to be unrestrected (IE, can exit maint freely, but need access to enter)
return get_dir(src, M) & unres_sides
-
+
/obj/machinery/door/proc/try_to_weld(obj/item/weldingtool/W, mob/user)
return
@@ -282,11 +278,8 @@
operating = FALSE
air_update_turf(1)
update_freelook_sight()
-
- // The `addtimer` system has the advantage of being cancelable
if(autoclose)
- autoclose_timer = addtimer(CALLBACK(src, .proc/autoclose), normalspeed ? auto_close_time : auto_close_time_dangerous, TIMER_UNIQUE | TIMER_STOPPABLE)
-
+ autoclose_in(normalspeed ? auto_close_time : auto_close_time_dangerous)
return TRUE
/obj/machinery/door/proc/close()
@@ -295,18 +288,15 @@
if(operating || welded)
return
if(safe)
- for(var/atom/movable/M in get_turf(src))
- if(M.density && M != src) //something is blocking the door
- if(autoclose)
- addtimer(CALLBACK(src, .proc/autoclose), 60)
- return
+ for(var/turf/turf in locs)
+ for(var/atom/movable/M in turf)
+ if(M.density && M != src) //something is blocking the door
+ if(autoclose)
+ autoclose_in(60)
+ return
operating = TRUE
- if(autoclose_timer)
- deltimer(autoclose_timer)
- autoclose_timer = 0
-
do_animate("closing")
layer = closingLayer
sleep(5)
@@ -354,10 +344,12 @@
return !(stat & NOPOWER)
/obj/machinery/door/proc/autoclose()
- autoclose_timer = 0
if(!QDELETED(src) && !density && !operating && !locked && !welded && autoclose)
close()
+/obj/machinery/door/proc/autoclose_in(wait)
+ addtimer(CALLBACK(src, .proc/autoclose), wait, TIMER_UNIQUE | TIMER_NO_HASH_WAIT | TIMER_OVERRIDE)
+
/obj/machinery/door/proc/update_freelook_sight()
if(!glass && cameranet)
cameranet.updateVisibility(src, 0)
diff --git a/code/game/machinery/mass_driver.dm b/code/game/machinery/mass_driver.dm
index 8bc5976d638..de14dce7d5b 100644
--- a/code/game/machinery/mass_driver.dm
+++ b/code/game/machinery/mass_driver.dm
@@ -160,8 +160,8 @@
var/obj/item/stack/cable_coil/C = W
to_chat(user, "You start adding cables to \the [src]...")
playsound(get_turf(src), C.usesound, 50, 1)
- if(do_after(user, 20 * C.toolspeed, target = src) && (C.amount >= 3) && (build == 2))
- C.use(3)
+ if(do_after(user, 20 * C.toolspeed, target = src) && (C.amount >= 2) && (build == 2))
+ C.use(2)
to_chat(user, "You've added cables to \the [src].")
build++
update_icon()
@@ -169,7 +169,7 @@
if(istype(W, /obj/item/wirecutters))
to_chat(user, "You begin to remove the wiring from \the [src].")
if(do_after(user, 10 * W.toolspeed, target = src) && (build == 3))
- new /obj/item/stack/cable_coil(loc,3)
+ new /obj/item/stack/cable_coil(loc,2)
playsound(get_turf(src), W.usesound, 50, 1)
to_chat(user, "You've removed the cables from \the [src].")
build--
@@ -179,8 +179,8 @@
var/obj/item/stack/rods/R = W
to_chat(user, "You begin to complete \the [src]...")
playsound(get_turf(src), R.usesound, 50, 1)
- if(do_after(user, 20 * R.toolspeed, target = src) && (R.amount >= 3) && (build == 3))
- R.use(3)
+ if(do_after(user, 20 * R.toolspeed, target = src) && (R.amount >= 2) && (build == 3))
+ R.use(2)
to_chat(user, "You've added the grille to \the [src].")
build++
update_icon()
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index 04e78e937aa..cf7937474c8 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -1132,7 +1132,6 @@
product_ads = "Go save some lives!;The best stuff for your medbay.;Only the finest tools.;Natural chemicals!;This stuff saves lives.;Don't you want some?"
icon_state = "wallmed"
icon_deny = "wallmed-deny"
- req_access = list(access_medical)
density = FALSE //It is wall-mounted, and thus, not dense. --Superxpdude
products = list(/obj/item/stack/medical/bruise_pack = 2, /obj/item/stack/medical/ointment = 2, /obj/item/reagent_containers/hypospray/autoinjector = 4, /obj/item/healthanalyzer = 1)
contraband = list(/obj/item/reagent_containers/syringe/charcoal = 4, /obj/item/reagent_containers/syringe/antiviral = 4, /obj/item/reagent_containers/food/pill/tox = 1)
@@ -1143,7 +1142,6 @@
desc = "Wall-mounted Medical Equipment dispenser."
icon_state = "wallmed"
icon_deny = "wallmed-deny"
- req_access = list(access_medical)
density = FALSE //It is wall-mounted, and thus, not dense. --Superxpdude
products = list(/obj/item/reagent_containers/hypospray/autoinjector = 5, /obj/item/reagent_containers/syringe/charcoal = 3, /obj/item/stack/medical/bruise_pack = 3,
/obj/item/stack/medical/ointment = 3, /obj/item/healthanalyzer = 3)
diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm
index 5b4a8143bef..8cce6cdcdfc 100644
--- a/code/game/mecha/working/ripley.dm
+++ b/code/game/mecha/working/ripley.dm
@@ -171,10 +171,8 @@
/obj/mecha/working/ripley/proc/update_pressure()
var/turf/T = get_turf(loc)
- var/datum/gas_mixture/environment = T.return_air()
- var/pressure = environment.return_pressure()
- if(pressure < 20)
+ if(lavaland_equipment_pressure_check(T))
step_in = 3
for(var/obj/item/mecha_parts/mecha_equipment/drill/drill in equipment)
drill.equip_cooldown = initial(drill.equip_cooldown)/2
diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
index 8fd1c061c32..7f1683ba415 100644
--- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm
+++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
@@ -140,6 +140,20 @@
..()
animate(src, alpha = 0, time = duration)
+/obj/effect/temp_visual/fire
+ icon = 'icons/goonstation/effects/fire.dmi'
+ icon_state = "3"
+ light_range = LIGHT_RANGE_FIRE
+ light_color = LIGHT_COLOR_FIRE
+ duration = 10
+ layer = MASSIVE_OBJ_LAYER
+ alpha = 250
+ blend_mode = BLEND_ADD
+
+/obj/effect/temp_visual/fire/New(loc)
+ color = heat2color(FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
+ ..()
+
/obj/effect/temp_visual/revenant
name = "spooky lights"
icon_state = "purplesparkles"
@@ -289,4 +303,33 @@
/obj/effect/temp_visual/dir_setting/firing_effect/magic
icon_state = "shieldsparkles"
- duration = 3
\ No newline at end of file
+ duration = 3
+
+/obj/effect/temp_visual/impact_effect
+ icon_state = "impact_bullet"
+ duration = 5
+
+/obj/effect/temp_visual/impact_effect/Initialize(mapload, x, y)
+ pixel_x = x
+ pixel_y = y
+ return ..()
+
+/obj/effect/temp_visual/impact_effect/red_laser
+ icon_state = "impact_laser"
+ duration = 4
+
+/obj/effect/temp_visual/impact_effect/blue_laser
+ icon_state = "impact_laser_blue"
+ duration = 4
+
+/obj/effect/temp_visual/impact_effect/green_laser
+ icon_state = "impact_laser_green"
+ duration = 4
+
+/obj/effect/temp_visual/impact_effect/purple_laser
+ icon_state = "impact_laser_purple"
+ duration = 4
+
+/obj/effect/temp_visual/impact_effect/ion
+ icon_state = "shieldsparkles"
+ duration = 6
\ No newline at end of file
diff --git a/code/game/objects/items/contraband.dm b/code/game/objects/items/contraband.dm
index 7ce7b07193d..77aef9bb71d 100644
--- a/code/game/objects/items/contraband.dm
+++ b/code/game/objects/items/contraband.dm
@@ -4,6 +4,7 @@
/obj/item/storage/pill_bottle/happy
name = "Happy pills"
desc = "Highly illegal drug. When you want to see the rainbow."
+ wrapper_color = COLOR_PINK
/obj/item/storage/pill_bottle/happy/New()
..()
@@ -18,6 +19,7 @@
/obj/item/storage/pill_bottle/zoom
name = "Zoom pills"
desc = "Highly illegal drug. Trade brain for speed."
+ wrapper_color = COLOR_BLUE
/obj/item/storage/pill_bottle/zoom/New()
..()
@@ -49,15 +51,12 @@
adulterants--
reagents.add_reagent(pick_list("chemistry_tools.json", "CYBERPUNK_drug_adulterants"), 3)
-
-
/obj/item/storage/pill_bottle/random_drug_bottle
name = "pill bottle (???)"
desc = "Huh."
+ allow_wrap = FALSE
/obj/item/storage/pill_bottle/random_drug_bottle/New()
..()
for(var/i in 1 to 5)
new /obj/item/reagent_containers/food/pill/random_drugs(src)
-
-
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index cad4ae25ac8..0400763b7f2 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -273,6 +273,8 @@ REAGENT SCANNER
user.show_message("Subject's genes are stable.")
add_fingerprint(user)
+/obj/item/healthanalyzer/attack_self(mob/user)
+ toggle_mode()
/obj/item/healthanalyzer/verb/toggle_mode()
set name = "Switch Verbosity"
diff --git a/code/game/objects/items/random_items.dm b/code/game/objects/items/random_items.dm
index 587b1d27d14..e51bac10005 100644
--- a/code/game/objects/items/random_items.dm
+++ b/code/game/objects/items/random_items.dm
@@ -123,6 +123,7 @@
/obj/item/storage/pill_bottle/random_meds
name = "unlabelled pillbottle"
desc = "The sheer recklessness of this bottle's existence astounds you."
+ allow_wrap = FALSE
var/labelled = FALSE
/obj/item/storage/pill_bottle/random_meds/New()
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index 9ec921fef92..f7df69cad2f 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -178,8 +178,12 @@ var/global/list/datum/stack_recipe/wood_recipes = list(
new /datum/stack_recipe("wooden buckler", /obj/item/shield/riot/buckler, 20, time = 40),
new /datum/stack_recipe("apiary", /obj/structure/beebox, 40, time = 50),
new /datum/stack_recipe("honey frame", /obj/item/honey_frame, 5, time = 10),
+ new /datum/stack_recipe("wooden bucket", /obj/item/reagent_containers/glass/bucket/wooden, 3, time = 10),
+ new /datum/stack_recipe("rake", /obj/item/cultivator/rake, 5, time = 10),
+ new /datum/stack_recipe("ore box", /obj/structure/ore_box, 4, time = 50, one_per_turf = TRUE, on_floor = TRUE),
new /datum/stack_recipe("baseball bat", /obj/item/melee/baseball_bat, 5, time = 15),
- new /datum/stack_recipe("fermenting barrel", /obj/structure/fermenting_barrel, 30, time = 50)
+ new /datum/stack_recipe("fermenting barrel", /obj/structure/fermenting_barrel, 30, time = 50),
+ new /datum/stack_recipe("firebrand", /obj/item/match/firebrand, 2, time = 100)
)
/obj/item/stack/sheet/wood
diff --git a/code/game/objects/items/weapons/dice.dm b/code/game/objects/items/weapons/dice.dm
index 084dac30a60..736ba1cc767 100644
--- a/code/game/objects/items/weapons/dice.dm
+++ b/code/game/objects/items/weapons/dice.dm
@@ -4,6 +4,7 @@
icon = 'icons/obj/dice.dmi'
icon_state = "dicebag"
can_hold = list(/obj/item/dice)
+ allow_wrap = FALSE
/obj/item/storage/pill_bottle/dice/New()
..()
diff --git a/code/game/objects/items/weapons/kitchen.dm b/code/game/objects/items/weapons/kitchen.dm
index 4f94a6b8a1b..21161c2642a 100644
--- a/code/game/objects/items/weapons/kitchen.dm
+++ b/code/game/objects/items/weapons/kitchen.dm
@@ -115,7 +115,8 @@
throw_range = 6
materials = list(MAT_METAL=12000)
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
- sharp = 1
+ sharp = TRUE
+ var/bayonet = FALSE //Can this be attached to a gun?
/obj/item/kitchen/knife/suicide_act(mob/user)
user.visible_message(pick("[user] is slitting [user.p_their()] wrists with the [src.name]! It looks like [user.p_theyre()] trying to commit suicide.", \
@@ -164,6 +165,7 @@
throwforce = 20
origin_tech = "materials=3;combat=4"
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "cut")
+ bayonet = TRUE
/obj/item/kitchen/knife/combat/survival
name = "survival knife"
diff --git a/code/game/objects/items/weapons/lighters.dm b/code/game/objects/items/weapons/lighters.dm
index ab946de5f0f..56d237c4eda 100644
--- a/code/game/objects/items/weapons/lighters.dm
+++ b/code/game/objects/items/weapons/lighters.dm
@@ -224,3 +224,13 @@
var/mask_item = M.get_item_by_slot(slot_wear_mask)
if(istype(mask_item, /obj/item/clothing/mask/cigarette))
return mask_item
+
+
+/obj/item/match/firebrand
+ name = "firebrand"
+ desc = "An unlit firebrand. It makes you wonder why it's not just called a stick."
+ smoketime = 20 //40 seconds
+
+/obj/item/match/firebrand/New()
+ ..()
+ matchignite()
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm
index e7342774619..3fe5c140407 100644
--- a/code/game/objects/items/weapons/storage/boxes.dm
+++ b/code/game/objects/items/weapons/storage/boxes.dm
@@ -113,7 +113,7 @@
New()
..()
contents = list()
- new /obj/item/clothing/mask/breath(src)
+ new /obj/item/clothing/mask/gas/explorer(src)
new /obj/item/tank/emergency_oxygen/engi(src)
new /obj/item/crowbar/red(src)
new /obj/item/reagent_containers/hypospray/autoinjector(src)
@@ -372,6 +372,20 @@
new /obj/item/implantpad(src)
new /obj/item/locator(src)
+/obj/item/storage/box/minertracker
+ name = "boxed tracking implant kit"
+ desc = "For finding those who have died on the accursed lavaworld."
+ icon_state = "implant"
+
+/obj/item/storage/box/minertracker/New()
+ ..()
+ new /obj/item/implantcase/tracking(src)
+ new /obj/item/implantcase/tracking(src)
+ new /obj/item/implantcase/tracking(src)
+ new /obj/item/implanter(src)
+ new /obj/item/implantpad(src)
+ new /obj/item/locator(src)
+
/obj/item/storage/box/chemimp
name = "chemical implant kit"
desc = "Box of stuff used to implant chemicals."
diff --git a/code/game/objects/items/weapons/storage/firstaid.dm b/code/game/objects/items/weapons/storage/firstaid.dm
index fab82df4b4e..8d8cb77e597 100644
--- a/code/game/objects/items/weapons/storage/firstaid.dm
+++ b/code/game/objects/items/weapons/storage/firstaid.dm
@@ -254,10 +254,21 @@
var/applying_meds = FALSE //To Prevent spam clicking and generating runtimes from apply a deleting pill multiple times.
var/rapid_intake_message = "unscrews the cap on the pill bottle and begins dumping the entire contents down their throat!"
var/rapid_post_instake_message = "downs the entire bottle of pills in one go!"
+ var/allow_wrap = TRUE
+ var/wrapper_color = null
/obj/item/storage/pill_bottle/New()
..()
base_name = name
+ if(allow_wrap)
+ apply_wrap()
+
+/obj/item/storage/pill_bottle/proc/apply_wrap()
+ if(wrapper_color)
+ overlays.Cut()
+ var/image/I = image(icon, "pillbottle_wrap")
+ I.color = wrapper_color
+ overlays += I
/obj/item/storage/pill_bottle/attack(mob/M, mob/user)
if(iscarbon(M) && contents.len)
@@ -274,6 +285,9 @@
else
return ..()
+/obj/item/storage/pill_bottle/ert
+ wrapper_color = COLOR_MAROON
+
/obj/item/storage/pill_bottle/ert/New()
..()
new /obj/item/reagent_containers/food/pill/salicylic(src)
@@ -319,15 +333,18 @@
/obj/item/storage/pill_bottle/patch_pack
name = "Patch Pack"
+ desc = "It's a container for storing medical patches."
icon_state = "patch_pack"
can_hold = list(/obj/item/reagent_containers/food/pill/patch)
cant_hold = list()
rapid_intake_message = "flips the lid of the Patch Pack open and begins rapidly stamping patches on themselves!"
rapid_post_instake_message = "stamps the entire contents of the Patch Pack all over their entire body!"
+ allow_wrap = FALSE
/obj/item/storage/pill_bottle/charcoal
name = "Pill bottle (Charcoal)"
desc = "Contains pills used to counter toxins."
+ wrapper_color = COLOR_GREEN
New()
..()
@@ -342,6 +359,7 @@
/obj/item/storage/pill_bottle/painkillers
name = "Pill Bottle (Salicylic Acid)"
desc = "Contains various pills for minor pain relief."
+ wrapper_color = COLOR_RED
/obj/item/storage/pill_bottle/painkillers/New()
..()
@@ -354,8 +372,11 @@
new /obj/item/reagent_containers/food/pill/salicylic(src)
new /obj/item/reagent_containers/food/pill/salicylic(src)
+/obj/item/storage/pill_bottle/fakedeath
+ allow_wrap = FALSE
+
/obj/item/storage/pill_bottle/fakedeath/New()
..()
new /obj/item/reagent_containers/food/pill/fakedeath(src)
new /obj/item/reagent_containers/food/pill/fakedeath(src)
- new /obj/item/reagent_containers/food/pill/fakedeath(src)
\ No newline at end of file
+ new /obj/item/reagent_containers/food/pill/fakedeath(src)
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm
index f998cbff801..189cbc5893d 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm
@@ -110,6 +110,7 @@
/obj/item/storage/pill_bottle/psychiatrist
name = "psychiatrist's pill bottle"
desc = "Contains various pills to calm or sedate patients."
+ wrapper_color = COLOR_PALE_BTL_GREEN
/obj/item/storage/pill_bottle/psychiatrist/New()
..()
diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm
index d44ec20c515..4a2dadffcc7 100644
--- a/code/game/objects/structures/crates_lockers/crates.dm
+++ b/code/game/objects/structures/crates_lockers/crates.dm
@@ -5,9 +5,9 @@
icon_state = "crate"
icon_opened = "crateopen"
icon_closed = "crate"
- climbable = 1
+ climbable = TRUE
// mouse_drag_pointer = MOUSE_ACTIVE_POINTER //???
- var/rigged = 0
+ var/rigged = FALSE
var/obj/item/paper/manifest/manifest
// A list of beacon names that the crate will announce the arrival of, when delivered.
var/list/announce_beacons = list()
@@ -23,16 +23,16 @@
overlays += "manifest"
/obj/structure/closet/crate/can_open()
- return 1
+ return TRUE
/obj/structure/closet/crate/can_close()
- return 1
+ return TRUE
/obj/structure/closet/crate/open()
if(src.opened)
- return 0
+ return FALSE
if(!src.can_open())
- return 0
+ return FALSE
if(rigged && locate(/obj/item/radio/electropack) in src)
if(isliving(usr))
@@ -47,18 +47,18 @@
for(var/mob/M in src) //Mobs
M.forceMove(loc)
icon_state = icon_opened
- src.opened = 1
+ src.opened = TRUE
if(climbable)
structure_shaken()
- return 1
+ return TRUE
/obj/structure/closet/crate/close()
if(!src.opened)
- return 0
+ return FALSE
if(!src.can_close())
- return 0
+ return FALSE
playsound(src.loc, 'sound/machines/click.ogg', 15, 1, -3)
var/itemcount = 0
@@ -75,8 +75,8 @@
itemcount++
icon_state = icon_closed
- src.opened = 0
- return 1
+ src.opened = FALSE
+ return TRUE
/obj/structure/closet/crate/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/rcs) && !src.opened)
@@ -105,7 +105,7 @@
return
playsound(E.loc, E.usesound, 50, 1)
to_chat(user, "Teleporting [src.name]...")
- E.teleporting = 1
+ E.teleporting = TRUE
if(!do_after(user, 50 * E.toolspeed, target = src))
E.teleporting = 0
return
@@ -127,9 +127,9 @@
return
playsound(E.loc, E.usesound, 50, 1)
to_chat(user, "Teleporting [src.name]...")
- E.teleporting = 1
+ E.teleporting = TRUE
if(!do_after(user, 50 * E.toolspeed, target = src))
- E.teleporting = 0
+ E.teleporting = FALSE
return
E.teleporting = 0
if(!(E.rcell && E.rcell.use(E.chargecost)))
@@ -154,14 +154,16 @@
else if(istype(W, /obj/item/stack/packageWrap))
return
else if(istype(W, /obj/item/stack/cable_coil))
+ var/obj/item/stack/cable_coil/C = W
if(rigged)
to_chat(user, "[src] is already rigged!")
return
- to_chat(user, "You rig [src].")
- user.drop_item()
- qdel(W)
- rigged = 1
- return
+ if(C.use(15))
+ to_chat(user, "You rig [src].")
+ rigged = TRUE
+ else
+ to_chat(user, "You need atleast 15 wires to rig [src]!")
+ return
else if(istype(W, /obj/item/radio/electropack))
if(rigged)
to_chat(user, "You attach [W] to [src].")
@@ -172,7 +174,7 @@
if(rigged)
to_chat(user, "You cut away the wiring.")
playsound(loc, W.usesound, 100, 1)
- rigged = 0
+ rigged = FALSE
return
else return attack_hand(user)
@@ -653,4 +655,4 @@
new /obj/item/storage/bag/ore(src)
new /obj/item/clothing/glasses/meson(src)
new /obj/item/card/id/golem(src)
- new /obj/item/flashlight/lantern(src)
\ No newline at end of file
+ new /obj/item/flashlight/lantern(src)
diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm
index 4a70729d7e9..9f3829a8277 100644
--- a/code/game/objects/structures/false_walls.dm
+++ b/code/game/objects/structures/false_walls.dm
@@ -97,12 +97,9 @@
else
icon_state = "fwall_open"
-/obj/structure/falsewall/proc/ChangeToWall(delete = 1)
+/obj/structure/falsewall/proc/ChangeToWall(delete = TRUE)
var/turf/T = get_turf(src)
- if(!walltype || walltype == "metal")
- T.ChangeTurf(/turf/simulated/wall)
- else
- T.ChangeTurf(text2path("/turf/simulated/wall/mineral/[walltype]"))
+ T.ChangeTurf(walltype)
if(delete)
qdel(src)
return T
diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
index 005f0e721fb..15e578ed88f 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
@@ -64,6 +64,12 @@
if(usr.incapacitated())
to_chat(usr, "You can't do that right now!")
return
+ if(!usr.has_right_hand() && !usr.has_left_hand())
+ to_chat(usr, "You try to grab the chair, but you are missing both of your hands!")
+ return
+ if(usr.get_active_hand() && usr.get_inactive_hand())
+ to_chat(usr, "You try to grab the chair, but your hands are already full!")
+ return
if(!ishuman(usr))
return
usr.visible_message("[usr] grabs \the [src.name].", "You grab \the [src.name].")
diff --git a/code/game/turfs/simulated/floor/asteroid.dm b/code/game/turfs/simulated/floor/asteroid.dm
index 5f2ad4b629c..04ac165fc56 100644
--- a/code/game/turfs/simulated/floor/asteroid.dm
+++ b/code/game/turfs/simulated/floor/asteroid.dm
@@ -5,6 +5,7 @@
baseturf = /turf/simulated/floor/plating/asteroid
icon_state = "asteroid"
icon_plating = "asteroid"
+ footstep_sounds = list()
var/environment_type = "asteroid"
var/turf_type = /turf/simulated/floor/plating/asteroid //Because caves do whacky shit to revert to normal
var/dug = 0 //0 = has not yet been dug, 1 = has already been dug
diff --git a/code/game/turfs/simulated/floor/chasm.dm b/code/game/turfs/simulated/floor/chasm.dm
index 6a213400d04..17807bd255b 100644
--- a/code/game/turfs/simulated/floor/chasm.dm
+++ b/code/game/turfs/simulated/floor/chasm.dm
@@ -22,6 +22,11 @@
if(!drop_stuff())
STOP_PROCESSING(SSprocessing, src)
+/turf/open/chasm/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
+ underlay_appearance.icon = 'icons/turf/floors.dmi'
+ underlay_appearance.icon_state = "basalt"
+ return TRUE
+
/turf/simulated/floor/chasm/attackby(obj/item/C, mob/user, params, area/area_restriction)
..()
if(istype(C, /obj/item/stack/rods))
diff --git a/code/game/turfs/simulated/floor/fancy_floor.dm b/code/game/turfs/simulated/floor/fancy_floor.dm
index 97065cd9711..12b1654994c 100644
--- a/code/game/turfs/simulated/floor/fancy_floor.dm
+++ b/code/game/turfs/simulated/floor/fancy_floor.dm
@@ -117,6 +117,9 @@
burnt = 1
update_icon()
+/turf/open/floor/carpet/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
+ return FALSE
+
/turf/simulated/floor/carpet/black
icon = 'icons/turf/floors/carpet_black.dmi'
floor_tile = /obj/item/stack/tile/carpet/black
@@ -127,6 +130,7 @@
icon_state = "0"
floor_tile = /obj/item/stack/tile/fakespace
broken_states = list("damaged")
+ plane = PLANE_SPACE
/turf/simulated/floor/fakespace/New()
..()
@@ -137,3 +141,9 @@
icon_state = "arcade"
floor_tile = /obj/item/stack/tile/arcade_carpet
smooth = SMOOTH_FALSE
+
+/turf/open/floor/fakespace/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
+ underlay_appearance.icon = 'icons/turf/space.dmi'
+ underlay_appearance.icon_state = SPACE_ICON_STATE
+ underlay_appearance.plane = PLANE_SPACE
+ return TRUE
diff --git a/code/game/turfs/simulated/floor/indestructible.dm b/code/game/turfs/simulated/floor/indestructible.dm
index 6c1679776e6..3705e24eea0 100644
--- a/code/game/turfs/simulated/floor/indestructible.dm
+++ b/code/game/turfs/simulated/floor/indestructible.dm
@@ -81,5 +81,8 @@
planetary_atmos = TRUE
desc = "A floor with a square pattern. It's faintly cool to the touch."
+/turf/open/indestructible/hierophant/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
+ return FALSE
+
/turf/simulated/floor/indestructible/hierophant/two
icon_state = "hierophant2"
diff --git a/code/game/turfs/simulated/floor/lava.dm b/code/game/turfs/simulated/floor/lava.dm
index 0882bb18766..66d7eaca83d 100644
--- a/code/game/turfs/simulated/floor/lava.dm
+++ b/code/game/turfs/simulated/floor/lava.dm
@@ -41,6 +41,11 @@
/turf/simulated/floor/plating/lava/remove_plating()
return
+/turf/open/lava/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
+ underlay_appearance.icon = 'icons/turf/floors.dmi'
+ underlay_appearance.icon_state = "basalt"
+ return TRUE
+
/turf/simulated/floor/plating/lava/proc/is_safe()
var/static/list/lava_safeties_typecache = typecacheof(list(/obj/structure/lattice/catwalk, /obj/structure/stone_tile))
var/list/found_safeties = typecache_filter_list(contents, lava_safeties_typecache)
diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm
index 2ef4602d268..9ff6ddb8876 100644
--- a/code/game/turfs/simulated/floor/plating.dm
+++ b/code/game/turfs/simulated/floor/plating.dm
@@ -7,6 +7,8 @@
broken_states = list("damaged1", "damaged2", "damaged3", "damaged4", "damaged5")
burnt_states = list("floorscorched1", "floorscorched2")
+ var/unfastened = FALSE
+
footstep_sounds = list(
"human" = list('sound/effects/footstep/plating_human.ogg'),
"xeno" = list('sound/effects/footstep/plating_xeno.ogg')
@@ -31,6 +33,12 @@
if(!broken && !burnt)
icon_state = icon_plating //Because asteroids are 'platings' too.
+/turf/simulated/floor/plating/examine(mob/user)
+ . = ..()
+
+ if(unfastened)
+ to_chat(user, "It has been unfastened.")
+
/turf/simulated/floor/plating/attackby(obj/item/C, mob/user, params)
if(..())
return TRUE
@@ -64,7 +72,16 @@
to_chat(user, "This section is too damaged to support a tile! Use a welder to fix the damage.")
return TRUE
- else if(iswelder(C))
+ else if(isscrewdriver(C))
+ var/obj/item/screwdriver/screwdriver = C
+ to_chat(user, "You start [unfastened ? "fastening" : "unfastening"] [src].")
+ playsound(src, screwdriver.usesound, 50, 1)
+ if(do_after(user, 20 * screwdriver.toolspeed, target = src) && screwdriver)
+ to_chat(user, "You [unfastened ? "fasten" : "unfasten"] [src].")
+ unfastened = !unfastened
+ return TRUE
+
+ else if(iswelder(C) && unfastened)
var/obj/item/weldingtool/welder = C
if(welder.isOn())
if(!welder.remove_fuel(0, user))
diff --git a/code/game/turfs/simulated/minerals.dm b/code/game/turfs/simulated/minerals.dm
index 119f0b000d9..aee23831050 100644
--- a/code/game/turfs/simulated/minerals.dm
+++ b/code/game/turfs/simulated/minerals.dm
@@ -48,6 +48,13 @@
setDir(angle2dir(rotation + dir2angle(dir)))
queue_smooth(src)
+/turf/simulated/mineral/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
+ if(turf_type)
+ underlay_appearance.icon = initial(turf_type.icon)
+ underlay_appearance.icon_state = initial(turf_type.icon_state)
+ return TRUE
+ return ..()
+
/turf/simulated/mineral/attackby(var/obj/item/pickaxe/P as obj, mob/user as mob, params)
if(!user.IsAdvancedToolUser())
to_chat(usr, "You don't have the dexterity to do this!")
diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm
index 5a8f842307e..26b79c9e9f4 100644
--- a/code/game/turfs/simulated/walls.dm
+++ b/code/game/turfs/simulated/walls.dm
@@ -1,3 +1,7 @@
+#define WALL_DENT_HIT 1
+#define WALL_DENT_SHOT 2
+#define MAX_DENT_DECALS 15
+
/turf/simulated/wall
name = "wall"
desc = "A huge chunk of metal used to seperate rooms."
@@ -25,7 +29,7 @@
var/slicing_duration = 100
var/engraving //engraving on the wall
var/engraving_quality
-
+ var/list/dent_decals
var/sheet_type = /obj/item/stack/sheet/metal
var/sheet_amount = 2
var/girder_type = /obj/structure/girder
@@ -167,6 +171,8 @@
/turf/simulated/wall/blob_act()
if(prob(50))
dismantle_wall()
+ else
+ add_dent(WALL_DENT_HIT)
/turf/simulated/wall/rpd_act(mob/user, obj/item/rpd/our_rpd)
if(our_rpd.mode == RPD_ATMOS_MODE)
@@ -191,6 +197,8 @@
M.occupant_message("You smash through the wall.")
visible_message("[src.name] smashes through the wall!")
playsound(src, 'sound/effects/meteorimpact.ogg', 100, 1)
+ else
+ add_dent(WALL_DENT_HIT)
// Wall-rot effect, a nasty fungus that destroys walls.
/turf/simulated/wall/proc/rot()
@@ -260,6 +268,7 @@
dismantle_wall(TRUE)
else
playsound(src, 'sound/effects/bang.ogg', 50, 1)
+ add_dent(WALL_DENT_HIT)
to_chat(user, text("You punch the wall."))
return TRUE
@@ -296,7 +305,6 @@
if(try_wallmount(I, user, params))
return
-
// The magnetic gripper does a separate attackby, so bail from this one
if(istype(I, /obj/item/gripper))
return
@@ -327,7 +335,7 @@
return TRUE // this means "don't continue trying to find alternative uses in attackby", not "decon succeeded"
var/response = "Dismantle"
- if(damage)
+ if(damage || LAZYLEN(dent_decals))
response = alert(user, "Would you like to repair or dismantle [src]?", "[src]", "Repair", "Dismantle")
switch(response)
@@ -336,6 +344,8 @@
playsound(src, WT.usesound, 100, 1)
if(do_after(user, max(5, damage / 5) * WT.toolspeed, target = src) && WT && WT.isOn())
to_chat(user, "You finish repairing the damage to [src].")
+ cut_overlay(dent_decals)
+ dent_decals.Cut()
take_damage(-damage)
else
to_chat(user, "You begin slicing through the outer plating.")
@@ -435,3 +445,27 @@
/turf/simulated/wall/narsie_act()
if(prob(20))
ChangeTurf(/turf/simulated/wall/cult)
+
+/turf/simulated/wall/proc/add_dent(denttype, x=rand(-8, 8), y=rand(-8, 8))
+ if(LAZYLEN(dent_decals) >= MAX_DENT_DECALS)
+ return
+
+ var/mutable_appearance/decal = mutable_appearance('icons/effects/effects.dmi', "", BULLET_HOLE_LAYER)
+ switch(denttype)
+ if(WALL_DENT_SHOT)
+ decal.icon_state = "bullet_hole"
+ if(WALL_DENT_HIT)
+ decal.icon_state = "impact[rand(1, 3)]"
+
+ decal.pixel_x = x
+ decal.pixel_y = y
+
+ if(LAZYLEN(dent_decals))
+ cut_overlay(dent_decals)
+ dent_decals += decal
+ else
+ dent_decals = list(decal)
+
+ add_overlay(dent_decals)
+
+#undef MAX_DENT_DECALS
\ No newline at end of file
diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm
index 0d6428b10a2..40c0d83272e 100644
--- a/code/game/turfs/space/space.dm
+++ b/code/game/turfs/space/space.dm
@@ -16,6 +16,7 @@
var/destination_z
var/destination_x
var/destination_y
+ plane = PLANE_SPACE
/turf/space/Initialize(mapload)
if(!istype(src, /turf/space/transit))
@@ -262,4 +263,10 @@
/turf/space/attack_ghost(mob/dead/observer/user)
if(destination_z)
var/turf/T = locate(destination_x, destination_y, destination_z)
- user.forceMove(T)
\ No newline at end of file
+ user.forceMove(T)
+
+/turf/space/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
+ underlay_appearance.icon = 'icons/turf/space.dmi'
+ underlay_appearance.icon_state = SPACE_ICON_STATE
+ underlay_appearance.plane = PLANE_SPACE
+ return TRUE
diff --git a/code/game/turfs/space/transit.dm b/code/game/turfs/space/transit.dm
index 79bf171ce1f..15c553b3f95 100644
--- a/code/game/turfs/space/transit.dm
+++ b/code/game/turfs/space/transit.dm
@@ -1,5 +1,6 @@
/turf/space/transit
var/pushdirection // push things that get caught in the transit tile this direction
+ plane = PLANE_SPACE
//Overwrite because we dont want people building rods in space.
/turf/space/transit/attackby(obj/O as obj, mob/user as mob, params)
@@ -151,3 +152,9 @@
icon_state = "speedspace_ns_[state]"
transform = turn(matrix(), angle)
+
+/turf/space/transit/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
+ underlay_appearance.icon = 'icons/turf/space.dmi'
+ underlay_appearance.icon_state = SPACE_ICON_STATE
+ underlay_appearance.plane = PLANE_SPACE
+ return TRUE
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index e315ad26ad0..51285932f00 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -470,6 +470,12 @@
if(ismob(A) || .)
A.ratvar_act()
+/turf/proc/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
+ underlay_appearance.icon = icon
+ underlay_appearance.icon_state = icon_state
+ underlay_appearance.dir = adjacency_dir
+ return TRUE
+
/turf/proc/add_blueprints(atom/movable/AM)
var/image/I = new
I.appearance = AM.appearance
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 7687b22f71c..1176e733dde 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -644,7 +644,7 @@ var/list/admin_verbs_ticket = list(
if(!message)
return
for(var/mob/V in hearers(O))
- V.show_message(message, 2)
+ V.show_message(admin_pencode_to_html(message), 2)
log_admin("[key_name(usr)] made [O] at [O.x], [O.y], [O.z] make a sound")
message_admins("[key_name_admin(usr)] made [O] at [O.x], [O.y], [O.z] make a sound")
feedback_add_details("admin_verb","MS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index e45224b175b..be136204739 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -2186,7 +2186,7 @@
if(!input)
qdel(P)
return
- input = P.parsepencode(input) // Encode everything from pencode to html
+ input = admin_pencode_to_html(html_encode(input)) // Encode everything from pencode to html
var/customname = clean_input("Pick a title for the fax.", "Fax Title", , owner)
if(!customname)
diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm
index 2352c442313..1069e981c37 100644
--- a/code/modules/admin/verbs/adminpm.dm
+++ b/code/modules/admin/verbs/adminpm.dm
@@ -110,7 +110,7 @@
if(!msg)
return
else
- msg = pencode_to_html(msg)
+ msg = admin_pencode_to_html(msg)
var/recieve_span = "playerreply"
var/send_pm_type = " "
@@ -161,7 +161,9 @@
var/emoji_msg = "[msg]"
recieve_message = "[type] from-[recieve_pm_type][C.holder ? key_name(src, TRUE, type) : key_name_hidden(src, TRUE, type)]: [emoji_msg]"
to_chat(C, recieve_message)
- to_chat(src, "[send_pm_type][type] to-[holder ? key_name(C, TRUE, type) : key_name_hidden(C, TRUE, type)]: [emoji_msg]")
+ var/ping_link = check_rights(R_ADMIN, 0, mob) ? "(PING)" : ""
+ var/window_link = "(WINDOW)"
+ to_chat(src, "[send_pm_type][type] to-[holder ? key_name(C, TRUE, type) : key_name_hidden(C, TRUE, type)]: [emoji_msg] [ping_link] [window_link]")
/*if(holder && !C.holder)
C.last_pm_recieved = world.time
@@ -380,7 +382,6 @@
window_flash(C)
C.pm_tracker.show_ui(C.mob)
to_chat(usr, "Forced open [C]'s messages window.")
- show_ui(usr)
return
if(href_list["reply"])
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index b8d93950843..2c7c6181b1d 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -58,6 +58,9 @@
if(!msg)
return
+
+ msg = admin_pencode_to_html(msg)
+
if(usr)
if(usr.client)
if(usr.client.holder)
@@ -136,7 +139,7 @@
if( !msg )
return
- msg = pencode_to_html(msg)
+ msg = admin_pencode_to_html(msg)
to_chat(M, msg)
log_admin("DirectNarrate: [key_name(usr)] to ([key_name(M)]): [msg]")
diff --git a/code/modules/awaymissions/mission_code/academy.dm b/code/modules/awaymissions/mission_code/academy.dm
index d15b3e3075d..e41e29a747f 100644
--- a/code/modules/awaymissions/mission_code/academy.dm
+++ b/code/modules/awaymissions/mission_code/academy.dm
@@ -193,7 +193,7 @@
servant_mind.objectives += O
servant_mind.transfer_to(H)
- var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as the servant of [user.real_name]?", ROLE_WIZARD, poll_time = 50)
+ var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as the servant of [user.real_name]?", ROLE_WIZARD, poll_time = 300)
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
message_admins("[ADMIN_LOOKUPFLW(C)] was spawned as Dice Servant")
diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm
index 95f6c16ba97..2d4092ff159 100644
--- a/code/modules/client/client procs.dm
+++ b/code/modules/client/client procs.dm
@@ -433,6 +433,9 @@
GLOB.admins -= src
GLOB.directory -= ckey
GLOB.clients -= src
+ if(movingmob)
+ movingmob.client_mobs_in_contents -= mob
+ UNSETEMPTY(movingmob.client_mobs_in_contents)
Master.UpdateTickRate()
return ..()
diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm
index 97f9ddc6169..7fce23b9e4c 100644
--- a/code/modules/client/preference/preferences.dm
+++ b/code/modules/client/preference/preferences.dm
@@ -201,6 +201,8 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
//Gear stuff
var/list/gear = list()
var/gear_tab = "General"
+ // Parallax
+ var/parallax = PARALLAX_HIGH
/datum/preferences/New(client/C)
parent = C
@@ -462,6 +464,19 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
dat += "OOC Color: Change
"
if(config.allow_Metadata)
dat += "OOC Notes: Edit
"
+ dat += "Parallax (Fancy Space): "
+ switch (parallax)
+ if(PARALLAX_LOW)
+ dat += "Low"
+ if(PARALLAX_MED)
+ dat += "Medium"
+ if(PARALLAX_INSANE)
+ dat += "Insane"
+ if(PARALLAX_DISABLE)
+ dat += "Disabled"
+ else
+ dat += "High"
+ dat += "
"
dat += "Play Admin MIDIs: [(sound & SOUND_MIDI) ? "Yes" : "No"]
"
dat += "Play Lobby Music: [(sound & SOUND_LOBBY) ? "Yes" : "No"]
"
dat += "Randomized Character Slot: [randomslot ? "Yes" : "No"]
"
@@ -2072,6 +2087,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
if(href_list["tab"])
current_tab = text2num(href_list["tab"])
+
if("ambientocclusion")
toggles ^= AMBIENT_OCCLUSION
if(parent && parent.screen && parent.screen.len)
@@ -2080,6 +2096,19 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
if(toggles & AMBIENT_OCCLUSION)
PM.filters += FILTER_AMBIENT_OCCLUSION
+ if("parallax")
+ var/parallax_styles = list(
+ "Off" = PARALLAX_DISABLE,
+ "Low" = PARALLAX_LOW,
+ "Medium" = PARALLAX_MED,
+ "High" = PARALLAX_HIGH,
+ "Insane" = PARALLAX_INSANE
+ )
+ parallax = parallax_styles[input(user, "Pick a parallax style", "Parallax Style") as null|anything in parallax_styles]
+ if(parent && parent.mob && parent.mob.hud_used)
+ parent.mob.hud_used.update_parallax_pref()
+
+
ShowChoices(user)
return 1
diff --git a/code/modules/client/preference/preferences_mysql.dm b/code/modules/client/preference/preferences_mysql.dm
index cdbfe2afb2f..6090538f2b3 100644
--- a/code/modules/client/preference/preferences_mysql.dm
+++ b/code/modules/client/preference/preferences_mysql.dm
@@ -20,7 +20,8 @@
clientfps,
atklog,
fuid,
- afk_watch
+ afk_watch,
+ parallax
FROM [format_table_name("player")]
WHERE ckey='[C.ckey]'"}
)
@@ -54,6 +55,7 @@
atklog = text2num(query.item[18])
fuid = text2num(query.item[19])
afk_watch = text2num(query.item[20])
+ parallax = text2num(query.item[21])
//Sanitize
ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor))
@@ -75,6 +77,7 @@
atklog = sanitize_integer(atklog, 0, 100, initial(atklog))
fuid = sanitize_integer(fuid, 0, 10000000, initial(fuid))
afk_watch = sanitize_integer(afk_watch, 0, 1, initial(afk_watch))
+ parallax = sanitize_integer(parallax, 0, 16, initial(parallax))
return 1
/datum/preferences/proc/save_preferences(client/C)
@@ -105,7 +108,8 @@
ghost_anonsay='[ghost_anonsay]',
clientfps='[clientfps]',
atklog='[atklog]',
- afk_watch='[afk_watch]'
+ afk_watch='[afk_watch]',
+ parallax='[parallax]'
WHERE ckey='[C.ckey]'"}
)
diff --git a/code/modules/clothing/gloves/miscellaneous.dm b/code/modules/clothing/gloves/miscellaneous.dm
index 8e5e658e31a..a06b01de65d 100644
--- a/code/modules/clothing/gloves/miscellaneous.dm
+++ b/code/modules/clothing/gloves/miscellaneous.dm
@@ -38,6 +38,21 @@
max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT
burn_state = FIRE_PROOF
+/obj/item/clothing/gloves/bracer
+ name = "bone bracers"
+ desc = "For when you're expecting to get slapped on the wrist. Offers modest protection to your arms."
+ icon_state = "bracers"
+ item_state = "bracers"
+ item_color = null //So they don't wash.
+ transfer_prints = TRUE
+ strip_delay = 40
+ body_parts_covered = ARMS
+ cold_protection = ARMS
+ min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT
+ max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT
+ resistance_flags = NONE
+ armor = list(melee = 15, bullet = 25, laser = 15, energy = 15, bomb = 20, bio = 10, rad = 0)
+
/obj/item/clothing/gloves/botanic_leather
desc = "These leather gloves protect against thorns, barbs, prickles, spikes and other harmful objects of floral origin."
name = "botanist's leather gloves"
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index 96c2ed46f7a..ae8502f7246 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -527,14 +527,15 @@
icon_state = "bonearmor"
item_state = "bonearmor"
blood_overlay_type = "armor"
- armor = list("melee" = 35, "bullet" = 25, "laser" = 25, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
+ armor = list(melee = 35, bullet = 25, laser = 25, energy = 10, bomb = 25, bio = 0, rad = 0)
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS
-/obj/item/clothing/head/skullhelmet
+/obj/item/clothing/head/helmet/skull
name = "skull helmet"
desc = "An intimidating tribal helmet, it doesn't look very comfortable."
- flags = BLOCKHAIR
+ flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE
flags_cover = HEADCOVERSEYES
- armor = list("melee" = 25, "bullet" = 25, "laser" = 25, "energy" = 10, "bomb" = 10, "bio" = 5, "rad" = 20, "fire" = 40, "acid" = 20)
+ armor = list(melee = 25, bullet = 25, laser = 25, energy = 10, bomb = 10, bio = 5, rad = 20)
icon_state = "skull"
- item_state = "skull"
\ No newline at end of file
+ item_state = "skull"
+ strip_delay = 100
\ No newline at end of file
diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm
index 1520e19dcfc..58338efea61 100644
--- a/code/modules/crafting/recipes.dm
+++ b/code/modules/crafting/recipes.dm
@@ -385,42 +385,11 @@
)
category = CAT_WEAPON
-/datum/crafting_recipe/bonfire
- name = "Bonfire"
- time = 60
- reqs = list(/obj/item/grown/log = 5)
- result = /obj/structure/bonfire
- category = CAT_PRIMAL
-
-/datum/crafting_recipe/boneaxe
- name = "Bone Axe"
- result = /obj/item/twohanded/fireaxe/boneaxe
- time = 50
- reqs = list(/obj/item/stack/sheet/bone = 6,
- /obj/item/stack/sheet/sinew = 3)
- category = CAT_PRIMAL
-
-/datum/crafting_recipe/bonespear
- name = "Bone Spear"
- result = /obj/item/twohanded/spear/bonespear
+/datum/crafting_recipe/bonearmor
+ name = "Bone Armor"
+ result = /obj/item/clothing/suit/armor/bone
time = 30
- reqs = list(/obj/item/stack/sheet/bone = 4,
- /obj/item/stack/sheet/sinew = 1)
- category = CAT_PRIMAL
-
-/datum/crafting_recipe/bonedagger
- name = "Bone Dagger"
- result = /obj/item/kitchen/knife/combat/survival/bone
- time = 20
- reqs = list(/obj/item/stack/sheet/bone = 2)
- category = CAT_PRIMAL
-
-/datum/crafting_recipe/bonecodpiece
- name = "Skull Codpiece"
- result = /obj/item/clothing/accessory/necklace/skullcodpiece
- time = 20
- reqs = list(/obj/item/stack/sheet/bone = 2,
- /obj/item/stack/sheet/animalhide/goliath_hide = 1)
+ reqs = list(/obj/item/stack/sheet/bone = 6)
category = CAT_PRIMAL
/datum/crafting_recipe/bonetalisman
@@ -431,16 +400,25 @@
/obj/item/stack/sheet/sinew = 1)
category = CAT_PRIMAL
-/datum/crafting_recipe/bonearmor
- name = "Bone Armor"
- result = /obj/item/clothing/suit/armor/bone
- time = 30
- reqs = list(/obj/item/stack/sheet/bone = 6)
+/datum/crafting_recipe/bonecodpiece
+ name = "Skull Codpiece"
+ result = /obj/item/clothing/accessory/necklace/skullcodpiece
+ time = 20
+ reqs = list(/obj/item/stack/sheet/bone = 2,
+ /obj/item/stack/sheet/animalhide/goliath_hide = 1)
+ category = CAT_PRIMAL
+
+/datum/crafting_recipe/bracers
+ name = "Bone Bracers"
+ result = /obj/item/clothing/gloves/bracer
+ time = 20
+ reqs = list(/obj/item/stack/sheet/bone = 2,
+ /obj/item/stack/sheet/sinew = 1)
category = CAT_PRIMAL
/datum/crafting_recipe/skullhelm
name = "Skull Helmet"
- result = /obj/item/clothing/head/skullhelmet
+ result = /obj/item/clothing/head/helmet/skull
time = 30
reqs = list(/obj/item/stack/sheet/bone = 4)
category = CAT_PRIMAL
@@ -463,6 +441,13 @@
/obj/item/stack/sheet/animalhide/ashdrake = 5)
category = CAT_PRIMAL
+/datum/crafting_recipe/firebrand
+ name = "Firebrand"
+ result = /obj/item/match/firebrand
+ time = 100 //Long construction time. Making fire is hard work.
+ reqs = list(/obj/item/stack/sheet/wood = 2)
+ category = CAT_PRIMAL
+
/datum/crafting_recipe/tribal_splint
name = "Tribal Splint"
time = 20
@@ -471,6 +456,50 @@
result = /obj/item/stack/medical/splint/tribal
category = CAT_PRIMAL
+/datum/crafting_recipe/bonedagger
+ name = "Bone Dagger"
+ result = /obj/item/kitchen/knife/combat/survival/bone
+ time = 20
+ reqs = list(/obj/item/stack/sheet/bone = 2)
+ category = CAT_PRIMAL
+
+/datum/crafting_recipe/bonespear
+ name = "Bone Spear"
+ result = /obj/item/twohanded/spear/bonespear
+ time = 30
+ reqs = list(/obj/item/stack/sheet/bone = 4,
+ /obj/item/stack/sheet/sinew = 1)
+ category = CAT_PRIMAL
+
+/datum/crafting_recipe/boneaxe
+ name = "Bone Axe"
+ result = /obj/item/twohanded/fireaxe/boneaxe
+ time = 50
+ reqs = list(/obj/item/stack/sheet/bone = 6,
+ /obj/item/stack/sheet/sinew = 3)
+ category = CAT_PRIMAL
+
+/datum/crafting_recipe/bonfire
+ name = "Bonfire"
+ time = 60
+ reqs = list(/obj/item/grown/log = 5)
+ result = /obj/structure/bonfire
+ category = CAT_PRIMAL
+
+/datum/crafting_recipe/rake //Category resorting incoming
+ name = "Rake"
+ time = 30
+ reqs = list(/obj/item/stack/sheet/wood = 5)
+ result = /obj/item/cultivator/rake
+ category = CAT_PRIMAL
+
+/datum/crafting_recipe/woodbucket
+ name = "Wooden Bucket"
+ time = 30
+ reqs = list(/obj/item/stack/sheet/wood = 3)
+ result = /obj/item/reagent_containers/glass/bucket/wooden
+ category = CAT_PRIMAL
+
/datum/crafting_recipe/guillotine
name = "Guillotine"
result = /obj/structure/guillotine
diff --git a/code/modules/events/alien_infestation.dm b/code/modules/events/alien_infestation.dm
index 590ff374ad6..2d3cb8465c9 100644
--- a/code/modules/events/alien_infestation.dm
+++ b/code/modules/events/alien_infestation.dm
@@ -26,6 +26,7 @@
if(C)
GLOB.respawnable_list -= C.client
var/mob/living/carbon/alien/larva/new_xeno = new(vent.loc)
+ new_xeno.amount_grown += (0.75 * new_xeno.max_grown) //event spawned larva start off almost ready to evolve.
new_xeno.key = C.key
if(SSticker && SSticker.mode)
SSticker.mode.xenos += new_xeno.mind
diff --git a/code/modules/hydroponics/hydroitemdefines.dm b/code/modules/hydroponics/hydroitemdefines.dm
index 14080c62bba..899146f160d 100644
--- a/code/modules/hydroponics/hydroitemdefines.dm
+++ b/code/modules/hydroponics/hydroitemdefines.dm
@@ -72,6 +72,16 @@
attack_verb = list("slashed", "sliced", "cut", "clawed")
hitsound = 'sound/weapons/bladeslice.ogg'
+/obj/item/cultivator/rake
+ name = "rake"
+ icon_state = "rake"
+ w_class = WEIGHT_CLASS_NORMAL
+ attack_verb = list("slashed", "sliced", "bashed", "clawed")
+ hitsound = null
+ materials = null
+ flags = NONE
+ burn_state = FLAMMABLE
+
/obj/item/hatchet
name = "hatchet"
desc = "A very sharp axe blade upon a short fibremetal handle. It has a long history of chopping things, but now it is used for chopping wood."
diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm
new file mode 100644
index 00000000000..47b3fb01501
--- /dev/null
+++ b/code/modules/mining/equipment/kinetic_crusher.dm
@@ -0,0 +1,439 @@
+/*********************Mining Hammer****************/
+/obj/item/twohanded/kinetic_crusher
+ icon = 'icons/obj/mining.dmi'
+ icon_state = "crusher"
+ item_state = "crusher0"
+ name = "proto-kinetic crusher"
+ desc = "An early design of the proto-kinetic accelerator, it is little more than a combination of various mining tools cobbled together, forming a high-tech club. \
+ While it is an effective mining tool, it did little to aid any but the most skilled and/or suicidal miners against local fauna."
+ force = 0 //You can't hit stuff unless wielded
+ w_class = WEIGHT_CLASS_BULKY
+ slot_flags = SLOT_BACK
+ force_unwielded = 0
+ force_wielded = 20
+ throwforce = 5
+ throw_speed = 4
+ armour_penetration = 10
+ materials = list(MAT_METAL = 1150, MAT_GLASS = 2075)
+ hitsound = 'sound/weapons/bladeslice.ogg'
+ attack_verb = list("smashed", "crushed", "cleaved", "chopped", "pulped")
+ sharp = TRUE
+ actions_types = list(/datum/action/item_action/toggle_light)
+ var/list/trophies = list()
+ var/charged = TRUE
+ var/charge_time = 15
+ var/detonation_damage = 50
+ var/backstab_bonus = 30
+ var/light_on = FALSE
+ var/brightness_on = 5
+
+/obj/item/twohanded/kinetic_crusher/Destroy()
+ QDEL_LIST(trophies)
+ return ..()
+
+/obj/item/twohanded/kinetic_crusher/examine(mob/living/user)
+ ..()
+ to_chat(user, "Mark a large creature with the destabilizing force, then hit them in melee to do [force + detonation_damage] damage.")
+ to_chat(user, "Does [force + detonation_damage + backstab_bonus] damage if the target is backstabbed, instead of [force + detonation_damage].")
+ for(var/t in trophies)
+ var/obj/item/crusher_trophy/T = t
+ to_chat(user, "It has \a [T] attached, which causes [T.effect_desc()].")
+
+/obj/item/twohanded/kinetic_crusher/attackby(obj/item/I, mob/living/user)
+ if(iscrowbar(I))
+ if(LAZYLEN(trophies))
+ to_chat(user, "You remove [src]'s trophies.")
+ playsound(loc, I.usesound, 100, 1)
+ for(var/t in trophies)
+ var/obj/item/crusher_trophy/T = t
+ T.remove_from(src, user)
+ else
+ to_chat(user, "There are no trophies on [src].")
+ else if(istype(I, /obj/item/crusher_trophy))
+ var/obj/item/crusher_trophy/T = I
+ T.add_to(src, user)
+ else
+ return ..()
+
+/obj/item/twohanded/kinetic_crusher/attack(mob/living/target, mob/living/carbon/user)
+ if(!wielded)
+ to_chat(user, "[src] is too heavy to use with one hand. You fumble and drop everything.")
+ user.drop_r_hand()
+ user.drop_l_hand()
+ return
+ var/datum/status_effect/crusher_damage/C = target.has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
+ var/target_health = target.health
+ ..()
+ for(var/t in trophies)
+ if(!QDELETED(target))
+ var/obj/item/crusher_trophy/T = t
+ T.on_melee_hit(target, user)
+ if(!QDELETED(C) && !QDELETED(target))
+ C.total_damage += target_health - target.health //we did some damage, but let's not assume how much we did
+
+/obj/item/twohanded/kinetic_crusher/afterattack(atom/target, mob/living/user, proximity_flag, clickparams)
+ . = ..()
+ if(!wielded)
+ return
+ if(!proximity_flag && charged)//Mark a target, or mine a tile.
+ var/turf/proj_turf = user.loc
+ if(!isturf(proj_turf))
+ return
+ var/obj/item/projectile/destabilizer/D = new /obj/item/projectile/destabilizer(proj_turf)
+ for(var/t in trophies)
+ var/obj/item/crusher_trophy/T = t
+ T.on_projectile_fire(D, user)
+ D.preparePixelProjectile(target, get_turf(target), user, clickparams)
+ D.firer = user
+ D.hammer_synced = src
+ playsound(user, 'sound/weapons/plasma_cutter.ogg', 100, 1)
+ D.fire()
+ charged = FALSE
+ update_icon()
+ addtimer(CALLBACK(src, .proc/Recharge), charge_time)
+ return
+ if(proximity_flag && isliving(target))
+ var/mob/living/L = target
+ var/datum/status_effect/crusher_mark/CM = L.has_status_effect(STATUS_EFFECT_CRUSHERMARK)
+ if(!CM || CM.hammer_synced != src || !L.remove_status_effect(STATUS_EFFECT_CRUSHERMARK))
+ return
+ var/datum/status_effect/crusher_damage/C = L.has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
+ var/target_health = L.health
+ for(var/t in trophies)
+ var/obj/item/crusher_trophy/T = t
+ T.on_mark_detonation(target, user)
+ if(!QDELETED(L))
+ if(!QDELETED(C))
+ C.total_damage += target_health - L.health //we did some damage, but let's not assume how much we did
+ new /obj/effect/temp_visual/kinetic_blast(get_turf(L))
+ var/backstab_dir = get_dir(user, L)
+ var/def_check = L.getarmor(type = "bomb")
+ if((user.dir & backstab_dir) && (L.dir & backstab_dir))
+ if(!QDELETED(C))
+ C.total_damage += detonation_damage + backstab_bonus //cheat a little and add the total before killing it, so certain mobs don't have much lower chances of giving an item
+ L.apply_damage(detonation_damage + backstab_bonus, BRUTE, blocked = def_check)
+ playsound(user, 'sound/weapons/kenetic_accel.ogg', 100, 1) //Seriously who spelled it wrong
+ else
+ if(!QDELETED(C))
+ C.total_damage += detonation_damage
+ L.apply_damage(detonation_damage, BRUTE, blocked = def_check)
+
+/obj/item/twohanded/kinetic_crusher/proc/Recharge()
+ if(!charged)
+ charged = TRUE
+ update_icon()
+ playsound(src.loc, 'sound/weapons/kenetic_reload.ogg', 60, 1)
+
+/obj/item/twohanded/kinetic_crusher/ui_action_click(mob/user, actiontype)
+ light_on = !light_on
+ playsound(user, 'sound/weapons/empty.ogg', 100, TRUE)
+ update_brightness(user)
+ update_icon()
+
+/obj/item/twohanded/kinetic_crusher/proc/update_brightness(mob/user = null)
+ if(light_on)
+ set_light(brightness_on)
+ else
+ set_light(0)
+
+/obj/item/twohanded/kinetic_crusher/update_icon()
+ ..()
+ cut_overlays()
+ if(!charged)
+ add_overlay("[icon_state]_uncharged")
+ if(light_on)
+ add_overlay("[icon_state]_lit")
+ spawn(1)
+ for(var/X in actions)
+ var/datum/action/A = X
+ A.UpdateButtonIcon()
+ item_state = "crusher[wielded]"
+
+//destablizing force
+/obj/item/projectile/destabilizer
+ name = "destabilizing force"
+ icon_state = "pulse1"
+ nodamage = TRUE
+ damage = 0 //We're just here to mark people. This is still a melee weapon.
+ damage_type = BRUTE
+ flag = "bomb"
+ range = 6
+ log_override = TRUE
+ var/obj/item/twohanded/kinetic_crusher/hammer_synced
+
+/obj/item/projectile/destabilizer/Destroy()
+ hammer_synced = null
+ return ..()
+
+/obj/item/projectile/destabilizer/on_hit(atom/target, blocked = FALSE)
+ if(isliving(target))
+ var/mob/living/L = target
+ var/had_effect = (L.has_status_effect(STATUS_EFFECT_CRUSHERMARK)) //used as a boolean
+ var/datum/status_effect/crusher_mark/CM = L.apply_status_effect(STATUS_EFFECT_CRUSHERMARK, hammer_synced)
+ if(hammer_synced)
+ for(var/t in hammer_synced.trophies)
+ var/obj/item/crusher_trophy/T = t
+ T.on_mark_application(target, CM, had_effect)
+ var/target_turf = get_turf(target)
+ if(ismineralturf(target_turf))
+ var/turf/simulated/mineral/M = target_turf
+ new /obj/effect/temp_visual/kinetic_blast(M)
+ M.gets_drilled(firer)
+ ..()
+
+//trophies
+/obj/item/crusher_trophy
+ name = "tail spike"
+ desc = "A strange spike with no usage."
+ icon = 'icons/obj/lavaland/artefacts.dmi'
+ icon_state = "tail_spike"
+ var/bonus_value = 10 //if it has a bonus effect, this is how much that effect is
+ var/denied_type = /obj/item/crusher_trophy
+
+/obj/item/crusher_trophy/examine(mob/living/user)
+ ..()
+ to_chat(user, "Causes [effect_desc()] when attached to a kinetic crusher.")
+
+/obj/item/crusher_trophy/proc/effect_desc()
+ return "errors"
+
+/obj/item/crusher_trophy/attackby(obj/item/A, mob/living/user)
+ if(istype(A, /obj/item/twohanded/kinetic_crusher))
+ add_to(A, user)
+ else
+ ..()
+
+/obj/item/crusher_trophy/proc/add_to(obj/item/twohanded/kinetic_crusher/H, mob/living/user)
+ for(var/t in H.trophies)
+ var/obj/item/crusher_trophy/T = t
+ if(istype(T, denied_type) || istype(src, T.denied_type))
+ to_chat(user, "You can't seem to attach [src] to [H]. Maybe remove a few trophies?")
+ return FALSE
+ if(!user.drop_item())
+ return
+ forceMove(H)
+ H.trophies += src
+ to_chat(user, "You attach [src] to [H].")
+ return TRUE
+
+/obj/item/crusher_trophy/proc/remove_from(obj/item/twohanded/kinetic_crusher/H, mob/living/user)
+ forceMove(get_turf(H))
+ H.trophies -= src
+ return TRUE
+
+/obj/item/crusher_trophy/proc/on_melee_hit(mob/living/target, mob/living/user) //the target and the user
+
+/obj/item/crusher_trophy/proc/on_projectile_fire(obj/item/projectile/destabilizer/marker, mob/living/user) //the projectile fired and the user
+
+/obj/item/crusher_trophy/proc/on_mark_application(mob/living/target, datum/status_effect/crusher_mark/mark, had_mark) //the target, the mark applied, and if the target had a mark before
+
+/obj/item/crusher_trophy/proc/on_mark_detonation(mob/living/target, mob/living/user) //the target and the user
+
+//goliath
+/obj/item/crusher_trophy/goliath_tentacle
+ name = "goliath tentacle"
+ desc = "A sliced-off goliath tentacle. Suitable as a trophy for a kinetic crusher."
+ icon_state = "goliath_tentacle"
+ denied_type = /obj/item/crusher_trophy/goliath_tentacle
+ bonus_value = 2
+ var/missing_health_ratio = 0.1
+ var/missing_health_desc = 10
+
+/obj/item/crusher_trophy/goliath_tentacle/effect_desc()
+ return "mark detonation to do [bonus_value] more damage for every [missing_health_desc] health you are missing"
+
+/obj/item/crusher_trophy/goliath_tentacle/on_mark_detonation(mob/living/target, mob/living/user)
+ var/missing_health = user.health - user.maxHealth
+ missing_health *= missing_health_ratio //bonus is active at all times, even if you're above 90 health
+ missing_health *= bonus_value //multiply the remaining amount by bonus_value
+ if(missing_health > 0)
+ target.adjustBruteLoss(missing_health) //and do that much damage
+
+//watcher
+/obj/item/crusher_trophy/watcher_wing
+ name = "watcher wing"
+ desc = "A wing ripped from a watcher. Suitable as a trophy for a kinetic crusher."
+ icon_state = "watcher_wing"
+ denied_type = /obj/item/crusher_trophy/watcher_wing
+ bonus_value = 5
+
+/obj/item/crusher_trophy/watcher_wing/effect_desc()
+ return "mark detonation to prevent certain creatures from using certain attacks for [bonus_value*0.1] second\s"
+
+/obj/item/crusher_trophy/watcher_wing/on_mark_detonation(mob/living/target, mob/living/user)
+ if(ishostile(target))
+ var/mob/living/simple_animal/hostile/H = target
+ if(H.ranged) //briefly delay ranged attacks
+ if(H.ranged_cooldown >= world.time)
+ H.ranged_cooldown += bonus_value
+ else
+ H.ranged_cooldown = bonus_value + world.time
+
+//magmawing watcher
+/obj/item/crusher_trophy/blaster_tubes/magma_wing
+ name = "magmawing watcher wing"
+ desc = "A still-searing wing from a magmawing watcher. Suitable as a trophy for a kinetic crusher."
+ icon_state = "magma_wing"
+ gender = NEUTER
+ bonus_value = 5
+
+/obj/item/crusher_trophy/blaster_tubes/magma_wing/effect_desc()
+ return "mark detonation to make the next destabilizer shot deal [bonus_value] damage"
+
+/obj/item/crusher_trophy/blaster_tubes/magma_wing/on_projectile_fire(obj/item/projectile/destabilizer/marker, mob/living/user)
+ if(deadly_shot)
+ marker.name = "heated [marker.name]"
+ marker.icon_state = "lava"
+ marker.damage = bonus_value
+ marker.nodamage = FALSE
+ deadly_shot = FALSE
+
+//icewing watcher
+/obj/item/crusher_trophy/watcher_wing/ice_wing
+ name = "icewing watcher wing"
+ desc = "A carefully preserved frozen wing from an icewing watcher. Suitable as a trophy for a kinetic crusher."
+ icon_state = "ice_wing"
+ bonus_value = 8
+
+//legion
+/obj/item/crusher_trophy/legion_skull
+ name = "legion skull"
+ desc = "A dead and lifeless legion skull. Suitable as a trophy for a kinetic crusher."
+ icon_state = "legion_skull"
+ denied_type = /obj/item/crusher_trophy/legion_skull
+ bonus_value = 3
+
+/obj/item/crusher_trophy/legion_skull/effect_desc()
+ return "a kinetic crusher to recharge [bonus_value*0.1] second\s faster"
+
+/obj/item/crusher_trophy/legion_skull/add_to(obj/item/twohanded/kinetic_crusher/H, mob/living/user)
+ . = ..()
+ if(.)
+ H.charge_time -= bonus_value
+
+/obj/item/crusher_trophy/legion_skull/remove_from(obj/item/twohanded/kinetic_crusher/H, mob/living/user)
+ . = ..()
+ if(.)
+ H.charge_time += bonus_value
+
+//blood-drunk hunter
+/obj/item/crusher_trophy/miner_eye
+ name = "eye of a blood-drunk hunter"
+ desc = "Its pupil is collapsed and turned to mush. Suitable as a trophy for a kinetic crusher."
+ icon_state = "hunter_eye"
+ denied_type = /obj/item/crusher_trophy/miner_eye
+
+/obj/item/crusher_trophy/miner_eye/effect_desc()
+ return "mark detonation to grant stun immunity and 90% damage reduction for 1 second"
+
+/obj/item/crusher_trophy/miner_eye/on_mark_detonation(mob/living/target, mob/living/user)
+ user.apply_status_effect(STATUS_EFFECT_BLOODDRUNK)
+
+//ash drake
+/obj/item/crusher_trophy/tail_spike
+ desc = "A spike taken from an ash drake's tail. Suitable as a trophy for a kinetic crusher."
+ denied_type = /obj/item/crusher_trophy/tail_spike
+ bonus_value = 5
+
+/obj/item/crusher_trophy/tail_spike/effect_desc()
+ return "mark detonation to do [bonus_value] damage to nearby creatures and push them back"
+
+/obj/item/crusher_trophy/tail_spike/on_mark_detonation(mob/living/target, mob/living/user)
+ for(var/mob/living/L in oview(2, user))
+ if(L.stat == DEAD)
+ continue
+ playsound(L, 'sound/magic/fireball.ogg', 20, 1)
+ new /obj/effect/temp_visual/fire(L.loc)
+ addtimer(CALLBACK(src, .proc/pushback, L, user), 1) //no free backstabs, we push AFTER module stuff is done
+ L.adjustFireLoss(bonus_value)
+
+/obj/item/crusher_trophy/tail_spike/proc/pushback(mob/living/target, mob/living/user)
+ if(!QDELETED(target) && !QDELETED(user) && (!target.anchored || ismegafauna(target))) //megafauna will always be pushed
+ step(target, get_dir(user, target))
+
+//bubblegum
+/obj/item/crusher_trophy/demon_claws
+ name = "demon claws"
+ desc = "A set of blood-drenched claws from a massive demon's hand. Suitable as a trophy for a kinetic crusher."
+ icon_state = "demon_claws"
+ gender = PLURAL
+ denied_type = /obj/item/crusher_trophy/demon_claws
+ bonus_value = 10
+ var/static/list/damage_heal_order = list(BRUTE, BURN, OXY)
+
+/obj/item/crusher_trophy/demon_claws/effect_desc()
+ return "melee hits to do [bonus_value * 0.2] more damage and heal you for [bonus_value * 0.1], with 5X effect on mark detonation"
+
+/obj/item/crusher_trophy/demon_claws/add_to(obj/item/twohanded/kinetic_crusher/H, mob/living/user)
+ . = ..()
+ if(.)
+ H.force += bonus_value * 0.2
+ H.force_unwielded += bonus_value * 0.2
+ H.force_wielded += bonus_value * 0.2
+ H.detonation_damage += bonus_value * 0.8
+
+/obj/item/crusher_trophy/demon_claws/remove_from(obj/item/twohanded/kinetic_crusher/H, mob/living/user)
+ . = ..()
+ if(.)
+ H.force -= bonus_value * 0.2
+ H.force_unwielded -= bonus_value * 0.2
+ H.force_wielded -= bonus_value * 0.2
+ H.detonation_damage -= bonus_value * 0.8
+
+/obj/item/crusher_trophy/demon_claws/on_melee_hit(mob/living/target, mob/living/user)
+ user.heal_ordered_damage(bonus_value * 0.1, damage_heal_order)
+
+/obj/item/crusher_trophy/demon_claws/on_mark_detonation(mob/living/target, mob/living/user)
+ user.heal_ordered_damage(bonus_value * 0.4, damage_heal_order)
+
+//colossus
+/obj/item/crusher_trophy/blaster_tubes
+ name = "blaster tubes"
+ desc = "The blaster tubes from a colossus's arm. Suitable as a trophy for a kinetic crusher."
+ icon_state = "blaster_tubes"
+ gender = PLURAL
+ denied_type = /obj/item/crusher_trophy/blaster_tubes
+ bonus_value = 15
+ var/deadly_shot = FALSE
+
+/obj/item/crusher_trophy/blaster_tubes/effect_desc()
+ return "mark detonation to make the next destabilizer shot deal [bonus_value] damage but move slower"
+
+/obj/item/crusher_trophy/blaster_tubes/on_projectile_fire(obj/item/projectile/destabilizer/marker, mob/living/user)
+ if(deadly_shot)
+ marker.name = "deadly [marker.name]"
+ marker.icon_state = "chronobolt"
+ marker.damage = bonus_value
+ marker.nodamage = FALSE
+ marker.speed = 2
+ deadly_shot = FALSE
+
+/obj/item/crusher_trophy/blaster_tubes/on_mark_detonation(mob/living/target, mob/living/user)
+ deadly_shot = TRUE
+ addtimer(CALLBACK(src, .proc/reset_deadly_shot), 300, TIMER_UNIQUE|TIMER_OVERRIDE)
+
+/obj/item/crusher_trophy/blaster_tubes/proc/reset_deadly_shot()
+ deadly_shot = FALSE
+
+//hierophant
+/obj/item/crusher_trophy/vortex_talisman
+ name = "vortex talisman"
+ desc = "A glowing trinket that was originally the Hierophant's beacon. Suitable as a trophy for a kinetic crusher."
+ icon_state = "vortex_talisman"
+ denied_type = /obj/item/crusher_trophy/vortex_talisman
+
+/obj/item/crusher_trophy/vortex_talisman/effect_desc()
+ return "mark detonation to create a barrier you can pass"
+
+/obj/item/crusher_trophy/vortex_talisman/on_mark_detonation(mob/living/target, mob/living/user)
+ var/turf/T = get_turf(user)
+ new /obj/effect/temp_visual/hierophant/wall/crusher(T, user) //a wall only you can pass!
+ var/turf/otherT = get_step(T, turn(user.dir, 90))
+ if(otherT)
+ new /obj/effect/temp_visual/hierophant/wall/crusher(otherT, user)
+ otherT = get_step(T, turn(user.dir, -90))
+ if(otherT)
+ new /obj/effect/temp_visual/hierophant/wall/crusher(otherT, user)
+
+/obj/effect/temp_visual/hierophant/wall/crusher
+ duration = 75
\ No newline at end of file
diff --git a/code/modules/mining/equipment_locker.dm b/code/modules/mining/equipment_locker.dm
index 1001a2aa514..37569b7b58e 100644
--- a/code/modules/mining/equipment_locker.dm
+++ b/code/modules/mining/equipment_locker.dm
@@ -400,54 +400,57 @@
density = 1
anchored = 1.0
var/obj/item/card/id/inserted_id
- var/list/prize_list = list(
- new /datum/data/mining_equipment("Stimpack", /obj/item/reagent_containers/hypospray/autoinjector/stimpack, 50),
- new /datum/data/mining_equipment("Teporone MediPen", /obj/item/reagent_containers/hypospray/autoinjector/teporone, 50),
- new /datum/data/mining_equipment("MediPen Bundle", /obj/item/storage/box/autoinjector/utility, 200),
- new /datum/data/mining_equipment("Whiskey", /obj/item/reagent_containers/food/drinks/bottle/whiskey, 100),
- new /datum/data/mining_equipment("Cigar", /obj/item/clothing/mask/cigarette/cigar/havana, 150),
- new /datum/data/mining_equipment("Soap", /obj/item/soap/nanotrasen, 200),
- new /datum/data/mining_equipment("Laser Pointer", /obj/item/laser_pointer, 300),
- new /datum/data/mining_equipment("Alien Toy", /obj/item/clothing/mask/facehugger/toy, 300),
- new /datum/data/mining_equipment("Advanced Scanner", /obj/item/t_scanner/adv_mining_scanner, 400),
- new /datum/data/mining_equipment("Hivelord Stabilizer", /obj/item/hivelordstabilizer, 400),
- new /datum/data/mining_equipment("Mining Drone", /obj/item/mining_drone_cube, 500),
- new /datum/data/mining_equipment("Drone Melee Upgrade", /obj/item/mine_bot_upgrade, 400),
- new /datum/data/mining_equipment("Drone Health Upgrade", /obj/item/mine_bot_upgrade/health, 400),
- new /datum/data/mining_equipment("Drone Ranged Upgrade", /obj/item/mine_bot_upgrade/cooldown, 600),
- new /datum/data/mining_equipment("Kinetic Crusher", /obj/item/twohanded/required/kinetic_crusher, 750),
- new /datum/data/mining_equipment("Shelter Capsule", /obj/item/survivalcapsule, 400),
- new /datum/data/mining_equipment("Luxury Shelter Capsule", /obj/item/survivalcapsule/luxury, 3000),
- new /datum/data/mining_equipment("Explorer\'s Webbing", /obj/item/storage/belt/mining, 500),
- new /datum/data/mining_equipment("Drone AI Upgrade", /obj/item/slimepotion/sentience/mining, 1000),
- new /datum/data/mining_equipment("GAR mesons", /obj/item/clothing/glasses/meson/gar, 500),
- new /datum/data/mining_equipment("Brute First-Aid Kit", /obj/item/storage/firstaid/brute, 600),
- new /datum/data/mining_equipment("Jaunter", /obj/item/wormhole_jaunter, 600),
- new /datum/data/mining_equipment("Kinetic Accelerator", /obj/item/gun/energy/kinetic_accelerator, 750),
- new /datum/data/mining_equipment("Resonator", /obj/item/resonator, 800),
- new /datum/data/mining_equipment("Lazarus Injector", /obj/item/lazarus_injector, 1000),
- new /datum/data/mining_equipment("Silver Pickaxe", /obj/item/pickaxe/silver, 1000),
- new /datum/data/mining_equipment("Lazarus Capsule", /obj/item/mobcapsule, 800),
- new /datum/data/mining_equipment("Lazarus Capsule belt", /obj/item/storage/belt/lazarus, 200),
- new /datum/data/mining_equipment("Jetpack", /obj/item/tank/jetpack/carbondioxide/mining, 2000),
- new /datum/data/mining_equipment("Space Cash", /obj/item/stack/spacecash/c1000, 2000),
- new /datum/data/mining_equipment("Diamond Pickaxe", /obj/item/pickaxe/diamond, 2000),
- new /datum/data/mining_equipment("Super Resonator", /obj/item/resonator/upgraded, 2500),
- new /datum/data/mining_equipment("Jump Boots", /obj/item/clothing/shoes/bhop, 2500),
- new /datum/data/mining_equipment("Mining Hardsuit", /obj/item/storage/box/mininghardsuit, 2000),
- new /datum/data/mining_equipment("1 Marker Beacon", /obj/item/stack/marker_beacon, 10),
- new /datum/data/mining_equipment("10 Marker Beacons", /obj/item/stack/marker_beacon/ten, 100),
- new /datum/data/mining_equipment("30 Marker Beacons", /obj/item/stack/marker_beacon/thirty, 300),
- 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/card/mining_point_card, 500),
- new /datum/data/mining_equipment("Mining Conscription Kit", /obj/item/storage/backpack/duffel/mining_conscript, 1000),
+ var/list/prize_list = list( //if you add something to this, please, for the love of god, sort it by price/type. use tabs and not spaces.
+ new /datum/data/mining_equipment("1 Marker Beacon", /obj/item/stack/marker_beacon, 10),
+ new /datum/data/mining_equipment("10 Marker Beacons", /obj/item/stack/marker_beacon/ten, 100),
+ new /datum/data/mining_equipment("30 Marker Beacons", /obj/item/stack/marker_beacon/thirty, 300),
+ new /datum/data/mining_equipment("Whiskey", /obj/item/reagent_containers/food/drinks/bottle/whiskey, 100),
+ new /datum/data/mining_equipment("Absinthe", /obj/item/reagent_containers/food/drinks/bottle/absinthe/premium, 100),
+ new /datum/data/mining_equipment("Cigar", /obj/item/clothing/mask/cigarette/cigar/havana, 150),
+ new /datum/data/mining_equipment("Soap", /obj/item/soap/nanotrasen, 200),
+ new /datum/data/mining_equipment("Laser Pointer", /obj/item/laser_pointer, 300),
+ new /datum/data/mining_equipment("Alien Toy", /obj/item/clothing/mask/facehugger/toy, 300),
+ new /datum/data/mining_equipment("Stabilizing Serum", /obj/item/hivelordstabilizer, 400),
+ new /datum/data/mining_equipment("Space Cash", /obj/item/stack/spacecash/c1000, 2000),
+ new /datum/data/mining_equipment("Point Transfer Card", /obj/item/card/mining_point_card, 500),
+ new /datum/data/mining_equipment("Fulton Beacon", /obj/item/fulton_core, 400),
+ new /datum/data/mining_equipment("Shelter Capsule", /obj/item/survivalcapsule, 400),
+ new /datum/data/mining_equipment("GAR Meson Scanners", /obj/item/clothing/glasses/meson/gar, 500),
+ new /datum/data/mining_equipment("Explorer's Webbing", /obj/item/storage/belt/mining, 500),
+ new /datum/data/mining_equipment("Survival Medipen", /obj/item/reagent_containers/hypospray/autoinjector/survival, 500),
+ new /datum/data/mining_equipment("Brute First-Aid Kit", /obj/item/storage/firstaid/brute, 600),
+ new /datum/data/mining_equipment("Tracking Implant Kit", /obj/item/storage/box/minertracker, 600),
+ new /datum/data/mining_equipment("Jaunter", /obj/item/wormhole_jaunter, 750),
+ new /datum/data/mining_equipment("Kinetic Crusher", /obj/item/twohanded/kinetic_crusher, 750),
+ new /datum/data/mining_equipment("Kinetic Accelerator", /obj/item/gun/energy/kinetic_accelerator, 750),
+ new /datum/data/mining_equipment("Advanced Scanner", /obj/item/t_scanner/adv_mining_scanner, 800),
+ new /datum/data/mining_equipment("Resonator", /obj/item/resonator, 800),
+ new /datum/data/mining_equipment("Fulton Pack", /obj/item/extraction_pack, 1000),
+ new /datum/data/mining_equipment("Lazarus Injector", /obj/item/lazarus_injector, 1000),
+ new /datum/data/mining_equipment("Silver Pickaxe", /obj/item/pickaxe/silver, 1000),
+ new /datum/data/mining_equipment("Mining Conscription Kit", /obj/item/storage/backpack/duffel/mining_conscript, 1500),
+ new /datum/data/mining_equipment("Jetpack", /obj/item/tank/jetpack/carbondioxide/mining, 2000),
+ new /datum/data/mining_equipment("Mining Hardsuit", /obj/item/clothing/suit/space/hardsuit/mining, 2000),
+ new /datum/data/mining_equipment("Diamond Pickaxe", /obj/item/pickaxe/diamond, 2000),
+ new /datum/data/mining_equipment("Super Resonator", /obj/item/resonator/upgraded, 2500),
+ new /datum/data/mining_equipment("Jump Boots", /obj/item/clothing/shoes/bhop, 2500),
+ new /datum/data/mining_equipment("Luxury Shelter Capsule", /obj/item/survivalcapsule/luxury, 3000),
+ new /datum/data/mining_equipment("Nanotrasen Minebot", /obj/item/mining_drone_cube, 800),
+ new /datum/data/mining_equipment("Minebot Melee Upgrade", /obj/item/mine_bot_upgrade, 400),
+ new /datum/data/mining_equipment("Minebot Armor Upgrade", /obj/item/mine_bot_upgrade/health, 400),
+ new /datum/data/mining_equipment("Minebot Cooldown Upgrade", /obj/item/borg/upgrade/modkit/cooldown/minebot, 600),
+ new /datum/data/mining_equipment("Minebot AI Upgrade", /obj/item/slimepotion/sentience/mining, 1000),
+ new /datum/data/mining_equipment("KA Minebot Passthrough", /obj/item/borg/upgrade/modkit/minebot_passthrough, 100),
+ new /datum/data/mining_equipment("Lazarus Capsule", /obj/item/mobcapsule, 800),
+ new /datum/data/mining_equipment("Lazarus Capsule belt", /obj/item/storage/belt/lazarus, 200),
+ 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)
)
/obj/machinery/mineral/equipment_vendor/golem
@@ -599,16 +602,14 @@
..()
/obj/machinery/mineral/equipment_vendor/proc/RedeemVoucher(obj/item/mining_voucher/voucher, mob/redeemer)
- var/items = list("Kinetic Accelerator", "Survival Capsule and Explorer's Webbing", "Resonator Kit", "Minebot Kit", "Crusher Kit", "Mining Conscription Kit", "Advanced Scanner")
+ var/items = list("Survival Capsule and Explorer's Webbing", "Resonator Kit", "Minebot Kit", "Extraction and Rescue Kit", "Crusher Kit", "Mining Conscription Kit")
var/selection = input(redeemer, "Pick your equipment", "Mining Voucher Redemption") as null|anything in items
if(!selection || !Adjacent(redeemer) || QDELETED(voucher) || voucher.loc != redeemer)
return
- var/drop_location = loc
+ var/drop_location = drop_location()
switch(selection)
- if("Kinetic Accelerator")
- new /obj/item/gun/energy/kinetic_accelerator(drop_location)
if("Survival Capsule and Explorer's Webbing")
new /obj/item/storage/belt/mining(drop_location)
if("Resonator Kit")
@@ -618,13 +619,15 @@
new /obj/item/mining_drone_cube(drop_location)
new /obj/item/weldingtool/hugetank(drop_location)
new /obj/item/clothing/head/welding(drop_location)
+ if("Extraction and Rescue Kit")
+ new /obj/item/extraction_pack(drop_location)
+ new /obj/item/fulton_core(drop_location)
+ new /obj/item/stack/marker_beacon/thirty(drop_location)
if("Crusher Kit")
new /obj/item/extinguisher/mini(drop_location)
- new /obj/item/twohanded/required/kinetic_crusher(drop_location)
+ new /obj/item/twohanded/kinetic_crusher(drop_location)
if("Mining Conscription Kit")
new /obj/item/storage/backpack/duffel/mining_conscript(drop_location)
- if("Advanced Scanner")
- new /obj/item/t_scanner/adv_mining_scanner(drop_location)
qdel(voucher)
@@ -688,14 +691,16 @@
/obj/item/storage/backpack/duffel/mining_conscript/New()
..()
- new /obj/item/pickaxe(src)
new /obj/item/clothing/glasses/meson(src)
new /obj/item/t_scanner/adv_mining_scanner/lesser(src)
new /obj/item/storage/bag/ore(src)
- new /obj/item/clothing/under/rank/miner/lavaland(src)
+ new /obj/item/clothing/suit/hooded/explorer(src)
new /obj/item/encryptionkey/headset_cargo(src)
- new /obj/item/clothing/mask/gas(src)
+ new /obj/item/clothing/mask/gas/explorer(src)
new /obj/item/card/id/mining_access_card(src)
+ new /obj/item/gun/energy/kinetic_accelerator(src)
+ new /obj/item/kitchen/knife/combat/survival(src)
+ new /obj/item/flashlight/seclite(src)
/**********************Jaunter**********************/
@@ -786,30 +791,20 @@
origin_tech = "magnets=3;engineering=3"
desc = "A handheld device that creates small fields of energy that resonate until they detonate, crushing rock. It can also be activated without a target to create a field at the user's location, to act as a delayed time trap. It's more effective in a vaccuum."
w_class = WEIGHT_CLASS_NORMAL
- force = 8
+ force = 15
throwforce = 10
- var/cooldown = 0
- var/fieldsactive = 0
- var/burst_time = 50
- var/fieldlimit = 3
+ var/burst_time = 30
+ var/fieldlimit = 4
+ var/list/fields = list()
+ var/quick_burst_mod = 0.8
/obj/item/resonator/upgraded
name = "upgraded resonator"
desc = "An upgraded version of the resonator that can produce more fields at once."
icon_state = "resonator_u"
origin_tech = "materials=4;powerstorage=3;engineering=3;magnets=3"
- fieldlimit = 5
-
-/obj/item/resonator/proc/CreateResonance(var/target, var/creator)
- var/turf/T = get_turf(target)
- if(locate(/obj/effect/resonance) in T)
- return
- if(fieldsactive < fieldlimit)
- playsound(src,'sound/weapons/resonator_fire.ogg',50,1)
- new /obj/effect/resonance(T, creator, burst_time)
- fieldsactive++
- spawn(burst_time)
- fieldsactive--
+ fieldlimit = 6
+ quick_burst_mod = 1
/obj/item/resonator/attack_self(mob/user)
if(burst_time == 50)
@@ -819,48 +814,88 @@
burst_time = 50
to_chat(user, "You set the resonator's fields to detonate after 5 seconds.")
-/obj/item/resonator/afterattack(atom/target, mob/user, proximity_flag)
- if(proximity_flag)
- if(!check_allowed_items(target, 1)) return
- CreateResonance(target, user)
+/obj/item/resonator/proc/CreateResonance(target, mob/user)
+ var/turf/T = get_turf(target)
+ var/obj/effect/temp_visual/resonance/R = locate(/obj/effect/temp_visual/resonance) in T
+ if(R)
+ R.damage_multiplier = quick_burst_mod
+ R.burst()
+ return
+ if(LAZYLEN(fields) < fieldlimit)
+ new /obj/effect/temp_visual/resonance(T, user, src, burst_time)
+ user.changeNext_move(CLICK_CD_MELEE)
-/obj/effect/resonance
+/obj/item/resonator/pre_attackby(atom/target, mob/user, params)
+ if(check_allowed_items(target, 1))
+ CreateResonance(target, user)
+ return TRUE
+
+/obj/effect/temp_visual/resonance
name = "resonance field"
- desc = "A resonating field that significantly damages anything inside of it when the field eventually ruptures."
+ desc = "A resonating field that significantly damages anything inside of it when the field eventually ruptures. More damaging in low pressure environments."
icon = 'icons/effects/effects.dmi'
icon_state = "shield1"
- layer = 4.1
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ duration = 50
var/resonance_damage = 20
+ var/damage_multiplier = 1
+ var/creator
+ var/obj/item/resonator/res
-/obj/effect/resonance/New(loc, var/creator = null, var/timetoburst)
- var/turf/proj_turf = get_turf(src)
- if(!istype(proj_turf))
- return
- if(istype(proj_turf, /turf/simulated/mineral))
- var/turf/simulated/mineral/M = proj_turf
- spawn(timetoburst)
- playsound(src,'sound/weapons/resonator_blast.ogg',50,1)
- M.gets_drilled(creator)
- qdel(src)
+/obj/effect/temp_visual/resonance/New(loc, set_creator, set_resonator, set_duration)
+ duration = set_duration
+ . = ..()
+ creator = set_creator
+ res = set_resonator
+ if(res)
+ res.fields += src
+ playsound(src,'sound/weapons/resonator_fire.ogg',50,1)
+ transform = matrix() * 0.75
+ animate(src, transform = matrix() * 1.5, time = duration)
+ deltimer(timerid)
+ timerid = addtimer(CALLBACK(src, .proc/burst), duration, TIMER_STOPPABLE)
+
+/obj/effect/temp_visual/resonance/Destroy()
+ if(res)
+ res.fields -= src
+ res = null
+ creator = null
+ return ..()
+
+/obj/effect/temp_visual/resonance/proc/check_pressure(turf/proj_turf)
+ if(!proj_turf)
+ proj_turf = get_turf(src)
+ resonance_damage = initial(resonance_damage)
+ if(lavaland_equipment_pressure_check(proj_turf))
+ name = "strong [initial(name)]"
+ resonance_damage *= 3
else
- var/datum/gas_mixture/environment = proj_turf.return_air()
- var/pressure = environment.return_pressure()
- if(pressure < 50)
- name = "strong resonance field"
- resonance_damage = 50
- spawn(timetoburst)
- playsound(src,'sound/weapons/resonator_blast.ogg',50,1)
- if(creator)
- for(var/mob/living/L in src.loc)
- add_attack_logs(creator, L, "Resonance field'ed")
- to_chat(L, "The [src.name] ruptured with you in it!")
- L.adjustBruteLoss(resonance_damage)
- else
- for(var/mob/living/L in src.loc)
- to_chat(L, "The [src.name] ruptured with you in it!")
- L.adjustBruteLoss(resonance_damage)
- qdel(src)
+ name = initial(name)
+ resonance_damage *= damage_multiplier
+
+/obj/effect/temp_visual/resonance/proc/burst()
+ var/turf/T = get_turf(src)
+ new /obj/effect/temp_visual/resonance_crush(T)
+ if(ismineralturf(T))
+ var/turf/simulated/mineral/M = T
+ M.gets_drilled(creator)
+ check_pressure(T)
+ playsound(T,'sound/weapons/resonator_blast.ogg',50,1)
+ for(var/mob/living/L in T)
+ if(creator)
+ add_attack_logs(creator, L, "Resonance field'ed")
+ to_chat(L, "[src] ruptured with you in it!")
+ L.apply_damage(resonance_damage, BRUTE)
+ qdel(src)
+
+/obj/effect/temp_visual/resonance_crush
+ icon_state = "shield1"
+ layer = ABOVE_ALL_MOB_LAYER
+ duration = 4
+
+/obj/effect/temp_visual/resonance_crush/New()
+ ..()
+ transform = matrix()*1.5
+ animate(src, transform = matrix() * 0.1, alpha = 50, time = 4)
/**********************Facehugger toy**********************/
@@ -1113,103 +1148,4 @@
return ..()
C.preserved = 1
to_chat(user, "You inject the hivelord core with the stabilizer. It will no longer go inert.")
- qdel(src)
-
-/*********************Mining Hammer****************/
-/obj/item/twohanded/required/kinetic_crusher
- icon = 'icons/obj/mining.dmi'
- icon_state = "mining_hammer1"
- item_state = "mining_hammer1"
- name = "proto-kinetic crusher"
- desc = "An early design of the proto-kinetic accelerator, it is little more than an combination of various mining tools cobbled together, forming a high-tech club.\
- While it is an effective mining tool, it did little to aid any but the most skilled and/or suicidal miners against local fauna. \
- \nMark a mob with the destabilizing force, then hit them in melee to activate it for extra damage. Extra damage if backstabbed in this fashion. \
- This weapon is only particularly effective against large creatures."
- force = 20 //As much as a bone spear, but this is significantly more annoying to carry around due to requiring the use of both hands at all times
- w_class = WEIGHT_CLASS_BULKY
- slot_flags = SLOT_BACK
- force_unwielded = 20 //It's never not wielded so these are the same
- force_wielded = 20
- throwforce = 5
- throw_speed = 4
- light_range = 4
- armour_penetration = 10
- materials = list(MAT_METAL=1150, MAT_GLASS=2075)
- hitsound = 'sound/weapons/bladeslice.ogg'
- attack_verb = list("smashes", "crushes", "cleaves", "chops", "pulps")
- sharp = 1
- var/charged = 1
- var/charge_time = 16
- var/atom/mark = null
- var/marked_image = null
-
-/obj/item/projectile/destabilizer
- name = "destabilizing force"
- icon_state = "pulse1"
- damage = 0 //We're just here to mark people. This is still a melee weapon.
- damage_type = BRUTE
- flag = "bomb"
- range = 6
- var/obj/item/twohanded/required/kinetic_crusher/hammer_synced = null
-
-/obj/item/projectile/destabilizer/on_hit(atom/target, blocked = 0, hit_zone)
- if(hammer_synced)
- if(hammer_synced.mark == target)
- return ..()
- if(isliving(target))
- if(hammer_synced.mark && hammer_synced.marked_image)
- hammer_synced.mark.underlays -= hammer_synced.marked_image
- hammer_synced.marked_image = null
- var/mob/living/L = target
- if(L.mob_size >= MOB_SIZE_LARGE)
- hammer_synced.mark = L
- var/image/I = image('icons/effects/effects.dmi', loc = L, icon_state = "shield2",pixel_y = (-L.pixel_y),pixel_x = (-L.pixel_x))
- L.underlays += I
- hammer_synced.marked_image = I
- var/target_turf = get_turf(target)
- if(istype(target_turf, /turf/simulated/mineral))
- var/turf/simulated/mineral/M = target_turf
- new /obj/effect/temp_visual/kinetic_blast(M)
- M.gets_drilled(firer)
- ..()
-
-/obj/item/twohanded/required/kinetic_crusher/afterattack(atom/target, mob/user, proximity_flag)
- if(!proximity_flag && charged)//Mark a target, or mine a tile.
- var/turf/proj_turf = get_turf(src)
- if(!istype(proj_turf, /turf))
- return
- var/datum/gas_mixture/environment = proj_turf.return_air()
- var/pressure = environment.return_pressure()
- if(pressure > 50)
- playsound(user, 'sound/weapons/empty.ogg', 100, 1)
- return
- var/obj/item/projectile/destabilizer/D = new /obj/item/projectile/destabilizer(user.loc)
- D.preparePixelProjectile(target,get_turf(target), user)
- D.hammer_synced = src
- playsound(user, 'sound/weapons/plasma_cutter.ogg', 100, 1)
- D.fire()
- charged = 0
- icon_state = "mining_hammer1_uncharged"
- spawn(charge_time)
- Recharge()
- return
- if(proximity_flag && target == mark && isliving(target))
- var/mob/living/L = target
- new /obj/effect/temp_visual/kinetic_blast(get_turf(L))
- mark = 0
- if(L.mob_size >= MOB_SIZE_LARGE)
- L.underlays -= marked_image
- QDEL_NULL(marked_image)
- var/backstab = check_target_facings(user, L)
- var/def_check = L.getarmor(type = "bomb")
- if(backstab == FACING_INIT_FACING_TARGET_TARGET_FACING_PERPENDICULAR || backstab == FACING_SAME_DIR)
- L.apply_damage(80, BRUTE, blocked = def_check)
- playsound(user, 'sound/weapons/kenetic_accel.ogg', 100, 1) //Seriously who spelled it wrong
- else
- L.apply_damage(50, BRUTE, blocked = def_check)
-
-/obj/item/twohanded/required/kinetic_crusher/proc/Recharge()
- if(!charged)
- charged = 1
- icon_state = "mining_hammer1"
- playsound(loc, 'sound/weapons/kenetic_reload.ogg', 60, 1)
+ qdel(src)
\ No newline at end of file
diff --git a/code/modules/mining/explorer_gear.dm b/code/modules/mining/explorer_gear.dm
index a9464efe959..566694d480d 100644
--- a/code/modules/mining/explorer_gear.dm
+++ b/code/modules/mining/explorer_gear.dm
@@ -41,4 +41,57 @@
"Drask" = 'icons/mob/species/drask/head.dmi',
"Grey" = 'icons/mob/species/grey/head.dmi',
"Skrell" = 'icons/mob/species/skrell/head.dmi'
- )
\ No newline at end of file
+ )
+
+/obj/item/clothing/suit/space/hostile_environment
+ name = "H.E.C.K. suit"
+ desc = "Hostile Environment Cross-Kinetic Suit: A suit designed to withstand the wide variety of hazards from Lavaland. It wasn't enough for its last owner."
+ icon_state = "hostile_env"
+ item_state = "hostile_env"
+ flags = THICKMATERIAL //not spaceproof
+ max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
+ burn_state = FIRE_PROOF | LAVA_PROOF
+ slowdown = 0
+ armor = list(melee = 70, bullet = 40, laser = 10, energy = 10, bomb = 50, bio = 100, rad = 100)
+ allowed = list(/obj/item/flashlight, /obj/item/tank, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator, /obj/item/pickaxe)
+
+/obj/item/clothing/suit/space/hostile_environment/New()
+ ..()
+ AddComponent(/datum/component/spraycan_paintable)
+ START_PROCESSING(SSobj, src)
+
+/obj/item/clothing/suit/space/hostile_environment/Destroy()
+ STOP_PROCESSING(SSobj, src)
+ return ..()
+
+/obj/item/clothing/suit/space/hostile_environment/process()
+ var/mob/living/carbon/C = loc
+ if(istype(C) && prob(2)) //cursed by bubblegum
+ if(prob(15))
+ new /obj/effect/hallucination/oh_yeah(get_turf(C), C)
+ to_chat(C, "[pick("I AM IMMORTAL.","I SHALL TAKE BACK WHAT'S MINE.","I SEE YOU.","YOU CANNOT ESCAPE ME FOREVER.","DEATH CANNOT HOLD ME.")]")
+ else
+ to_chat(C, "[pick("You hear faint whispers.","You smell ash.","You feel hot.","You hear a roar in the distance.")]")
+
+/obj/item/clothing/head/helmet/space/hostile_environment
+ name = "H.E.C.K. helmet"
+ desc = "Hostile Environiment Cross-Kinetic Helmet: A helmet designed to withstand the wide variety of hazards from Lavaland. It wasn't enough for its last owner."
+ icon_state = "hostile_env"
+ item_state = "hostile_env"
+ w_class = WEIGHT_CLASS_NORMAL
+ max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
+ flags = THICKMATERIAL // no space protection
+ armor = list(melee = 70, bullet = 40, laser = 10, energy = 10, bomb = 50, bio = 100, rad = 100)
+ burn_state = FIRE_PROOF | LAVA_PROOF
+
+/obj/item/clothing/head/helmet/space/hostile_environment/New()
+ ..()
+ AddComponent(/datum/component/spraycan_paintable)
+ update_icon()
+
+/obj/item/clothing/head/helmet/space/hostile_environment/update_icon()
+ ..()
+ cut_overlays()
+ var/mutable_appearance/glass_overlay = mutable_appearance(icon, "hostile_env_glass")
+ glass_overlay.appearance_flags = RESET_COLOR
+ add_overlay(glass_overlay)
\ No newline at end of file
diff --git a/code/modules/mining/fulton.dm b/code/modules/mining/fulton.dm
new file mode 100644
index 00000000000..2d09c6a8e7a
--- /dev/null
+++ b/code/modules/mining/fulton.dm
@@ -0,0 +1,195 @@
+GLOBAL_LIST_EMPTY(total_extraction_beacons)
+
+/obj/item/extraction_pack
+ name = "fulton extraction pack"
+ desc = "A balloon that can be used to extract equipment or personnel to a Fulton Recovery Beacon. Anything not bolted down can be moved. Link the pack to a beacon by using the pack in hand."
+ icon = 'icons/obj/fulton.dmi'
+ icon_state = "extraction_pack"
+ w_class = WEIGHT_CLASS_NORMAL
+ var/obj/structure/extraction_point/beacon
+ var/list/beacon_networks = list("station")
+ var/uses_left = 3
+ var/can_use_indoors
+ var/safe_for_living_creatures = TRUE
+ var/max_force_fulton = MOVE_FORCE_STRONG
+
+/obj/item/extraction_pack/examine(mob/user)
+ ..()
+ to_chat(user, "It has [uses_left] use\s remaining.")
+
+/obj/item/extraction_pack/attack_self(mob/user)
+ var/list/possible_beacons = list()
+ for(var/B in GLOB.total_extraction_beacons)
+ var/obj/structure/extraction_point/EP = B
+ if(EP.beacon_network in beacon_networks)
+ possible_beacons += EP
+
+ if(!possible_beacons.len)
+ to_chat(user, "There are no extraction beacons in existence!")
+ return
+
+ else
+ var/A
+
+ A = input("Select a beacon to connect to", "Balloon Extraction Pack", A) as null|anything in possible_beacons
+
+ if(!A)
+ return
+ beacon = A
+ to_chat(user, "You link the extraction pack to the beacon system.")
+
+/obj/item/extraction_pack/afterattack(atom/movable/A, mob/living/carbon/human/user, flag, params)
+ . = ..()
+ if(!beacon)
+ to_chat(user, "[src] is not linked to a beacon, and cannot be used!")
+ return
+ if(!can_use_indoors)
+ var/area/area = get_area(A)
+ if(!area.outdoors)
+ to_chat(user, "[src] can only be used on things that are outdoors!")
+ return
+ if(!flag)
+ return
+ if(!istype(A))
+ return
+ else
+ if(!safe_for_living_creatures && check_for_living_mobs(A))
+ to_chat(user, "[src] is not safe for use with living creatures, they wouldn't survive the trip back!")
+ return
+ if(!isturf(A.loc)) // no extracting stuff inside other stuff
+ return
+ if(A.anchored || (A.move_resist > max_force_fulton))
+ return
+ to_chat(user, "You start attaching the pack to [A]...")
+ if(do_after(user, 50, target = A))
+ to_chat(user, "You attach the pack to [A] and activate it.")
+ if(loc == user && istype(user.back, /obj/item/storage/backpack))
+ var/obj/item/storage/backpack/B = user.back
+ if(B.can_be_inserted(src, stop_messages = TRUE))
+ B.handle_item_insertion(src)
+ uses_left--
+ if(uses_left <= 0)
+ user.drop_item(src)
+ forceMove(A)
+ var/mutable_appearance/balloon
+ var/mutable_appearance/balloon2
+ var/mutable_appearance/balloon3
+ if(isliving(A))
+ var/mob/living/M = A
+ M.Weaken(16) // Keep them from moving during the duration of the extraction
+ M.buckled = 0 // Unbuckle them to prevent anchoring problems
+ else
+ A.anchored = TRUE
+ A.density = FALSE
+ var/obj/effect/extraction_holder/holder_obj = new(A.loc)
+ holder_obj.appearance = A.appearance
+ A.forceMove(holder_obj)
+ balloon2 = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_expand")
+ balloon2.pixel_y = 10
+ balloon2.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
+ holder_obj.add_overlay(balloon2)
+ sleep(4)
+ balloon = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_balloon")
+ balloon.pixel_y = 10
+ balloon.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
+ holder_obj.cut_overlay(balloon2)
+ holder_obj.add_overlay(balloon)
+ playsound(holder_obj.loc, 'sound/items/fultext_deploy.ogg', 50, 1, -3)
+ animate(holder_obj, pixel_z = 10, time = 20)
+ sleep(20)
+ animate(holder_obj, pixel_z = 15, time = 10)
+ sleep(10)
+ animate(holder_obj, pixel_z = 10, time = 10)
+ sleep(10)
+ animate(holder_obj, pixel_z = 15, time = 10)
+ sleep(10)
+ animate(holder_obj, pixel_z = 10, time = 10)
+ sleep(10)
+ playsound(holder_obj.loc, 'sound/items/fultext_launch.ogg', 50, 1, -3)
+ animate(holder_obj, pixel_z = 1000, time = 30)
+ if(ishuman(A))
+ var/mob/living/carbon/human/L = A
+ L.SetParalysis(0)
+ L.drowsyness = 0
+ L.SetSleeping(0)
+ sleep(30)
+ var/list/flooring_near_beacon = list()
+ for(var/turf/floor in orange(1, beacon))
+ if(floor.density)
+ continue
+ flooring_near_beacon += floor
+ holder_obj.forceMove(pick(flooring_near_beacon))
+ animate(holder_obj, pixel_z = 10, time = 50)
+ sleep(50)
+ animate(holder_obj, pixel_z = 15, time = 10)
+ sleep(10)
+ animate(holder_obj, pixel_z = 10, time = 10)
+ sleep(10)
+ balloon3 = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_retract")
+ balloon3.pixel_y = 10
+ balloon3.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
+ holder_obj.cut_overlay(balloon)
+ holder_obj.add_overlay(balloon3)
+ sleep(4)
+ holder_obj.cut_overlay(balloon3)
+ A.anchored = FALSE // An item has to be unanchored to be extracted in the first place.
+ A.density = initial(A.density)
+ animate(holder_obj, pixel_z = 0, time = 5)
+ sleep(5)
+ A.forceMove(holder_obj.loc)
+ qdel(holder_obj)
+ if(uses_left <= 0)
+ qdel(src)
+
+
+/obj/item/fulton_core
+ name = "extraction beacon signaller"
+ desc = "Emits a signal which fulton recovery devices can lock onto. Activate in hand to create a beacon."
+ icon = 'icons/obj/stock_parts.dmi'
+ icon_state = "subspace_amplifier"
+
+/obj/item/fulton_core/attack_self(mob/user)
+ if(do_after(user, 15, target = user) && !QDELETED(src))
+ new /obj/structure/extraction_point(get_turf(user))
+ qdel(src)
+
+/obj/structure/extraction_point
+ name = "fulton recovery beacon"
+ desc = "A beacon for the fulton recovery system. Activate a pack in your hand to link it to a beacon."
+ icon = 'icons/obj/fulton.dmi'
+ icon_state = "extraction_point"
+ anchored = TRUE
+ density = FALSE
+ var/beacon_network = "station"
+
+/obj/structure/extraction_point/New()
+ ..()
+ name += " ([rand(100,999)]) ([get_location_name(src)])"
+ GLOB.total_extraction_beacons += src
+
+/obj/structure/extraction_point/Destroy()
+ GLOB.total_extraction_beacons -= src
+ return ..()
+
+/obj/effect/extraction_holder
+ name = "extraction holder"
+ desc = "you shouldnt see this"
+ var/atom/movable/stored_obj
+
+/obj/item/extraction_pack/proc/check_for_living_mobs(atom/A)
+ if(isliving(A))
+ var/mob/living/L = A
+ if(L.stat != DEAD)
+ return TRUE
+ for(var/thing in A.GetAllContents())
+ if(isliving(A))
+ var/mob/living/L = A
+ if(L.stat != DEAD)
+ return TRUE
+ return FALSE
+
+/obj/effect/extraction_holder/singularity_pull()
+ return
+
+/obj/effect/extraction_holder/singularity_pull()
+ return
\ No newline at end of file
diff --git a/code/modules/mining/lavaland/loot/ashdragon_loot.dm b/code/modules/mining/lavaland/loot/ashdragon_loot.dm
index 4f8f01498d0..6a30c565547 100644
--- a/code/modules/mining/lavaland/loot/ashdragon_loot.dm
+++ b/code/modules/mining/lavaland/loot/ashdragon_loot.dm
@@ -15,6 +15,15 @@
if(4)
new /obj/item/dragons_blood(src)
+
+/obj/structure/closet/crate/necropolis/dragon/crusher
+ name = "firey dragon chest"
+
+/obj/structure/closet/crate/necropolis/dragon/crusher/New()
+ ..()
+ new /obj/item/crusher_trophy/tail_spike(src)
+
+
// Spectral Blade
/obj/item/melee/ghost_sword
diff --git a/code/modules/mining/lavaland/loot/bubblegum_loot.dm b/code/modules/mining/lavaland/loot/bubblegum_loot.dm
index bb0031ea77d..6cc33e1ad92 100644
--- a/code/modules/mining/lavaland/loot/bubblegum_loot.dm
+++ b/code/modules/mining/lavaland/loot/bubblegum_loot.dm
@@ -3,6 +3,8 @@
/obj/structure/closet/crate/necropolis/bubblegum/New()
..()
+ new /obj/item/clothing/suit/space/hostile_environment(src)
+ new /obj/item/clothing/head/helmet/space/hostile_environment(src)
var/loot = rand(1,3)
switch(loot)
if(1)
@@ -12,6 +14,13 @@
if(3)
new /obj/item/gun/magic/staff/spellblade(src)
+/obj/structure/closet/crate/necropolis/bubblegum/crusher
+ name = "bloody bubblegum chest"
+
+/obj/structure/closet/crate/necropolis/bubblegum/crusher/New()
+ ..()
+ new /obj/item/crusher_trophy/demon_claws(src)
+
// Mayhem
/obj/item/mayhem
diff --git a/code/modules/mining/lavaland/loot/colossus_loot.dm b/code/modules/mining/lavaland/loot/colossus_loot.dm
index 2490f6f48db..9b6bd8c5893 100644
--- a/code/modules/mining/lavaland/loot/colossus_loot.dm
+++ b/code/modules/mining/lavaland/loot/colossus_loot.dm
@@ -1,3 +1,22 @@
+//Colossus
+/obj/structure/closet/crate/necropolis/colossus
+ name = "colossus chest"
+
+/obj/structure/closet/crate/necropolis/colossus/New()
+ ..()
+ var/list/choices = subtypesof(/obj/machinery/anomalous_crystal)
+ var/random_crystal = pick(choices)
+ new random_crystal(src)
+ new /obj/item/organ/internal/vocal_cords/colossus(src)
+
+/obj/structure/closet/crate/necropolis/colossus/crusher
+ name = "angelic colossus chest"
+
+/obj/structure/closet/crate/necropolis/colossus/crusher/New()
+ ..()
+ new /obj/item/crusher_trophy/blaster_tubes(src)
+
+
//Black Box
/obj/machinery/smartfridge/black_box
diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index 7eed5577aeb..ab9b7979d03 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -8,18 +8,18 @@
icon_closed = "necrocrate"
burn_state = LAVA_PROOF | FIRE_PROOF
unacidable = 1
-
+
/obj/structure/closet/crate/necropolis/tendril
desc = "It's watching you suspiciously."
/obj/structure/closet/crate/necropolis/tendril/New(add_loot = TRUE)
..()
-
+
if(!add_loot)
return
- var/loot = rand(1,24)
- switch(loot)
+ var/loot = rand(1,25)
+ switch(loot)
if(1)
new /obj/item/shared_storage/red(src)
if(2)
@@ -37,7 +37,10 @@
new /obj/item/clothing/suit/hooded/cultrobes(src)
new /obj/item/bedsheet/cult(src)
if(8)
- new /obj/item/organ/internal/brain/xeno(src)
+ if(prob(50))
+ new /obj/item/disk/design_disk/modkit_disc/resonator_blast(src)
+ else
+ new /obj/item/disk/design_disk/modkit_disc/rapid_repeater(src)
if(9)
new /obj/item/organ/internal/heart/cursed/wizard(src)
if(10)
@@ -54,7 +57,10 @@
if(15)
new /obj/item/guardiancreator(src)
if(16)
- new /obj/item/borg/upgrade/modkit/aoe/turfs/andmobs(src)
+ if(prob(50))
+ new /obj/item/disk/design_disk/modkit_disc/mob_and_turf_aoe(src)
+ else
+ new /obj/item/disk/design_disk/modkit_disc/bounty(src)
if(17)
new /obj/item/warp_cube/red(src)
if(18)
@@ -73,6 +79,9 @@
new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/inquisitor(src)
if(24)
new /obj/item/spellbook/oneuse/summonitem(src)
+ if(25)
+ new /obj/item/borg/upgrade/modkit/lifesteal(src)
+ new /obj/item/bedsheet/cult(src)
/obj/structure/closet/crate/necropolis/puzzle
name = "puzzling chest"
@@ -88,3 +97,63 @@
new /obj/item/wisp_lantern(src)
if(3)
new /obj/item/prisoncube(src)
+
+//KA modkit design discs
+/obj/item/disk/design_disk/modkit_disc
+ name = "KA Mod Disk"
+ desc = "A design disc containing the design for a unique kinetic accelerator modkit. It's compatible with a research console."
+ icon_state = "datadisk1"
+ var/modkit_design = /datum/design/unique_modkit
+
+/obj/item/disk/design_disk/modkit_disc/New()
+ . = ..()
+ blueprint = new modkit_design
+
+/obj/item/disk/design_disk/modkit_disc/mob_and_turf_aoe
+ name = "Offensive Mining Explosion Mod Disk"
+ modkit_design = /datum/design/unique_modkit/offensive_turf_aoe
+
+/obj/item/disk/design_disk/modkit_disc/rapid_repeater
+ name = "Rapid Repeater Mod Disk"
+ modkit_design = /datum/design/unique_modkit/rapid_repeater
+
+/obj/item/disk/design_disk/modkit_disc/resonator_blast
+ name = "Resonator Blast Mod Disk"
+ modkit_design = /datum/design/unique_modkit/resonator_blast
+
+/obj/item/disk/design_disk/modkit_disc/bounty
+ name = "Death Syphon Mod Disk"
+ modkit_design = /datum/design/unique_modkit/bounty
+
+/datum/design/unique_modkit
+ category = list("Mining", "Cyborg Upgrade Modules") //can't be normally obtained
+ build_type = PROTOLATHE | MECHFAB
+
+/datum/design/unique_modkit/offensive_turf_aoe
+ name = "Kinetic Accelerator Offensive Mining Explosion Mod"
+ desc = "A device which causes kinetic accelerators to fire AoE blasts that destroy rock and damage creatures."
+ id = "hyperaoemod"
+ materials = list(MAT_METAL = 7000, MAT_GLASS = 3000, MAT_SILVER= 3000, MAT_GOLD = 3000, MAT_DIAMOND = 4000)
+ build_path = /obj/item/borg/upgrade/modkit/aoe/turfs/andmobs
+
+/datum/design/unique_modkit/rapid_repeater
+ name = "Kinetic Accelerator Rapid Repeater Mod"
+ desc = "A device which greatly reduces a kinetic accelerator's cooldown on striking a living target or rock, but greatly increases its base cooldown."
+ id = "repeatermod"
+ materials = list(MAT_METAL = 5000, MAT_GLASS = 5000, MAT_URANIUM = 8000, MAT_BLUESPACE = 2000)
+ build_path = /obj/item/borg/upgrade/modkit/cooldown/repeater
+
+/datum/design/unique_modkit/resonator_blast
+ name = "Kinetic Accelerator Resonator Blast Mod"
+ desc = "A device which causes kinetic accelerators to fire shots that leave and detonate resonator blasts."
+ id = "resonatormod"
+ materials = list(MAT_METAL = 5000, MAT_GLASS = 5000, MAT_SILVER= 5000, MAT_URANIUM = 5000)
+ build_path = /obj/item/borg/upgrade/modkit/resonator_blasts
+
+/datum/design/unique_modkit/bounty
+ name = "Kinetic Accelerator Death Syphon Mod"
+ desc = "A device which causes kinetic accelerators to permanently gain damage against creature types killed with it."
+ id = "bountymod"
+ materials = list(MAT_METAL = 4000, MAT_SILVER = 4000, MAT_GOLD = 4000, MAT_BLUESPACE = 4000)
+ reagents_list = list("blood" = 40)
+ build_path = /obj/item/borg/upgrade/modkit/bounty
\ No newline at end of file
diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm
index f10b78dc526..87b919ea238 100644
--- a/code/modules/mining/mine_items.dm
+++ b/code/modules/mining/mine_items.dm
@@ -17,35 +17,20 @@
icon_closed = "mixed"
/obj/structure/closet/wardrobe/miner/New()
- ..()
- contents = list()
- new /obj/item/storage/backpack/duffel(src)
- new /obj/item/storage/backpack/industrial(src)
- new /obj/item/storage/backpack/satchel_eng(src)
- new /obj/item/clothing/under/rank/miner(src)
- new /obj/item/clothing/under/rank/miner(src)
- new /obj/item/clothing/under/rank/miner(src)
- new /obj/item/clothing/shoes/workboots(src)
- new /obj/item/clothing/shoes/workboots(src)
- new /obj/item/clothing/shoes/workboots(src)
- new /obj/item/clothing/gloves/fingerless(src)
- new /obj/item/clothing/gloves/fingerless(src)
- new /obj/item/clothing/gloves/fingerless(src)
-
-/obj/structure/closet/wardrobe/miner/lavaland
-
-/obj/structure/closet/wardrobe/miner/lavaland/New()
..()
contents = list()
new /obj/item/storage/backpack/duffel(src)
new /obj/item/storage/backpack/explorer(src)
- new /obj/item/storage/backpack/explorer(src)
+ new /obj/item/storage/backpack/satchel/explorer(src)
new /obj/item/clothing/under/rank/miner/lavaland(src)
new /obj/item/clothing/under/rank/miner/lavaland(src)
new /obj/item/clothing/under/rank/miner/lavaland(src)
new /obj/item/clothing/shoes/workboots/mining(src)
new /obj/item/clothing/shoes/workboots/mining(src)
new /obj/item/clothing/shoes/workboots/mining(src)
+ new /obj/item/clothing/gloves/color/black(src)
+ new /obj/item/clothing/gloves/color/black(src)
+ new /obj/item/clothing/gloves/color/black(src)
/obj/structure/closet/secure_closet/miner
name = "miner's equipment"
@@ -59,14 +44,18 @@
/obj/structure/closet/secure_closet/miner/New()
..()
+// new /obj/item/stack/sheet/mineral/sandbags(src, 5)
+// new /obj/item/storage/box/emptysandbags(src)
new /obj/item/shovel(src)
- new /obj/item/pickaxe(src)
+ new /obj/item/pickaxe/mini(src)
new /obj/item/radio/headset/headset_cargo/mining(src)
- new /obj/item/t_scanner/adv_mining_scanner/lesser(src)
+ new /obj/item/flashlight/seclite(src)
+ new /obj/item/storage/bag/plants(src)
new /obj/item/storage/bag/ore(src)
+ new /obj/item/t_scanner/adv_mining_scanner/lesser(src)
+ new /obj/item/gun/energy/kinetic_accelerator(src)
new /obj/item/clothing/glasses/meson(src)
new /obj/item/survivalcapsule(src)
- new /obj/item/stack/marker_beacon/ten
/**********************Shuttle Computer**************************/
@@ -122,6 +111,15 @@
throwforce = 1
attack_verb = list("ineffectively hit")
+/obj/item/pickaxe/mini
+ name = "compact pickaxe"
+ desc = "A smaller, compact version of the standard pickaxe."
+ icon_state = "minipick"
+ force = 10
+ throwforce = 7
+ w_class = WEIGHT_CLASS_NORMAL
+ materials = list(MAT_METAL = 1000)
+
/obj/item/pickaxe/silver
name = "silver-plated pickaxe"
icon_state = "spickaxe"
diff --git a/code/modules/mining/minebot.dm b/code/modules/mining/minebot.dm
index 5b20aad5047..2ff2a686439 100644
--- a/code/modules/mining/minebot.dm
+++ b/code/modules/mining/minebot.dm
@@ -5,6 +5,7 @@
/mob/living/simple_animal/hostile/mining_drone
name = "nanotrasen minebot"
desc = "The instructions printed on the side read: This is a small robot used to support miners, can be set to search and collect loose ore, or to help fend off wildlife. A mining scanner can instruct it to drop loose ore. Field repairs can be done with a welder."
+ gender = NEUTER
icon = 'icons/obj/aibots.dmi'
icon_state = "mining_drone"
icon_living = "mining_drone"
@@ -14,36 +15,31 @@
a_intent = INTENT_HARM
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)
minbodytemp = 0
- wander = 0
idle_vision_range = 5
move_to_delay = 10
- retreat_distance = 1
- minimum_distance = 2
health = 125
maxHealth = 125
melee_damage_lower = 15
melee_damage_upper = 15
- obj_damage = 0
+ obj_damage = 10
environment_smash = 0
- check_friendly_fire = 1
- stop_automated_movement_when_pulled = 1
+ check_friendly_fire = TRUE
+ stop_automated_movement_when_pulled = TRUE
attacktext = "drills"
attack_sound = 'sound/weapons/circsawhit.ogg'
- ranged = 1
sentience_type = SENTIENCE_MINEBOT
- ranged_message = "shoots"
- ranged_cooldown_time = 30
- projectiletype = /obj/item/projectile/kinetic
- projectilesound = 'sound/weapons/gunshots/gunshot4.ogg'
speak_emote = list("states")
wanted_objects = list(/obj/item/stack/ore/diamond, /obj/item/stack/ore/gold, /obj/item/stack/ore/silver,
/obj/item/stack/ore/plasma, /obj/item/stack/ore/uranium, /obj/item/stack/ore/iron,
/obj/item/stack/ore/bananium, /obj/item/stack/ore/tranquillite, /obj/item/stack/ore/glass,
/obj/item/stack/ore/titanium)
healable = 0
+ loot = list(/obj/effect/decal/cleanable/robot_debris)
+ del_on_death = TRUE
var/mode = MINEDRONE_COLLECT
var/light_on = 0
var/mesons_active
+ var/obj/item/gun/energy/kinetic_accelerator/minebot/stored_gun
var/datum/action/innate/minedrone/toggle_light/toggle_light_action
var/datum/action/innate/minedrone/toggle_meson_vision/toggle_meson_vision_action
@@ -52,6 +48,8 @@
/mob/living/simple_animal/hostile/mining_drone/New()
..()
+ stored_gun = new(src)
+ zone_sel = new /obj/screen/zone_sel(src) //Gross, but necessary TO-DO; remove this.
toggle_light_action = new()
toggle_light_action.Grant(src)
toggle_meson_vision_action = new()
@@ -72,8 +70,27 @@
..()
check_friendly_fire = 0
+/mob/living/simple_animal/hostile/mining_drone/examine(mob/user)
+ . = ..()
+ var/t_He = p_they(TRUE)
+ var/t_him = p_them()
+ var/t_s = p_s()
+ if(health < maxHealth)
+ if(health >= maxHealth * 0.5)
+ . += "[t_He] look[t_s] slightly dented."
+ else
+ . += "[t_He] look[t_s] severely dented!"
+ . += {"Using a mining scanner on [t_him] will instruct [t_him] to drop stored ore. [max(0, LAZYLEN(contents) - 1)] Stored Ore\n
+ Field repairs can be done with a welder."}
+ if(stored_gun && stored_gun.max_mod_capacity)
+ . += "[stored_gun.get_remaining_mod_capacity()]% mod capacity remaining."
+ for(var/A in stored_gun.get_modkits())
+ var/obj/item/borg/upgrade/modkit/M = A
+ . += "There is \a [M] installed, using [M.cost]% capacity."
+
+
/mob/living/simple_animal/hostile/mining_drone/attackby(obj/item/I, mob/user, params)
- if(istype(I, /obj/item/weldingtool) && user.a_intent == INTENT_HELP)
+ if(iswelder(I) && user.a_intent == INTENT_HELP)
var/obj/item/weldingtool/W = I
if(W.welding && !stat)
if(AIStatus != AI_OFF && AIStatus != AI_IDLE)
@@ -90,29 +107,18 @@
to_chat(user, "You instruct [src] to drop any collected ore.")
DropOre()
return
+ if(iscrowbar(I) || istype(I, /obj/item/borg/upgrade/modkit))
+ I.melee_attack_chain(user, stored_gun, params)
+ return
..()
/mob/living/simple_animal/hostile/mining_drone/death()
- // Only execute the below if we successfully died
- . = ..()
- if(!.)
- return FALSE
- visible_message("[src] is destroyed!")
- new /obj/effect/decal/cleanable/blood/gibs/robot(loc)
DropOre(0)
- qdel(src)
-
-/mob/living/simple_animal/hostile/mining_drone/Shoot(atom/targeted_atom)
- var/obj/item/projectile/kinetic/K = ..()
- var/turf/proj_turf = get_turf(K)
- if(!isturf(proj_turf))
- return
- var/datum/gas_mixture/environment = proj_turf.return_air()
- var/pressure = environment.return_pressure()
- if(pressure > 50)
- K.name = "weakened [K.name]"
-
- K.damage *= K.pressure_decrease
+ if(stored_gun)
+ for(var/obj/item/borg/upgrade/modkit/M in stored_gun.modkits)
+ M.uninstall(stored_gun)
+ deathmessage = "blows apart!"
+ . = ..()
/mob/living/simple_animal/hostile/mining_drone/attack_hand(mob/living/carbon/human/M)
if(M.a_intent == INTENT_HELP)
@@ -125,12 +131,24 @@
return
..()
+/mob/living/simple_animal/hostile/mining_drone/CanPass(atom/movable/O)
+ if(istype(O, /obj/item/projectile/kinetic))
+ var/obj/item/projectile/kinetic/K = O
+ if(K.kinetic_gun)
+ for(var/A in K.kinetic_gun.get_modkits())
+ var/obj/item/borg/upgrade/modkit/M = A
+ if(istype(M, /obj/item/borg/upgrade/modkit/minebot_passthrough))
+ return TRUE
+ if(istype(O, /obj/item/projectile/destabilizer))
+ return TRUE
+ return ..()
+
/mob/living/simple_animal/hostile/mining_drone/proc/SetCollectBehavior()
mode = MINEDRONE_COLLECT
idle_vision_range = 9
search_objects = 2
- wander = 1
- ranged = 0
+ wander = TRUE
+ ranged = FALSE
minimum_distance = 1
retreat_distance = null
icon_state = "mining_drone"
@@ -140,18 +158,25 @@
mode = MINEDRONE_ATTACK
idle_vision_range = 7
search_objects = 0
- wander = 0
- ranged = 1
- retreat_distance = 1
- minimum_distance = 2
+ wander = FALSE
+ ranged = TRUE
+ retreat_distance = 2
+ minimum_distance = 1
icon_state = "mining_drone_offense"
to_chat(src, "You are set to attack mode. You can now attack from range.")
/mob/living/simple_animal/hostile/mining_drone/AttackingTarget()
- if(istype(target, /obj/item/stack/ore) && mode == MINEDRONE_COLLECT)
+ if(istype(target, /obj/item/stack/ore) && mode == MINEDRONE_COLLECT)
CollectOre()
return
- ..()
+ if(isliving(target))
+ SetOffenseBehavior()
+ return ..()
+
+/mob/living/simple_animal/hostile/mining_drone/OpenFire(atom/A)
+ if(CheckFriendlyFire(A))
+ return
+ stored_gun.afterattack(A, src) //of the possible options to allow minebots to have KA mods, would you believe this is the best?
/mob/living/simple_animal/hostile/mining_drone/proc/CollectOre()
for(var/obj/item/stack/ore/O in range(1, src))
@@ -160,14 +185,12 @@
/mob/living/simple_animal/hostile/mining_drone/proc/DropOre(message = 1)
if(!contents.len)
if(message)
- to_chat(src, "You attempt to dump your stored ore, but you have none.")
+ to_chat(src, "You attempt to dump your stored ore, but you have none.")
return
if(message)
to_chat(src, "You dump your stored ore.")
for(var/obj/item/stack/ore/O in contents)
- contents -= O
- O.forceMove(loc)
- return
+ O.forceMove(drop_location())
/mob/living/simple_animal/hostile/mining_drone/adjustHealth(amount)
if(mode != MINEDRONE_ATTACK && amount > 0)
@@ -176,13 +199,10 @@
/mob/living/simple_animal/hostile/mining_drone/proc/toggle_mode()
switch(mode)
- if(MINEDRONE_COLLECT)
- SetOffenseBehavior()
if(MINEDRONE_ATTACK)
SetCollectBehavior()
- else //This should never happen.
- mode = MINEDRONE_COLLECT
- SetCollectBehavior()
+ else
+ SetOffenseBehavior()
//Actions for sentient minebots
@@ -264,41 +284,24 @@
if(M.melee_damage_upper != initial(M.melee_damage_upper))
to_chat(user, "[M] already has a combat upgrade installed!")
return
- M.melee_damage_lower = 22
- M.melee_damage_upper = 22
+ M.melee_damage_lower += 7
+ M.melee_damage_upper += 7
to_chat(user, "You upgrade [M]'s combat module.")
qdel(src)
//Health
/obj/item/mine_bot_upgrade/health
- name = "minebot chassis upgrade"
+ name = "minebot armor upgrade"
/obj/item/mine_bot_upgrade/health/upgrade_bot(mob/living/simple_animal/hostile/mining_drone/M, mob/user)
if(M.maxHealth != initial(M.maxHealth))
to_chat(user, "[M] already has a reinforced chassis!")
return
- var/previous = M.maxHealth
- M.maxHealth = 170
- M.health += M.maxHealth - previous
- to_chat(user, "You reinforce [M]'s chassis.")
+ M.maxHealth += 45
+ M.updatehealth()
qdel(src)
-
-//Cooldown
-
-/obj/item/mine_bot_upgrade/cooldown
- name = "minebot cooldown upgrade"
-
-/obj/item/mine_bot_upgrade/cooldown/upgrade_bot(mob/living/simple_animal/hostile/mining_drone/M, mob/user)
- if(M.ranged_cooldown_time != initial(M.ranged_cooldown_time))
- to_chat(user, "[M] already has a decreased weapon cooldown!")
- return
- M.ranged_cooldown_time = 10
- to_chat(user, "You upgrade [M]'s ranged weaponry, reducing its cooldown.")
- qdel(src)
-
-
//AI
/obj/item/slimepotion/sentience/mining
name = "minebot AI upgrade"
@@ -307,6 +310,20 @@
icon = 'icons/obj/doors/door_assembly.dmi'
sentience_type = SENTIENCE_MINEBOT
origin_tech = "programming=6"
+ var/base_health_add = 5 //sentient minebots are penalized for beign sentient; they have their stats reset to normal plus these values
+ var/base_damage_add = 1 //this thus disables other minebot upgrades
+ var/base_speed_add = 1
+ var/base_cooldown_add = 10 //base cooldown isn't reset to normal, it's just added on, since it's not practical to disable the cooldown module
+
+/obj/item/slimepotion/sentience/mining/after_success(mob/living/user, mob/living/simple_animal/SM)
+ if(istype(SM, /mob/living/simple_animal/hostile/mining_drone))
+ var/mob/living/simple_animal/hostile/mining_drone/M = SM
+ M.maxHealth = initial(M.maxHealth) + base_health_add
+ M.melee_damage_lower = initial(M.melee_damage_lower) + base_damage_add
+ M.melee_damage_upper = initial(M.melee_damage_upper) + base_damage_add
+ M.move_to_delay = initial(M.move_to_delay) + base_speed_add
+ if(M.stored_gun)
+ M.stored_gun.overheat_time += base_cooldown_add
#undef MINEDRONE_COLLECT
#undef MINEDRONE_ATTACK
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 731f53c7838..ab855b5dc80 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -236,6 +236,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
return 1
/mob/dead/observer/Move(NewLoc, direct)
+ update_parallax_contents()
following = null
setDir(direct)
ghostimage.setDir(dir)
@@ -417,6 +418,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
return
forceMove(pick(L))
+ update_parallax_contents()
following = null
/mob/dead/observer/verb/follow()
@@ -511,6 +513,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(T && isturf(T)) //Make sure the turf exists, then move the source to that destination.
A.forceMove(T)
+ M.update_parallax_contents()
+ following = null
return
to_chat(A, "This mob is not located in the game world.")
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index 73a76e00420..d573d2a8191 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -586,7 +586,8 @@ var/global/list/damage_icon_parts = list()
standing.overlays += image("icon" = A.sprite_sheets[dna.species.name], "icon_state" = "[A.icon_state]")
else
standing.overlays += image("icon" = 'icons/mob/ties.dmi', "icon_state" = "[tie_color]")
-
+ standing.alpha = w_uniform.alpha
+ standing.color = w_uniform.color
overlays_standing[UNIFORM_LAYER] = standing
else
// Automatically drop anything in store / id / belt if you're not wearing a uniform. //CHECK IF NECESARRY
@@ -769,6 +770,8 @@ var/global/list/damage_icon_parts = list()
var/image/bloodsies = image("icon" = dna.species.blood_mask, "icon_state" = "shoeblood")
bloodsies.color = shoes.blood_color
standing.overlays += bloodsies
+ standing.alpha = shoes.alpha
+ standing.color = shoes.color
overlays_standing[SHOES_LAYER] = standing
else
if(feet_blood_DNA)
@@ -819,6 +822,8 @@ var/global/list/damage_icon_parts = list()
var/image/bloodsies = image("icon" = dna.species.blood_mask, "icon_state" = "helmetblood")
bloodsies.color = head.blood_color
standing.overlays += bloodsies
+ standing.alpha = head.alpha
+ standing.color = head.color
overlays_standing[HEAD_LAYER] = standing
apply_overlay(HEAD_LAYER)
@@ -886,6 +891,8 @@ var/global/list/damage_icon_parts = list()
bloodsies.color = wear_suit.blood_color
standing.overlays += bloodsies
+ standing.alpha = wear_suit.alpha
+ standing.color = wear_suit.color
overlays_standing[SUIT_LAYER] = standing
apply_overlay(SUIT_LAYER)
@@ -951,6 +958,8 @@ var/global/list/damage_icon_parts = list()
var/image/bloodsies = image("icon" = dna.species.blood_mask, "icon_state" = "maskblood")
bloodsies.color = wear_mask.blood_color
standing.overlays += bloodsies
+ standing.alpha = wear_mask.alpha
+ standing.color = wear_mask.color
overlays_standing[FACEMASK_LAYER] = standing
apply_overlay(FACEMASK_LAYER)
@@ -973,6 +982,8 @@ var/global/list/damage_icon_parts = list()
standing = mutable_appearance('icons/mob/back.dmi', "[back.icon_state]", layer = -BACK_LAYER)
//create the image
+ standing.alpha = back.alpha
+ standing.color = back.color
overlays_standing[BACK_LAYER] = standing
apply_overlay(BACK_LAYER)
diff --git a/code/modules/mob/living/carbon/slime/slime.dm b/code/modules/mob/living/carbon/slime/slime.dm
index 914c810da27..38dadbbbfa7 100644
--- a/code/modules/mob/living/carbon/slime/slime.dm
+++ b/code/modules/mob/living/carbon/slime/slime.dm
@@ -146,6 +146,44 @@
stat(null,"Power Level: [powerlevel]")
+/mob/living/carbon/slime/updatehealth(reason)
+ . = ..()
+ update_health_hud()
+
+/mob/living/carbon/slime/proc/update_health_hud()
+ if(hud_used)
+ var/severity = 0
+ var/healthpercent = (health/maxHealth) * 100
+ if(stat != DEAD)
+ switch(healthpercent)
+ if(100 to INFINITY)
+ healths.icon_state = "slime_health0"
+ if(80 to 100)
+ healths.icon_state = "slime_health1"
+ severity = 1
+ if(60 to 80)
+ healths.icon_state = "slime_health2"
+ severity = 2
+ if(40 to 60)
+ healths.icon_state = "slime_health3"
+ severity = 3
+ if(20 to 40)
+ healths.icon_state = "slime_health4"
+ severity = 4
+ if(0 to 20)
+ healths.icon_state = "slime_health5"
+ severity = 5
+ if(-199 to 0)
+ healths.icon_state = "slime_health6"
+ severity = 6
+ else
+ healths.icon_state = "slime_health7"
+ severity = 6
+ if(severity > 0)
+ overlay_fullscreen("brute", /obj/screen/fullscreen/brute, severity)
+ else
+ clear_fullscreen("brute")
+
/mob/living/carbon/slime/adjustFireLoss(amount)
..(-abs(amount)) // Heals them
return
diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm
index afca9ad8798..4f2323e2025 100644
--- a/code/modules/mob/living/damage_procs.dm
+++ b/code/modules/mob/living/damage_procs.dm
@@ -44,6 +44,22 @@
if(BRAIN)
return adjustBrainLoss(damage)
+/mob/living/proc/get_damage_amount(damagetype = BRUTE)
+ switch(damagetype)
+ if(BRUTE)
+ return getBruteLoss()
+ if(BURN)
+ return getFireLoss()
+ if(TOX)
+ return getToxLoss()
+ if(OXY)
+ return getOxyLoss()
+ if(CLONE)
+ return getCloneLoss()
+ if(STAMINA)
+ return getStaminaLoss()
+
+
/mob/living/proc/apply_damages(var/brute = 0, var/burn = 0, var/tox = 0, var/oxy = 0, var/clone = 0, var/def_zone = null, var/blocked = 0, var/stamina = 0)
if(blocked >= 100) return 0
if(brute) apply_damage(brute, BRUTE, def_zone, blocked)
@@ -309,4 +325,16 @@
updatehealth("take overall damage")
/mob/living/proc/has_organic_damage()
- return (maxHealth - health)
\ No newline at end of file
+ return (maxHealth - health)
+
+//heal up to amount damage, in a given order
+/mob/living/proc/heal_ordered_damage(amount, list/damage_types)
+ . = amount //we'll return the amount of damage healed
+ for(var/i in damage_types)
+ var/amount_to_heal = min(amount, get_damage_amount(i)) //heal only up to the amount of damage we have
+ if(amount_to_heal)
+ apply_damage_type(-amount_to_heal, i)
+ amount -= amount_to_heal //remove what we healed from our current amount
+ if(!amount)
+ break
+ . -= amount //if there's leftover healing, remove it from what we return
\ No newline at end of file
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index f9dba949b4b..57c67f5fd61 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -256,8 +256,10 @@
death()
to_chat(src, "You have given up life and succumbed to death.")
+
/mob/living/proc/InCritical()
return (health < HEALTH_THRESHOLD_CRIT && health > HEALTH_THRESHOLD_DEAD && stat == UNCONSCIOUS)
+
/mob/living/ex_act(severity)
..()
diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm
index 7344c6469c4..c3c47235b91 100644
--- a/code/modules/mob/living/silicon/ai/freelook/eye.dm
+++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm
@@ -31,6 +31,7 @@
ai.camera_visibility(src)
if(ai.client && !ai.multicam_on)
ai.client.eye = src
+ update_parallax_contents()
//Holopad
if(ai.master_multicam)
ai.master_multicam.refresh_view()
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 131477d086e..b9ed81f7180 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -576,6 +576,8 @@ var/list/robot_verbs_default = list(
/mob/living/silicon/robot/restrained()
return 0
+/mob/living/silicon/robot/InCritical()
+ return low_power_mode
/mob/living/silicon/robot/ex_act(severity)
switch(severity)
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 2cb9ddf6252..bac58d8f124 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -337,4 +337,5 @@
/////////////////////////////////// EAR DAMAGE ////////////////////////////////////
/mob/living/silicon/can_hear()
- . = TRUE
\ No newline at end of file
+ . = TRUE
+
diff --git a/code/modules/mob/living/simple_animal/friendly/slime.dm b/code/modules/mob/living/simple_animal/friendly/slime.dm
index 13e7c893d86..ac913170c86 100644
--- a/code/modules/mob/living/simple_animal/friendly/slime.dm
+++ b/code/modules/mob/living/simple_animal/friendly/slime.dm
@@ -12,8 +12,8 @@
response_disarm = "shoos"
response_harm = "stomps on"
emote_see = list("jiggles", "bounces in place")
- var/colour = "grey"
pass_flags = PASSTABLE
+ var/colour = "grey"
/mob/living/simple_animal/slime/adult
health = 200
@@ -24,3 +24,37 @@
/mob/living/simple_animal/slime/New()
..()
overlays += "aslime-:33"
+
+/mob/living/simple_animal/slime/updatehealth(reason)
+ . = ..()
+ update_health_hud()
+
+/mob/living/simple_animal/slime/proc/update_health_hud()
+ if(hud_used)
+ var/severity = 0
+ var/healthpercent = (health/maxHealth) * 100
+ switch(healthpercent)
+ if(100 to INFINITY)
+ healths.icon_state = "slime_health0"
+ if(80 to 100)
+ healths.icon_state = "slime_health1"
+ severity = 1
+ if(60 to 80)
+ healths.icon_state = "slime_health2"
+ severity = 2
+ if(40 to 60)
+ healths.icon_state = "slime_health3"
+ severity = 3
+ if(20 to 40)
+ healths.icon_state = "slime_health4"
+ severity = 4
+ if(1 to 20)
+ healths.icon_state = "slime_health5"
+ severity = 5
+ else
+ healths.icon_state = "slime_health7"
+ severity = 6
+ if(severity > 0)
+ overlay_fullscreen("brute", /obj/screen/fullscreen/brute, severity)
+ else
+ clear_fullscreen("brute")
diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm
index 9c787639ba4..a96c78d09d6 100644
--- a/code/modules/mob/living/simple_animal/hostile/hostile.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm
@@ -309,14 +309,18 @@
else
M.Goto(src,M.move_to_delay,M.minimum_distance)
-/mob/living/simple_animal/hostile/proc/OpenFire(atom/A)
+/mob/living/simple_animal/hostile/proc/CheckFriendlyFire(atom/A)
if(check_friendly_fire)
for(var/turf/T in getline(src,A)) // Not 100% reliable but this is faster than simulating actual trajectory
for(var/mob/living/L in T)
if(L == src || L == A)
continue
- if(faction_check(L) && !attack_same)
- return
+ if(faction_check_mob(L) && !attack_same)
+ return TRUE
+
+/mob/living/simple_animal/hostile/proc/OpenFire(atom/A)
+ if(CheckFriendlyFire(A))
+ return
visible_message("[src] [ranged_message] at [A]!")
if(rapid)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
index 7fd32bd71ec..d45e6f6ead8 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
@@ -37,6 +37,7 @@ Difficulty: Medium
ranged = 1
ranged_cooldown_time = 16
pixel_x = -16
+ crusher_loot = list(/obj/item/melee/energy/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator, /obj/item/crusher_trophy/miner_eye)
loot = list(/obj/item/melee/energy/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator)
wander = FALSE
del_on_death = TRUE
@@ -48,7 +49,7 @@ Difficulty: Medium
var/guidance = FALSE
deathmessage = "falls to the ground, decaying into glowing particles."
death_sound = "bodyfall"
-
+
/obj/item/gps/internal/miner
icon_state = null
gpstag = "Resonant Signal"
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 a53b8092e54..ac5e40025c6 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
@@ -42,6 +42,7 @@ Difficulty: Hard
ranged = 1
pixel_x = -32
del_on_death = 1
+ crusher_loot = list(/obj/structure/closet/crate/necropolis/bubblegum/crusher)
loot = list(/obj/structure/closet/crate/necropolis/bubblegum)
var/charging = 0
medal_type = BOSS_MEDAL_BUBBLEGUM
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 5d66061335c..3ebea47e353 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
@@ -45,7 +45,8 @@ Difficulty: Very Hard
del_on_death = 1
medal_type = BOSS_MEDAL_COLOSSUS
score_type = COLOSSUS_SCORE
- loot = list(/obj/machinery/anomalous_crystal/random, /obj/item/organ/internal/vocal_cords/colossus)
+ crusher_loot = list(/obj/structure/closet/crate/necropolis/colossus/crusher)
+ loot = list(/obj/structure/closet/crate/necropolis/colossus)
butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/animalhide/ashdrake = 10, /obj/item/stack/sheet/bone = 30)
deathmessage = "disintegrates, leaving a glowing core in its wake."
death_sound = 'sound/misc/demon_dies.ogg'
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
index 68db8cb1274..0789d00832d 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
@@ -43,6 +43,7 @@ Difficulty: Medium
move_to_delay = 10
ranged = 1
pixel_x = -16
+ crusher_loot = list(/obj/structure/closet/crate/necropolis/dragon/crusher)
loot = list(/obj/structure/closet/crate/necropolis/dragon)
butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/animalhide/ashdrake = 10, /obj/item/stack/sheet/bone = 30)
var/swooping = 0
@@ -271,6 +272,7 @@ Difficulty: Medium
melee_damage_lower = 30
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
loot = list()
+ crusher_loot = list()
/mob/living/simple_animal/hostile/megafauna/dragon/lesser/grant_achievement(medaltype,scoretype)
return
\ No newline at end of file
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 7f974149556..bb4e9297605 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
@@ -53,6 +53,7 @@ Difficulty: Hard
ranged_cooldown_time = 40
aggro_vision_range = 23
loot = list(/obj/item/hierophant_staff)
+ crusher_loot = list(/obj/item/hierophant_staff, /obj/item/crusher_trophy/vortex_talisman)
wander = FALSE
var/burst_range = 3 //range on burst aoe
var/beam_range = 5 //range on cross blast beams
@@ -556,6 +557,37 @@ Difficulty: Hard
playsound(M,'sound/weapons/sear.ogg', 50, 1, -4)
M.take_damage(damage, BURN, 0, 0)
+/obj/effect/temp_visual/hierophant/wall //smoothing and pooling were not friends, but pooling is dead.
+ name = "vortex wall"
+ icon = 'icons/turf/walls/hierophant_wall_temp.dmi'
+ icon_state = "wall"
+ light_range = MINIMUM_USEFUL_LIGHT_RANGE
+ duration = 100
+ smooth = SMOOTH_TRUE
+
+/obj/effect/temp_visual/hierophant/wall/New(loc, new_caster)
+ ..()
+ queue_smooth_neighbors(src)
+ queue_smooth(src)
+
+/obj/effect/temp_visual/hierophant/wall/Destroy()
+ queue_smooth_neighbors(src)
+ return ..()
+
+/obj/effect/temp_visual/hierophant/wall/CanPass(atom/movable/mover, turf/target)
+ if(QDELETED(caster))
+ return FALSE
+ if(mover == caster.pulledby)
+ return TRUE
+ if(istype(mover, /obj/item/projectile))
+ var/obj/item/projectile/P = mover
+ if(P.firer == caster)
+ return TRUE
+ if(mover == caster)
+ return TRUE
+ return FALSE
+
+
/obj/effect/hierophant
name = "hierophant rune"
desc = "A powerful magic mark allowing whomever attunes themself to it to return to it at will."
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 a32aceb33e3..f57559d549a 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
@@ -31,6 +31,7 @@
/obj/structure/barricade,
/obj/machinery/field,
/obj/machinery/power/emitter)
+ var/list/crusher_loot
var/medal_type
var/score_type = BOSS_SCORE
var/elimination = 0
@@ -43,6 +44,10 @@
layer = LARGE_MOB_LAYER //Looks weird with them slipping under mineral walls and cameras and shit otherwise
mouse_opacity = MOUSE_OPACITY_OPAQUE // Easier to click on in melee, they're giant targets anyway
+/mob/living/simple_animal/hostile/megafauna/New()
+ ..()
+ apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
+
/mob/living/simple_animal/hostile/megafauna/Destroy()
QDEL_NULL(internal_gps)
. = ..()
@@ -53,11 +58,17 @@
/mob/living/simple_animal/hostile/megafauna/death(gibbed)
// this happens before the parent call because `del_on_death` may be set
if(can_die() && !admin_spawned)
- feedback_set_details("megafauna_kills","[initial(name)]")
+ var/datum/status_effect/crusher_damage/C = has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
+ if(C && crusher_loot && C.total_damage >= maxHealth * 0.6)
+ spawn_crusher_loot()
if(!elimination) //used so the achievment only occurs for the last legion to die.
grant_achievement(medal_type,score_type)
+ feedback_set_details("megafauna_kills","[initial(name)]")
return ..()
+/mob/living/simple_animal/hostile/megafauna/proc/spawn_crusher_loot()
+ loot = crusher_loot
+
/mob/living/simple_animal/hostile/megafauna/AttackingTarget()
..()
if(isliving(target))
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/basilisk.dm b/code/modules/mob/living/simple_animal/hostile/mining/basilisk.dm
index 28aacd37a73..ad8dcf44699 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/basilisk.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/basilisk.dm
@@ -77,6 +77,7 @@
stat_attack = 1
flying = TRUE
robust_searching = 1
+ crusher_loot = /obj/item/crusher_trophy/watcher_wing
loot = list()
butcher_results = list(/obj/item/stack/ore/diamond = 2, /obj/item/stack/sheet/sinew = 2, /obj/item/stack/sheet/bone = 1)
@@ -102,6 +103,8 @@
light_power = 2.5
light_color = LIGHT_COLOR_ORANGE
projectiletype = /obj/item/projectile/temp/basilisk/magmawing
+ crusher_loot = /obj/item/crusher_trophy/blaster_tubes/magma_wing
+ crusher_drop_mod = 60
/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/icewing
name = "icewing watcher"
@@ -114,6 +117,8 @@
health = 170
projectiletype = /obj/item/projectile/temp/basilisk/icewing
butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/bone = 1) //No sinew; the wings are too fragile to be usable
+ crusher_loot = /obj/item/crusher_trophy/watcher_wing/ice_wing
+ crusher_drop_mod = 30
/obj/item/projectile/temp/basilisk/magmawing
name = "scorching blast"
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm b/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm
index a1c488b4068..dae7a688cb3 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm
@@ -83,6 +83,7 @@
icon_dead = "goliath_dead"
throw_message = "does nothing to the tough hide of the"
pre_attack_icon = "goliath2"
+ crusher_loot = /obj/item/crusher_trophy/goliath_tentacle
butcher_results = list(/obj/item/reagent_containers/food/snacks/goliath = 2, /obj/item/stack/sheet/animalhide/goliath_hide = 1, /obj/item/stack/sheet/bone = 2)
loot = list()
stat_attack = TRUE
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm
index 60c1f5e08e7..c90a06a9fb8 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm
@@ -45,6 +45,9 @@
/mob/living/simple_animal/hostile/asteroid/hivelord/AttackingTarget()
OpenFire()
+/mob/living/simple_animal/hostile/asteroid/hivelord/spawn_crusher_loot()
+ loot += crusher_loot //we don't butcher
+
/mob/living/simple_animal/hostile/asteroid/hivelord/death(gibbed)
// Only execute the below if we successfully died
. = ..(gibbed)
@@ -231,6 +234,7 @@
speak_emote = list("echoes")
attack_sound = 'sound/weapons/pierce.ogg'
throw_message = "bounces harmlessly off of"
+ crusher_loot = /obj/item/crusher_trophy/legion_skull
loot = list(/obj/item/organ/internal/hivelord_core/legion)
brood_type = /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion
del_on_death = 1
@@ -403,7 +407,7 @@
if(prob(95))
head = /obj/item/clothing/head/helmet/gladiator
else
- head = /obj/item/clothing/head/skullhelmet
+ head = /obj/item/clothing/head/helmet/skull
suit = /obj/item/clothing/suit/armor/bone
if(prob(5))
back = pickweight(list(/obj/item/twohanded/spear/bonespear = 3, /obj/item/twohanded/fireaxe/boneaxe = 2))
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/mining.dm b/code/modules/mob/living/simple_animal/hostile/mining/mining.dm
index e23624a5a9d..434869c1d6d 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/mining.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/mining.dm
@@ -1,4 +1,4 @@
-/mob/living/simple_animal/hostile/asteroid/
+/mob/living/simple_animal/hostile/asteroid
vision_range = 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)
unsuitable_atmos_damage = 15
@@ -13,12 +13,18 @@
response_harm = "strikes"
status_flags = 0
a_intent = INTENT_HARM
+ var/crusher_loot
var/throw_message = "bounces off of"
var/icon_aggro = null // for swapping to when we get aggressive
var/fromtendril = FALSE
see_in_dark = 8
see_invisible = SEE_INVISIBLE_MINIMUM
mob_size = MOB_SIZE_LARGE
+ var/crusher_drop_mod = 25
+
+/mob/living/simple_animal/hostile/asteroid/New()
+ ..()
+ apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
/mob/living/simple_animal/hostile/asteroid/Aggro()
..()
@@ -46,3 +52,12 @@
visible_message("The [T.name] [src.throw_message] [src.name]!")
return
..()
+
+/mob/living/simple_animal/hostile/asteroid/death(gibbed)
+ var/datum/status_effect/crusher_damage/C = has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
+ if(C && crusher_loot && prob((C.total_damage/maxHealth) * crusher_drop_mod)) //on average, you'll need to kill 4 creatures before getting the item
+ spawn_crusher_loot()
+ ..(gibbed)
+
+/mob/living/simple_animal/hostile/asteroid/proc/spawn_crusher_loot()
+ butcher_results[crusher_loot] = 1
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/hostile/netherworld.dm b/code/modules/mob/living/simple_animal/hostile/netherworld.dm
index fc39035618e..70d279fd400 100644
--- a/code/modules/mob/living/simple_animal/hostile/netherworld.dm
+++ b/code/modules/mob/living/simple_animal/hostile/netherworld.dm
@@ -69,6 +69,7 @@
desc = null //see examine()
icon_state = "nether"
health = 50
+ maxHealth = 50
spawn_time = 600 //1 minute
max_mobs = 15
icon = 'icons/mob/nest.dmi'
@@ -76,9 +77,9 @@
mob_types = list(/mob/living/simple_animal/hostile/netherworld/migo, /mob/living/simple_animal/hostile/netherworld, /mob/living/simple_animal/hostile/netherworld/blankbody)
faction = list("nether")
-/mob/living/simple_animal/hostile/spawner/nether/Initialize()
- .=..()
- START_PROCESSING(SSprocessing, src)
+/mob/living/simple_animal/hostile/spawner/nether/death()
+ . = ..()
+ qdel(src)
/mob/living/simple_animal/hostile/spawner/nether/examine(mob/user)
..()
@@ -96,7 +97,8 @@
"Touching the portal, you are quickly pulled through into a world of unimaginable horror!")
contents.Add(user)
-/mob/living/simple_animal/hostile/spawner/nether/process()
+/mob/living/simple_animal/hostile/spawner/nether/Life()
+ . = ..()
for(var/mob/living/M in contents)
if(M)
playsound(src, 'sound/magic/demon_consume.ogg', 50, 1)
diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm
index cf021cb2618..9e844d6cf21 100644
--- a/code/modules/paperwork/paper.dm
+++ b/code/modules/paperwork/paper.dm
@@ -54,8 +54,6 @@
/obj/item/paper/update_icon()
..()
- if(icon_state == "paper_talisman")
- return
if(info)
icon_state = "paper_words"
return
diff --git a/code/modules/projectiles/firing.dm b/code/modules/projectiles/firing.dm
index 9d16a9c2123..c2333da9107 100644
--- a/code/modules/projectiles/firing.dm
+++ b/code/modules/projectiles/firing.dm
@@ -40,14 +40,16 @@
if(!istype(targloc) || !istype(curloc) || !BB)
return 0
BB.ammo_casing = src
-
+
if(target && get_dist(user, target) <= 1) //Point blank shot must always hit
+ BB.prehit(target)
target.bullet_act(BB, BB.def_zone)
QDEL_NULL(BB)
return 1
if(targloc == curloc)
if(target) //if the target is right on our location we go straight to bullet_act()
+ BB.prehit(target)
target.bullet_act(BB, BB.def_zone)
QDEL_NULL(BB)
return 1
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index d5dfb454e09..eea2c2253e8 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -50,6 +50,12 @@
var/obj/item/flashlight/gun_light = null
var/can_flashlight = 0
+ var/can_bayonet = FALSE //if a bayonet can be added or removed if it already has one.
+ var/obj/item/kitchen/knife/bayonet
+ var/mutable_appearance/knife_overlay
+ var/knife_x_offset = 0
+ var/knife_y_offset = 0
+
var/list/upgrades = list()
var/ammo_x_offset = 0 //used for positioning ammo count overlay on sprite
@@ -69,12 +75,27 @@
verbs += /obj/item/gun/proc/toggle_gunlight
build_zooming()
+/obj/item/gun/Destroy()
+ QDEL_NULL(bayonet)
+ return ..()
+
+/obj/item/gun/handle_atom_del(atom/A)
+ if(A == bayonet)
+ clear_bayonet()
+ return ..()
+
/obj/item/gun/examine(mob/user)
..()
if(unique_reskin && !current_skin)
to_chat(user, "Alt-click it to reskin it.")
if(unique_rename)
to_chat(user, "Use a pen on it to rename it.")
+ if(bayonet)
+ to_chat(user, "It has \a [bayonet] [can_bayonet ? "" : "permanently "]affixed to it.")
+ if(can_bayonet) //if it has a bayonet and this is false, the bayonet is permanent.
+ to_chat(user, "[bayonet] looks like it can be unscrewed from [src].")
+ else if(can_bayonet)
+ to_chat(user, "It has a bayonet lug on it.")
/obj/item/gun/proc/process_chamber()
return 0
@@ -233,11 +254,19 @@ obj/item/gun/proc/newshot()
user.update_inv_r_hand()
feedback_add_details("gun_fired","[type]")
-/obj/item/gun/attack(mob/M as mob, mob/user)
+/obj/item/gun/attack(mob/M, mob/user)
if(user.a_intent == INTENT_HARM) //Flogging
- ..()
- else
- return
+ if(bayonet)
+ M.attackby(bayonet, user)
+ else
+ return ..()
+
+/obj/item/gun/attack_obj(obj/O, mob/user)
+ if(user.a_intent == INTENT_HARM)
+ if(bayonet)
+ O.attackby(bayonet, user)
+ return
+ return ..()
/obj/item/gun/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/flashlight/seclite))
@@ -257,7 +286,7 @@ obj/item/gun/proc/newshot()
if(loc == user)
A.Grant(user)
- if(istype(I, /obj/item/screwdriver))
+ if(isscrewdriver(I))
if(gun_light && can_flashlight)
for(var/obj/item/flashlight/seclite/S in src)
to_chat(user, "You unscrew the seclite from [src].")
@@ -268,11 +297,32 @@ obj/item/gun/proc/newshot()
update_icon()
for(var/datum/action/item_action/toggle_gunlight/TGL in actions)
qdel(TGL)
+ else if(bayonet && can_bayonet) //if it has a bayonet, and the bayonet can be removed
+ bayonet.forceMove(get_turf(user))
+ clear_bayonet()
if(unique_rename)
if(istype(I, /obj/item/pen))
rename_gun(user)
- ..()
+ if(istype(I, /obj/item/kitchen/knife))
+ var/obj/item/kitchen/knife/K = I
+ if(!can_bayonet || !K.bayonet || bayonet) //ensure the gun has an attachment point available, and that the knife is compatible with it.
+ return ..()
+ if(!user.drop_item())
+ return
+ K.forceMove(src)
+ to_chat(user, "You attach [K] to [src]'s bayonet lug.")
+ bayonet = K
+ var/state = "bayonet" //Generic state.
+ if(bayonet.icon_state in icon_states('icons/obj/guns/bayonets.dmi')) //Snowflake state?
+ state = bayonet.icon_state
+ var/icon/bayonet_icons = 'icons/obj/guns/bayonets.dmi'
+ knife_overlay = mutable_appearance(bayonet_icons, state)
+ knife_overlay.pixel_x = knife_x_offset
+ knife_overlay.pixel_y = knife_y_offset
+ overlays += knife_overlay
+ else
+ return ..()
/obj/item/gun/proc/toggle_gunlight()
set name = "Toggle Gun Light"
@@ -305,6 +355,15 @@ obj/item/gun/proc/newshot()
var/datum/action/A = X
A.UpdateButtonIcon()
+/obj/item/gun/proc/clear_bayonet()
+ if(!bayonet)
+ return
+ bayonet = null
+ if(knife_overlay)
+ overlays -= knife_overlay
+ knife_overlay = null
+ return TRUE
+
/obj/item/gun/extinguish_light()
if(gun_light.on)
toggle_gunlight()
diff --git a/code/modules/projectiles/guns/dartgun.dm b/code/modules/projectiles/guns/dartgun.dm
index 7b39bfa3be8..97f4eaebf1c 100644
--- a/code/modules/projectiles/guns/dartgun.dm
+++ b/code/modules/projectiles/guns/dartgun.dm
@@ -101,6 +101,8 @@
beakers += B
to_chat(user, "You slot [B] into [src].")
src.updateUsrDialog()
+ else
+ return ..()
/obj/item/gun/dartgun/can_shoot()
if(!cartridge)
diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm
index cbc230c1e98..6e4de3c49fa 100644
--- a/code/modules/projectiles/guns/energy.dm
+++ b/code/modules/projectiles/guns/energy.dm
@@ -140,6 +140,8 @@
if(gun_light.on)
iconF = "flight_on"
overlays += image(icon = icon, icon_state = iconF, pixel_x = flight_x_offset, pixel_y = flight_y_offset)
+ if(bayonet && can_bayonet)
+ overlays += knife_overlay
if(itemState)
itemState += "[ratio]"
item_state = itemState
diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
index fa483903012..d214309728e 100644
--- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
+++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
@@ -16,10 +16,15 @@
var/holds_charge = FALSE
var/unique_frequency = FALSE // modified by KA modkits
var/overheat = FALSE
+ can_bayonet = TRUE
+ knife_x_offset = 20
+ knife_y_offset = 12
var/max_mod_capacity = 100
var/list/modkits = list()
+ var/recharge_timerid
+
var/empty_state = "kineticgun_empty"
/obj/item/gun/energy/kinetic_accelerator/examine(mob/user)
@@ -30,20 +35,20 @@
var/obj/item/borg/upgrade/modkit/M = A
to_chat(user, "There is a [M.name] mod installed, using [M.cost]% capacity.")
-/obj/item/gun/energy/kinetic_accelerator/attackby(obj/item/A, mob/user)
- if(istype(A, /obj/item/crowbar))
+/obj/item/gun/energy/kinetic_accelerator/attackby(obj/item/I, mob/user)
+ if(iscrowbar(I))
if(modkits.len)
to_chat(user, "You pry the modifications out.")
- playsound(loc, A.usesound, 100, 1)
+ playsound(loc, I.usesound, 100, 1)
for(var/obj/item/borg/upgrade/modkit/M in modkits)
M.uninstall(src)
else
to_chat(user, "There are no modifications currently installed.")
- else if(istype(A, /obj/item/borg/upgrade/modkit))
- var/obj/item/borg/upgrade/modkit/MK = A
+ else if(istype(I, /obj/item/borg/upgrade/modkit))
+ var/obj/item/borg/upgrade/modkit/MK = I
MK.install(src, user)
else
- ..()
+ return ..()
/obj/item/gun/energy/kinetic_accelerator/proc/get_remaining_mod_capacity()
var/current_capacity_used = 0
@@ -58,6 +63,7 @@
. += A
/obj/item/gun/energy/kinetic_accelerator/proc/modify_projectile(obj/item/projectile/kinetic/K)
+ K.kinetic_gun = src //do something special on-hit, easy!
for(var/A in get_modkits())
var/obj/item/borg/upgrade/modkit/M = A
M.modify_projectile(K)
@@ -67,6 +73,12 @@
unique_frequency = TRUE
max_mod_capacity = 80
+/obj/item/gun/energy/kinetic_accelerator/minebot
+ trigger_guard = TRIGGER_GUARD_ALLOW_ALL
+ overheat_time = 20
+ holds_charge = TRUE
+ unique_frequency = TRUE
+
/obj/item/gun/energy/kinetic_accelerator/New()
. = ..()
if(!holds_charge)
@@ -83,7 +95,7 @@
/obj/item/gun/energy/kinetic_accelerator/dropped()
. = ..()
- if(!holds_charge)
+ if(!QDELING(src) && !holds_charge)
// Put it on a delay because moving item from slot to hand
// calls dropped().
spawn(2)
@@ -97,24 +109,25 @@
power_supply.use(500)
update_icon()
-/obj/item/gun/energy/kinetic_accelerator/proc/attempt_reload()
+/obj/item/gun/energy/kinetic_accelerator/proc/attempt_reload(recharge_time)
if(overheat)
return
+ if(!recharge_time)
+ recharge_time = overheat_time
overheat = TRUE
var/carried = 0
if(!unique_frequency)
- for(var/obj/item/gun/energy/kinetic_accelerator/K in \
- loc.GetAllContents())
-
- carried++
+ for(var/obj/item/gun/energy/kinetic_accelerator/K in loc.GetAllContents())
+ if(!K.unique_frequency)
+ carried++
carried = max(carried, 1)
else
carried = 1
- spawn(overheat_time * carried)
- reload()
+ deltimer(recharge_timerid)
+ recharge_timerid = addtimer(CALLBACK(src, .proc/reload), recharge_time * carried, TIMER_STOPPABLE)
/obj/item/gun/energy/kinetic_accelerator/emp_act(severity)
return
@@ -138,6 +151,8 @@
if(gun_light.on)
iconF = "flight_on"
overlays += image(icon = icon, icon_state = iconF, pixel_x = flight_x_offset, pixel_y = flight_y_offset)
+ if(bayonet && can_bayonet)
+ overlays += knife_overlay
/obj/item/gun/energy/kinetic_accelerator/experimental
@@ -161,16 +176,6 @@
var/obj/item/gun/energy/kinetic_accelerator/KA = loc
KA.modify_projectile(BB)
- var/turf/proj_turf = get_turf(BB)
- if(!isturf(proj_turf))
- return
- var/datum/gas_mixture/environment = proj_turf.return_air()
- var/pressure = environment.return_pressure()
- if(pressure > 50)
- BB.name = "weakened [BB.name]"
- var/obj/item/projectile/kinetic/K = BB
- K.damage *= K.pressure_decrease
-
//Projectiles
/obj/item/projectile/kinetic
@@ -181,10 +186,9 @@
flag = "bomb"
range = 3
+ var/pressure_decrease_active = FALSE
var/pressure_decrease = 0.25
- var/turf_aoe = FALSE
- var/mob_aoe = FALSE
- var/list/hit_overlays = list()
+ var/obj/item/gun/energy/kinetic_accelerator/kinetic_gun
/obj/item/projectile/kinetic/pod
range = 4
@@ -193,9 +197,22 @@
damage = 50
pressure_decrease = 0.5
-/obj/item/projectile/kinetic/pod/enhanced
- turf_aoe = TRUE
- mob_aoe = TRUE
+/obj/item/projectile/kinetic/Destroy()
+ kinetic_gun = null
+ return ..()
+
+/obj/item/projectile/kinetic/prehit(atom/target)
+ . = ..()
+ if(.)
+ if(kinetic_gun)
+ var/list/mods = kinetic_gun.get_modkits()
+ for(var/obj/item/borg/upgrade/modkit/M in mods)
+ M.projectile_prehit(src, target, kinetic_gun)
+ if(!lavaland_equipment_pressure_check(get_turf(target)))
+ name = "weakened [name]"
+ damage = damage * pressure_decrease
+ pressure_decrease_active = TRUE
+
/obj/item/projectile/kinetic/on_range()
strike_thing()
@@ -209,30 +226,22 @@
var/turf/target_turf = get_turf(target)
if(!target_turf)
target_turf = get_turf(src)
+ if(kinetic_gun) //hopefully whoever shot this was not very, very unfortunate.
+ var/list/mods = kinetic_gun.get_modkits()
+ for(var/obj/item/borg/upgrade/modkit/M in mods)
+ M.projectile_strike_predamage(src, target_turf, target, kinetic_gun)
+ for(var/obj/item/borg/upgrade/modkit/M in mods)
+ M.projectile_strike(src, target_turf, target, kinetic_gun)
if(ismineralturf(target_turf))
var/turf/simulated/mineral/M = target_turf
M.gets_drilled(firer)
var/obj/effect/temp_visual/kinetic_blast/K = new /obj/effect/temp_visual/kinetic_blast(target_turf)
K.color = color
- for(var/type in hit_overlays)
- new type(target_turf)
- if(turf_aoe)
- for(var/T in RANGE_TURFS(1, target_turf) - target_turf)
- if(ismineralturf(T))
- var/turf/simulated/mineral/M = T
- M.gets_drilled(firer)
- if(mob_aoe)
- for(var/mob/living/L in range(1, target_turf) - firer - target)
- var/armor = L.run_armor_check(def_zone, flag, "", "", armour_penetration)
- L.apply_damage(damage*mob_aoe, damage_type, def_zone, armor)
- L.visible_message("[L] is hit by \a [src]!",
- "You are hit by \a [src]!")
- add_attack_logs(firer, L, "Shot with a [type]")
//Modkits
/obj/item/borg/upgrade/modkit
- name = "modification kit"
+ name = "kinetic accelerator modification kit"
desc = "An upgrade for kinetic accelerators."
icon = 'icons/obj/objects.dmi'
icon_state = "modkit"
@@ -244,6 +253,8 @@
var/maximum_of_type = 1
var/cost = 30
var/modifier = 1 //For use in any mod kit that has numerical modifiers
+ var/minebot_upgrade = TRUE
+ var/minebot_exclusive = FALSE
/obj/item/borg/upgrade/modkit/examine(mob/user)
if(..(user, 1))
@@ -253,7 +264,7 @@
if(istype(A, /obj/item/gun/energy/kinetic_accelerator) && !issilicon(user))
install(A, user)
else
- ..()
+ return ..()
/obj/item/borg/upgrade/modkit/action(mob/living/silicon/robot/R)
if(..())
@@ -264,6 +275,13 @@
/obj/item/borg/upgrade/modkit/proc/install(obj/item/gun/energy/kinetic_accelerator/KA, mob/user)
. = TRUE
+ if(minebot_upgrade)
+ if(minebot_exclusive && !istype(KA.loc, /mob/living/simple_animal/hostile/mining_drone))
+ to_chat(user, "The modkit you're trying to install is only rated for minebot use.")
+ return FALSE
+ else if(istype(KA.loc, /mob/living/simple_animal/hostile/mining_drone))
+ to_chat(user, "The modkit you're trying to install is not rated for minebot use.")
+ return FALSE
if(denied_type)
var/number_of_denied = 0
for(var/A in KA.get_modkits())
@@ -292,6 +310,12 @@
/obj/item/borg/upgrade/modkit/proc/modify_projectile(obj/item/projectile/kinetic/K)
+//use this one for effects you want to trigger before any damage is done at all and before damage is decreased by pressure
+/obj/item/borg/upgrade/modkit/proc/projectile_prehit(obj/item/projectile/kinetic/K, atom/target, obj/item/gun/energy/kinetic_accelerator/KA)
+//use this one for effects you want to trigger before mods that do damage
+/obj/item/borg/upgrade/modkit/proc/projectile_strike_predamage(obj/item/projectile/kinetic/K, turf/target_turf, atom/target, obj/item/gun/energy/kinetic_accelerator/KA)
+//and this one for things that don't need to trigger before other damage-dealing mods
+/obj/item/borg/upgrade/modkit/proc/projectile_strike(obj/item/projectile/kinetic/K, turf/target_turf, atom/target, obj/item/gun/energy/kinetic_accelerator/KA)
//Range
/obj/item/borg/upgrade/modkit/range
@@ -317,8 +341,9 @@
//Cooldown
/obj/item/borg/upgrade/modkit/cooldown
name = "cooldown decrease"
- desc = "Decreases the cooldown of a kinetic accelerator."
- modifier = 2.5
+ desc = "Decreases the cooldown of a kinetic accelerator. Not rated for minebot use."
+ modifier = 3.2
+ minebot_upgrade = FALSE
/obj/item/borg/upgrade/modkit/cooldown/install(obj/item/gun/energy/kinetic_accelerator/KA, mob/user)
. = ..()
@@ -329,25 +354,61 @@
KA.overheat_time += modifier
..()
+/obj/item/borg/upgrade/modkit/cooldown/minebot
+ name = "minebot cooldown decrease"
+ desc = "Decreases the cooldown of a kinetic accelerator. Only rated for minebot use."
+ icon_state = "door_electronics"
+ icon = 'icons/obj/module.dmi'
+ denied_type = /obj/item/borg/upgrade/modkit/cooldown/minebot
+ modifier = 10
+ cost = 0
+ minebot_upgrade = TRUE
+ minebot_exclusive = TRUE
//AoE blasts
/obj/item/borg/upgrade/modkit/aoe
modifier = 0
+ var/turf_aoe = FALSE
+ var/stats_stolen = FALSE
-/obj/item/borg/upgrade/modkit/aoe/modify_projectile(obj/item/projectile/kinetic/K)
- K.name = "kinetic explosion"
- if(!K.turf_aoe && !K.mob_aoe)
- K.hit_overlays += /obj/effect/temp_visual/explosion/fast
- K.mob_aoe += modifier
+/obj/item/borg/upgrade/modkit/aoe/install(obj/item/gun/energy/kinetic_accelerator/KA, mob/user)
+ if(..())
+ return
+ for(var/obj/item/borg/upgrade/modkit/aoe/AOE in KA.modkits) //make sure only one of the aoe modules has values if somebody has multiple
+ if(AOE.stats_stolen || AOE == src)
+ continue
+ modifier += AOE.modifier //take its modifiers
+ AOE.modifier = 0
+ turf_aoe += AOE.turf_aoe
+ AOE.turf_aoe = FALSE
+ AOE.stats_stolen = TRUE
+
+/obj/item/borg/upgrade/modkit/aoe/uninstall(obj/item/gun/energy/kinetic_accelerator/KA)
+ ..()
+ modifier = initial(modifier) //get our modifiers back
+ turf_aoe = initial(turf_aoe)
+ stats_stolen = FALSE
+
+/obj/item/borg/upgrade/modkit/aoe/projectile_strike(obj/item/projectile/kinetic/K, turf/target_turf, atom/target, obj/item/gun/energy/kinetic_accelerator/KA)
+ if(stats_stolen)
+ return
+ new /obj/effect/temp_visual/explosion/fast(target_turf)
+ if(turf_aoe)
+ for(var/T in RANGE_TURFS(1, target_turf) - target_turf)
+ if(ismineralturf(T))
+ var/turf/simulated/mineral/M = T
+ M.gets_drilled(K.firer)
+ if(modifier)
+ for(var/mob/living/L in range(1, target_turf) - K.firer - target)
+ var/armor = L.run_armor_check(K.def_zone, K.flag, "", "", K.armour_penetration)
+ L.apply_damage(K.damage * modifier, K.damage_type, K.def_zone, armor)
+ to_chat(L, "You're struck by a [K.name]!")
/obj/item/borg/upgrade/modkit/aoe/turfs
name = "mining explosion"
desc = "Causes the kinetic accelerator to destroy rock in an AoE."
denied_type = /obj/item/borg/upgrade/modkit/aoe/turfs
-
-/obj/item/borg/upgrade/modkit/aoe/turfs/modify_projectile(obj/item/projectile/kinetic/K)
- ..()
- K.turf_aoe = TRUE
+ turf_aoe = TRUE
/obj/item/borg/upgrade/modkit/aoe/turfs/andmobs
name = "offensive mining explosion"
@@ -360,15 +421,111 @@
desc = "Causes the kinetic accelerator to damage mobs in an AoE."
modifier = 0.2
+//Minebot passthrough
+/obj/item/borg/upgrade/modkit/minebot_passthrough
+ name = "minebot passthrough"
+ desc = "Causes kinetic accelerator shots to pass through minebots."
+ cost = 0
+
+//Tendril-unique modules
+/obj/item/borg/upgrade/modkit/cooldown/repeater
+ name = "rapid repeater"
+ desc = "Quarters the kinetic accelerator's cooldown on striking a living target, but greatly increases the base cooldown."
+ denied_type = /obj/item/borg/upgrade/modkit/cooldown/repeater
+ modifier = -14 //Makes the cooldown 3 seconds(with no cooldown mods) if you miss. Don't miss.
+ cost = 50
+
+/obj/item/borg/upgrade/modkit/cooldown/repeater/projectile_strike_predamage(obj/item/projectile/kinetic/K, turf/target_turf, atom/target, obj/item/gun/energy/kinetic_accelerator/KA)
+ var/valid_repeat = FALSE
+ if(isliving(target))
+ var/mob/living/L = target
+ if(L.stat != DEAD)
+ valid_repeat = TRUE
+ if(ismineralturf(target_turf))
+ valid_repeat = TRUE
+ if(valid_repeat)
+ KA.overheat = FALSE
+ KA.attempt_reload(KA.overheat_time * 0.25) //If you hit, the cooldown drops to 0.75 seconds.
+
+/obj/item/borg/upgrade/modkit/lifesteal
+ name = "lifesteal crystal"
+ desc = "Causes kinetic accelerator shots to slightly heal the firer on striking a living target."
+ icon_state = "modkit_crystal"
+ modifier = 2.5 //Not a very effective method of healing.
+ cost = 20
+ var/static/list/damage_heal_order = list(BRUTE, BURN, OXY)
+
+/obj/item/borg/upgrade/modkit/lifesteal/projectile_prehit(obj/item/projectile/kinetic/K, atom/target, obj/item/gun/energy/kinetic_accelerator/KA)
+ if(isliving(target) && isliving(K.firer))
+ var/mob/living/L = target
+ if(L.stat == DEAD)
+ return
+ L = K.firer
+ L.heal_ordered_damage(modifier, damage_heal_order)
+
+/obj/item/borg/upgrade/modkit/resonator_blasts
+ name = "resonator blast"
+ desc = "Causes kinetic accelerator shots to leave and detonate resonator blasts."
+ denied_type = /obj/item/borg/upgrade/modkit/resonator_blasts
+ cost = 30
+ modifier = 0.25 //A bonus 15 damage if you burst the field on a target, 60 if you lure them into it.
+
+/obj/item/borg/upgrade/modkit/resonator_blasts/projectile_strike(obj/item/projectile/kinetic/K, turf/target_turf, atom/target, obj/item/gun/energy/kinetic_accelerator/KA)
+ if(target_turf && !ismineralturf(target_turf)) //Don't make fields on mineral turfs.
+ var/obj/effect/temp_visual/resonance/R = locate(/obj/effect/temp_visual/resonance) in target_turf
+ if(R)
+ R.damage_multiplier = modifier
+ R.burst()
+ return
+ new /obj/effect/temp_visual/resonance(target_turf, K.firer, null, 30)
+
+/obj/item/borg/upgrade/modkit/bounty
+ name = "death syphon"
+ desc = "Killing or assisting in killing a creature permanently increases your damage against that type of creature."
+ denied_type = /obj/item/borg/upgrade/modkit/bounty
+ modifier = 1.25
+ cost = 30
+ var/maximum_bounty = 25
+ var/list/bounties_reaped = list()
+
+/obj/item/borg/upgrade/modkit/bounty/projectile_prehit(obj/item/projectile/kinetic/K, atom/target, obj/item/gun/energy/kinetic_accelerator/KA)
+ if(isliving(target))
+ var/mob/living/L = target
+ var/list/existing_marks = L.has_status_effect_list(STATUS_EFFECT_SYPHONMARK)
+ for(var/i in existing_marks)
+ var/datum/status_effect/syphon_mark/SM = i
+ if(SM.reward_target == src) //we want to allow multiple people with bounty modkits to use them, but we need to replace our own marks so we don't multi-reward
+ SM.reward_target = null
+ qdel(SM)
+ L.apply_status_effect(STATUS_EFFECT_SYPHONMARK, src)
+
+/obj/item/borg/upgrade/modkit/bounty/projectile_strike(obj/item/projectile/kinetic/K, turf/target_turf, atom/target, obj/item/gun/energy/kinetic_accelerator/KA)
+ if(isliving(target))
+ var/mob/living/L = target
+ if(bounties_reaped[L.type])
+ var/kill_modifier = 1
+ if(K.pressure_decrease_active)
+ kill_modifier *= K.pressure_decrease
+ var/armor = L.run_armor_check(K.def_zone, K.flag, "", "", K.armour_penetration)
+ L.apply_damage(bounties_reaped[L.type]*kill_modifier, K.damage_type, K.def_zone, armor)
+
+/obj/item/borg/upgrade/modkit/bounty/proc/get_kill(mob/living/L)
+ var/bonus_mod = 1
+ if(ismegafauna(L)) //megafauna reward
+ bonus_mod = 4
+ if(!bounties_reaped[L.type])
+ bounties_reaped[L.type] = min(modifier * bonus_mod, maximum_bounty)
+ else
+ bounties_reaped[L.type] = min(bounties_reaped[L.type] + (modifier * bonus_mod), maximum_bounty)
//Indoors
/obj/item/borg/upgrade/modkit/indoors
name = "decrease pressure penalty"
- desc = "Increases the damage a kinetic accelerator does in a high pressure environment."
+ desc = "A syndicate modification kit that increases the damage a kinetic accelerator does in high pressure environments."
modifier = 2
denied_type = /obj/item/borg/upgrade/modkit/indoors
maximum_of_type = 2
- cost = 40
+ cost = 35
/obj/item/borg/upgrade/modkit/indoors/modify_projectile(obj/item/projectile/kinetic/K)
K.pressure_decrease *= modifier
@@ -431,7 +588,7 @@
/obj/item/borg/upgrade/modkit/tracer/adjustable
name = "adjustable tracer bolts"
- desc = "Causes kinetic accelerator bolts to have a adjustably-colored tracer trail and explosion. Use in-hand to change color."
+ desc = "Causes kinetic accelerator bolts to have an adjustable-colored tracer trail and explosion. Use in-hand to change color."
/obj/item/borg/upgrade/modkit/tracer/adjustable/attack_self(mob/user)
- bolt_color = input(user,"Choose Color") as color
+ bolt_color = input(user,"","Choose Color",bolt_color) as color|null
\ No newline at end of file
diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm
index fa34753c6a9..be60248cded 100644
--- a/code/modules/projectiles/guns/energy/special.dm
+++ b/code/modules/projectiles/guns/energy/special.dm
@@ -175,7 +175,7 @@
power_supply.give(500)
to_chat(user, "You insert [A] in [src], recharging it.")
else
- ..()
+ return ..()
/obj/item/gun/energy/plasmacutter/update_icon()
return
diff --git a/code/modules/projectiles/guns/grenade_launcher.dm b/code/modules/projectiles/guns/grenade_launcher.dm
index 0f05cfa32f6..81b8451eb77 100644
--- a/code/modules/projectiles/guns/grenade_launcher.dm
+++ b/code/modules/projectiles/guns/grenade_launcher.dm
@@ -28,6 +28,8 @@
to_chat(user, "[grenades.len] / [max_grenades] grenades.")
else
to_chat(user, "The grenade launcher cannot hold more grenades.")
+ else
+ return ..()
/obj/item/gun/grenadelauncher/afterattack(obj/target, mob/user , flag)
if(target == user)
diff --git a/code/modules/projectiles/guns/projectile.dm b/code/modules/projectiles/guns/projectile.dm
index 9defe7637d4..15efee700d2 100644
--- a/code/modules/projectiles/guns/projectile.dm
+++ b/code/modules/projectiles/guns/projectile.dm
@@ -24,6 +24,8 @@
icon_state = "[current_skin][suppressed ? "-suppressed" : ""][sawn_state ? "-sawn" : ""]"
else
icon_state = "[initial(icon_state)][suppressed ? "-suppressed" : ""][sawn_state ? "-sawn" : ""]"
+ if(bayonet && can_bayonet)
+ overlays += knife_overlay
/obj/item/gun/projectile/process_chamber(eject_casing = 1, empty_chamber = 1)
var/obj/item/ammo_casing/AC = chambered //Find chambered round
@@ -66,7 +68,6 @@
return
/obj/item/gun/projectile/attackby(var/obj/item/A as obj, mob/user as mob, params)
- ..()
if(istype(A, /obj/item/ammo_box/magazine))
var/obj/item/ammo_box/magazine/AM = A
if(istype(AM, mag_type))
@@ -108,7 +109,8 @@
else
to_chat(user, "You can't seem to figure out how to fit [S] on [src].")
return
- return 0
+ else
+ return ..()
/obj/item/gun/projectile/attack_hand(mob/user)
if(loc == user)
@@ -178,6 +180,9 @@
if(sawn_state == SAWN_OFF)
to_chat(user, "\The [src] is already shortened!")
return
+ if(bayonet)
+ to_chat(user, "You cannot saw-off [src] with [bayonet] attached!")
+ return
user.changeNext_move(CLICK_CD_MELEE)
user.visible_message("[user] begins to shorten \the [src].", "You begin to shorten \the [src]...")
diff --git a/code/modules/projectiles/guns/projectile/automatic.dm b/code/modules/projectiles/guns/projectile/automatic.dm
index 399925d0e8a..6601f75d52b 100644
--- a/code/modules/projectiles/guns/projectile/automatic.dm
+++ b/code/modules/projectiles/guns/projectile/automatic.dm
@@ -19,6 +19,8 @@
if(select == 1)
overlays += "[initial(icon_state)]burst"
icon_state = "[initial(icon_state)][magazine ? "-[magazine.max_ammo]" : ""][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]"
+ if(bayonet && can_bayonet)
+ overlays += knife_overlay
/obj/item/gun/projectile/automatic/attackby(var/obj/item/A as obj, mob/user as mob, params)
. = ..()
@@ -96,6 +98,9 @@
fire_sound = 'sound/weapons/gunshots/gunshot_smg.ogg'
fire_delay = 2
burst_size = 2
+ can_bayonet = TRUE
+ knife_x_offset = 26
+ knife_y_offset = 12
/obj/item/gun/projectile/automatic/c20r/New()
..()
@@ -123,6 +128,9 @@
can_suppress = 0
burst_size = 1
actions_types = list()
+ can_bayonet = TRUE
+ knife_x_offset = 25
+ knife_y_offset = 12
/obj/item/gun/projectile/automatic/wt550/update_icon()
..()
@@ -172,7 +180,7 @@
underbarrel.attack_self()
underbarrel.attackby(A, user, params)
else
- ..()
+ return ..()
/obj/item/gun/projectile/automatic/m90/update_icon()
..()
diff --git a/code/modules/projectiles/guns/projectile/revolver.dm b/code/modules/projectiles/guns/projectile/revolver.dm
index 3cba868a379..6f977f2e024 100644
--- a/code/modules/projectiles/guns/projectile/revolver.dm
+++ b/code/modules/projectiles/guns/projectile/revolver.dm
@@ -115,7 +115,6 @@
..()
/obj/item/gun/projectile/revolver/detective/attackby(obj/item/A, mob/user, params)
- ..()
if(istype(A, /obj/item/screwdriver))
if(magazine.caliber == "38")
to_chat(user, "You begin to reinforce the barrel of [src]...")
@@ -143,6 +142,8 @@
magazine.caliber = "38"
desc = initial(desc)
to_chat(user, "You remove the modifications on [src]. Now it will fire .38 rounds.")
+ else
+ return ..()
/obj/item/gun/projectile/revolver/fingergun //Summoned by the Finger Gun spell, from advanced mimery traitor item
name = "\improper finger gun"
@@ -347,7 +348,6 @@
options["Cancel"] = null
/obj/item/gun/projectile/revolver/doublebarrel/attackby(obj/item/A, mob/user, params)
- ..()
if(istype(A, /obj/item/ammo_box) || istype(A, /obj/item/ammo_casing))
chamber_round()
if(istype(A, /obj/item/melee/energy))
@@ -356,6 +356,8 @@
sawoff(user)
if(istype(A, /obj/item/circular_saw) || istype(A, /obj/item/gun/energy/plasmacutter))
sawoff(user)
+ else
+ return ..()
/obj/item/gun/projectile/revolver/doublebarrel/attack_self(mob/living/user)
var/num_unloaded = 0
@@ -394,7 +396,6 @@
var/slung = 0
/obj/item/gun/projectile/revolver/doublebarrel/improvised/attackby(obj/item/A, mob/user, params)
- ..()
if(istype(A, /obj/item/stack/cable_coil) && !sawn_state)
var/obj/item/stack/cable_coil/C = A
if(C.use(10))
@@ -406,6 +407,8 @@
else
to_chat(user, "You need at least ten lengths of cable if you want to make a sling.")
return
+ else
+ return ..()
/obj/item/gun/projectile/revolver/doublebarrel/improvised/update_icon()
..()
@@ -450,9 +453,10 @@
return
/obj/item/gun/projectile/revolver/doublebarrel/improvised/cane/attackby(obj/item/A, mob/user, params)
- ..()
if(istype(A, /obj/item/stack/cable_coil))
return
+ else
+ return ..()
/obj/item/gun/projectile/revolver/doublebarrel/improvised/cane/examine(mob/user) // HAD TO REPEAT EXAMINE CODE BECAUSE GUN CODE DOESNT STEALTH
var/f_name = "\a [src]."
diff --git a/code/modules/projectiles/guns/projectile/saw.dm b/code/modules/projectiles/guns/projectile/saw.dm
index 59bb2595714..b9bdb0c9701 100644
--- a/code/modules/projectiles/guns/projectile/saw.dm
+++ b/code/modules/projectiles/guns/projectile/saw.dm
@@ -50,14 +50,15 @@
to_chat(user, "You remove the magazine from [src].")
-/obj/item/gun/projectile/automatic/l6_saw/attackby(obj/item/A, mob/user, params)
+/obj/item/gun/projectile/automatic/l6_saw/attackby(obj/item/A, mob/user, params)
if(istype(A, /obj/item/ammo_box/magazine))
var/obj/item/ammo_box/magazine/AM = A
if(istype(AM, mag_type))
if(!cover_open)
to_chat(user, "[src]'s cover is closed! You can't insert a new mag.")
return
- ..()
+ else
+ return ..()
//ammo//
diff --git a/code/modules/projectiles/guns/projectile/shotgun.dm b/code/modules/projectiles/guns/projectile/shotgun.dm
index 366b9b6579f..46286bef2af 100644
--- a/code/modules/projectiles/guns/projectile/shotgun.dm
+++ b/code/modules/projectiles/guns/projectile/shotgun.dm
@@ -86,7 +86,6 @@
sawn_state = SAWN_INTACT
/obj/item/gun/projectile/shotgun/riot/attackby(obj/item/A, mob/user, params)
- ..()
if(istype(A, /obj/item/circular_saw) || istype(A, /obj/item/gun/energy/plasmacutter))
sawoff(user)
if(istype(A, /obj/item/melee/energy))
@@ -95,6 +94,8 @@
sawoff(user)
if(istype(A, /obj/item/pipe))
unsaw(A, user)
+ else
+ return ..()
/obj/item/gun/projectile/shotgun/riot/sawoff(mob/user)
if(sawn_state == SAWN_OFF)
@@ -210,6 +211,9 @@
mag_type = /obj/item/ammo_box/magazine/internal/boltaction
fire_sound = 'sound/weapons/gunshots/gunshot_rifle.ogg'
var/bolt_open = 0
+ can_bayonet = TRUE
+ knife_x_offset = 27
+ knife_y_offset = 13
/obj/item/gun/projectile/shotgun/boltaction/pump(mob/M)
playsound(M, 'sound/weapons/gun_interactions/rifle_load.ogg', 60, 1)
@@ -242,6 +246,7 @@
desc = "Careful not to lose your head."
var/guns_left = 30
mag_type = /obj/item/ammo_box/magazine/internal/boltaction/enchanted
+ can_bayonet = FALSE
/obj/item/gun/projectile/shotgun/boltaction/enchanted/New()
..()
diff --git a/code/modules/projectiles/guns/rocket.dm b/code/modules/projectiles/guns/rocket.dm
index fa6dce3f448..983c6f319fd 100644
--- a/code/modules/projectiles/guns/rocket.dm
+++ b/code/modules/projectiles/guns/rocket.dm
@@ -37,6 +37,8 @@
to_chat(user, "[rockets.len] / [max_rockets] rockets.")
else
to_chat(usr, "[src] cannot hold more rockets.")
+ else
+ return ..()
/obj/item/gun/rocketlauncher/can_shoot()
return rockets.len
diff --git a/code/modules/projectiles/guns/syringe_gun.dm b/code/modules/projectiles/guns/syringe_gun.dm
index 21d44fa8634..ca18cdcd82e 100644
--- a/code/modules/projectiles/guns/syringe_gun.dm
+++ b/code/modules/projectiles/guns/syringe_gun.dm
@@ -76,7 +76,8 @@
return 1
else
to_chat(user, "[src] cannot hold more syringes.")
- return 0
+ else
+ return ..()
/obj/item/gun/syringe/rapidsyringe
name = "rapid syringe gun"
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index a8d368d6aef..881635d0e21 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -30,9 +30,9 @@
var/spread = 0 //amount (in degrees) of projectile spread
var/legacy = FALSE //legacy projectile system
animate_movement = 0
-
+
var/ignore_source_check = FALSE
-
+
var/damage = 10
var/tile_dropoff = 0 //how much damage should be decremented as the bullet moves
var/tile_dropoff_s = 0 //same as above but for stamina
@@ -56,6 +56,7 @@
var/jitter = 0
var/forcedodge = 0 //to pass through everything
var/dismemberment = 0 //The higher the number, the greater the bonus to dismembering. 0 will not dismember at all.
+ var/impact_effect_type //what type of impact effect to show when hitting something
var/ricochets = 0
var/ricochets_max = 2
var/ricochet_chance = 0
@@ -80,11 +81,31 @@
/obj/item/projectile/proc/on_range() //if we want there to be effects when they reach the end of their range
qdel(src)
+/obj/item/projectile/proc/prehit(atom/target)
+ return TRUE
+
/obj/item/projectile/proc/on_hit(atom/target, blocked = 0, hit_zone)
var/turf/target_loca = get_turf(target)
+ var/hitx
+ var/hity
+ if(target == original)
+ hitx = target.pixel_x + p_x - 16
+ hity = target.pixel_y + p_y - 16
+ else
+ hitx = target.pixel_x + rand(-8, 8)
+ hity = target.pixel_y + rand(-8, 8)
+ if(!nodamage && (damage_type == BRUTE || damage_type == BURN) && iswallturf(target_loca) && prob(75))
+ var/turf/simulated/wall/W = target_loca
+ if(impact_effect_type)
+ new impact_effect_type(target_loca, hitx, hity)
+
+ W.add_dent(WALL_DENT_SHOT, hitx, hity)
+ return 0
if(alwayslog)
add_attack_logs(firer, target, "Shot with a [type]")
if(!isliving(target))
+ if(impact_effect_type)
+ new impact_effect_type(target_loca, hitx, hity)
return 0
var/mob/living/L = target
var/mob/living/carbon/human/H
@@ -115,7 +136,8 @@
M.bloody_hands(H)
/* Uncomment when bloody_body stops randomly not transferring blood colour.
M.bloody_body(H) */
-
+ else if(impact_effect_type)
+ new impact_effect_type(target_loca, hitx, hity)
var/organ_hit_text = ""
if(L.has_limbs)
organ_hit_text = " in \the [parse_zone(def_zone)]"
@@ -162,7 +184,7 @@
/obj/item/projectile/Bump(atom/A, yes)
if(!yes) //prevents double bumps.
return
-
+
if(check_ricochet(A) && check_ricochet_flag(A) && ricochets < ricochets_max)
ricochets++
if(A.handle_ricochet(src))
@@ -190,7 +212,7 @@
return
var/turf/target_turf = get_turf(A)
-
+ prehit(A)
var/permutation = A.bullet_act(src, def_zone) // searches for return value, could be deleted after run so check A isn't null
if(permutation == -1 || forcedodge)// the bullet passes through a dense object!
loc = target_turf
@@ -204,6 +226,7 @@
mobs_list += L
if(mobs_list.len)
var/mob/living/picked_mob = pick(mobs_list)
+ prehit(picked_mob)
picked_mob.bullet_act(src, def_zone)
qdel(src)
@@ -293,7 +316,7 @@ obj/item/projectile/Crossed(atom/movable/AM, oldloc) //A mob moving on a tile wi
/obj/item/projectile/proc/dumbfire(var/dir)
current = get_ranged_target_turf(src, dir, world.maxx) //world.maxx is the range. Not sure how to handle this better.
fire()
-
+
/obj/item/projectile/proc/on_ricochet(atom/A)
return
@@ -307,7 +330,7 @@ obj/item/projectile/Crossed(atom/movable/AM, oldloc) //A mob moving on a tile wi
if(A.flags_2 & CHECK_RICOCHET_1)
return TRUE
return FALSE
-
+
/obj/item/projectile/proc/setAngle(new_angle) //wrapper for overrides.
Angle = new_angle
return TRUE
diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm
index b34364c4c93..bad6b6db68b 100644
--- a/code/modules/projectiles/projectile/beams.dm
+++ b/code/modules/projectiles/projectile/beams.dm
@@ -8,6 +8,7 @@
hitsound_wall = 'sound/weapons/effects/searwall.ogg'
flag = "laser"
eyeblur = 2
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/red_laser
is_reflectable = TRUE
light_range = 2
light_color = LIGHT_COLOR_RED
@@ -38,6 +39,7 @@
irradiate = 30
forcedodge = 1
range = 15
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/green_laser
light_color = LIGHT_COLOR_GREEN
/obj/item/projectile/beam/disabler
@@ -48,12 +50,14 @@
flag = "energy"
hitsound = 'sound/weapons/tap.ogg'
eyeblur = 0
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser
light_color = LIGHT_COLOR_CYAN
/obj/item/projectile/beam/pulse
name = "pulse"
icon_state = "u_laser"
damage = 50
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser
light_color = LIGHT_COLOR_DARKBLUE
/obj/item/projectile/beam/pulse/on_hit(var/atom/target, var/blocked = 0)
@@ -70,6 +74,7 @@
damage = 30
legacy = 1
animate_movement = SLIDE_STEPS
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/green_laser
light_color = LIGHT_COLOR_GREEN
/obj/item/projectile/beam/emitter/singularity_pull()
@@ -84,6 +89,7 @@
flag = "laser"
var/suit_types = list(/obj/item/clothing/suit/redtag, /obj/item/clothing/suit/bluetag)
log_override = TRUE
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser
light_color = LIGHT_COLOR_DARKBLUE
/obj/item/projectile/beam/lasertag/on_hit(atom/target, blocked = 0)
@@ -102,6 +108,7 @@
/obj/item/projectile/beam/lasertag/redtag
icon_state = "laser"
suit_types = list(/obj/item/clothing/suit/bluetag)
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/red_laser
light_color = LIGHT_COLOR_RED
/obj/item/projectile/beam/lasertag/bluetag
@@ -115,6 +122,7 @@
stun = 5
weaken = 5
stutter = 5
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/purple_laser
light_color = LIGHT_COLOR_PINK
/obj/item/projectile/beam/immolator
@@ -142,14 +150,17 @@
icon_state = "purple_laser"
damage = 200
damage_type = BURN
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/purple_laser
light_color = LIGHT_COLOR_PURPLE
/obj/item/projectile/beam/instakill/blue
icon_state = "blue_laser"
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser
light_color = LIGHT_COLOR_DARKBLUE
/obj/item/projectile/beam/instakill/red
icon_state = "red_laser"
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/red_laser
light_color = LIGHT_COLOR_RED
/obj/item/projectile/beam/instakill/on_hit(atom/target)
diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm
index 1cde9ef5017..a973ce1dd87 100644
--- a/code/modules/projectiles/projectile/bullets.dm
+++ b/code/modules/projectiles/projectile/bullets.dm
@@ -5,6 +5,7 @@
damage_type = BRUTE
flag = "bullet"
hitsound_wall = "ricochet"
+ impact_effect_type = /obj/effect/temp_visual/impact_effect
/obj/item/projectile/bullet/weakbullet //beanbag, heavy stamina damage
name = "beanbag slug"
diff --git a/code/modules/projectiles/projectile/energy.dm b/code/modules/projectiles/projectile/energy.dm
index 5da56d179bd..e1ca470c95a 100644
--- a/code/modules/projectiles/projectile/energy.dm
+++ b/code/modules/projectiles/projectile/energy.dm
@@ -41,6 +41,7 @@
damage = 20
damage_type = CLONE
irradiate = 10
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/green_laser
/obj/item/projectile/energy/dart
name = "dart"
@@ -73,6 +74,7 @@
/obj/item/projectile/energy/shock_revolver
name = "shock bolt"
icon_state = "purple_laser"
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/purple_laser
var/chain
/obj/item/ammo_casing/energy/shock_revolver/ready_proj(atom/target, mob/living/user, quiet, zone_override = "")
diff --git a/code/modules/projectiles/projectile/reusable.dm b/code/modules/projectiles/projectile/reusable.dm
index 1c23605f2b3..bd249037946 100644
--- a/code/modules/projectiles/projectile/reusable.dm
+++ b/code/modules/projectiles/projectile/reusable.dm
@@ -3,6 +3,7 @@
desc = "How do you even reuse a bullet?"
var/ammo_type = /obj/item/ammo_casing/caseless/
var/dropped = 0
+ impact_effect_type = null
/obj/item/projectile/bullet/reusable/on_hit(atom/target, blocked = 0)
. = ..()
diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm
index d313195a40e..de11cb557a9 100644
--- a/code/modules/projectiles/projectile/special.dm
+++ b/code/modules/projectiles/projectile/special.dm
@@ -5,6 +5,7 @@
alwayslog = TRUE
damage_type = BURN
nodamage = 1
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/ion
flag = "energy"
/obj/item/projectile/ion/on_hit(var/atom/target, var/blocked = 0)
@@ -129,6 +130,7 @@
damage = 0
damage_type = TOX
nodamage = 1
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/green_laser
flag = "energy"
/obj/item/projectile/energy/floramut/on_hit(var/atom/target, var/blocked = 0)
@@ -244,18 +246,7 @@
damage = 5
range = 3
dismemberment = 20
-
-/obj/item/projectile/plasma/New()
- var/turf/proj_turf = get_turf(src)
- if(!istype(proj_turf, /turf))
- return
- var/datum/gas_mixture/environment = proj_turf.return_air()
- if(environment)
- var/pressure = environment.return_pressure()
- if(pressure < 30)
- name = "full strength plasma blast"
- damage *= 3
- ..()
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/purple_laser
/obj/item/projectile/plasma/on_hit(atom/target)
. = ..()
@@ -267,7 +258,8 @@
forcedodge = 0
/obj/item/projectile/plasma/adv
- range = 6
+ damage = 7
+ range = 5
/obj/item/projectile/plasma/adv/mech
damage = 10
diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm
index 36605867781..48b76b0de98 100644
--- a/code/modules/reagents/chemistry/machinery/chem_master.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_master.dm
@@ -133,6 +133,39 @@
if(loaded_pill_bottle)
loaded_pill_bottle.forceMove(loc)
loaded_pill_bottle = null
+ else if(href_list["change_pillbottle"])
+ if(loaded_pill_bottle)
+ var/list/wrappers = list("Default wrapper", "Red wrapper", "Green wrapper", "Pale green wrapper", "Blue wrapper", "Light blue wrapper", "Teal wrapper", "Yellow wrapper", "Orange wrapper", "Pink wrapper", "Brown wrapper")
+ var/chosen = input(usr, "Select a pillbottle wrapper", "Pillbottle wrapper", wrappers[1]) as null|anything in wrappers
+ if(!chosen)
+ return
+ var/color
+ switch(chosen)
+ if("Default wrapper")
+ loaded_pill_bottle.cut_overlays()
+ return
+ if("Red wrapper")
+ color = COLOR_RED
+ if("Green wrapper")
+ color = COLOR_GREEN
+ if("Pink wrapper")
+ color = COLOR_PINK
+ if("Teal wrapper")
+ color = COLOR_TEAL
+ if("Blue wrapper")
+ color = COLOR_BLUE
+ if("Brown wrapper")
+ color = COLOR_MAROON
+ if("Light blue wrapper")
+ color = COLOR_CYAN_BLUE
+ if("Yellow wrapper")
+ color = COLOR_YELLOW
+ if("Pale green wrapper")
+ color = COLOR_PALE_BTL_GREEN
+ if("Orange wrapper")
+ color = COLOR_ORANGE
+ loaded_pill_bottle.wrapper_color = color;
+ loaded_pill_bottle.apply_wrap();
else if(href_list["close"])
usr << browse(null, "window=chem_master")
onclose(usr, "chem_master")
@@ -185,7 +218,7 @@
dat += "(Back)"
else
dat += "Condimaster 3000Condiment infos:
Name:
[href_list["name"]]
Description:
[href_list["desc"]]
(Back)"
- usr << browse(dat, "window=chem_master;size=575x400")
+ usr << browse(dat, "window=chem_master;size=575x500")
return
else if(href_list["add"])
@@ -388,7 +421,7 @@
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
- ui = new(user, src, ui_key, "chem_master.tmpl", name, 575, 400)
+ ui = new(user, src, ui_key, "chem_master.tmpl", name, 575, 500)
ui.open()
/obj/machinery/chem_master/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state)
diff --git a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm
index 9ea55dd5af7..1e3bcb92db5 100644
--- a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm
+++ b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm
@@ -9,8 +9,9 @@
active_power_usage = 100
pass_flags = PASSTABLE
var/operating = 0
- var/obj/item/reagent_containers/beaker = null
- var/limit = 10
+ var/obj/item/reagent_containers/beaker = new /obj/item/reagent_containers/glass/beaker/large
+ var/limit = null
+ var/efficiency = null
//IMPORTANT NOTE! A negative number is a multiplier, a positive number is a flat amount to add. 0 means equal to the amount of the original reagent
var/list/blend_items = list (
@@ -88,10 +89,28 @@
var/list/holdingitems = list()
+/obj/machinery/reagentgrinder/empty
+ icon_state = "juicer0"
+ beaker = null
+
/obj/machinery/reagentgrinder/New()
..()
- beaker = new /obj/item/reagent_containers/glass/beaker/large(src)
- return
+ component_parts = list()
+ component_parts += new /obj/item/circuitboard/reagentgrinder(null)
+ component_parts += new /obj/item/stock_parts/manipulator(null)
+ component_parts += new /obj/item/stock_parts/manipulator(null)
+ component_parts += new /obj/item/stock_parts/matter_bin(null)
+ RefreshParts()
+
+/obj/machinery/reagentgrinder/RefreshParts()
+ var/H
+ var/T
+ for(var/obj/item/stock_parts/matter_bin/M in component_parts)
+ H += M.rating
+ for(var/obj/item/stock_parts/manipulator/M in component_parts)
+ T += M.rating
+ limit = 10*H
+ efficiency = 0.8+T*0.1
/obj/machinery/reagentgrinder/Destroy()
QDEL_NULL(beaker)
@@ -112,16 +131,29 @@
if(default_unfasten_wrench(user, I))
return
+ if(exchange_parts(user, I))
+ return
+
+ if(anchored && !beaker)
+ if(default_deconstruction_screwdriver(user, "juicer_open", "juicer0", I))
+ return
+
+ if(panel_open && istype(I, /obj/item/crowbar))
+ default_deconstruction_crowbar(I)
+ return
+
if (istype(I, /obj/item/reagent_containers) && (I.container_type & OPENCONTAINER) )
- if (!beaker)
+ if(beaker)
+ to_chat(user, "There's already a container inside.")
+ else if(panel_open)
+ to_chat(user, "Close the maintenance panel first.")
+ else
if(!user.drop_item())
return 1
beaker = I
beaker.loc = src
update_icon()
src.updateUsrDialog()
- else
- to_chat(user, "There's already a container inside.")
return 1 //no afterattack
if(is_type_in_list(I, dried_items))
@@ -331,7 +363,7 @@
var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume
var/amount = get_juice_amount(O)
- beaker.reagents.add_reagent(r_id, min(amount, space))
+ beaker.reagents.add_reagent(r_id, min(amount*efficiency, space))
if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
break
@@ -371,17 +403,17 @@
if(amount <= 0)
if(amount == 0)
if (O.reagents != null && O.reagents.has_reagent("nutriment"))
- beaker.reagents.add_reagent(r_id, min(O.reagents.get_reagent_amount("nutriment"), space))
+ beaker.reagents.add_reagent(r_id, min(O.reagents.get_reagent_amount("nutriment")*efficiency, space))
O.reagents.remove_reagent("nutriment", min(O.reagents.get_reagent_amount("nutriment"), space))
if (O.reagents != null && O.reagents.has_reagent("plantmatter"))
- beaker.reagents.add_reagent(r_id, min(O.reagents.get_reagent_amount("plantmatter"), space))
+ beaker.reagents.add_reagent(r_id, min(O.reagents.get_reagent_amount("plantmatter")*efficiency, space))
O.reagents.remove_reagent("plantmatter", min(O.reagents.get_reagent_amount("plantmatter"), space))
else
if (O.reagents != null && O.reagents.has_reagent("nutriment"))
- beaker.reagents.add_reagent(r_id, min(round(O.reagents.get_reagent_amount("nutriment")*abs(amount)), space))
+ beaker.reagents.add_reagent(r_id, min(round(O.reagents.get_reagent_amount("nutriment")*abs(amount)*efficiency), space))
O.reagents.remove_reagent("nutriment", min(O.reagents.get_reagent_amount("nutriment"), space))
if (O.reagents != null && O.reagents.has_reagent("plantmatter"))
- beaker.reagents.add_reagent(r_id, min(round(O.reagents.get_reagent_amount("plantmatter")*abs(amount)), space))
+ beaker.reagents.add_reagent(r_id, min(round(O.reagents.get_reagent_amount("plantmatter")*abs(amount)*efficiency), space))
O.reagents.remove_reagent("plantmatter", min(O.reagents.get_reagent_amount("plantmatter"), space))
@@ -403,7 +435,7 @@
for (var/r_id in allowed)
var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume
var/amount = allowed[r_id]
- beaker.reagents.add_reagent(r_id,min(amount, space))
+ beaker.reagents.add_reagent(r_id,min(amount*efficiency, space))
if (space < amount)
break
if (i == round(O.amount, 1))
@@ -419,9 +451,9 @@
var/amount = allowed[r_id]
if (amount == 0)
if (O.reagents != null && O.reagents.has_reagent(r_id))
- beaker.reagents.add_reagent(r_id,min(O.reagents.get_reagent_amount(r_id), space))
+ beaker.reagents.add_reagent(r_id,min(O.reagents.get_reagent_amount(r_id)*efficiency, space))
else
- beaker.reagents.add_reagent(r_id,min(amount, space))
+ beaker.reagents.add_reagent(r_id,min(amount*efficiency, space))
if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
break
@@ -436,7 +468,7 @@
var/amount = O.reagents.total_volume
O.reagents.trans_to(beaker, min(amount, space))
if (O.Uses > 0)
- beaker.reagents.add_reagent("slimejelly",min(20, space))
+ beaker.reagents.add_reagent("slimejelly",min(20*efficiency, space))
remove_object(O)
//Everything else - Transfers reagents from it into beaker
diff --git a/code/modules/reagents/chemistry/reagents/medicine.dm b/code/modules/reagents/chemistry/reagents/medicine.dm
index 77118450aaa..59d15cf50bd 100644
--- a/code/modules/reagents/chemistry/reagents/medicine.dm
+++ b/code/modules/reagents/chemistry/reagents/medicine.dm
@@ -1149,24 +1149,19 @@
id = "lavaland_extract"
description = "An extract of lavaland atmospheric and mineral elements. Heals the user in small doses, but is extremely toxic otherwise."
color = "#C8A5DC" // rgb: 200, 165, 220
- metabolization_rate = 0.7 //VERY strong chemical
overdose_threshold = 3 //To prevent people stacking massive amounts of a very strong healing reagent
can_synth = FALSE
/datum/reagent/medicine/lavaland_extract/on_mob_life(mob/living/carbon/M)
var/update_flags = STATUS_UPDATE_NONE
- update_flags |= M.adjustToxLoss(-3*REAGENTS_EFFECT_MULTIPLIER, FALSE)
- update_flags |= M.adjustOxyLoss(-3*REAGENTS_EFFECT_MULTIPLIER, FALSE)
- update_flags |= M.adjustBruteLoss(-6*REAGENTS_EFFECT_MULTIPLIER, FALSE)
- update_flags |= M.adjustFireLoss(-6*REAGENTS_EFFECT_MULTIPLIER, FALSE)
+ update_flags |= M.adjustBruteLoss(-5*REAGENTS_EFFECT_MULTIPLIER, FALSE)
+ update_flags |= M.adjustFireLoss(-5*REAGENTS_EFFECT_MULTIPLIER, FALSE)
return ..() | update_flags
/datum/reagent/medicine/lavaland_extract/overdose_process(mob/living/M) // This WILL be brutal
var/update_flags = STATUS_UPDATE_NONE
M.AdjustConfused(5)
- update_flags |= M.adjustBruteLoss(10*REAGENTS_EFFECT_MULTIPLIER, FALSE)
- update_flags |= M.adjustFireLoss(10*REAGENTS_EFFECT_MULTIPLIER, FALSE)
- update_flags |= M.adjustToxLoss(10*REAGENTS_EFFECT_MULTIPLIER, FALSE)
- update_flags |= M.Stun(7, FALSE)
- update_flags |= M.Weaken(7, FALSE)
+ update_flags |= M.adjustBruteLoss(3*REAGENTS_EFFECT_MULTIPLIER, FALSE)
+ update_flags |= M.adjustFireLoss(3*REAGENTS_EFFECT_MULTIPLIER, FALSE)
+ update_flags |= M.adjustToxLoss(3*REAGENTS_EFFECT_MULTIPLIER, FALSE)
return ..() | update_flags
diff --git a/code/modules/reagents/reagent_containers/glass_containers.dm b/code/modules/reagents/reagent_containers/glass_containers.dm
index d408db7f2f0..5221ae5e600 100644
--- a/code/modules/reagents/reagent_containers/glass_containers.dm
+++ b/code/modules/reagents/reagent_containers/glass_containers.dm
@@ -81,7 +81,7 @@
reagents.reaction(M, TOUCH)
reagents.clear_reagents()
- else
+ else
if(M != user)
M.visible_message("[user] attempts to feed something to [M].", \
"[user] attempts to feed something to you.")
@@ -348,6 +348,13 @@
slot_flags = SLOT_HEAD
container_type = OPENCONTAINER
+/obj/item/reagent_containers/glass/bucket/wooden
+ name = "wooden bucket"
+ icon_state = "woodbucket"
+ item_state = "woodbucket"
+ materials = null
+ burn_state = FLAMMABLE
+
/obj/item/reagent_containers/glass/bucket/equipped(mob/user, slot)
..()
if(slot == slot_head && reagents.total_volume)
diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm
index dace5928b2e..3abfbfd0e19 100644
--- a/code/modules/reagents/reagent_containers/hypospray.dm
+++ b/code/modules/reagents/reagent_containers/hypospray.dm
@@ -155,9 +155,9 @@
name = "survival medipen"
desc = "A medipen for surviving in the harshest of environments, heals and protects from environmental hazards.
WARNING: Do not inject more than one pen in quick succession."
icon_state = "stimpen"
- volume = 22
- amount_per_transfer_from_this = 22
- list_reagents = list("salbutamol" = 10, "epinephrine" = 5, "lavaland_extract" = 2, "salglu_solution" = 5) //Short burst of healing, followed by minor healing from the saline
+ volume = 42
+ amount_per_transfer_from_this = 42
+ list_reagents = list("salbutamol" = 10, "teporone" = 15, "epinephrine" = 10, "lavaland_extract" = 2, "weak_omnizine" = 5) //Short burst of healing, followed by minor healing from the saline
/obj/item/reagent_containers/hypospray/autoinjector/nanocalcium
name = "nanocalcium autoinjector"
diff --git a/code/modules/research/designs/machine_designs.dm b/code/modules/research/designs/machine_designs.dm
index c604105dc04..f50b3527aa2 100644
--- a/code/modules/research/designs/machine_designs.dm
+++ b/code/modules/research/designs/machine_designs.dm
@@ -182,6 +182,16 @@
build_path = /obj/item/circuitboard/chem_heater
category = list ("Medical Machinery")
+/datum/design/reagentgrinder
+ name = "Machine Design (All-In-One Grinder)"
+ desc = "The circuit board for an All-In-One Grinder."
+ id = "reagentgrinder"
+ req_tech = list("biotech" = 2, "materials" = 2, "programming" = 2)
+ build_type = IMPRINTER
+ materials = list(MAT_GLASS = 1000)
+ build_path = /obj/item/circuitboard/reagentgrinder
+ category = list ("Medical Machinery")
+
/datum/design/sleeper
name = "Machine Board (Sleeper)"
desc = "Allows for the construction of circuit boards used to build a Sleeper."
diff --git a/code/modules/research/designs/mining_designs.dm b/code/modules/research/designs/mining_designs.dm
index 14cd12c6837..76439c64987 100644
--- a/code/modules/research/designs/mining_designs.dm
+++ b/code/modules/research/designs/mining_designs.dm
@@ -1,16 +1,6 @@
/////////////////////////////////////////
/////////////////Mining//////////////////
/////////////////////////////////////////
-/datum/design/drill_diamond
- name = "Diamond Mining Drill"
- desc = "Yours is the drill that will pierce the heavens!"
- id = "drill_diamond"
- req_tech = list("materials" = 6, "powerstorage" = 5, "engineering" = 5)
- build_type = PROTOLATHE
- materials = list(MAT_METAL = 3000, MAT_GLASS = 1000, MAT_DIAMOND = 2000) //Yes, a whole diamond is needed.
- build_path = /obj/item/pickaxe/drill/diamonddrill
- category = list("Mining")
-
/datum/design/drill
name = "Mining Drill"
desc = "Yours is the drill that will pierce through the rock walls."
@@ -21,13 +11,23 @@
build_path = /obj/item/pickaxe/drill
category = list("Mining")
+/datum/design/drill_diamond
+ name = "Diamond Mining Drill"
+ desc = "Yours is the drill that will pierce the heavens!"
+ id = "drill_diamond"
+ req_tech = list("materials" = 6, "powerstorage" = 5, "engineering" = 5)
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 3000, MAT_GLASS = 1000, MAT_DIAMOND = 2000) //Yes, a whole diamond is needed.
+ build_path = /obj/item/pickaxe/drill/diamonddrill
+ category = list("Mining")
+
/datum/design/plasmacutter
name = "Plasma Cutter"
desc = "You could use it to cut limbs off of xenos! Or, you know, mine stuff."
id = "plasmacutter"
req_tech = list("materials" = 3, "plasmatech" = 3, "magnets" = 2)
build_type = PROTOLATHE
- materials = list(MAT_METAL = 2000, MAT_GLASS = 1000, MAT_PLASMA = 1500)
+ materials = list(MAT_METAL = 1500, MAT_GLASS = 500, MAT_PLASMA = 400)
build_path = /obj/item/gun/energy/plasmacutter
category = list("Mining")
@@ -37,7 +37,7 @@
id = "plasmacutter_adv"
req_tech = list("materials" = 4, "plasmatech" = 4, "engineering" = 2, "combat" = 3, "magnets" = 3)
build_type = PROTOLATHE
- materials = list(MAT_METAL = 4000, MAT_GLASS = 1000, MAT_PLASMA = 4000, MAT_GOLD = 500)
+ materials = list(MAT_METAL = 3000, MAT_GLASS = 1000, MAT_PLASMA = 2000, MAT_GOLD = 500)
build_path = /obj/item/gun/energy/plasmacutter/adv
category = list("Mining")
@@ -101,16 +101,6 @@
build_path = /obj/item/borg/upgrade/modkit/range
category = list("Mining", "Cyborg Upgrade Modules")
-/datum/design/superaccelerator
- name = "Kinetic Accelerator Pressure Mod"
- desc = "A modification kit which allows Kinetic Accelerators to do more damage while indoors."
- id = "indoormod"
- req_tech = list("materials" = 5, "powerstorage" = 4, "engineering" = 4, "magnets" = 4, "combat" = 3)
- build_type = PROTOLATHE | MECHFAB
- materials = list(MAT_METAL = 2000, MAT_GLASS = 1500, MAT_SILVER = 2000, MAT_URANIUM = 2000)
- build_path = /obj/item/borg/upgrade/modkit/indoors
- category = list("Mining", "Cyborg Upgrade Modules")
-
/datum/design/hyperaccelerator
name = "Kinetic Accelerator Mining AoE Mod"
desc = "A modification kit for Kinetic Accelerators which causes it to fire AoE blasts that destroy rock."
@@ -119,4 +109,4 @@
build_type = PROTOLATHE | MECHFAB
materials = list(MAT_METAL = 8000, MAT_GLASS = 1500, MAT_SILVER = 2000, MAT_GOLD = 2000, MAT_DIAMOND = 2000)
build_path = /obj/item/borg/upgrade/modkit/aoe/turfs
- category = list("Mining", "Cyborg Upgrade Modules")
+ category = list("Mining", "Cyborg Upgrade Modules")
\ No newline at end of file
diff --git a/code/modules/research/designs/spacepod_designs.dm b/code/modules/research/designs/spacepod_designs.dm
index 44bef918678..9930426df86 100644
--- a/code/modules/research/designs/spacepod_designs.dm
+++ b/code/modules/research/designs/spacepod_designs.dm
@@ -149,17 +149,6 @@
build_path = /obj/item/spacepod_equipment/weaponry/mining_laser
category = list("Pod_Weaponry")
-/datum/design/pod_mining_laser_hyper
- construction_time = 200
- name = "Enhanced Mining Laser"
- desc = "Allows for the construction of an enhanced mining laser."
- id = "pod_mining_laser_hyper"
- req_tech = list("materials" = 7, "powerstorage" = 6, "engineering" = 5, "magnets" = 6, "combat" = 4)
- build_type = PODFAB
- materials = list(MAT_METAL = 10000, MAT_GLASS = 5000, MAT_SILVER = 4000, MAT_GOLD = 4000, MAT_DIAMOND = 4000)
- build_path = /obj/item/spacepod_equipment/weaponry/mining_laser_hyper
- category = list("Pod_Weaponry")
-
//////////////////////////////////////////
//////SPACEPOD MISC. ITEMS////////////////
//////////////////////////////////////////
diff --git a/code/modules/research/research.dm b/code/modules/research/research.dm
index 4d1195e29ce..05786daed94 100644
--- a/code/modules/research/research.dm
+++ b/code/modules/research/research.dm
@@ -372,8 +372,9 @@ datum/tech/robotics
var/default_desc = "A disk for storing device design data for construction in lathes."
/obj/item/disk/design_disk/New()
- src.pixel_x = rand(-5.0, 5)
- src.pixel_y = rand(-5.0, 5)
+ ..()
+ pixel_x = rand(-5, 5)
+ pixel_y = rand(-5, 5)
/obj/item/disk/design_disk/proc/load_blueprint(datum/design/D)
name = "[default_name] \[[D]\]"
diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm
index 0587f6e4f73..81ca4bfeb9b 100644
--- a/code/modules/research/xenobiology/xenobiology.dm
+++ b/code/modules/research/xenobiology/xenobiology.dm
@@ -211,12 +211,16 @@
if(SM.flags_2 & HOLOGRAM_2) //Check to see if it's a holodeck creature
to_chat(SM, "You also become depressingly aware that you are not a real creature, but instead a holoform. Your existence is limited to the parameters of the holodeck.")
to_chat(user, "[M] accepts the potion and suddenly becomes attentive and aware. It worked!")
+ after_success(user, SM)
qdel(src)
else
to_chat(user, "[M] looks interested for a moment, but then looks back down. Maybe you should try again later.")
being_used = 0
..()
+/obj/item/slimepotion/sentience/proc/after_success(mob/living/user, mob/living/simple_animal/SM)
+ return
+
/obj/item/slimepotion/transference
name = "consciousness transference potion"
desc = "A strange slime-based chemical that, when used, allows the user to transfer their consciousness to a lesser being."
diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm
index 67765ef8ac5..42e710d0cf6 100644
--- a/code/modules/shuttle/on_move.dm
+++ b/code/modules/shuttle/on_move.dm
@@ -30,17 +30,21 @@
if(id_tag == "s_docking_airlock")
INVOKE_ASYNC(src, .proc/lock)
-/mob/onShuttleMove()
+/mob/onShuttleMove(turf/oldT, turf/T1, rotation)
if(!move_on_shuttle)
return 0
. = ..()
if(!.)
return
- if(client)
- if(buckled)
- shake_camera(src, 2, 1) // turn it down a bit come on
- else
- shake_camera(src, 7, 1)
+ if(!client)
+ return
+
+ if(buckled)
+ shake_camera(src, 2, 1) // turn it down a bit come on
+ else
+ shake_camera(src, 7, 1)
+
+ update_parallax_contents()
/mob/living/carbon/onShuttleMove()
. = ..()
@@ -54,8 +58,10 @@
if(smooth)
queue_smooth(src)
+/mob/postDock()
+ update_parallax_contents()
+
/obj/machinery/door/airlock/postDock(obj/docking_port/stationary/S1)
. = ..()
if(!S1.lock_shuttle_doors && id_tag == "s_docking_airlock")
INVOKE_ASYNC(src, .proc/unlock)
-
diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm
index 51ba6c6bad1..2d68c3db292 100644
--- a/code/modules/shuttle/shuttle.dm
+++ b/code/modules/shuttle/shuttle.dm
@@ -189,7 +189,7 @@
/obj/docking_port/stationary/transit
name = "In transit"
turf_type = /turf/space/transit
-
+ var/area/shuttle/transit/assigned_area
lock_shuttle_doors = 1
/obj/docking_port/stationary/transit/register()
@@ -358,7 +358,7 @@
var/obj/docking_port/stationary/S0 = get_docked()
var/obj/docking_port/stationary/S1 = findTransitDock()
if(S1)
- if(dock(S1))
+ if(dock(S1, , TRUE))
WARNING("shuttle \"[id]\" could not enter transit space. Docked at [S0 ? S0.id : "null"]. Transit dock [S1 ? S1.id : "null"].")
else
previous = S0
@@ -429,7 +429,7 @@
//this is the main proc. It instantly moves our mobile port to stationary port S1
//it handles all the generic behaviour, such as sanity checks, closing doors on the shuttle, stunning mobs, etc
-/obj/docking_port/mobile/proc/dock(obj/docking_port/stationary/S1, force=FALSE)
+/obj/docking_port/mobile/proc/dock(obj/docking_port/stationary/S1, force=FALSE, transit=FALSE)
// Crashing this ship with NO SURVIVORS
if(S1.get_docked() == src)
remove_ripples()
@@ -492,6 +492,7 @@
var/turf/simulated/Ts1 = T1
Ts1.copy_air_with_tile(T0)
+ areaInstance.moving = TRUE
//move mobile to new location
for(var/atom/movable/AM in T0)
AM.onShuttleMove(T0, T1, rotation)
@@ -512,6 +513,7 @@
T0.CalculateAdjacentTurfs()
SSair.add_to_active(T0,1)
+ areaInstance.moving = transit
for(var/A1 in L1)
var/turf/T1 = A1
T1.postDock(S1)
diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm
index b6a7e7bb28f..9da43d08fbf 100644
--- a/code/modules/shuttle/supply.dm
+++ b/code/modules/shuttle/supply.dm
@@ -247,7 +247,8 @@
/obj/machinery/clonepod,
/obj/effect/hierophant,
/obj/item/warp_cube,
- /obj/machinery/quantumpad
+ /obj/machinery/quantumpad,
+ /obj/structure/extraction_point
)
if(A)
if(is_type_in_list(A, blacklist))
diff --git a/code/modules/spacepods/equipment.dm b/code/modules/spacepods/equipment.dm
index e64087d5561..d509b4f745c 100644
--- a/code/modules/spacepods/equipment.dm
+++ b/code/modules/spacepods/equipment.dm
@@ -131,16 +131,6 @@
fire_delay = 10
fire_sound = 'sound/weapons/kenetic_accel.ogg'
-/obj/item/spacepod_equipment/weaponry/mining_laser_hyper
- name = "enhanced mining laser system"
- desc = "An enhanced mining laser system for space pods, fires bursts of energy that cut through rock."
- icon = 'icons/goonstation/pods/ship.dmi'
- icon_state = "pod_w_laser"
- projectile_type = /obj/item/projectile/kinetic/pod/enhanced
- shot_cost = 200
- fire_delay = 8
- fire_sound = 'sound/weapons/kenetic_accel.ogg'
-
/*
///////////////////////////////////////
/////////Misc. System///////////////////
diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm
index 6dbc6f4febe..97c54c64e47 100644
--- a/code/modules/surgery/organs/organ_internal.dm
+++ b/code/modules/surgery/organs/organ_internal.dm
@@ -226,6 +226,8 @@
health = 3
var/organhonked = 0
var/suffering_delay = 900
+ var/datum/component/waddle
+ var/datum/component/squeak
/obj/item/organ/internal/honktumor/insert(mob/living/carbon/M, special = 0)
..()
@@ -236,6 +238,8 @@
genemutcheck(M,CLUMSYBLOCK,null,MUTCHK_FORCED)
genemutcheck(M,COMICBLOCK,null,MUTCHK_FORCED)
organhonked = world.time
+ waddle = M.AddComponent(/datum/component/waddling)
+ squeak = M.AddComponent(/datum/component/squeak, list('sound/items/bikehorn.ogg' = 1), 50)
/obj/item/organ/internal/honktumor/remove(mob/living/carbon/M, special = 0)
. = ..()
@@ -246,6 +250,8 @@
M.dna.SetSEState(COMICBLOCK,0)
genemutcheck(M,CLUMSYBLOCK,null,MUTCHK_FORCED)
genemutcheck(M,COMICBLOCK,null,MUTCHK_FORCED)
+ QDEL_NULL(waddle)
+ QDEL_NULL(squeak)
qdel(src)
/obj/item/organ/internal/honktumor/on_life()
@@ -282,6 +288,28 @@
owner.nutrition = 9000
owner.overeatduration = 9000
+
+/obj/item/organ/internal/honkbladder
+ name = "honk bladder"
+ desc = "a air filled sac that produces honking noises."
+ icon_state = "honktumor"//Not making a new icon
+ origin_tech = "biotech=1"
+ w_class = WEIGHT_CLASS_TINY
+ parent_organ = "groin"
+ slot = "honk_bladder"
+ health = 3
+ var/datum/component/squeak
+
+/obj/item/organ/internal/honkbladder/insert(mob/living/carbon/M, special = 0)
+
+ squeak = M.AddComponent(/datum/component/squeak, list('sound/effects/clownstep1.ogg'=1,'sound/effects/clownstep2.ogg'=1), 50)
+
+/obj/item/organ/internal/honkbladder/remove(mob/living/carbon/M, special = 0)
+ . = ..()
+
+ QDEL_NULL(squeak)
+ qdel(src)
+
/obj/item/organ/internal/beard
name = "beard organ"
desc = "Let they who is worthy wear the beard of Thorbjorndottir."
diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm
index 94f6be4cc9a..9d91682f057 100644
--- a/code/modules/surgery/organs/vocal_cords.dm
+++ b/code/modules/surgery/organs/vocal_cords.dm
@@ -125,6 +125,9 @@ var/static/regex/multispin_words = regex("like a record baby")
return
owner.say(".x[command]")
+/obj/item/organ/internal/vocal_cords/colossus/prepare_eat()
+ return
+
/obj/item/organ/internal/vocal_cords/colossus/can_speak_with()
if(world.time < next_command)
to_chat(owner, "You must wait [(next_command - world.time)/10] seconds before Speaking again.")
diff --git a/config/example/dbconfig.txt b/config/example/dbconfig.txt
index 2404119d52f..ad859d92543 100644
--- a/config/example/dbconfig.txt
+++ b/config/example/dbconfig.txt
@@ -9,7 +9,7 @@
## This value must be set to the version of the paradise schema in use.
## If this value does not match, the SQL database will not be loaded and an error will be generated.
## Roundstart will be delayed.
-DB_VERSION 8
+DB_VERSION 9
## Server the MySQL database can be found at.
# Examples: localhost, 200.135.5.43, www.mysqldb.com, etc.
diff --git a/html/browser/marked.js b/html/browser/marked.js
index 6fe0e1e4e41..fa151b6befd 100644
--- a/html/browser/marked.js
+++ b/html/browser/marked.js
@@ -11,16 +11,26 @@ function parse(node) {
parse(node.childNodes[i]);
}
- if(!node.innerHTML) {
+ if (!node.innerHTML || node.tagName === 'A') {
return;
}
- node.innerHTML = marked(node.innerHTML.replace(/
/gi, '\n'), { breaks: true });
+
+ node.innerHTML = marked(node.innerHTML.replace(/
/gi, '\n').replace(/\t/gi, ''), { breaks: true, gfm: false });
}
-function main() {
+window.onload = function() {
+ var para = marked.Renderer.prototype.paragraph;
+ var field = '';
+ marked.Renderer.prototype.paragraph = function(text) {
+ if (text.slice(0, field.length) === field ||
+ text.slice(0, 2) === '= 0) {
+ return text;
+ }
+ return para(text);
+ };
+
if ($('#markdown')) {
parse($('#markdown'));
}
}
-
-window.onload = main;
diff --git a/html/changelogs/AutoChangeLog-pr-11615.yml b/html/changelogs/AutoChangeLog-pr-11615.yml
new file mode 100644
index 00000000000..1c7cb32141e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11615.yml
@@ -0,0 +1,5 @@
+author: "AffectedArc07, Keekenox, Floyd/Qustinnus"
+delete-after: True
+changes:
+ - rscadd: "P A R A L L A X (That fancy space thing)"
+ - imageadd: "Adds a new Parallax layer that resembles Lavaland (Lava Planet), it spawns on a random location near the station. You need your parallax on high to see it."
diff --git a/html/changelogs/AutoChangeLog-pr-11767.yml b/html/changelogs/AutoChangeLog-pr-11767.yml
new file mode 100644
index 00000000000..a1ab9b83753
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11767.yml
@@ -0,0 +1,6 @@
+author: "Arkatos"
+delete-after: True
+changes:
+ - imageadd: "Added colored pillbottles"
+ - rscadd: "Added an option to change color of the pillbottles to ChemMaster3000"
+ - rscadd: "Added new description to patch packs"
diff --git a/html/changelogs/AutoChangeLog-pr-11774.yml b/html/changelogs/AutoChangeLog-pr-11774.yml
new file mode 100644
index 00000000000..2671e0bd231
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11774.yml
@@ -0,0 +1,4 @@
+author: "Arkatos"
+delete-after: True
+changes:
+ - tweak: "Jump to Node ability now shows a location of each Blob node"
diff --git a/html/changelogs/AutoChangeLog-pr-11776.yml b/html/changelogs/AutoChangeLog-pr-11776.yml
new file mode 100644
index 00000000000..6040b3f474a
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11776.yml
@@ -0,0 +1,4 @@
+author: "Arkatos"
+delete-after: True
+changes:
+ - rscadd: "Added SlimeHUD when playing as a slime. This means slimes will have their own unique health doll and pull icon."
diff --git a/html/changelogs/AutoChangeLog-pr-11783.yml b/html/changelogs/AutoChangeLog-pr-11783.yml
new file mode 100644
index 00000000000..11c3bec4ac4
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11783.yml
@@ -0,0 +1,5 @@
+author: "Couls"
+delete-after: True
+changes:
+ - rscadd: "hit effects!"
+ - imageadd: "hit effect sprites for lasers, bullet hole and dent decals for walls"
diff --git a/html/changelogs/AutoChangeLog-pr-11810.yml b/html/changelogs/AutoChangeLog-pr-11810.yml
new file mode 100644
index 00000000000..b87ad624c90
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11810.yml
@@ -0,0 +1,5 @@
+author: "Arkatos"
+delete-after: True
+changes:
+ - rscadd: "Action buttons can now be dragged onto each other to swap places"
+ - bugfix: "Fixed a case where dragging locked action buttons could result in white tooltip over the screen"
diff --git a/html/changelogs/AutoChangeLog-pr-11827.yml b/html/changelogs/AutoChangeLog-pr-11827.yml
new file mode 100644
index 00000000000..584dfed8901
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11827.yml
@@ -0,0 +1,4 @@
+author: "TDSSS"
+delete-after: True
+changes:
+ - tweak: "Gave the HoP fax long-ranged faxing capabilities."
diff --git a/html/changelogs/AutoChangeLog-pr-11833.yml b/html/changelogs/AutoChangeLog-pr-11833.yml
new file mode 100644
index 00000000000..2e7470e33cb
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11833.yml
@@ -0,0 +1,4 @@
+author: "dovydas12345"
+delete-after: True
+changes:
+ - bugfix: "Fixes being able to pick up chairs and stools when you have items in both hand or when you don't have hands."
diff --git a/html/changelogs/AutoChangeLog-pr-11834.yml b/html/changelogs/AutoChangeLog-pr-11834.yml
new file mode 100644
index 00000000000..99a23206448
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11834.yml
@@ -0,0 +1,4 @@
+author: "dovydas12345"
+delete-after: True
+changes:
+ - rscadd: "Adds a ERT shuttle console which is accessible to ERT members"
diff --git a/html/changelogs/AutoChangeLog-pr-11843.yml b/html/changelogs/AutoChangeLog-pr-11843.yml
new file mode 100644
index 00000000000..ace0ff2485b
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11843.yml
@@ -0,0 +1,4 @@
+author: "JKnutson101"
+delete-after: True
+changes:
+ - bugfix: "Issue where Emergency NanoMed Vendors required Medical ID to Access."
diff --git a/html/changelogs/AutoChangeLog-pr-11844.yml b/html/changelogs/AutoChangeLog-pr-11844.yml
new file mode 100644
index 00000000000..448d227c770
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11844.yml
@@ -0,0 +1,4 @@
+author: "JKnutson101"
+delete-after: True
+changes:
+ - rscadd: "Added the ability for cyborgs with zero battery to use the 'succumb' verb."
diff --git a/html/changelogs/AutoChangeLog-pr-11845.yml b/html/changelogs/AutoChangeLog-pr-11845.yml
new file mode 100644
index 00000000000..2582e3c3752
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11845.yml
@@ -0,0 +1,5 @@
+author: "Tayyyyyyy"
+delete-after: True
+changes:
+ - bugfix: "Fix extra newline after field and disable Github Flavored Markdown in papers (normal markdown still works)"
+ - bugfix: "autogenerated papers no longer appear as HTML code"
diff --git a/html/changelogs/AutoChangeLog-pr-11863.yml b/html/changelogs/AutoChangeLog-pr-11863.yml
new file mode 100644
index 00000000000..ebbb86a7e35
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11863.yml
@@ -0,0 +1,4 @@
+author: "EmanTheAlmighty"
+delete-after: True
+changes:
+ - tweak: "The AI can now toggle airlock safeties instead of toggling door bolt lights by pressing middle mouse."
diff --git a/html/changelogs/AutoChangeLog-pr-11875.yml b/html/changelogs/AutoChangeLog-pr-11875.yml
new file mode 100644
index 00000000000..35009a885a0
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11875.yml
@@ -0,0 +1,5 @@
+author: "SteelSlayer"
+delete-after: True
+changes:
+ - bugfix: "Wizard rounds now end if all wizards and apprentices are either dead, inside cyborgs, or in MMIs"
+ - tweak: "Re-enabled the wizard's hud. Wizards can now see their own antag icon along with seeing other wizard's and apprentice's icons"
diff --git a/html/changelogs/AutoChangeLog-pr-11894.yml b/html/changelogs/AutoChangeLog-pr-11894.yml
new file mode 100644
index 00000000000..1257ab8f981
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11894.yml
@@ -0,0 +1,5 @@
+author: "TheSardele"
+delete-after: True
+changes:
+ - rscadd: "All-In-one Grinders can now be constructed and upgraded"
+ - rscadd: "All-In-one Grinders now produce more reagents when upgraded."
diff --git a/html/changelogs/AutoChangeLog-pr-11899.yml b/html/changelogs/AutoChangeLog-pr-11899.yml
new file mode 100644
index 00000000000..95579acd428
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11899.yml
@@ -0,0 +1,6 @@
+author: "SteelSlayer"
+delete-after: True
+changes:
+ - bugfix: "When a cult sacrifice target leaves the round via cryo, the game will reassign a new target for them"
+ - rscadd: "Added an alarm sound that plays for cultists when their sacrifice target leave the round via cryo"
+ - rscadd: "When a cult sacrifice target leaves the round via cryo, the game will update every cultist's notes to reflect the change"
diff --git a/html/changelogs/AutoChangeLog-pr-11924.yml b/html/changelogs/AutoChangeLog-pr-11924.yml
new file mode 100644
index 00000000000..1c237842514
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11924.yml
@@ -0,0 +1,4 @@
+author: "TDSSS"
+delete-after: True
+changes:
+ - tweak: "midround event spawned xeno larva now need less time to grow up and evolve."
diff --git a/html/changelogs/AutoChangeLog-pr-11937.yml b/html/changelogs/AutoChangeLog-pr-11937.yml
new file mode 100644
index 00000000000..6c4eb842bda
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11937.yml
@@ -0,0 +1,4 @@
+author: "farie82"
+delete-after: True
+changes:
+ - bugfix: "Rigging a crate now doesn't delete your coil stack anymore but instead uses 15 of it. Borgs can use it safely again"
diff --git a/html/changelogs/AutoChangeLog-pr-11965.yml b/html/changelogs/AutoChangeLog-pr-11965.yml
new file mode 100644
index 00000000000..f70891de781
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11965.yml
@@ -0,0 +1,4 @@
+author: "TDSSS"
+delete-after: True
+changes:
+ - tweak: "cult talisman got unique icons to tell them apart"
diff --git a/html/changelogs/AutoChangeLog-pr-11981.yml b/html/changelogs/AutoChangeLog-pr-11981.yml
new file mode 100644
index 00000000000..2e17430b9a9
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11981.yml
@@ -0,0 +1,16 @@
+author: "Fox McCloud"
+delete-after: True
+changes:
+ - rscadd: "Majorly updates lavaland"
+ - rscadd: "Miner starting equipment altered. They now start with a kinetic accelerator"
+ - rscadd: "Miners start off with a mini pickaxe"
+ - rscadd: "Adds in the boxed implant kit, regular shelter capsule, and mining drone passthrough upgrade to the mining equipment vendor"
+ - tweak: "re-ordered the equipment vendor, so things are grouped together more logically"
+ - rscadd: "Added a number of new kinetic accelerator upgrades acquirable through tendril chests"
+ - tweak: "Mining bot now uses an actual kinetic accelerator as opposed to a \"Look alike\"; you can upgrade its internal gun with various kinetic accelerator modkits."
+ - tweak: "Sentient mining bot nerfed; you can no longer apply the armor or melee buff to them; offset by the fact you can upgrade their kinetic gun."
+ - tweak: "Indoor pressure mod removed from R&D and made into a miner traitor item"
+ - tweak: "Resonators have an increased amount of fields and do more damage in low pressure. Additionally, if you place a field on a tile that already has a field, it'll cause it to detonate early"
+ - tweak: "Plasmacutter no longer does increased damage in low pressure, Advanced plasma cutter does slightly more base damage but has a bit less range. Price has been cut at R&D"
+ - rscdel: "removed the AoE Mob+Turf upgrade for mining pods"
+ - bugfix: "Fixes ripleys being slow on lavaland"
diff --git a/html/changelogs/AutoChangeLog-pr-11984.yml b/html/changelogs/AutoChangeLog-pr-11984.yml
new file mode 100644
index 00000000000..49600d2025b
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11984.yml
@@ -0,0 +1,5 @@
+author: "Markolie"
+delete-after: True
+changes:
+ - tweak: "Players now have thirty seconds instead of just five seconds to select if they want to be somebody's butler through a die of fate roll."
+ - bugfix: "The Netherworld portal is now properly destroyed upon being killed. In addition, its max health is now equal to its starting health."
diff --git a/html/changelogs/AutoChangeLog-pr-11995.yml b/html/changelogs/AutoChangeLog-pr-11995.yml
new file mode 100644
index 00000000000..63e511de1e9
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11995.yml
@@ -0,0 +1,4 @@
+author: "Markolie"
+delete-after: True
+changes:
+ - tweak: "The iron ore sprite that shows up when using the miner scanner no longer has a background, making it blend in better with the actual rock."
diff --git a/html/changelogs/AutoChangeLog-pr-11998.yml b/html/changelogs/AutoChangeLog-pr-11998.yml
new file mode 100644
index 00000000000..b431624ce94
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-11998.yml
@@ -0,0 +1,4 @@
+author: "Tayyyyyyy"
+delete-after: True
+changes:
+ - tweak: "message window links added to PM send receipt"
diff --git a/html/changelogs/AutoChangeLog-pr-12002.yml b/html/changelogs/AutoChangeLog-pr-12002.yml
new file mode 100644
index 00000000000..00cad9242aa
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12002.yml
@@ -0,0 +1,5 @@
+author: "Markolie"
+delete-after: True
+changes:
+ - bugfix: "Tightening the bolts of a falsewall now works properly."
+ - tweak: "Deconstructing plating now requires it to be unfastened using a screwdriver first, in order to prevent it from being accidentally deconstructed with a welder."
diff --git a/html/changelogs/AutoChangeLog-pr-12007.yml b/html/changelogs/AutoChangeLog-pr-12007.yml
new file mode 100644
index 00000000000..e6599f791f1
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12007.yml
@@ -0,0 +1,4 @@
+author: "Couls"
+delete-after: True
+changes:
+ - tweak: "there are much less one-way airlocks on station"
diff --git a/html/changelogs/AutoChangeLog-pr-12011.yml b/html/changelogs/AutoChangeLog-pr-12011.yml
new file mode 100644
index 00000000000..c9df4ed1d3f
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12011.yml
@@ -0,0 +1,4 @@
+author: "Shadow-Quill"
+delete-after: True
+changes:
+ - tweak: "Mass drivers now need two rods/cable coil instead of three to construct."
diff --git a/html/changelogs/AutoChangeLog-pr-12014.yml b/html/changelogs/AutoChangeLog-pr-12014.yml
new file mode 100644
index 00000000000..f0af236a0cb
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12014.yml
@@ -0,0 +1,5 @@
+author: "Shadow-Quill"
+delete-after: True
+changes:
+ - bugfix: "The RD's office door can now be opened by the RD, instead of by just the Captain."
+ - tweak: "Science lockdown can now only be (de)activated by the RD, instead of any scientist."
diff --git a/html/changelogs/AutoChangeLog-pr-12017.yml b/html/changelogs/AutoChangeLog-pr-12017.yml
new file mode 100644
index 00000000000..050f27f75d4
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12017.yml
@@ -0,0 +1,4 @@
+author: "Fox McCloud"
+delete-after: True
+changes:
+ - bugfix: "Fixes walking on lavaland sounding like walking on metal plating"
diff --git a/html/changelogs/AutoChangeLog-pr-12024.yml b/html/changelogs/AutoChangeLog-pr-12024.yml
new file mode 100644
index 00000000000..d0affbcd67b
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12024.yml
@@ -0,0 +1,7 @@
+author: "Fox McCloud"
+delete-after: True
+changes:
+ - rscadd: "Adds in kinetic crusher trophies"
+ - tweak: "Kinetic crusher can be wielded/unwielded (but you can't attack with it unwielded)"
+ - rscadd: "Adds the HECK suit as Bubblegum loot"
+ - rscadd: "Adds the kinetic accelerator bounty mod as Tendril loot"
diff --git a/html/changelogs/AutoChangeLog-pr-12028.yml b/html/changelogs/AutoChangeLog-pr-12028.yml
new file mode 100644
index 00000000000..6574e9a042d
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12028.yml
@@ -0,0 +1,4 @@
+author: "Shadow-Quill"
+delete-after: True
+changes:
+ - tweak: "Using a health analyzer in-hand will switch the verbosity."
diff --git a/html/changelogs/AutoChangeLog-pr-12033.yml b/html/changelogs/AutoChangeLog-pr-12033.yml
new file mode 100644
index 00000000000..3f9312b4e16
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12033.yml
@@ -0,0 +1,4 @@
+author: "Fox McCloud"
+delete-after: True
+changes:
+ - rscadd: "Add fulton extract packs to the mining vendor; rescue precious valuable or dead miners!"
diff --git a/html/changelogs/AutoChangeLog-pr-12035.yml b/html/changelogs/AutoChangeLog-pr-12035.yml
new file mode 100644
index 00000000000..4bf80bf148f
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12035.yml
@@ -0,0 +1,4 @@
+author: "Fox McCloud"
+delete-after: True
+changes:
+ - tweak: "Adds mini-fans to the mining, engineering, and security shuttles"
diff --git a/html/changelogs/AutoChangeLog-pr-12039.yml b/html/changelogs/AutoChangeLog-pr-12039.yml
new file mode 100644
index 00000000000..551c136207f
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12039.yml
@@ -0,0 +1,7 @@
+author: "Fox McCloud"
+delete-after: True
+changes:
+ - rscadd: "Adds a number of primal recipes: rake (cultivator), wooden bucket, firebrand (long burning match), and bone bracers (armored arm protection that goes on your glove slot)"
+ - rscadd: "Can attach bayonets to C20rs, bolt action rifles, security auto-rifles, and kinetic accelerator; harm intent to stab with them"
+ - rscadd: "can craft ore boxes out of wood"
+ - bugfix: "Skull helmets are now proper helmets"
diff --git a/html/changelogs/AutoChangeLog-pr-12040.yml b/html/changelogs/AutoChangeLog-pr-12040.yml
new file mode 100644
index 00000000000..51542da25c9
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12040.yml
@@ -0,0 +1,4 @@
+author: "Tayyyyyyy"
+delete-after: True
+changes:
+ - bugfix: "Many shuttle flight directions fixed"
diff --git a/html/changelogs/AutoChangeLog-pr-12043.yml b/html/changelogs/AutoChangeLog-pr-12043.yml
new file mode 100644
index 00000000000..51b0dbb1e35
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12043.yml
@@ -0,0 +1,7 @@
+author: "Fox McCloud"
+delete-after: True
+changes:
+ - tweak: "Survival autoinjectors tweaked"
+ - rscadd: "Survival autoinjectors have 15 units of teporone in them"
+ - tweak: "Survival autoinjectors have double the epinpehrine and weak omnizine instead of saline glucose."
+ - tweak: "lavaland extract altered; it no longer heals tox or oxy, and heals slightly less brute and burn, but has nearly halved the metabolization rate and has a less harsh overdose"
diff --git a/html/changelogs/AutoChangeLog-pr-12044.yml b/html/changelogs/AutoChangeLog-pr-12044.yml
new file mode 100644
index 00000000000..7b9b664464e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12044.yml
@@ -0,0 +1,4 @@
+author: "DoctorDrugs"
+delete-after: True
+changes:
+ - tweak: "removed the ability to eat the divine vocal cords"
diff --git a/html/changelogs/AutoChangeLog-pr-12047.yml b/html/changelogs/AutoChangeLog-pr-12047.yml
new file mode 100644
index 00000000000..2d7ad050a64
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12047.yml
@@ -0,0 +1,4 @@
+author: "Fox McCloud"
+delete-after: True
+changes:
+ - bugfix: "Fixes airlocks spamming their open and close when you stand in them"
diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi
index 26526f68951..bea6f281f7a 100644
Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ
diff --git a/icons/effects/parallax.dmi b/icons/effects/parallax.dmi
new file mode 100644
index 00000000000..22f091ff11a
Binary files /dev/null and b/icons/effects/parallax.dmi differ
diff --git a/icons/mob/back.dmi b/icons/mob/back.dmi
index c58a6b635f4..36025c083b4 100644
Binary files a/icons/mob/back.dmi and b/icons/mob/back.dmi differ
diff --git a/icons/mob/hands.dmi b/icons/mob/hands.dmi
index a5a14094fd6..6d6165509c8 100644
Binary files a/icons/mob/hands.dmi and b/icons/mob/hands.dmi differ
diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi
index 7f84b29d04e..4bc39d8f80b 100644
Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ
diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi
index 47cb86a2c89..03f57f19a92 100644
Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ
diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi
index e4630c2764e..b11f98e74ed 100644
Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ
diff --git a/icons/mob/screen_alert.dmi b/icons/mob/screen_alert.dmi
index b18cb799817..cb6a2c6bd64 100644
Binary files a/icons/mob/screen_alert.dmi and b/icons/mob/screen_alert.dmi differ
diff --git a/icons/mob/screen_slime.dmi b/icons/mob/screen_slime.dmi
new file mode 100644
index 00000000000..d5786f3ca69
Binary files /dev/null and b/icons/mob/screen_slime.dmi differ
diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi
index f79ca1fb338..abce25ab86f 100644
Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ
diff --git a/icons/obj/chemical.dmi b/icons/obj/chemical.dmi
index 9c9f6d38e94..f007687d568 100644
Binary files a/icons/obj/chemical.dmi and b/icons/obj/chemical.dmi differ
diff --git a/icons/obj/clothing/gloves.dmi b/icons/obj/clothing/gloves.dmi
index 42f1eda0e74..f7f54357fdb 100644
Binary files a/icons/obj/clothing/gloves.dmi and b/icons/obj/clothing/gloves.dmi differ
diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi
index a20cf61eb33..a3d66d4d921 100644
Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ
diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi
index 8e5a4b8e879..8371295985f 100644
Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ
diff --git a/icons/obj/fulton.dmi b/icons/obj/fulton.dmi
new file mode 100644
index 00000000000..c56c275b3b1
Binary files /dev/null and b/icons/obj/fulton.dmi differ
diff --git a/icons/obj/fulton_balloon.dmi b/icons/obj/fulton_balloon.dmi
new file mode 100644
index 00000000000..5a1fa98e148
Binary files /dev/null and b/icons/obj/fulton_balloon.dmi differ
diff --git a/icons/obj/guns/bayonets.dmi b/icons/obj/guns/bayonets.dmi
new file mode 100644
index 00000000000..32b5448b8ed
Binary files /dev/null and b/icons/obj/guns/bayonets.dmi differ
diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi
index 05a5768ce89..23e49287922 100644
Binary files a/icons/obj/items.dmi and b/icons/obj/items.dmi differ
diff --git a/icons/obj/janitor.dmi b/icons/obj/janitor.dmi
index 83cb94a5ca3..730431590ae 100644
Binary files a/icons/obj/janitor.dmi and b/icons/obj/janitor.dmi differ
diff --git a/icons/obj/kitchen.dmi b/icons/obj/kitchen.dmi
index b39c3668294..0e9ee4649ac 100644
Binary files a/icons/obj/kitchen.dmi and b/icons/obj/kitchen.dmi differ
diff --git a/icons/obj/lavaland/artefacts.dmi b/icons/obj/lavaland/artefacts.dmi
index cd2c6da08ee..8e91b20368f 100644
Binary files a/icons/obj/lavaland/artefacts.dmi and b/icons/obj/lavaland/artefacts.dmi differ
diff --git a/icons/obj/mining.dmi b/icons/obj/mining.dmi
index 29196e625ae..82ab4786c37 100644
Binary files a/icons/obj/mining.dmi and b/icons/obj/mining.dmi differ
diff --git a/icons/obj/objects.dmi b/icons/obj/objects.dmi
index f9c13a5c332..f3cff7fbd9a 100644
Binary files a/icons/obj/objects.dmi and b/icons/obj/objects.dmi differ
diff --git a/icons/obj/paper.dmi b/icons/obj/paper.dmi
index ce3c79adc73..55781076833 100644
Binary files a/icons/obj/paper.dmi and b/icons/obj/paper.dmi differ
diff --git a/icons/turf/mining.dmi b/icons/turf/mining.dmi
index 9621ef05d5c..f648883072a 100644
Binary files a/icons/turf/mining.dmi and b/icons/turf/mining.dmi differ
diff --git a/icons/turf/walls/hierophant_wall_temp.dmi b/icons/turf/walls/hierophant_wall_temp.dmi
new file mode 100644
index 00000000000..9f0d4b8d23c
Binary files /dev/null and b/icons/turf/walls/hierophant_wall_temp.dmi differ
diff --git a/nano/templates/chem_master.tmpl b/nano/templates/chem_master.tmpl
index 385237727db..1d040d52af7 100644
--- a/nano/templates/chem_master.tmpl
+++ b/nano/templates/chem_master.tmpl
@@ -80,10 +80,27 @@
{{else}}
No beaker loaded
{{/if}}
-
- {{if data.loaded_pill_bottle}}
- {{:helper.link('Pill Bottle (' + data.loaded_pill_bottle_contents_len + '/' + data.loaded_pill_bottle_storage_slots + ')', 'eject', {'ejectp': 1})}}
- {{else}}
- {{:helper.link('No Pill Bottle', 'eject', {}, 'disabled')}}
- {{/if}}
-
\ No newline at end of file
+
+
+ {{if data.loaded_pill_bottle}}
+
+
+ |
+ {{:helper.link('Pill Bottle (' + data.loaded_pill_bottle_contents_len + '/' + data.loaded_pill_bottle_storage_slots + ')', 'eject', {'ejectp': 1})}}
+ |
+
+ {{:helper.link('Change Wrapper', 'pencil', {'change_pillbottle': 1})}}
+ |
+
+
+ {{else}}
+
+
+ |
+ {{:helper.link('No Pill Bottle', 'eject', {}, 'disabled')}}
+ |
+
+
+ {{/if}}
+
+
\ No newline at end of file
diff --git a/paradise.dme b/paradise.dme
index 7661fc9ac81..43192705d89 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -143,11 +143,13 @@
#include "code\_onclick\hud\monkey.dm"
#include "code\_onclick\hud\movable_screen_objects.dm"
#include "code\_onclick\hud\other_mobs.dm"
+#include "code\_onclick\hud\parallax.dm"
#include "code\_onclick\hud\picture_in_picture.dm"
#include "code\_onclick\hud\plane_master.dm"
#include "code\_onclick\hud\radial.dm"
#include "code\_onclick\hud\robot.dm"
#include "code\_onclick\hud\screen_objects.dm"
+#include "code\_onclick\hud\slime.dm"
#include "code\_onclick\hud\swarmer.dm"
#include "code\ATMOSPHERICS\atmospherics.dm"
#include "code\ATMOSPHERICS\datum_icon_manager.dm"
@@ -222,6 +224,7 @@
#include "code\controllers\subsystem\nightshift.dm"
#include "code\controllers\subsystem\npcpool.dm"
#include "code\controllers\subsystem\overlays.dm"
+#include "code\controllers\subsystem\parallax.dm"
#include "code\controllers\subsystem\radio.dm"
#include "code\controllers\subsystem\shuttles.dm"
#include "code\controllers\subsystem\spacedrift.dm"
@@ -277,6 +280,7 @@
#include "code\datums\components\ducttape.dm"
#include "code\datums\components\jestosterone.dm"
#include "code\datums\components\material_container.dm"
+#include "code\datums\components\paintable.dm"
#include "code\datums\components\squeak.dm"
#include "code\datums\components\waddling.dm"
#include "code\datums\diseases\_disease.dm"
@@ -1641,6 +1645,7 @@
#include "code\modules\mining\coins.dm"
#include "code\modules\mining\equipment_locker.dm"
#include "code\modules\mining\explorer_gear.dm"
+#include "code\modules\mining\fulton.dm"
#include "code\modules\mining\machine_processing.dm"
#include "code\modules\mining\machine_stacking.dm"
#include "code\modules\mining\machine_unloading.dm"
@@ -1651,6 +1656,7 @@
#include "code\modules\mining\ore.dm"
#include "code\modules\mining\satchel_ore_boxdm.dm"
#include "code\modules\mining\shelters.dm"
+#include "code\modules\mining\equipment\kinetic_crusher.dm"
#include "code\modules\mining\equipment\marker_beacons.dm"
#include "code\modules\mining\equipment\survival_pod.dm"
#include "code\modules\mining\laborcamp\laborshuttle.dm"
diff --git a/sound/items/fultext_deploy.ogg b/sound/items/fultext_deploy.ogg
new file mode 100644
index 00000000000..2433b9e0fe3
Binary files /dev/null and b/sound/items/fultext_deploy.ogg differ
diff --git a/sound/items/fultext_launch.ogg b/sound/items/fultext_launch.ogg
new file mode 100644
index 00000000000..2c874419927
Binary files /dev/null and b/sound/items/fultext_launch.ogg differ