This commit is contained in:
Fordoxia
2024-05-18 00:03:53 +01:00
269 changed files with 10351 additions and 10679 deletions
+1 -1
View File
@@ -113,7 +113,7 @@ jobs:
- name: Rebuild TGUI
run: |
if git diff-tree --name-only -r $(git rev-parse HEAD~2) | grep "tgui/public/"
if git diff-tree --name-only -r $(git rev-parse HEAD~2) | grep "tgui/public/" ; then
bash tgui/bin/tgui
git commit -m "Rebuild TGUI"
git push origin
+4 -1
View File
@@ -404,8 +404,11 @@ CREATE TABLE `notes` (
`server` varchar(50) NOT NULL,
`crew_playtime` mediumint(8) UNSIGNED DEFAULT '0',
`automated` TINYINT(3) UNSIGNED NULL DEFAULT '0',
`deleted` TINYINT(4) NOT NULL DEFAULT '0',
`deletedby` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci',
PRIMARY KEY (`id`),
KEY `ckey` (`ckey`)
KEY `ckey` (`ckey`),
KEY `deleted` (`deleted`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
/*!40101 SET character_set_client = @saved_cs_client */;
+7
View File
@@ -0,0 +1,7 @@
# Updating DB from 55-56 ~AffectedArc07
# Adds a new column to the notes table for tracking deleted notes
ALTER TABLE `notes`
ADD COLUMN `deleted` TINYINT NOT NULL DEFAULT 0 AFTER `automated`,
ADD COLUMN `deletedby` VARCHAR(32) NULL DEFAULT NULL AFTER `deleted`,
ADD INDEX `deleted` (`deleted`);
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+58 -49
View File
@@ -258,6 +258,10 @@
/obj/item/target,
/obj/item/target,
/obj/item/target,
/obj/item/target/syndicate,
/obj/item/target/syndicate,
/obj/item/target/syndicate,
/obj/item/target/syndicate,
/turf/simulated/floor/plasteel,
/area/station/security/range)
"acD" = (
@@ -453,7 +457,6 @@
/obj/machinery/camera{
c_tag = "Firing Range"
},
/obj/machinery/syndicatebomb/training,
/obj/effect/decal/cleanable/dirt,
/turf/simulated/floor/plasteel,
/area/station/security/range)
@@ -466,7 +469,7 @@
name = "east bump";
pixel_x = 24
},
/turf/simulated/floor/plating,
/turf/simulated/floor/plasteel,
/area/station/security/range)
"adn" = (
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
@@ -522,9 +525,8 @@
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 4
},
/obj/item/radio/intercom/department/security{
pixel_y = -28
},
/obj/machinery/nuclearbomb/training,
/obj/effect/decal/cleanable/dirt,
/turf/simulated/floor/plasteel,
/area/station/security/range)
"adE" = (
@@ -537,13 +539,34 @@
dir = 4
},
/obj/effect/decal/cleanable/dirt,
/obj/machinery/syndicatebomb/training,
/turf/simulated/floor/plasteel,
/area/station/security/range)
"adG" = (
/obj/item/disk/nuclear/training{
pixel_y = -2;
pixel_x = -7
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 9
},
/obj/effect/decal/cleanable/dirt,
/obj/structure/table/reinforced,
/obj/item/paper/nuclear_guide_spacing{
pixel_x = 10;
pixel_y = 7
},
/obj/item/paper/nuclear_guide_defusing{
pixel_x = 9;
pixel_y = 4
},
/obj/item/disk/nuclear/training{
pixel_x = -5
},
/obj/item/paper/nuclear_guide_operating{
pixel_x = 8;
pixel_y = 1
},
/turf/simulated/floor/plasteel,
/area/station/security/range)
"adH" = (
@@ -1696,10 +1719,22 @@
/area/station/command/office/hos)
"aij" = (
/obj/effect/decal/cleanable/dirt,
/obj/structure/rack,
/obj/item/target/syndicate,
/obj/item/target/syndicate,
/obj/item/target/syndicate,
/obj/item/storage/toolbox/mechanical{
pixel_x = 3;
pixel_y = 6
},
/obj/item/multitool{
pixel_y = -5;
pixel_x = 5
},
/obj/item/clothing/head/welding{
pixel_y = -2;
pixel_x = -6
},
/obj/structure/table/reinforced,
/obj/item/radio/intercom/department/security{
pixel_x = 28
},
/turf/simulated/floor/plasteel,
/area/station/security/range)
"aio" = (
@@ -11923,7 +11958,6 @@
/area/station/hallway/secondary/entry/north)
"aMC" = (
/obj/structure/table,
/obj/machinery/computer/mob_healer_terminal,
/turf/simulated/floor/carpet/arcade,
/area/station/public/arcade)
"aMD" = (
@@ -14876,9 +14910,6 @@
/area/station/medical/reception)
"aVy" = (
/obj/machinery/economy/vending/coffee,
/obj/machinery/computer/mob_healer_terminal{
pixel_x = 28
},
/obj/structure/sign/poster/official/random{
pixel_y = 32
},
@@ -35301,13 +35332,14 @@
/obj/machinery/door/airlock/engineering/glass{
name = "Laser Room"
},
/obj/effect/mapping_helpers/airlock/access/all/engineering/general,
/obj/effect/mapping_helpers/airlock/access/any/engineering/general,
/obj/structure/cable{
d1 = 1;
d2 = 2;
icon_state = "1-2"
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/obj/effect/mapping_helpers/airlock/access/any/engineering/atmos,
/turf/simulated/floor/plating,
/area/station/engineering/control)
"cmd" = (
@@ -38903,13 +38935,14 @@
/obj/machinery/door/airlock/engineering/glass{
name = "Laser Room"
},
/obj/effect/mapping_helpers/airlock/access/all/engineering/general,
/obj/effect/mapping_helpers/airlock/access/any/engineering/general,
/obj/structure/cable{
d1 = 1;
d2 = 2;
icon_state = "1-2"
},
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
/obj/effect/mapping_helpers/airlock/access/any/engineering/atmos,
/turf/simulated/floor/plating,
/area/station/engineering/control)
"cyS" = (
@@ -52294,12 +52327,6 @@
icon_state = "vault"
},
/area/station/engineering/gravitygenerator)
"dCJ" = (
/obj/structure/transit_tube/cap{
dir = 8
},
/turf/simulated/floor/plating,
/area/station/turret_protected/aisat/interior)
"dCM" = (
/obj/structure/disposalpipe/segment{
dir = 4
@@ -55778,13 +55805,6 @@
icon_state = "darkgreen"
},
/area/station/medical/medbay3)
"fes" = (
/obj/structure/chair{
dir = 4
},
/obj/machinery/computer/mob_battle_terminal/red,
/turf/simulated/floor/plasteel,
/area/station/public/dorms)
"feN" = (
/turf/simulated/floor/plasteel,
/area/station/hallway/secondary/entry/north)
@@ -57663,10 +57683,12 @@
layer = 4;
pixel_y = 32
},
/obj/structure/transit_tube/station,
/obj/structure/transit_tube_pod{
dir = 4
},
/obj/structure/transit_tube/station/reverse/flipped{
dir = 1
},
/turf/simulated/floor/plasteel{
icon_state = "dark"
},
@@ -64030,9 +64052,6 @@
name = "north bump";
pixel_y = 24
},
/obj/structure/transit_tube/cap{
dir = 4
},
/turf/simulated/floor/plasteel{
icon_state = "dark"
},
@@ -65342,12 +65361,6 @@
/obj/effect/spawner/window/reinforced,
/turf/simulated/floor/plating,
/area/station/supply/lobby)
"jPN" = (
/obj/machinery/computer/mob_battle_terminal/blue{
pixel_x = -32
},
/turf/simulated/floor/plasteel,
/area/station/public/dorms)
"jPZ" = (
/obj/structure/sign/poster/official/cleanliness{
pixel_x = 32
@@ -72410,11 +72423,11 @@
/turf/simulated/floor/plasteel,
/area/station/supply/storage)
"nrh" = (
/obj/structure/transit_tube/station,
/obj/structure/transit_tube_pod{
dir = 8
},
/obj/machinery/atmospherics/pipe/simple/visible/yellow,
/obj/structure/transit_tube/station/reverse,
/turf/simulated/floor/plating,
/area/station/turret_protected/aisat/interior)
"nrD" = (
@@ -76992,10 +77005,6 @@
},
/turf/simulated/floor/plating,
/area/station/security/permabrig)
"pwU" = (
/obj/effect/landmark/battle_mob_point,
/turf/simulated/floor/engine,
/area/holodeck/alphadeck)
"pxv" = (
/obj/machinery/atmospherics/unary/outlet_injector/on{
dir = 8;
@@ -82089,7 +82098,7 @@
id = "engsm";
name = "Radiation Shutters Control";
pixel_y = -24;
req_access_txt = "10"
req_access_txt = "32"
},
/obj/effect/turf_decal/stripes/line,
/turf/simulated/floor/engine,
@@ -131932,7 +131941,7 @@ aab
aaa
cQp
wza
dCJ
dnW
dnv
dnW
diz
@@ -132341,7 +132350,7 @@ nXr
aKQ
fRL
aPm
jPN
aPm
lkw
fho
aPm
@@ -132590,7 +132599,7 @@ awE
ayf
azn
arR
fes
tbC
tbC
tbC
aPm
@@ -133621,10 +133630,10 @@ atG
sHt
sHt
sHt
pwU
sHt
sHt
pwU
sHt
sHt
sHt
sHt
sHt
+297 -162
View File
@@ -2486,13 +2486,6 @@
/obj/machinery/ai_status_display,
/turf/simulated/wall/r_wall,
/area/station/turret_protected/aisat/interior)
"apu" = (
/obj/effect/decal/cleanable/dirt,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating{
icon_state = "asteroidplating"
},
/area/station/maintenance/fore2)
"apw" = (
/obj/structure/table,
/obj/item/storage/toolbox/emergency,
@@ -2752,37 +2745,41 @@
/turf/simulated/floor/plating/asteroid/ancient,
/area/station/maintenance/fpmaint)
"ard" = (
/obj/effect/decal/cleanable/dirt,
/obj/machinery/light/small,
/turf/simulated/floor/plating{
icon_state = "asteroidplating"
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 9
},
/area/station/security/permabrig)
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 4
},
/obj/machinery/syndicatebomb/training,
/obj/machinery/light,
/turf/simulated/floor/plasteel,
/area/station/security/defusal)
"arh" = (
/obj/item/vending_refill/cola,
/obj/item/multitool,
/obj/effect/decal/cleanable/dirt,
/obj/effect/spawner/grouped_spawner{
group_id = "tunnelbats";
max_per_spawner = 1;
name = "bat spawner";
path_to_spawn = /mob/living/simple_animal/hostile/scarybat;
total_amount = 20
/obj/item/disk/nuclear/training{
pixel_y = -2;
pixel_x = -7
},
/turf/simulated/floor/plating{
icon_state = "asteroidplating"
/obj/structure/table/reinforced,
/obj/item/paper/nuclear_guide_spacing{
pixel_x = 10;
pixel_y = 7
},
/area/station/maintenance/fore2)
"ark" = (
/obj/effect/decal/cleanable/dirt,
/turf/simulated/floor/plating{
icon_state = "asteroidplating"
/obj/item/paper/nuclear_guide_defusing{
pixel_x = 9;
pixel_y = 4
},
/area/station/maintenance/fore2)
"arl" = (
/obj/structure/closet/emcloset,
/turf/simulated/floor/plating,
/area/station/maintenance/fore2)
/obj/item/disk/nuclear/training{
pixel_x = -5
},
/obj/item/paper/nuclear_guide_operating{
pixel_x = 8;
pixel_y = 1
},
/turf/simulated/floor/plasteel{
icon_state = "redcorner"
},
/area/station/security/defusal)
"arm" = (
/obj/machinery/door/airlock/maintenance{
name = "Fore Asteroid Maintenance Access"
@@ -5829,6 +5826,13 @@
"aMC" = (
/turf/simulated/mineral/ancient,
/area/station/medical/break_room)
"aME" = (
/obj/machinery/door/airlock/maintenance,
/obj/effect/decal/cleanable/dirt,
/turf/simulated/floor/plating{
icon_state = "asteroidplating"
},
/area/station/security/permabrig)
"aMJ" = (
/obj/machinery/firealarm{
dir = 1;
@@ -11253,7 +11257,7 @@
/obj/machinery/door/airlock/engineering/glass{
name = "Laser Room"
},
/obj/effect/mapping_helpers/airlock/access/all/engineering/general,
/obj/effect/mapping_helpers/airlock/access/any/engineering/atmos,
/obj/structure/cable{
d1 = 1;
d2 = 2;
@@ -11261,6 +11265,7 @@
},
/obj/machinery/door/firedoor,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
/obj/effect/mapping_helpers/airlock/access/any/engineering/general,
/turf/simulated/floor/plasteel{
icon_state = "dark"
},
@@ -12062,19 +12067,21 @@
pixel_x = -3;
pixel_y = -2
},
/obj/item/clothing/glasses/sunglasses,
/turf/simulated/floor/plasteel,
/area/station/security/range)
"bsP" = (
/obj/item/radio/intercom{
pixel_y = -28;
name = "custom placement"
},
/obj/structure/table/reinforced,
/obj/item/clothing/glasses/sunglasses{
pixel_x = 3;
pixel_y = 3
},
/turf/simulated/floor/plasteel,
/area/station/security/range)
"bsP" = (
/obj/machinery/syndicatebomb/training,
/obj/structure/closet/bombclosetsecurity,
/obj/item/radio/intercom{
pixel_y = -28;
name = "custom placement"
/obj/item/clothing/glasses/sunglasses,
/obj/item/storage/box/flashbangs{
pixel_x = -16
},
/turf/simulated/floor/plasteel,
/area/station/security/range)
@@ -25812,13 +25819,16 @@
/turf/simulated/floor/wood,
/area/station/legal/magistrate)
"cKZ" = (
/obj/machinery/door/airlock/maintenance,
/obj/effect/mapping_helpers/airlock/access/all/security/general,
/obj/effect/decal/cleanable/dirt,
/turf/simulated/floor/plating{
icon_state = "asteroidplating"
/obj/machinery/atmospherics/unary/vent_scrubber/on,
/obj/item/radio/intercom{
name = "custom placement";
pixel_y = 28
},
/area/station/maintenance/fore2)
/obj/machinery/camera{
c_tag = "Defusal Workshop"
},
/turf/simulated/floor/plasteel,
/area/station/security/defusal)
"cLa" = (
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 4
@@ -28999,6 +29009,23 @@
icon_state = "darkyellow"
},
/area/station/engineering/atmos)
"cZi" = (
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 6
},
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 6
},
/obj/structure/cable/orange{
d2 = 2;
icon_state = "0-2"
},
/obj/machinery/power/apc/directional/west,
/turf/simulated/floor/plasteel{
dir = 8;
icon_state = "redcorner"
},
/area/station/security/defusal)
"cZr" = (
/obj/structure/chair{
dir = 8
@@ -29371,13 +29398,11 @@
/area/station/security/prison/cell_block/A)
"ddl" = (
/obj/effect/spawner/window/reinforced/grilled,
/obj/structure/cable/orange{
d1 = 1;
d2 = 4;
icon_state = "1-4"
},
/obj/structure/cable/orange,
/obj/machinery/door/firedoor,
/obj/structure/cable/orange{
d2 = 4;
icon_state = "0-4"
},
/turf/simulated/floor/plating,
/area/station/security/permabrig)
"ddn" = (
@@ -33148,9 +33173,10 @@
/obj/machinery/door/airlock/engineering/glass{
name = "Laser Room"
},
/obj/effect/mapping_helpers/airlock/access/all/engineering/general,
/obj/effect/mapping_helpers/airlock/access/any/engineering/atmos,
/obj/machinery/door/firedoor,
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/obj/effect/mapping_helpers/airlock/access/any/engineering/general,
/turf/simulated/floor/plasteel{
icon_state = "dark"
},
@@ -33955,6 +33981,17 @@
icon_state = "yellowcorner"
},
/area/station/hallway/primary/central/east)
"dEa" = (
/obj/machinery/light_switch{
name = "north bump";
pixel_y = 24
},
/obj/machinery/alarm/directional/west,
/turf/simulated/floor/plasteel{
dir = 1;
icon_state = "redcorner"
},
/area/station/security/defusal)
"dEi" = (
/obj/structure/table/wood,
/obj/item/ammo_box/shotgun/beanbag,
@@ -34819,6 +34856,24 @@
icon_state = "bluered"
},
/area/station/hallway/secondary/entry/west)
"dQG" = (
/obj/machinery/door/airlock/security/glass{
name = "Defusal Workshop"
},
/obj/effect/mapping_helpers/airlock/access/all/security/general,
/obj/machinery/door/firedoor,
/obj/structure/cable/orange{
d1 = 1;
d2 = 2;
icon_state = "1-2"
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
/turf/simulated/floor/plasteel{
dir = 4;
icon_state = "red"
},
/area/station/security/defusal)
"dQR" = (
/obj/machinery/door/airlock/maintenance{
name = "Aft Asteroid Maintenance"
@@ -36720,15 +36775,6 @@
/obj/machinery/hologram/holopad,
/turf/simulated/floor/plasteel,
/area/station/hallway/secondary/exit)
"eAn" = (
/obj/effect/decal/cleanable/dirt,
/obj/structure/closet/firecloset,
/obj/item/crowbar/red,
/obj/machinery/light{
dir = 1
},
/turf/simulated/floor/plating,
/area/station/maintenance/fore2)
"eAu" = (
/obj/effect/turf_decal/delivery,
/obj/machinery/recharge_station,
@@ -41487,6 +41533,25 @@
/obj/effect/spawner/random_spawners/dirt_often,
/turf/simulated/floor/transparent/glass/reinforced,
/area/station/maintenance/apmaint)
"gmV" = (
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 9
},
/obj/structure/table/reinforced,
/obj/item/clothing/head/welding{
pixel_x = 12;
pixel_y = 6
},
/obj/item/multitool{
pixel_x = -4;
pixel_y = 6
},
/obj/item/storage/toolbox/mechanical{
pixel_x = -3;
pixel_y = -2
},
/turf/simulated/floor/plasteel,
/area/station/security/defusal)
"gmZ" = (
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 5
@@ -42842,6 +42907,21 @@
icon_state = "whitebluecorner"
},
/area/station/medical/surgery/secondary)
"gLb" = (
/obj/item/vending_refill/cola,
/obj/item/multitool,
/obj/effect/decal/cleanable/dirt,
/obj/effect/spawner/grouped_spawner{
group_id = "tunnelbats";
max_per_spawner = 1;
name = "bat spawner";
path_to_spawn = /mob/living/simple_animal/hostile/scarybat;
total_amount = 20
},
/turf/simulated/floor/plating{
icon_state = "asteroidplating"
},
/area/station/security/permabrig)
"gLj" = (
/obj/structure/table/wood,
/obj/effect/spawner/lootdrop/maintenance/eight,
@@ -43849,6 +43929,15 @@
icon_state = "red"
},
/area/station/security/storage)
"hcm" = (
/obj/effect/decal/cleanable/dirt,
/obj/structure/closet/firecloset,
/obj/item/crowbar/red,
/obj/machinery/light{
dir = 1
},
/turf/simulated/floor/plating,
/area/station/security/permabrig)
"hco" = (
/obj/structure/cable/orange{
d1 = 4;
@@ -44431,6 +44520,14 @@
/obj/effect/spawner/window/reinforced/grilled,
/turf/simulated/floor/plating,
/area/station/turret_protected/aisat/interior/secondary)
"hnL" = (
/obj/machinery/atmospherics/unary/vent_pump/on,
/obj/machinery/firealarm{
name = "north bump";
pixel_y = 24
},
/turf/simulated/floor/plasteel,
/area/station/security/defusal)
"hoa" = (
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 6
@@ -50739,12 +50836,12 @@
/turf/simulated/floor/plating,
/area/station/hallway/primary/central/west)
"jjh" = (
/obj/structure/cable/orange{
d1 = 2;
d2 = 8;
icon_state = "2-8"
},
/obj/effect/decal/cleanable/dirt,
/obj/structure/cable/orange{
d1 = 4;
d2 = 8;
icon_state = "4-8"
},
/turf/simulated/floor/plasteel,
/area/station/security/permabrig)
"jjp" = (
@@ -53865,20 +53962,6 @@
temperature = 80
},
/area/station/science/xenobiology)
"khV" = (
/obj/effect/spawner/window/reinforced/grilled,
/obj/structure/cable/orange{
d1 = 4;
d2 = 8;
icon_state = "4-8"
},
/obj/structure/cable/orange{
d2 = 8;
icon_state = "0-8"
},
/obj/machinery/door/firedoor,
/turf/simulated/floor/plating,
/area/station/security/brig)
"kic" = (
/obj/structure/closet/wardrobe/grey,
/turf/simulated/floor/mineral/titanium/blue,
@@ -59525,6 +59608,15 @@
icon_state = "cafeteria"
},
/area/station/service/kitchen)
"lQa" = (
/obj/effect/spawner/window/reinforced/grilled,
/obj/machinery/door/firedoor,
/obj/structure/cable/orange{
d2 = 8;
icon_state = "0-8"
},
/turf/simulated/floor/plating,
/area/station/security/permabrig)
"lQy" = (
/obj/machinery/optable,
/obj/machinery/light{
@@ -60954,11 +61046,6 @@
/obj/effect/spawner/random_spawners/dirt_often,
/turf/simulated/floor/plating,
/area/station/maintenance/disposal/external/southwest)
"moQ" = (
/obj/effect/spawner/lootdrop/maintenance,
/obj/effect/decal/cleanable/dirt,
/turf/simulated/floor/plating,
/area/station/maintenance/fore2)
"moY" = (
/obj/structure/closet/secure_closet/medical3,
/obj/machinery/light,
@@ -62522,15 +62609,6 @@
},
/turf/simulated/floor/plating,
/area/station/security/brig)
"mSf" = (
/obj/effect/spawner/window/reinforced/grilled,
/obj/structure/cable/orange{
d2 = 8;
icon_state = "0-8"
},
/obj/machinery/door/firedoor,
/turf/simulated/floor/plating,
/area/station/security/permabrig)
"mSh" = (
/obj/structure/girder,
/turf/simulated/floor/plating,
@@ -62825,13 +62903,12 @@
/turf/simulated/floor/plating,
/area/station/maintenance/maintcentral)
"mVr" = (
/obj/item/clothing/shoes/orange,
/obj/item/clothing/under/color/orange/prison,
/obj/effect/decal/cleanable/dirt,
/turf/simulated/floor/plating{
icon_state = "asteroidplating"
/obj/machinery/nuclearbomb/training,
/turf/simulated/floor/plasteel{
dir = 4;
icon_state = "redcorner"
},
/area/station/maintenance/fore2)
/area/station/security/defusal)
"mVs" = (
/obj/structure/disposalpipe/segment/corner{
dir = 8;
@@ -63272,6 +63349,16 @@
/obj/structure/sign/securearea,
/turf/simulated/wall,
/area/station/engineering/tech_storage)
"nde" = (
/obj/structure/cable/orange{
d1 = 2;
d2 = 8;
icon_state = "2-8"
},
/turf/simulated/floor/plasteel{
icon_state = "floorgrime"
},
/area/station/security/permabrig)
"ndl" = (
/obj/effect/spawner/window/reinforced/polarized/grilled{
id = "rd"
@@ -65368,6 +65455,11 @@
icon_state = "neutralcorner"
},
/area/station/hallway/primary/fore/east)
"nNB" = (
/obj/effect/spawner/lootdrop/maintenance,
/obj/effect/decal/cleanable/dirt,
/turf/simulated/floor/plating,
/area/station/security/permabrig)
"nNF" = (
/obj/machinery/door/airlock/maintenance{
name = "Service SMES Access"
@@ -65403,6 +65495,10 @@
},
/turf/simulated/floor/plating,
/area/station/hallway/primary/port/north)
"nOr" = (
/obj/structure/closet/emcloset,
/turf/simulated/floor/plating,
/area/station/security/permabrig)
"nOu" = (
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/obj/structure/disposalpipe/segment,
@@ -69524,6 +69620,9 @@
icon_state = "dark"
},
/area/station/turret_protected/ai)
"peU" = (
/turf/simulated/wall/r_wall,
/area/station/security/defusal)
"pfe" = (
/obj/structure/chair/wood{
dir = 1
@@ -77318,6 +77417,30 @@
},
/turf/simulated/floor/plasteel,
/area/station/public/locker)
"rGv" = (
/obj/structure/cable/orange{
d1 = 4;
d2 = 8;
icon_state = "4-8"
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 4
},
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 4
},
/obj/structure/disposalpipe/segment{
dir = 4
},
/obj/structure/cable/orange{
d1 = 1;
d2 = 8;
icon_state = "1-8"
},
/turf/simulated/floor/plasteel{
icon_state = "dark"
},
/area/station/security/brig)
"rGw" = (
/obj/structure/disposalpipe/segment/corner,
/obj/machinery/atmospherics/pipe/simple/hidden/cyan{
@@ -82602,12 +82725,6 @@
icon_state = "whitegreen"
},
/area/station/medical/virology)
"tpw" = (
/obj/effect/landmark/battle_mob_point,
/turf/simulated/floor/engine{
name = "Holodeck Projector Floor"
},
/area/holodeck/alphadeck)
"tpA" = (
/turf/simulated/floor/plasteel{
icon_state = "dark"
@@ -83579,16 +83696,18 @@
/area/station/maintenance/port)
"tFL" = (
/obj/effect/spawner/window/reinforced/grilled,
/obj/structure/cable/orange{
d2 = 8;
icon_state = "0-8"
},
/obj/structure/cable/orange{
d1 = 4;
d2 = 8;
icon_state = "4-8"
},
/obj/machinery/door/firedoor,
/obj/structure/cable/orange{
d1 = 1;
d2 = 4;
icon_state = "1-4"
},
/obj/structure/cable/orange{
d1 = 1;
d2 = 8;
icon_state = "1-8"
},
/obj/structure/cable/orange,
/turf/simulated/floor/plating,
/area/station/security/permabrig)
"tFY" = (
@@ -91624,6 +91743,14 @@
icon_state = "darkyellow"
},
/area/station/engineering/control)
"weh" = (
/obj/item/clothing/shoes/orange,
/obj/item/clothing/under/color/orange/prison,
/obj/effect/decal/cleanable/dirt,
/turf/simulated/floor/plating{
icon_state = "asteroidplating"
},
/area/station/security/permabrig)
"weN" = (
/obj/structure/cable{
d1 = 4;
@@ -92008,6 +92135,13 @@
},
/turf/simulated/floor/plasteel,
/area/station/hallway/primary/aft/west)
"wiU" = (
/obj/effect/decal/cleanable/dirt,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating{
icon_state = "asteroidplating"
},
/area/station/security/permabrig)
"wiV" = (
/obj/structure/mirror{
pixel_x = -28
@@ -95268,7 +95402,7 @@
id = "engsm";
name = "Radiation Shutters Control";
pixel_y = 24;
req_access_txt = "10"
req_access_txt = "32"
},
/obj/machinery/camera{
c_tag = "SM South";
@@ -98581,6 +98715,7 @@
/obj/machinery/light/small{
dir = 4
},
/obj/structure/closet/bombclosetsecurity,
/turf/simulated/floor/plasteel{
icon_state = "dark"
},
@@ -116641,10 +116776,10 @@ bEM
pDn
pDn
pDn
tpw
pDn
pDn
tpw
pDn
pDn
pDn
pDn
pDn
@@ -118894,7 +119029,7 @@ rHj
cDb
rHj
aQL
aQL
nde
tFL
rNK
rNK
@@ -119152,10 +119287,10 @@ gLk
cVR
amO
myY
tFL
lQa
rNK
rNK
khV
lPn
yfX
fOj
awv
@@ -119409,11 +119544,11 @@ dpC
rHj
adc
rHj
mSf
rNK
rNK
lPn
yfX
peU
peU
peU
peU
wGz
uaJ
awB
uqz
@@ -119666,12 +119801,12 @@ rHj
rHj
vNP
sFU
afd
afd
afd
afd
wGz
uaJ
peU
dEa
cZi
dQG
dsy
rGv
dtr
uqz
aLp
@@ -119923,10 +120058,10 @@ rHj
cgX
tkn
dqz
tkn
rHj
peU
hnL
ard
afd
peU
daG
sVX
daG
@@ -120176,13 +120311,13 @@ aTz
afd
aTz
aTz
rHj
aTz
aTz
afd
afd
cKZ
aME
mYJ
peU
cKZ
gmV
fqh
eBm
krP
@@ -120433,11 +120568,11 @@ afd
afd
aTz
aTz
aTz
aTz
aTz
afd
vXM
tkn
weh
gLb
peU
mVr
arh
fqh
@@ -120690,13 +120825,13 @@ abW
abW
afd
aTz
aTz
aTz
aTz
afd
eAn
moQ
ark
hcm
nNB
adc
peU
peU
peU
fqh
xax
pZs
@@ -120945,15 +121080,15 @@ rNK
cRv
abW
abW
abW
afd
aTz
afd
vNP
wiU
nOr
afd
aTz
aTz
aTz
afd
vrQ
apu
arl
asu
atc
eZh
@@ -121202,15 +121337,15 @@ rNK
cRv
cRv
cRv
abW
afd
aTz
aTz
aTz
aTz
afd
afd
aTz
afd
aTz
aTz
fqh
bOR
gyQ
+95 -61
View File
@@ -28019,6 +28019,34 @@
icon_state = "neutralfull"
},
/area/station/hallway/primary/port/north)
"bDD" = (
/obj/item/disk/nuclear/training{
pixel_y = -2;
pixel_x = -7
},
/obj/structure/table/reinforced,
/obj/item/paper/nuclear_guide_spacing{
pixel_x = 10;
pixel_y = 7
},
/obj/item/paper/nuclear_guide_defusing{
pixel_x = 9;
pixel_y = 4
},
/obj/item/disk/nuclear/training{
pixel_x = -5
},
/obj/item/paper/nuclear_guide_operating{
pixel_x = 8;
pixel_y = 1
},
/obj/effect/decal/cleanable/dirt,
/obj/machinery/atmospherics/unary/vent_scrubber/on{
dir = 1
},
/obj/machinery/alarm/directional/south,
/turf/simulated/floor/plasteel,
/area/station/security/range)
"bDE" = (
/obj/item/kirbyplants,
/obj/machinery/status_display{
@@ -35212,7 +35240,7 @@
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
/obj/structure/table,
/obj/machinery/syndicatebomb/training,
/obj/item/toy/figure/crew/secofficer,
/turf/simulated/floor/plasteel{
icon_state = "dark"
},
@@ -40235,6 +40263,16 @@
/turf/simulated/floor/plasteel,
/area/station/security/range)
"cju" = (
/obj/machinery/syndicatebomb/training,
/turf/simulated/floor/plasteel,
/area/station/security/range)
"cjv" = (
/obj/structure/window/reinforced{
dir = 8
},
/turf/simulated/floor/plating,
/area/station/security/range)
"cjw" = (
/obj/structure/table/reinforced,
/obj/machinery/recharger{
pixel_x = -6;
@@ -40247,27 +40285,8 @@
pixel_x = 7;
pixel_y = 3
},
/obj/machinery/atmospherics/unary/vent_pump/on,
/turf/simulated/floor/plasteel,
/area/station/security/range)
"cjv" = (
/obj/structure/window/reinforced{
dir = 8
},
/turf/simulated/floor/plating,
/area/station/security/range)
"cjw" = (
/obj/structure/sign/securearea{
pixel_y = 32
},
/turf/simulated/floor/plating,
/area/station/security/range)
"cjx" = (
/obj/machinery/light{
dir = 1
},
/turf/simulated/floor/plating,
/area/station/security/range)
"cjy" = (
/obj/machinery/atmospherics/unary/vent_pump/on,
/turf/simulated/floor/plating,
@@ -40863,9 +40882,6 @@
icon_state = "4-8"
},
/obj/effect/decal/cleanable/dirt,
/obj/effect/turf_decal/stripes/line{
dir = 8
},
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 4
},
@@ -40901,10 +40917,13 @@
d2 = 8;
icon_state = "4-8"
},
/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{
dir = 1
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 4
},
/obj/machinery/atmospherics/pipe/manifold/hidden/supply,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 4
},
/obj/effect/decal/cleanable/dirt,
/turf/simulated/floor/plasteel,
/area/station/security/range)
"clf" = (
@@ -41413,7 +41432,6 @@
icon_state = "1-2"
},
/obj/effect/decal/cleanable/dirt,
/obj/effect/turf_decal/stripes/line,
/turf/simulated/floor/plasteel,
/area/station/security/range)
"cmC" = (
@@ -41437,18 +41455,8 @@
/turf/simulated/floor/plating,
/area/station/security/range)
"cmF" = (
/obj/structure/table/reinforced,
/obj/machinery/alarm/directional/south,
/obj/item/gun/energy/laser/practice,
/obj/item/gun/energy/laser/practice,
/obj/item/clothing/ears/earmuffs,
/obj/item/clothing/ears/earmuffs,
/obj/machinery/atmospherics/unary/vent_scrubber/on{
dir = 1
},
/obj/effect/turf_decal/stripes/line{
dir = 6
},
/obj/machinery/nuclearbomb/training,
/obj/effect/decal/cleanable/dirt,
/turf/simulated/floor/plasteel,
/area/station/security/range)
"cmG" = (
@@ -44275,13 +44283,6 @@
icon_state = "neutralfull"
},
/area/station/hallway/primary/starboard/south)
"cut" = (
/obj/machinery/light,
/obj/structure/sign/securearea{
pixel_y = -32
},
/turf/simulated/floor/plating,
/area/station/security/range)
"cuu" = (
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 4
@@ -59862,6 +59863,14 @@
icon_state = "whitebluefull"
},
/area/station/maintenance/starboard)
"dxV" = (
/obj/structure/table/reinforced,
/obj/item/gun/energy/laser/practice,
/obj/item/gun/energy/laser/practice,
/obj/item/clothing/ears/earmuffs,
/obj/item/clothing/ears/earmuffs,
/turf/simulated/floor/plasteel,
/area/station/security/range)
"dyb" = (
/turf/simulated/floor/plating,
/area/station/maintenance/theatre)
@@ -67079,6 +67088,23 @@
/obj/structure/cable,
/turf/simulated/floor/plasteel/white,
/area/station/science/explab)
"eOg" = (
/obj/structure/table/reinforced,
/obj/machinery/atmospherics/unary/vent_pump/on,
/obj/item/clothing/head/welding{
pixel_x = 9;
pixel_y = 10
},
/obj/item/multitool{
pixel_x = -6;
pixel_y = 8
},
/obj/item/storage/toolbox/mechanical{
pixel_y = -2;
pixel_x = -3
},
/turf/simulated/floor/plasteel,
/area/station/security/range)
"eOt" = (
/obj/structure/table/glass,
/obj/structure/cable{
@@ -69896,6 +69922,19 @@
dir = 5
},
/area/space/nearstation)
"gAP" = (
/obj/structure/cable{
d1 = 4;
d2 = 8;
icon_state = "4-8"
},
/obj/machinery/atmospherics/pipe/manifold/hidden/supply,
/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{
dir = 1
},
/obj/effect/decal/cleanable/dirt,
/turf/simulated/floor/plasteel,
/area/station/security/range)
"gAR" = (
/obj/structure/closet/wardrobe/pjs,
/obj/structure/cable{
@@ -80599,7 +80638,6 @@
"ngl" = (
/obj/structure/table,
/obj/item/storage/fancy/donut_box,
/obj/item/toy/figure/crew/secofficer,
/turf/simulated/floor/plasteel{
icon_state = "dark"
},
@@ -87511,9 +87549,6 @@
/area/station/maintenance/starboard)
"rjL" = (
/obj/effect/decal/cleanable/dirt,
/obj/structure/transit_tube/cap{
dir = 8
},
/obj/item/radio/intercom{
name = "south bump";
pixel_y = -28
@@ -92501,7 +92536,8 @@
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 4
},
/turf/simulated/floor/plating,
/obj/effect/decal/cleanable/dirt,
/turf/simulated/floor/plasteel,
/area/station/security/range)
"tVV" = (
/turf/simulated/floor/plasteel{
@@ -97302,9 +97338,7 @@
/obj/machinery/ai_status_display{
pixel_y = -32
},
/obj/structure/transit_tube/station{
dir = 1
},
/obj/structure/transit_tube/station/reverse/flipped,
/turf/simulated/floor/plasteel{
dir = 8;
icon_state = "vault"
@@ -152270,9 +152304,9 @@ cgr
hFc
cgr
jIs
cjv
iCU
cjv
eOg
gAP
bDD
cjr
brS
bHF
@@ -152529,7 +152563,7 @@ ccL
jIs
cjw
tVO
cjz
dxV
cjr
eeN
lnU
@@ -152784,9 +152818,9 @@ ccM
ceC
cgo
jIs
cjx
tVO
cut
cjv
iCU
cjv
cjr
cpa
cqI
+161 -62
View File
@@ -806,9 +806,6 @@
/turf/simulated/wall,
/area/station/public/arcade)
"ajb" = (
/obj/machinery/computer/mob_battle_terminal/red{
pixel_y = 30
},
/obj/item/kirbyplants/plant20,
/turf/simulated/floor/plasteel{
icon_state = "darkgrey"
@@ -3389,9 +3386,6 @@
name = "east bump";
pixel_x = 27
},
/obj/machinery/computer/mob_battle_terminal/blue{
pixel_y = -30
},
/turf/simulated/floor/plasteel{
icon_state = "darkgrey"
},
@@ -8848,7 +8842,7 @@
id = "engsm";
name = "Radiation Shutters Control";
pixel_x = 24;
req_access_txt = "10"
req_access_txt = "32"
},
/obj/effect/turf_decal/stripes/line{
dir = 4
@@ -19452,10 +19446,12 @@
/turf/simulated/floor/wood,
/area/station/command/office/captain/bedroom)
"bsI" = (
/obj/structure/transit_tube/station,
/obj/structure/sign/securearea{
pixel_y = 32
},
/obj/structure/transit_tube/station/reverse/flipped{
dir = 1
},
/turf/simulated/floor/plasteel{
dir = 4;
icon_state = "darkbluecorners"
@@ -47045,13 +47041,25 @@
/turf/simulated/floor/wood,
/area/station/service/bar)
"exm" = (
/obj/effect/spawner/window/reinforced/grilled,
/obj/structure/cable{
d2 = 8;
icon_state = "0-8"
/obj/machinery/door/airlock/security/glass,
/obj/effect/mapping_helpers/airlock/autoname,
/obj/effect/mapping_helpers/airlock/access/any/security/general,
/obj/machinery/door/firedoor,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 4
},
/turf/simulated/floor/plating,
/area/station/security/main)
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 4
},
/obj/structure/cable{
d1 = 4;
d2 = 8;
icon_state = "4-8"
},
/turf/simulated/floor/plasteel{
icon_state = "redfull"
},
/area/station/security/defusal)
"exI" = (
/obj/structure/table/glass,
/obj/item/hand_labeler,
@@ -48607,6 +48615,37 @@
},
/turf/simulated/floor/carpet,
/area/station/legal/lawoffice)
"ffH" = (
/obj/item/disk/nuclear/training{
pixel_y = -2;
pixel_x = -7
},
/obj/item/paper/nuclear_guide_spacing{
pixel_x = 10;
pixel_y = 7
},
/obj/item/paper/nuclear_guide_defusing{
pixel_x = 9;
pixel_y = 4
},
/obj/item/disk/nuclear/training{
pixel_x = -5
},
/obj/item/paper/nuclear_guide_operating{
pixel_x = 8;
pixel_y = 1
},
/obj/structure/table,
/obj/machinery/camera{
c_tag = "Defusal Workshop"
},
/obj/machinery/firealarm{
dir = 4;
pixel_x = 24;
name = "east bump"
},
/turf/simulated/floor/plasteel,
/area/station/security/defusal)
"fga" = (
/obj/machinery/door/firedoor,
/obj/structure/disposalpipe/segment{
@@ -49977,6 +50016,24 @@
/obj/effect/decal/cleanable/blood,
/turf/simulated/floor/bluegrid,
/area/station/maintenance/starboard)
"fFo" = (
/obj/structure/table,
/obj/item/radio/intercom{
name = "south bump";
pixel_y = -28
},
/obj/item/clothing/head/welding{
pixel_x = -4;
pixel_y = 19
},
/obj/item/multitool{
pixel_x = 7;
pixel_y = 13
},
/obj/item/storage/toolbox/mechanical,
/obj/machinery/alarm/directional/east,
/turf/simulated/floor/plasteel,
/area/station/security/defusal)
"fFL" = (
/obj/machinery/atmospherics/meter,
/obj/machinery/atmospherics/pipe/simple/visible/yellow,
@@ -50222,12 +50279,12 @@
/area/station/hallway/primary/central/north)
"fJr" = (
/obj/machinery/disposal,
/obj/structure/cable{
d1 = 4;
d2 = 8;
icon_state = "4-8"
},
/obj/structure/disposalpipe/trunk,
/obj/structure/cable{
d1 = 1;
d2 = 8;
icon_state = "1-8"
},
/turf/simulated/floor/plasteel{
icon_state = "darkred"
},
@@ -53400,9 +53457,6 @@
/obj/structure/table,
/obj/item/stack/medical/bruise_pack,
/obj/item/stack/medical/ointment,
/obj/machinery/computer/mob_healer_terminal{
pixel_y = 30
},
/turf/simulated/floor/plasteel{
dir = 1;
icon_state = "whiteblue"
@@ -53831,9 +53885,6 @@
},
/area/station/medical/virology)
"hkm" = (
/obj/structure/transit_tube/cap{
dir = 4
},
/obj/machinery/status_display{
layer = 4;
pixel_y = 32
@@ -59778,6 +59829,23 @@
"jKj" = (
/turf/simulated/wall/r_wall,
/area/station/engineering/ai_transit_tube)
"jKG" = (
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 9
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 10
},
/obj/structure/cable{
d1 = 4;
d2 = 8;
icon_state = "4-8"
},
/turf/simulated/floor/plasteel{
dir = 8;
icon_state = "red"
},
/area/station/security/defusal)
"jKP" = (
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 4
@@ -60579,6 +60647,14 @@
},
/turf/simulated/floor/plating,
/area/station/medical/virology)
"jXY" = (
/obj/machinery/nuclearbomb/training,
/obj/machinery/atmospherics/unary/vent_scrubber/on,
/turf/simulated/floor/plasteel{
dir = 8;
icon_state = "red"
},
/area/station/security/defusal)
"jYj" = (
/obj/machinery/atmospherics/pipe/manifold/visible/cyan{
dir = 8;
@@ -66792,7 +66868,7 @@
name = "Supermatter Engine Room"
},
/obj/machinery/door/firedoor,
/obj/effect/mapping_helpers/airlock/access/all/engineering/general,
/obj/effect/mapping_helpers/airlock/access/any/engineering/general,
/obj/structure/cable{
d1 = 4;
d2 = 8;
@@ -66801,6 +66877,7 @@
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 4
},
/obj/effect/mapping_helpers/airlock/access/any/engineering/atmos,
/turf/simulated/floor/plating,
/area/station/engineering/control)
"mCX" = (
@@ -69551,6 +69628,9 @@
/obj/effect/mapping_helpers/airlock/access/all/engineering/external,
/turf/simulated/floor/plating,
/area/station/engineering/control)
"nEV" = (
/turf/simulated/wall/r_wall,
/area/station/security/defusal)
"nFf" = (
/obj/structure/table/glass,
/obj/item/reagent_containers/dropper,
@@ -72815,7 +72895,6 @@
name = "Supermatter Engine Room"
},
/obj/machinery/door/firedoor,
/obj/effect/mapping_helpers/airlock/access/all/engineering/general,
/obj/structure/cable{
d1 = 4;
d2 = 8;
@@ -72824,6 +72903,8 @@
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 4
},
/obj/effect/mapping_helpers/airlock/access/any/engineering/general,
/obj/effect/mapping_helpers/airlock/access/any/engineering/atmos,
/turf/simulated/floor/plating,
/area/station/engineering/control)
"pgs" = (
@@ -79389,6 +79470,21 @@
icon_state = "dark"
},
/area/station/security/permabrig)
"rOj" = (
/obj/machinery/syndicatebomb/training,
/obj/machinery/light_switch{
dir = 4;
name = "west bump";
pixel_x = -24
},
/obj/machinery/atmospherics/unary/vent_pump/on{
dir = 1
},
/turf/simulated/floor/plasteel{
dir = 8;
icon_state = "red"
},
/area/station/security/defusal)
"rOp" = (
/obj/machinery/door/airlock/tranquillite{
name = "Old Mime's Storage"
@@ -79617,6 +79713,22 @@
icon_state = "whitebluefull"
},
/area/station/medical/exam_room)
"rUg" = (
/obj/structure/table,
/obj/machinery/light{
dir = 4
},
/obj/item/book/manual/wiki/hacking{
pixel_x = 3;
pixel_y = 3
},
/obj/machinery/power/apc/directional/east,
/obj/structure/cable{
d2 = 8;
icon_state = "0-8"
},
/turf/simulated/floor/plasteel,
/area/station/security/defusal)
"rUl" = (
/obj/structure/lattice/catwalk,
/obj/machinery/atmospherics/pipe/simple/heat_exchanging{
@@ -83836,10 +83948,6 @@
icon_state = "cafeteria"
},
/area/station/service/kitchen)
"tNe" = (
/obj/effect/spawner/random_spawners/wall_rusted_probably,
/turf/simulated/wall/r_wall,
/area/station/maintenance/fore)
"tNg" = (
/obj/machinery/door/firedoor,
/turf/simulated/floor/plasteel{
@@ -88708,15 +88816,6 @@
},
/area/station/medical/surgery/observation)
"vVR" = (
/obj/structure/table,
/obj/item/screwdriver{
pixel_x = -2;
pixel_y = 18
},
/obj/item/wirecutters{
pixel_y = 5
},
/obj/machinery/syndicatebomb/training,
/turf/simulated/floor/plasteel{
dir = 8;
icon_state = "red"
@@ -124925,7 +125024,7 @@ aaa
aaa
laH
aaa
apO
sRw
fJr
hwP
vgv
@@ -125183,11 +125282,11 @@ aaa
laH
abq
apO
jSU
apO
nEV
nEV
exm
apO
apO
nEV
nEV
xyP
apO
apO
@@ -125440,11 +125539,11 @@ aaa
aaa
aaa
laH
aaa
aaa
aaa
aaa
tNe
nEV
jXY
jKG
rOj
nEV
oQV
ajg
jiR
@@ -125697,11 +125796,11 @@ aaa
aaa
aaa
laH
aaa
aaa
aaa
aaa
ahH
nEV
ffH
rUg
fFo
nEV
alW
akR
aDY
@@ -125954,11 +126053,11 @@ aaa
aaa
aaa
laH
aaa
aaa
aaa
aaa
ahH
nEV
nEV
nEV
nEV
nEV
aDY
wLB
cnV
@@ -126216,8 +126315,8 @@ abq
abq
abq
ajg
ajg
aVY
ahH
ahH
ajg
aWv
cXu
+3
View File
@@ -141,6 +141,9 @@
//LAVALAND
#define LAVALAND_EQUIPMENT_EFFECT_PRESSURE 50 //what pressure you have to be under to increase the effect of equipment meant for lavaland
#define LAVALAND_TEMPERATURE 500
#define LAVALAND_OXYGEN 8
#define LAVALAND_NITROGEN 14
// Reactions
#define N2O_DECOMPOSITION_MIN_ENERGY 1400
+7 -6
View File
@@ -28,12 +28,13 @@
#define BOT_EAT_TILE 19 // adding said tiles to inventory (floorbots)
//Bot types
#define SEC_BOT (1<<0) // Secutritrons (Beepsky) and ED-209s
#define MULE_BOT (1<<1) // MULEbots
#define FLOOR_BOT (1<<2) // Floorbots
#define CLEAN_BOT (1<<3) // Cleanbots
#define MED_BOT (1<<4) // Medibots
#define HONK_BOT (1<<5) // Honkbots
#define SEC_BOT "Security" // Secutritrons (Beepsky) and ED-209s
#define MULE_BOT "Mule" // MULEbots
#define FLOOR_BOT "Floorbot" // Floorbots
#define CLEAN_BOT "Cleanbot" // Cleanbots
#define MED_BOT "Medibot" // Medibots
#define HONK_BOT "Honkbot" // Honkbots
#define GRIEF_BOT "Grief" // Griefsky
//Sentience types
#define SENTIENCE_ORGANIC 1
-2
View File
@@ -1,7 +1,5 @@
//Damage things //TODO: merge these down to reduce on defines
//Way to waste perfectly good damagetype names (BRUTE) on this... If you were really worried about case sensitivity, you could have just used lowertext(damagetype) in the proc...
#define CUT "cut"
#define BRUISE "bruise"
#define BRUTE "brute"
#define BURN "fire"
#define TOX "tox"
+8 -3
View File
@@ -342,6 +342,8 @@
#define COMSIG_MIND_TRANSER_TO "mind_transfer_to"
///called on the mob instead of the mind
#define COMSIG_BODY_TRANSFER_TO "body_transfer_to"
///called when the mind is initialized (called every time the mob logins)
#define COMSIG_MIND_INITIALIZE "mind_initialize"
// /mob signals
@@ -717,9 +719,12 @@
// /obj/item/gun signals
/// called in /obj/item/gun/process_fire (user, target, params, zone_override)
#define COMSIG_MOB_FIRED_GUN "mob_fired_gun"
/// called in /obj/item/gun/process_fire (user, target)
///called in /obj/item/gun/fire_gun (user, target, flag, params)
#define COMSIG_GUN_TRY_FIRE "gun_try_fire"
#define COMPONENT_CANCEL_GUN_FIRE (1<<0)
///called in /obj/item/gun/afterattack (user, target, flag, params)
#define COMSIG_MOB_TRY_FIRE "mob_fired_gun"
///called in /obj/item/gun/process_fire (user, target)
#define COMSIG_GUN_FIRED "gun_fired"
/// called in /datum/component/automatic_fire/proc/on_mouse_down: (client/clicker, atom/target, turf/location, control, params)
#define COMSIG_AUTOFIRE_ONMOUSEDOWN "autofire_onmousedown"
+11
View File
@@ -57,6 +57,8 @@
#define EMOTE_TARGET_BHVR_RAW 4
/// The emote target should be just a number. Anything else will be rejected.
#define EMOTE_TARGET_BHVR_NUM 5
/// The emote target is used elsewhere, and processing should be skipped.
#define EMOTE_TARGET_BHVR_IGNORE 6
// This set determines the type of target that we want to check for.
@@ -75,3 +77,12 @@
/// List of emotes useable by ghosties
#define USABLE_DEAD_EMOTES list("*flip", "*spin")
// Strings used for the rock paper scissors emote and status effect
#define RPS_EMOTE_ROCK "rock"
#define RPS_EMOTE_PAPER "paper"
#define RPS_EMOTE_SCISSORS "scissors"
#define RPS_EMOTE_THEY_WIN "aww"
#define RPS_EMOTE_WE_WIN "yay"
#define RPS_EMOTE_TIE "tie"
+9 -1
View File
@@ -1,5 +1,13 @@
// Used for secondary goals.
/// Used for secondary goals.
/// TOO easy, not accepted for variety goals.
#define FOOD_GOAL_SKIP 0
/// Easy food, ask for a lot for single goals.
#define FOOD_GOAL_EASY 1
/// Normal food, ask for a middling amount for single goals.
#define FOOD_GOAL_NORMAL 2
/// Hard reagent, ask for a little for single goals.
#define FOOD_GOAL_HARD 3
/// TOO hard, accepted for variety goals, but never used for single goals.
#define FOOD_GOAL_EXCESSIVE 4
/// Same as FOOD_GOAL_EXCESSIVE, just different name to indicate that there's another version of this food that's used in variety goals.
#define FOOD_GOAL_DUPLICATE FOOD_GOAL_EXCESSIVE
+6
View File
@@ -0,0 +1,6 @@
#define HIDES_COVERED_FULL 3
#define PLATES_COVERED_FULL 3
#define DRAKE_HIDES_COVERED_SLIGHT 1
#define DRAKE_HIDES_COVERED_MODERATE 2
#define DRAKE_HIDES_COVERED_FULL 3
+5 -1
View File
@@ -250,6 +250,10 @@
0.4,0.6,0.0,\
0.2,0.2,0.6)
#define MATRIX_STANDARD list(1.0,0.0,0.0,\
0.0,1.0,0.0,\
0.0,0.0,1.0)
/*
Used for wire name appearances. Replaces the color name on the left with the one on the right.
The color on the left is the one used as the actual color of the wire, but it doesn't look good when written.
@@ -398,7 +402,7 @@
#define INVESTIGATE_BOMB "bombs"
// The SQL version required by this version of the code
#define SQL_VERSION 55
#define SQL_VERSION 56
// Vending machine stuff
#define CAT_NORMAL (1<<0)
+1
View File
@@ -298,6 +298,7 @@
#define HEALTH_HUD_OVERRIDE_HEALTHY 3
// Eye protection
#define FLASH_PROTECTION_VERYVUNERABLE -4
#define FLASH_PROTECTION_EXTRA_SENSITIVE -2
#define FLASH_PROTECTION_SENSITIVE -1
#define FLASH_PROTECTION_NONE 0
#define FLASH_PROTECTION_FLASH 1
-17
View File
@@ -1,17 +0,0 @@
#define NANOMOB_TYPE_FIRE /datum/mob_type/fire
#define NANOMOB_TYPE_WATER /datum/mob_type/water
#define NANOMOB_TYPE_GRASS /datum/mob_type/grass
#define NANOMOB_TYPE_ELECTRIC /datum/mob_type/electric
#define NANOMOB_TYPE_GROUND /datum/mob_type/ground
#define NANOMOB_TYPE_ROCK /datum/mob_type/rock
#define NANOMOB_TYPE_BUG /datum/mob_type/bug
#define NANOMOB_TYPE_POISON /datum/mob_type/poison
#define NANOMOB_TYPE_NORMAL /datum/mob_type/normal
#define NANOMOB_TYPE_FIGHTING /datum/mob_type/fighting
#define NANOMOB_TYPE_PSYCHIC /datum/mob_type/psychic
#define NANOMOB_TYPE_GHOST /datum/mob_type/ghost
#define NANOMOB_TYPE_ICE /datum/mob_type/ice
#define NANOMOB_TYPE_FLYING /datum/mob_type/flying
#define NANOMOB_TYPE_BLUESPACE /datum/mob_type/bluespace
#define NANOMOB_TYPE_DARK /datum/mob_type/dark
#define NANOMOB_TYPE_STEEL /datum/mob_type/steel
+13
View File
@@ -5,3 +5,16 @@
#define DEBRIS_GLASS "glass"
#define DEBRIS_LEAF "leaf"
#define DEBRIS_SNOW "snow"
/*
* Generator defines
*/
#define GEN_NUM "num"
#define GEN_VECTOR "vector"
#define GEN_BOX "box"
#define GEN_COLOR "color"
#define GEN_CIRCLE "circle"
#define GEN_SPHERE "sphere"
#define GEN_SQUARE "square"
#define GEN_CUBE "cube"
+6
View File
@@ -34,7 +34,13 @@
#define BLOOD_TYPE_FAKE_BLOOD "Vh Null"
/// Used for secondary goals.
/// TOO easy, not accepted for variety goals.
#define REAGENT_GOAL_SKIP 0
/// Easy reagent, ask for a lot for single goals.
#define REAGENT_GOAL_EASY 1
/// Normal reagent, ask for a middling amount for single goals.
#define REAGENT_GOAL_NORMAL 2
/// Hard reagent, ask for a little for single goals.
#define REAGENT_GOAL_HARD 3
/// TOO hard, accepted for variety goals, but never used for single goals.
#define REAGENT_GOAL_EXCESSIVE 4
+1
View File
@@ -178,6 +178,7 @@
#define STATUS_EFFECT_HIGHFIVE /datum/status_effect/high_five
#define STATUS_EFFECT_DAP /datum/status_effect/high_five/dap
#define STATUS_EFFECT_HANDSHAKE /datum/status_effect/high_five/handshake
#define STATUS_EFFECT_RPS /datum/status_effect/high_five/rps
#define STATUS_EFFECT_CHARGING /datum/status_effect/charging
-1
View File
@@ -91,7 +91,6 @@
// If the subsystem isn't listed here it's either DEFAULT or PROCESS (if it's a processing subsystem child)
#define FIRE_PRIORITY_PING 10
#define FIRE_PRIORITY_NANOMOB 10
#define FIRE_PRIORITY_NIGHTSHIFT 10
#define FIRE_PRIORITY_IDLE_NPC 10
#define FIRE_PRIORITY_CLEANUP 10
+5 -3
View File
@@ -46,9 +46,11 @@
#define WIRE_BOMB_ACTIVATE "Activate" // Will start a bombs timer if pulsed, will hint if pulsed while already active, will stop a timer a bomb on cut.
// Nuclear bomb
#define WIRE_BOMB_LIGHT "Bomb Light"
#define WIRE_BOMB_TIMING "Bomb Timing"
#define WIRE_BOMB_SAFETY "Bomb Safety"
#define WIRE_NUKE_SAFETY "Safety"
#define WIRE_NUKE_DETONATOR "Detonator"
#define WIRE_NUKE_DISARM "Disarm"
#define WIRE_NUKE_LIGHT "Lights"
#define WIRE_NUKE_CONTROL "Control Panel"
// Particle accelerator
#define WIRE_PARTICLE_POWER "Power Toggle" // Toggles whether the PA is on or not.
+5
View File
@@ -0,0 +1,5 @@
///How the scope component is toggled.
/// Wielding the object with both hands toggles the zoom. Requires the two-handed component to work.
#define ZOOM_METHOD_WIELD 1
/// Activated by clicking an item action button specified by the `item_action_type` var.
#define ZOOM_METHOD_ITEM_ACTION 2
+1
View File
@@ -223,6 +223,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_CAN_VIEW_HEALTH "can_view_health" // Also used for /Stat
#define TRAIT_MAGPULSE "magnetificent" // Used for anything that is magboot related
#define TRAIT_NOSLIP "noslip"
#define TRAIT_SCOPED "user_scoped"
#define TRAIT_MEPHEDRONE_ADAPTED "mephedrone_adapted" // Trait that changes the ending effects of twitch leaving your system
#define TRAIT_NOKNOCKDOWNSLOWDOWN "noknockdownslowdown" //If this person has this trait, they are not slowed via knockdown, but they can be hit by bullets like a self knockdown
#define TRAIT_CAN_STRIP "can_strip" // This mob can strip other mobs.
+3
View File
@@ -35,6 +35,9 @@ GLOBAL_LIST_EMPTY(beacons)
GLOBAL_LIST_EMPTY(shuttle_caller_list) //list of all communication consoles, comms consoles circuit and AIs, for automatic shuttle calls when there are none.
GLOBAL_LIST_EMPTY(tracked_implants) //list of all current implants that are tracked to work out what sort of trek everyone is on. Sadly not on lavaworld not implemented...
GLOBAL_LIST_EMPTY(pinpointer_list) //list of all pinpointers. Used to change stuff they are pointing to all at once.
GLOBAL_LIST_EMPTY(nuke_list) //list of (real) nukes
GLOBAL_LIST_EMPTY(syndi_nuke_list) //list of syndicate nukes
GLOBAL_LIST_EMPTY(nad_list) //list of (real) nuclear authentication disks
GLOBAL_LIST_EMPTY(nuclear_uplink_list) //list of all existing nuke ops uplinks
GLOBAL_LIST_EMPTY(abductor_equipment) //list of all abductor equipment
GLOBAL_LIST_EMPTY(global_intercoms) //list of all intercomms, across all z-levels
+1
View File
@@ -88,6 +88,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_FORCED_STANDING" = TRAIT_FORCED_STANDING,
"TRAIT_NOSLIP" = TRAIT_NOSLIP,
"TRAIT_MAGPULSE" = TRAIT_MAGPULSE,
"TRAIT_SCOPED" = TRAIT_SCOPED,
"TRAIT_MEPHEDRONE_ADAPTED" = TRAIT_MEPHEDRONE_ADAPTED,
"TRAIT_NOKNOCKDOWNSLOWDOWN" = TRAIT_NOKNOCKDOWNSLOWDOWN,
"TRAIT_CAN_STRIP" = TRAIT_CAN_STRIP
+2
View File
@@ -239,6 +239,8 @@ GLOBAL_LIST_EMPTY(radial_menus)
return
else
next_check = world.time + check_delay
// if you're wondering why your radial menus aren't clickable while debugging:
// it's probably the stoplag call here, try it again without any breakpoints
stoplag(1)
/datum/radial_menu/Destroy()
+1
View File
@@ -68,6 +68,7 @@ SUBSYSTEM_DEF(economy)
var/credits_per_easy_food_goal = 300
var/credits_per_normal_food_goal = 450
var/credits_per_hard_food_goal = 600
var/credits_per_variety_food_goal = 450
var/credits_per_ripley_goal = 600
var/credits_per_kudzu_goal = 600
/// credits lost for sending unsecured cargo
@@ -1,155 +0,0 @@
SUBSYSTEM_DEF(mob_hunt)
name = "Nano-Mob Hunter GO Server"
priority = FIRE_PRIORITY_NANOMOB // Low priority, no need for MC_TICK_CHECK due to extremely low performance impact.
flags = SS_NO_INIT
offline_implications = "Nano-Mob Hunter will no longer spawn mobs. No immediate action is needed."
cpu_display = SS_CPUDISPLAY_LOW
var/max_normal_spawns = 15 //change this to adjust the number of normal spawns that can exist at one time. trapped spawns (from traitors) don't count towards this
var/list/normal_spawns = list()
var/max_trap_spawns = 15 //change this to adjust the number of trap spawns that can exist at one time. traps spawned beyond this point clear the oldest traps
var/list/trap_spawns = list()
var/list/connected_clients = list()
var/server_status = 1 //1 is online, 0 is offline
var/reset_cooldown = 0 //number of controller cycles before the manual_reboot proc can be used again (ignored if server is offline so you can always boot back up)
var/obj/machinery/computer/mob_battle_terminal/red_terminal
var/obj/machinery/computer/mob_battle_terminal/blue_terminal
var/battle_turn = null
/datum/controller/subsystem/mob_hunt/fire(resumed = FALSE)
if(reset_cooldown) //if reset_cooldown is set (we are on cooldown, duh), reduce the remaining cooldown every cycle
reset_cooldown--
if(!server_status)
return
client_mob_update()
if(length(normal_spawns) < max_normal_spawns)
spawn_mob()
//leaving this here in case admins want to use it for a random mini-event or something
/datum/controller/subsystem/mob_hunt/proc/server_crash(recover_time = 3000)
server_status = 0
for(var/datum/data/pda/app/mob_hunter_game/client in connected_clients)
client.disconnect("Server Crash")
for(var/obj/effect/nanomob/N in trap_spawns)
N.despawn()
for(var/obj/effect/nanomob/N in normal_spawns)
N.despawn()
//just in case
normal_spawns.Cut()
trap_spawns.Cut()
connected_clients.Cut()
if(!isnum(recover_time))
recover_time = 3000
if(recover_time > 0) //when provided with a negative or zero valued recover_time argument, the server won't auto-restart but can be manually rebooted still
//set a timer to automatically recover after recover_time has passed (can be manually restarted if you get impatient too)
addtimer(CALLBACK(src, PROC_REF(auto_recover)), recover_time, TIMER_UNIQUE)
/datum/controller/subsystem/mob_hunt/proc/client_mob_update()
var/list/ex_players = list()
for(var/datum/data/pda/app/mob_hunter_game/client in connected_clients)
var/mob/living/carbon/human/H = client.get_player()
if(connected_clients[client])
if(!H || H != connected_clients[client])
ex_players |= connected_clients[client]
connected_clients[client] = H
if(length(ex_players)) //to make sure we don't do this if we didn't lose any player since the last update
for(var/obj/effect/nanomob/N in (normal_spawns + trap_spawns))
N.conceal(ex_players)
/datum/controller/subsystem/mob_hunt/proc/auto_recover()
if(server_status != 0)
return
server_status = 1
while(length(normal_spawns) < max_normal_spawns) //repopulate the server's spawns completely if we auto-recover from crash
spawn_mob()
/datum/controller/subsystem/mob_hunt/proc/manual_reboot()
if(server_status && reset_cooldown)
return 0
for(var/obj/effect/nanomob/N in trap_spawns)
N.despawn()
for(var/obj/effect/nanomob/N in normal_spawns)
N.despawn()
server_status = 1
reset_cooldown = 25 //25 controller cycle cooldown for manual restarts
return 1
/datum/controller/subsystem/mob_hunt/proc/spawn_mob()
var/list/nanomob_types = subtypesof(/datum/mob_hunt)
var/datum/mob_hunt/mob_info = pick(nanomob_types)
new mob_info()
/datum/controller/subsystem/mob_hunt/proc/register_spawn(datum/mob_hunt/mob_info)
if(!mob_info)
return 0
var/obj/effect/nanomob/new_mob = new /obj/effect/nanomob(mob_info.spawn_point, mob_info)
normal_spawns += new_mob
new_mob.reveal()
return 1
/datum/controller/subsystem/mob_hunt/proc/register_trap(datum/mob_hunt/mob_info)
if(!mob_info)
return 0
if(!mob_info.is_trap)
return register_spawn(mob_info)
var/obj/effect/nanomob/new_mob = new /obj/effect/nanomob(mob_info.spawn_point, mob_info)
trap_spawns += new_mob
new_mob.reveal()
if(length(trap_spawns) > max_trap_spawns)
var/obj/effect/nanomob/old_trap = trap_spawns[1]
old_trap.despawn()
return 1
/datum/controller/subsystem/mob_hunt/proc/start_check()
if(battle_turn) //somehow we got called mid-battle, so lets just stop now
return
if(red_terminal && red_terminal.ready && blue_terminal && blue_terminal.ready)
battle_turn = pick("Red", "Blue")
red_terminal.atom_say("Battle starting!")
blue_terminal.atom_say("Battle starting!")
if(battle_turn == "Red")
red_terminal.atom_say("Red Player's Turn!")
else if(battle_turn == "Blue")
blue_terminal.atom_say("Blue Player's Turn!")
/datum/controller/subsystem/mob_hunt/proc/launch_attack(team, raw_damage, datum/mob_type/attack_type)
if(!team || !raw_damage)
return
var/obj/machinery/computer/mob_battle_terminal/target = null
if(team == "Red")
target = blue_terminal
else if(team == "Blue")
target = red_terminal
else
return
target.receive_attack(raw_damage, attack_type)
/datum/controller/subsystem/mob_hunt/proc/end_battle(loser, surrender = 0)
var/obj/machinery/computer/mob_battle_terminal/winner_terminal = null
var/obj/machinery/computer/mob_battle_terminal/loser_terminal = null
if(loser == "Red")
loser_terminal = red_terminal
winner_terminal = blue_terminal
else if(loser == "Blue")
loser_terminal = blue_terminal
winner_terminal = red_terminal
battle_turn = null
winner_terminal.ready = FALSE
loser_terminal.ready = FALSE
if(surrender) //surrender doesn't give exp, to avoid people just farming exp without actually doing a battle
winner_terminal.atom_say("Your rival surrendered!")
else
var/progress_message = winner_terminal.mob_info.gain_exp()
winner_terminal.atom_say("[winner_terminal.team] Player wins!")
winner_terminal.atom_say(progress_message)
/datum/controller/subsystem/mob_hunt/proc/end_turn()
red_terminal.updateUsrDialog()
blue_terminal.updateUsrDialog()
if(!battle_turn)
return
if(battle_turn == "Red")
battle_turn = "Blue"
blue_terminal.atom_say("Blue's turn.")
else if(battle_turn == "Blue")
battle_turn = "Red"
blue_terminal.atom_say("Red's turn.")
+6
View File
@@ -38,6 +38,8 @@ SUBSYSTEM_DEF(shuttle)
var/custom_escape_shuttle_loading = FALSE
/// Whether or not a shuttle is currently being loaded at the template landmark, if it exists.
var/loading_shuttle_at_preview_template = FALSE
/// Have we locked in the emergency shuttle, to prevent people from breaking things / wasting player money?
var/emergency_locked_in = FALSE
/datum/controller/subsystem/shuttle/Initialize()
if(!emergency)
@@ -316,6 +318,8 @@ SUBSYSTEM_DEF(shuttle)
if(loading_shuttle_at_preview_template)
CRASH("A shuttle was already loading at the preview template when another was loaded")
S.preload()
loading_shuttle_at_preview_template = TRUE
var/turf/landmark_turf = get_turf(locate("landmark*Shuttle Import"))
S.load(landmark_turf, centered = TRUE)
@@ -377,6 +381,8 @@ SUBSYSTEM_DEF(shuttle)
timer = emergency.timer
mode = emergency.mode
dock = emergency.get_docked()
if(!dock) //lance moment
dock = getDock("emergency_away")
else
dock = loaded_shuttle.findRoundstartDock()
+2 -1
View File
@@ -78,6 +78,8 @@
/datum/action/proc/Trigger(left_click = TRUE)
if(!IsAvailable())
return FALSE
if(SEND_SIGNAL(src, COMSIG_ACTION_TRIGGER, src) & COMPONENT_ACTION_BLOCK_TRIGGER)
return FALSE
return TRUE
/datum/action/proc/AltTrigger()
@@ -570,7 +572,6 @@
var/obj/item/clothing/shoes/magboots/gravity/G = target
G.dash(usr)
///prset for organ actions
/datum/action/item_action/organ_action
check_flags = AB_CHECK_CONSCIOUS
+1 -30
View File
@@ -3,35 +3,6 @@
* Originally from https://github.com/tgstation/TerraGov-Marine-Corps/pull/12752
*/
/particles/debris
icon = 'icons/effects/particles/generic_particles.dmi'
width = 500
height = 500
count = 10
spawning = 10
lifespan = 0.5 SECONDS
fade = 0.3 SECONDS
drift = generator("circle", 0, 7)
scale = 0.3
velocity = list(50, 0)
friction = generator("num", 0.1, 0.15)
spin = generator("num", -20, 20)
/particles/impact_smoke
icon = 'icons/effects/effects.dmi'
icon_state = "smoke"
width = 500
height = 500
count = 20
spawning = 20
lifespan = 0.8 SECONDS
fade = 10 SECONDS
grow = 0.1
scale = 0.2
spin = generator("num", -20, 20)
velocity = list(50, 0)
friction = generator("num", 0.1, 0.5)
/datum/component/debris
/// Icon state of debris when impacted by a projectile
var/debris
@@ -76,7 +47,7 @@
if(debris && P.damage_type == BRUTE)
debris_visuals = new(parent, /particles/debris)
debris_visuals.particles.position = generator("circle", position_offset, position_offset)
debris_visuals.particles.position = generator(GEN_CIRCLE, position_offset, position_offset)
debris_visuals.particles.velocity = list(x_component, y_component)
debris_visuals.layer = ABOVE_OBJ_LAYER + 0.02
debris_visuals.particles.icon_state = debris
+3
View File
@@ -262,6 +262,9 @@
current_windup_reduction = (current_windup_reduction + round(autofire_shot_delay * windup_autofire_reduction_multiplier))
timerid = addtimer(CALLBACK(src, PROC_REF(windup_reset), FALSE), windup_spindown, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_STOPPABLE)
if(shooter.next_move_modifier) //DNA vault, mephemdrone, bluespace slowness debuff.
next_delay = round(next_delay * shooter.next_move_modifier, SSprojectiles.wait)
COOLDOWN_START(src, next_shot_cd, next_delay)
if(SEND_SIGNAL(parent, COMSIG_AUTOFIRE_SHOT, target, shooter, allow_akimbo, mouse_parameters) & COMPONENT_AUTOFIRE_SHOT_SUCCESS)
+273
View File
@@ -0,0 +1,273 @@
///A component that allows players to use the item to zoom out. Mainly intended for firearms, but now works with other items too.
/datum/component/scope
/// How far the view can be moved from the player. At 1, it can be moved by the player's view distance; other values scale linearly.
var/range_modifier = 1
/// Fullscreen object we use for tracking.
var/atom/movable/screen/fullscreen/stretch/cursor_catcher/scope/tracker
/// The owner of the tracker's ckey. For comparing with the current owner mob, in case the client has left it (e.g. ghosted).
var/tracker_owner_ckey
/// The method which we zoom in and out
var/zoom_method = ZOOM_METHOD_ITEM_ACTION
/// if not null, an item action will be added. Redundant if the mode is ZOOM_METHOD_RIGHT_CLICK or ZOOM_METHOD_WIELD.
var/item_action_type
/// Time to scope up, if you want the scope to take time to boot up. Used by the LWAP
var/time_to_scope
/// Do we let the user scope and click on the middle of their screen?
var/allow_middle_click = FALSE
/// Do we have the scope cancel on move?
var/movement_cancels_scope = FALSE
/datum/component/scope/Initialize(range_modifier = 1, zoom_method = ZOOM_METHOD_ITEM_ACTION, item_action_type = /datum/action/zoom, time_to_scope = 0, allow_middle_click = FALSE, movement_cancels_scope = FALSE)
if(!isitem(parent))
return COMPONENT_INCOMPATIBLE
src.range_modifier = range_modifier
src.zoom_method = zoom_method
src.item_action_type = item_action_type
src.time_to_scope = time_to_scope
src.allow_middle_click = allow_middle_click
src.movement_cancels_scope = movement_cancels_scope
/datum/component/scope/Destroy(force)
if(is_zoomed_in())
stop_zooming(tracker.owner)
return ..()
/datum/component/scope/RegisterWithParent()
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) //Checks for being removed for person, not mob movement
if(zoom_method == ZOOM_METHOD_WIELD)
RegisterSignal(parent, SIGNAL_ADDTRAIT(TRAIT_WIELDED), PROC_REF(on_wielded))
RegisterSignal(parent, SIGNAL_REMOVETRAIT(TRAIT_WIELDED), PROC_REF(on_unwielded))
if(item_action_type)
var/obj/item/parent_item = parent
var/datum/action/scope = new item_action_type(parent)
parent_item.actions += scope
RegisterSignal(scope, COMSIG_ACTION_TRIGGER, PROC_REF(on_action_trigger))
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, PROC_REF(on_examine))
if(istype(parent, /obj/item/gun))
RegisterSignal(parent, COMSIG_GUN_TRY_FIRE, PROC_REF(on_gun_fire))
/datum/component/scope/UnregisterFromParent()
if(item_action_type)
var/obj/item/parent_item = parent
var/datum/action/scope = locate(item_action_type) in parent_item.actions
parent_item.actions -= scope
UnregisterSignal(parent, list(
COMSIG_MOVABLE_MOVED,
SIGNAL_ADDTRAIT(TRAIT_WIELDED),
SIGNAL_REMOVETRAIT(TRAIT_WIELDED),
COMSIG_GUN_TRY_FIRE,
COMSIG_PARENT_EXAMINE,
))
/datum/component/scope/process()
var/mob/user_mob = tracker.owner
var/client/user_client = user_mob.client
if(!user_client)
stop_zooming(user_mob)
return
tracker.calculate_params()
animate(user_client, world.tick_lag, pixel_x = tracker.given_x, pixel_y = tracker.given_y)
/datum/component/scope/proc/on_move(atom/movable/source, atom/oldloc, dir, forced)
SIGNAL_HANDLER // COMSIG_MOVABLE_MOVED
if(!is_zoomed_in())
return
if(source.loc != tracker.owner) //Dropped.
to_chat(tracker.owner, "<span class='warning'>[parent]'s scope is overloaded by movement and shuts down!</span>")
stop_zooming(tracker.owner)
/datum/component/scope/proc/on_action_trigger(datum/action/source)
SIGNAL_HANDLER // COMSIG_ACTION_TRIGGER
var/obj/item/item = source.target
var/mob/living/user = item.loc
if(is_internal_organ(item))
var/obj/item/organ/internal/O = item
user = O.owner
if(is_zoomed_in())
stop_zooming(user)
else
INVOKE_ASYNC(src, PROC_REF(zoom), user)
/datum/component/scope/proc/on_wielded(obj/item/source, trait)
SIGNAL_HANDLER // SIGNAL_ADDTRAIT(TRAIT_WIELDED)
var/mob/living/user = source.loc
INVOKE_ASYNC(src, PROC_REF(zoom), user)
/datum/component/scope/proc/on_unwielded(obj/item/source, trait)
SIGNAL_HANDLER // SIGNAL_REMOVETRAIT(TRAIT_WIELDED)
var/mob/living/user = source.loc
stop_zooming(user)
/datum/component/scope/proc/on_gun_fire(obj/item/gun/source, mob/living/user, atom/target, flag, params)
SIGNAL_HANDLER // COMSIG_GUN_TRY_FIRE
if(!tracker?.given_turf || target == get_target(tracker.given_turf))
return NONE
INVOKE_ASYNC(source, TYPE_PROC_REF(/obj/item, afterattack), get_target(tracker.given_turf), user)
return COMPONENT_CANCEL_GUN_FIRE
/datum/component/scope/proc/on_examine(datum/source, mob/user, list/examine_list)
SIGNAL_HANDLER // COMSIG_PARENT_EXAMINE
var/scope = istype(parent, /obj/item/gun) ? "scope in" : "zoom out"
switch(zoom_method)
if(ZOOM_METHOD_WIELD)
examine_list += "<span class='notice'>You can [scope] by wielding it with both hands.</span>"
/**
* We find and return the best target to hit on a given turf.
*
* Arguments:
* * target_turf: The turf we are looking for targets on.
*/
/datum/component/scope/proc/get_target(turf/target_turf)
var/list/non_dense_targets = list()
for(var/atom/movable/possible_target in target_turf)
if(possible_target.layer <= PROJECTILE_HIT_THRESHHOLD_LAYER)
continue
if(possible_target.invisibility > tracker.owner.see_invisible)
continue
if(!possible_target.mouse_opacity)
continue
if(iseffect(possible_target))
continue
if(ismob(possible_target))
if(possible_target == tracker.owner)
continue
return possible_target
if(!possible_target.density)
non_dense_targets += possible_target
continue
return possible_target
if(length(non_dense_targets))
return non_dense_targets[1]
return target_turf
/**
* We start zooming by adding our tracker overlay and starting our processing.
*
* Arguments:
* * user: The mob we are starting zooming on.
*/
/datum/component/scope/proc/zoom(mob/user)
if(isnull(user.client))
return
if(HAS_TRAIT(user, TRAIT_SCOPED))
to_chat(user, "<span class='warning'>You are already zoomed in!</span>")
return
if(time_to_scope)
if(!do_after_once(user, time_to_scope, target = parent))
return
user.playsound_local(parent, 'sound/weapons/scope.ogg', 75, TRUE)
tracker = user.overlay_fullscreen("scope", /atom/movable/screen/fullscreen/stretch/cursor_catcher/scope, istype(parent, /obj/item/gun))
tracker.assign_to_mob(user, range_modifier)
if(movement_cancels_scope)
RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(on_move))
if(allow_middle_click)
RegisterSignal(tracker, COMSIG_CLICK, PROC_REF(generic_click))
tracker_owner_ckey = user.ckey
if(user.is_holding(parent))
RegisterSignals(user, list(COMSIG_CARBON_SWAP_HANDS, COMSIG_PARENT_QDELETING), PROC_REF(stop_zooming))
else // The item is likely worn.
RegisterSignal(user, COMSIG_PARENT_QDELETING, PROC_REF(stop_zooming))
var/static/list/capacity_signals = list(
COMSIG_LIVING_STATUS_PARALYSE,
COMSIG_LIVING_STATUS_STUN,
)
RegisterSignals(user, capacity_signals, PROC_REF(on_incapacitated))
START_PROCESSING(SSprojectiles, src)
ADD_TRAIT(user, TRAIT_SCOPED, "[UID(src)]")
if(istype(parent, /obj/item/gun))
var/obj/item/gun/G = parent
G.on_scope_success(user)
return TRUE
/datum/component/scope/proc/on_incapacitated(mob/living/source, amount = 0, ignore_canstun = FALSE)
SIGNAL_HANDLER // COMSIG_LIVING_STATUS_PARALYSE, COMSIG_LIVING_STATUS_STUN
if(amount > 0)
stop_zooming(source)
/datum/component/scope/proc/generic_click(/obj/source, location, control, params)
SIGNAL_HANDLER // COMSIG_CLICK
INVOKE_ASYNC(tracker.owner, TYPE_PROC_REF(/mob, ClickOn), get_target(tracker.given_turf), params)
/**
* We stop zooming, canceling processing, resetting stuff back to normal and deleting our tracker.
*
* Arguments:
* * user: The mob we are canceling zooming on.
*/
/datum/component/scope/proc/stop_zooming(mob/user)
SIGNAL_HANDLER // COMSIG_CARBON_SWAP_HANDS, COMSIG_PARENT_QDELETING
if(!HAS_TRAIT(user, TRAIT_SCOPED))
return
STOP_PROCESSING(SSprojectiles, src)
UnregisterSignal(user, list(
COMSIG_LIVING_STATUS_PARALYSE,
COMSIG_LIVING_STATUS_STUN,
COMSIG_CARBON_SWAP_HANDS,
COMSIG_PARENT_QDELETING,
))
REMOVE_TRAIT(user, TRAIT_SCOPED, "[UID(src)]")
user.playsound_local(parent, 'sound/weapons/scope.ogg', 75, TRUE, frequency = -1)
user.clear_fullscreen("scope")
// if the client has ended up in another mob, find that mob so we can fix their cursor
var/mob/true_user
if(user.ckey != tracker_owner_ckey)
true_user = get_mob_by_ckey(tracker_owner_ckey)
if(!isnull(true_user))
user = true_user
if(user.client)
animate(user.client, 0.2 SECONDS, pixel_x = 0, pixel_y = 0)
UnregisterSignal(user, COMSIG_MOVABLE_MOVED)
QDEL_NULL(tracker)
tracker_owner_ckey = null
if(istype(parent, /obj/item/gun))
var/obj/item/gun/G = parent
G.on_scope_end(user)
/datum/component/scope/proc/is_zoomed_in()
return !!tracker
/atom/movable/screen/fullscreen/stretch/cursor_catcher/scope
icon = 'icons/mob/screen_scope.dmi'
icon_state = "scope"
/// Multiplier for given_X an given_y.
var/range_modifier = 1
/atom/movable/screen/fullscreen/stretch/cursor_catcher/scope/assign_to_mob(mob/new_owner, range_modifier)
src.range_modifier = range_modifier
return ..()
/atom/movable/screen/fullscreen/stretch/cursor_catcher/scope/Click(location, control, params)
if(usr == owner)
calculate_params()
SEND_SIGNAL(src, COMSIG_CLICK, location, control, params)
return ..()
/atom/movable/screen/fullscreen/stretch/cursor_catcher/scope/calculate_params()
var/list/modifiers = params2list(mouse_params)
var/icon_x = text2num(LAZYACCESS(modifiers, "vis-x"))
if(isnull(icon_x))
icon_x = text2num(LAZYACCESS(modifiers, "icon-x"))
var/icon_y = text2num(LAZYACCESS(modifiers, "vis-y"))
if(isnull(icon_y))
icon_y = text2num(LAZYACCESS(modifiers, "icon-y"))
given_x = round(range_modifier * (icon_x - view_list[1] * world.icon_size / 2))
given_y = round(range_modifier * (icon_y - view_list[2] * world.icon_size / 2))
given_turf = locate(owner.x + round(given_x / world.icon_size, 1), owner.y + round(given_y / world.icon_size, 1), owner.z)
/datum/action/zoom
name = "Toggle Scope"
check_flags = AB_CHECK_CONSCIOUS|AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_LYING
button_icon_state = "sniper_zoom"
+8
View File
@@ -951,6 +951,14 @@
log_admin("[key_name(usr)] has added [amount] units of [chosen_id] to \the [A]")
message_admins("<span class='notice'>[key_name(usr)] has added [amount] units of [chosen_id] to \the [A]</span>")
else if(href_list["editreagents"])
if(!check_rights(R_DEBUG|R_ADMIN))
return
var/atom/A = locateUID(href_list["editreagents"])
try_open_reagent_editor(A)
else if(href_list["explode"])
if(!check_rights(R_DEBUG|R_EVENT)) return
+1 -1
View File
@@ -35,7 +35,7 @@
/// Handles the actual shattering part, throwing shards of whatever is defined on the component everywhere
/datum/element/shatters_when_thrown/proc/shatter(atom/movable/source, atom/hit_atom)
var/generator/scatter_gen = generator("circle", 0, 48, NORMAL_RAND)
var/generator/scatter_gen = generator(GEN_CIRCLE, 0, 48, NORMAL_RAND)
var/scatter_turf = get_turf(hit_atom)
for(var/obj/item/scattered_item as anything in source.contents)
+21 -9
View File
@@ -147,16 +147,16 @@
*
* Arguments:
* * user - Person that is trying to send the emote.
* * params - Parameters added after the emote.
* * emote_arg - String parameter added after the emote.
* * type_override - Override to the current emote_type.
* * intentional - Bool that says whether the emote was forced (FALSE) or not (TRUE).
*
* Returns TRUE if it was able to run the emote, FALSE otherwise.
*/
/datum/emote/proc/run_emote(mob/user, params, type_override, intentional = FALSE)
/datum/emote/proc/run_emote(mob/user, emote_arg, type_override, intentional = FALSE)
. = TRUE
var/msg = select_message_type(user, message, intentional)
if(params && message_param)
if(emote_arg && message_param)
// In this case, we did make some changes to the message that will be used, and we want to add the postfix on with the new parameters.
// This is applicable to things like mimes, who this lets have a target on their canned emote responses.
// Note that we only do this if we would otherwise have a message param, meaning there should be some target by default.
@@ -164,17 +164,17 @@
if(message_param == EMOTE_PARAM_USE_POSTFIX || (msg != message && message_postfix))
if(!message_postfix)
CRASH("Emote was specified to use postfix but message_postfix is empty.")
msg = select_param(user, params, "[remove_ending_punctuation(msg)] [message_postfix]", msg)
msg = select_param(user, emote_arg, "[remove_ending_punctuation(msg)] [message_postfix]", msg)
else if(msg == message)
// In this case, we're not making any substitutions in select_message_type, but we do have some params we want to sub in.
msg = select_param(user, params, message_param, message)
msg = select_param(user, emote_arg, message_param, message)
// If this got propogated up, jump out.
if(msg == EMOTE_ACT_STOP_EXECUTION)
return TRUE
if(isnull(msg))
to_chat(user, "<span class='warning'>'[params]' isn't a valid parameter for [key].</span>")
to_chat(user, "<span class='warning'>'[emote_arg]' isn't a valid parameter for [key].</span>")
return TRUE
msg = replace_pronoun(user, msg)
@@ -230,13 +230,13 @@
* Try to run an emote, checking can_run_emote once before executing the emote itself.
*
* * user - User of the emote
* * params - Params of the emote to be passed to run_emote
* * params - An optional extra argument included after the emote key.
* * type_override - emote type to override the existing one with, if given.
* * intentional - Whether or not the emote was triggered intentionally (if false, the emote was forced by code).
*
* Returns TRUE if the emote was able to be run (or failed successfully), or FALSE if the emote is unusable.
*/
/datum/emote/proc/try_run_emote(mob/user, params, type_override, intentional = FALSE)
/datum/emote/proc/try_run_emote(mob/user, emote_arg, type_override, intentional = FALSE)
// You can use this signal to block execution of emotes from components/other sources.
var/sig_res = SEND_SIGNAL(user, COMSIG_MOB_PREEMOTE, key, intentional)
switch(sig_res)
@@ -245,9 +245,18 @@
if(COMPONENT_BLOCK_EMOTE_SILENT)
return TRUE
. = run_emote(user, params, type_override, intentional)
. = run_emote(user, emote_arg, type_override, intentional)
// safeguard in case these get modified
reset_emote()
/**
* Reset the emote back to its original state.
* Necessary if you've made modifications to the emote itself over the course of its
* execution, as emotes are singletons, and changes would be reflected on every usage of the emote.
*/
/datum/emote/proc/reset_emote()
SHOULD_CALL_PARENT(TRUE)
message = initial(message)
message_param = initial(message_param)
@@ -421,6 +430,9 @@
*/
/datum/emote/proc/select_param(mob/user, params, substitution, base_message)
if(target_behavior == EMOTE_TARGET_BHVR_IGNORE)
return base_message
if(target_behavior == EMOTE_TARGET_BHVR_RAW)
return replacetext(substitution, "%t", params)
+2
View File
@@ -1786,6 +1786,7 @@
//Initialisation procs
/mob/proc/mind_initialize()
SHOULD_CALL_PARENT(TRUE)
if(mind)
mind.key = key
else
@@ -1797,6 +1798,7 @@
if(!mind.name)
mind.name = real_name
mind.current = src
SEND_SIGNAL(src, COMSIG_MIND_INITIALIZE)
//HUMAN
/mob/living/carbon/human/mind_initialize()
+14 -1
View File
@@ -50,7 +50,20 @@
/datum/outfit/proc/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
//to be overriden for toggling internals, id binding, access etc
return
SHOULD_CALL_PARENT(TRUE)
if(visualsOnly)
return
if(H.mind)
on_mind_initialize(H)
return
RegisterSignal(H, COMSIG_MIND_INITIALIZE, PROC_REF(on_mind_initialize))
// Guaranteed access to mind, will never be called if visualsOnly = TRUE
/datum/outfit/proc/on_mind_initialize(mob/living/carbon/human/H)
SIGNAL_HANDLER // COMSIG_MIND_INITIALIZE
SHOULD_CALL_PARENT(TRUE)
UnregisterSignal(H, COMSIG_MIND_INITIALIZE) // prevent this call from being called multiple times on a human
/datum/outfit/proc/equip(mob/living/carbon/human/H, visualsOnly = FALSE)
pre_equip(H, visualsOnly)
+22 -26
View File
@@ -3,21 +3,15 @@
/datum/outfit/admin/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
. = ..()
if(!visualsOnly && H.mind)
H.mind.assigned_role = name
H.job = name
/datum/outfit/admin/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
. = ..()
if(visualsOnly)
return
if(H.mind)
H.mind.offstation_role = TRUE
else
H.RegisterSignal(H, COMSIG_HUMAN_LOGIN, TYPE_PROC_REF(/mob/living/carbon/human, apply_offstation_roles))
H.job = name
/datum/outfit/admin/on_mind_initialize(mob/living/carbon/human/H)
. = ..()
H.mind.assigned_role = name
H.mind.offstation_role = TRUE
/proc/apply_to_card(obj/item/card/id/I, mob/living/carbon/human/H, list/access = list(), rank, special_icon)
if(!istype(I) || !istype(H))
@@ -1250,17 +1244,17 @@
if(istype(I))
apply_to_card(I, H, get_all_accesses(), "Ancient One", "data")
if(H.mind)
if(!H.mind.has_antag_datum(/datum/antagonist/vampire))
H.mind.make_vampire(TRUE)
var/datum/antagonist/vampire/V = H.mind.has_antag_datum(/datum/antagonist/vampire)
V.bloodusable = 9999
V.bloodtotal = 9999
V.add_subclass(SUBCLASS_ANCIENT, FALSE)
H.dna.SetSEState(GLOB.jumpblock, TRUE)
singlemutcheck(H, GLOB.jumpblock, MUTCHK_FORCED)
H.update_mutations()
H.gene_stability = 100
/datum/outfit/admin/ancient_vampire/on_mind_initialize(mob/living/carbon/human/H)
. = ..()
H.mind.make_vampire()
var/datum/antagonist/vampire/V = H.mind.has_antag_datum(/datum/antagonist/vampire)
V.bloodusable = 9999
V.bloodtotal = 9999
V.add_subclass(SUBCLASS_ANCIENT, FALSE)
H.dna.SetSEState(GLOB.jumpblock, TRUE)
singlemutcheck(H, GLOB.jumpblock, MUTCHK_FORCED)
H.update_mutations()
H.gene_stability = 100
/datum/outfit/admin/wizard
name = "Blue Wizard"
@@ -1490,10 +1484,6 @@
H.real_name = "Unknown" //Enforcers sacrifice their name to Oblivion for their power
for(var/spell_path in spell_paths)
var/S = new spell_path
H.mind.AddSpell(S)
var/obj/item/clothing/suit/hooded/oblivion/robes = H.wear_suit
if(istype(robes))
robes.ToggleHood()
@@ -1502,6 +1492,12 @@
if(istype(I))
apply_to_card(I, H, get_all_accesses(), "Oblivion Enforcer")
/datum/outfit/admin/enforcer/on_mind_initialize(mob/living/carbon/human/H)
. = ..()
for(var/spell_path in spell_paths)
var/S = new spell_path
H.mind.AddSpell(S)
/datum/outfit/admin/viper
name = "Solar Federation Viper Infiltrator"
+105
View File
@@ -0,0 +1,105 @@
/*
MARK: Impact debris + smoke
*/
/particles/debris
icon = 'icons/effects/particles/generic_particles.dmi'
width = 500
height = 500
count = 10
spawning = 10
lifespan = 0.5 SECONDS
fade = 0.3 SECONDS
drift = generator(GEN_CIRCLE, 0, 7)
scale = 0.3
velocity = list(50, 0)
friction = generator(GEN_NUM, 0.1, 0.15)
spin = generator(GEN_NUM, -20, 20)
/particles/impact_smoke
icon = 'icons/effects/effects.dmi'
icon_state = "smoke"
width = 500
height = 500
count = 20
spawning = 20
lifespan = 0.8 SECONDS
fade = 10 SECONDS
grow = 0.1
scale = 0.2
spin = generator(GEN_NUM, -20, 20)
velocity = list(50, 0)
friction = generator(GEN_NUM, 0.1, 0.5)
/*
MARK: Explosion smoke
*/
/particles/explosion_smoke
icon = 'icons/effects/96x96.dmi'
icon_state = "smoke3"
width = 1000
height = 1000
count = 45
spawning = 45
gradient = list("#FA9632", "#C3630C", "#333333", "#808080", "#FFFFFF")
lifespan = 2.5 SECONDS
fade = 2 SECONDS
color = generator(GEN_NUM, 0, 0.25)
color_change = generator(GEN_NUM, 0.04, 0.05)
velocity = generator(GEN_CIRCLE, 15, 15)
drift = generator(GEN_CIRCLE, 0, 1, NORMAL_RAND)
spin = generator(GEN_NUM, -20, 20)
friction = generator(GEN_NUM, 0.1, 0.5)
gravity = list(1, 2)
scale = 0.25
grow = 0.05
/particles/explosion_smoke/deva
scale = 0.5
velocity = generator(GEN_CIRCLE, 23, 23)
/particles/explosion_smoke/small
count = 15
spawning = 15
scale = 0.25
velocity = generator(GEN_CIRCLE, 10, 10)
/particles/smoke_wave
icon = 'icons/effects/96x96.dmi'
icon_state = "smoke3"
width = 750
height = 750
count = 75
spawning = 75
lifespan = 3 SECONDS
fade = 6 SECONDS
gradient = list("#BA9F6D", "#808080", "#FFFFFF")
color = generator(GEN_NUM, 0, 0.25)
color_change = generator(GEN_NUM, 0.08, 0.07)
velocity = generator(GEN_CIRCLE, 15, 15)
rotation = generator(GEN_NUM, -45, 45)
scale = 0.15
grow = 0.05
friction = 0.1
/particles/smoke_wave/small
count = 45
spawning = 45
scale = 0.05
lifespan = 2 SECONDS
fade = 5 SECONDS
/particles/sparks_outwards
icon = 'icons/effects/64x64.dmi'
icon_state = "flare"
width = 750
height = 750
count = 40
spawning = 20
lifespan = 5 SECONDS
fade = 2 SECONDS
position = generator(GEN_SPHERE, 8, 8)
velocity = generator(GEN_CIRCLE, 30, 30)
scale = 0.1
friction = 0.1
+8
View File
@@ -224,3 +224,11 @@
suffix = "lavaland_surface_watcher_grave.dmm"
cost = 5
allow_duplicates = FALSE
/datum/map_template/ruin/lavaland/shuttlecrash
name = "Crashed Passenger Shuttle"
id = "shuttlecrash"
description = "A passenger shuttle crashsite of indeterminate origin."
suffix = "lavaland_surface_shuttlecrash.dmm"
cost = 5
allow_duplicates = FALSE
+40
View File
@@ -8,6 +8,9 @@
var/description
var/admin_notes
/datum/map_template/shuttle/proc/preload()
return
/datum/map_template/shuttle/New()
if(port_id && suffix)
shuttle_id = "[port_id]_[suffix]"
@@ -125,6 +128,43 @@
description = "Guaranteed to get you somewhere FAST. With a custom-built plasma engine, this bad boy will put more distance between you and certain danger than any other!"
admin_notes = "The aft of the ship has a plasma tank that starts ignited. May get released by crew. The plasma windows next to the engine heaters will also erupt into flame, and also risk getting released by crew."
/datum/map_template/shuttle/emergency/lance
suffix = "lance"
name = "The Lance Crew Evacuation System"
description = "A brand new shuttle by Nanotrasen's finest in shuttle-engineering, it's designed to tactically slam into a destroyed station, \
dispatching threats and saving crew at the same time! \
Be careful to stay out of it's path. Comes with a beacon to choose where it docks!"
admin_notes = "WARNING: This shuttle is designed to crash into the station. It has turrets, similar to the raven. Place down the beacon please. Once the shuttle is loaded, it cannot be unloaded."
/datum/map_template/shuttle/emergency/lance/preload()
message_admins("Preloading [name]!")
var/obj/docking_port/stationary/CCport
CCport = SSshuttle.getDock("emergency_away")
CCport.setDir(4)
CCport.forceMove(locate(136, 107, 1))
CCport.height = 50
CCport.dheight = 0
CCport.width = 19
CCport.dwidth = 9
var/obj/docking_port/stationary/CCtransit
CCtransit = SSshuttle.getDock("emergency_transit")
CCtransit.setDir(2)
CCtransit.forceMove(locate(113, 68, 1))
CCtransit.height = 50
CCtransit.dheight = 0
CCtransit.width = 19
CCtransit.dwidth = 9
var/obj/docking_port/stationary/syndicate
syndicate = SSshuttle.getDock("emergency_syndicate")
syndicate.setDir(8)
syndicate.forceMove(locate(202, 199, 1))
syndicate.height = 50
syndicate.dheight = 0
syndicate.width = 19
syndicate.dwidth = 9
qdel(SSshuttle.getDock("emergency_home"), TRUE)
SSshuttle.emergency_locked_in = TRUE
/datum/map_template/shuttle/ferry/base
suffix = "base"
name = "transport ferry"
+111 -24
View File
@@ -69,6 +69,20 @@
user.remove_status_effect(type)
highfived.remove_status_effect(type)
/datum/status_effect/high_five/proc/wiz_effect(mob/living/carbon/user, mob/living/carbon/highfived)
user.status_flags |= GODMODE
highfived.status_flags |= GODMODE
explosion(get_turf(user), 5, 2, 1, 3, cause = id)
// explosions have a spawn so this makes sure that we don't get gibbed
addtimer(CALLBACK(src, PROC_REF(wiz_cleanup), user, highfived), 0.3 SECONDS) // I want to be sure this lasts long enough, with lag.
add_attack_logs(user, highfived, "caused a wizard [id] explosion")
/datum/status_effect/high_five/proc/post_start()
return
/datum/status_effect/high_five/proc/regular_effect(mob/living/carbon/user, mob/living/carbon/highfived)
user.visible_message("<span class='notice'><b>[user.name]</b> and <b>[highfived.name]</b> [success]</span>")
/datum/status_effect/high_five/on_apply()
if(!iscarbon(owner))
return FALSE
@@ -82,25 +96,23 @@
continue
if(is_wiz && iswizard(C))
user.visible_message("<span class='biggerdanger'><b>[user.name]</b> and <b>[C.name]</b> [critical_success]</span>")
user.status_flags |= GODMODE
C.status_flags |= GODMODE
explosion(get_turf(user), 5, 2, 1, 3, cause = id)
// explosions have a spawn so this makes sure that we don't get gibbed
addtimer(CALLBACK(src, PROC_REF(wiz_cleanup), user, C), 0.3 SECONDS) //I want to be sure this lasts long enough, with lag.
add_attack_logs(user, C, "caused a wizard [id] explosion")
wiz_effect(user, C)
both_wiz = TRUE
user.do_attack_animation(C, no_effect = TRUE)
C.do_attack_animation(user, no_effect = TRUE)
playsound(user, sound_effect, 80)
if(!both_wiz)
user.visible_message("<span class='notice'><b>[user.name]</b> and <b>[C.name]</b> [success]</span>")
regular_effect(user, C)
user.remove_status_effect(type)
C.remove_status_effect(type)
return FALSE
// We can return to break out of the loop here so we don't auto-remove (which causes the timer on the wizard highfive to break)
// This is safe because we only pass the continue if we don't have the status effect
return TRUE // DO NOT AUTOREMOVE
owner.custom_emote(EMOTE_VISIBLE, request)
owner.create_point_bubble_from_path(item_path, FALSE)
post_start()
/datum/status_effect/high_five/on_timeout()
owner.visible_message("[owner] [get_missed_message()]")
@@ -144,6 +156,96 @@
return pick(missed_messages)
/datum/status_effect/high_five/rps
id = "rps"
critical_success = "both play rock -- THEY'RE GOING IN FOR THE FISTBUMP!"
success = "play rock-paper-scissors!"
sound_effect = 'sound/effects/glassknock.ogg'
request = "wants to play rock-paper-scissors!"
item_path = /obj/item/claymore // it's time to d-d-d-d-d-d-d-duel!
/// The move that you'll be making.
var/move
/datum/status_effect/high_five/rps/get_missed_message()
var/list/missed_messages = list(
"just seems to be practicing against [owner.p_themselves()]. [owner.p_are(TRUE)] [owner.p_they()] losing?",
"seems more interested in a thumb war."
)
return pick(missed_messages)
/datum/status_effect/high_five/rps/proc/get_move_status(my_move, their_move)
if(my_move == their_move)
return RPS_EMOTE_TIE
switch(my_move)
if(RPS_EMOTE_ROCK)
return their_move == RPS_EMOTE_SCISSORS ? RPS_EMOTE_WE_WIN : RPS_EMOTE_THEY_WIN
if(RPS_EMOTE_PAPER)
return their_move == RPS_EMOTE_ROCK ? RPS_EMOTE_WE_WIN : RPS_EMOTE_THEY_WIN
if(RPS_EMOTE_SCISSORS)
return their_move == RPS_EMOTE_PAPER ? RPS_EMOTE_WE_WIN : RPS_EMOTE_THEY_WIN
else
CRASH("Unknown emote rock type")
/datum/status_effect/high_five/rps/post_start()
playsound(owner, 'sound/effects/glassknock.ogg', 50, FALSE)
/datum/status_effect/high_five/rps/regular_effect(mob/living/carbon/user, mob/living/carbon/highfived)
var/datum/status_effect/high_five/rps/their_status_effect = highfived.has_status_effect(type)
var/outcome = get_move_status(move, their_status_effect.move)
var/outcome_msg
switch(outcome)
if(RPS_EMOTE_TIE)
outcome_msg = "It's a tie!"
if(RPS_EMOTE_WE_WIN)
outcome_msg = "[user] wins!"
if(RPS_EMOTE_THEY_WIN)
outcome_msg = "[highfived] wins!"
user.visible_message(
"<span class='notice'>[user] plays <b>[move]</b>, and [highfived] plays <b>[their_status_effect.move]</b>.</span>",
"<span class='notice'>[highfived] plays <b>[their_status_effect.move]</b>.</span>",
"<span class='notice'>It sounds like rock-paper-scissors.</span>"
)
user.visible_message(
"<span class='warning'>[outcome_msg]</span>",
blind_message = "<span class='notice'>It sounds like [pick(user, highfived)] won!</span>" // you're blind how are you supposed to know
)
/datum/status_effect/high_five/rps/on_creation(mob/living/new_owner, made_move)
if(made_move)
if(!(made_move in list(RPS_EMOTE_ROCK, RPS_EMOTE_PAPER, RPS_EMOTE_SCISSORS)))
stack_trace("RPS emote was given an invalid move type on creation.")
else
move = made_move
return ..()
/datum/status_effect/high_five/rps/on_apply()
if(!isnull(move))
to_chat(owner, "<span class='notice'>You prepare to play <b>[move]</b>.</span>")
return ..() // we already have the move, probably from the emote passing it in
move = get_rock_paper_scissors_move(owner)
if(move == null)
return FALSE // make it auto-remove itself
to_chat(owner, "<span class='notice'>You prepare to play <b>[move]</b>.</span>")
return ..()
/proc/get_rock_paper_scissors_move(mob/living/carbon/user)
var/list/move_icons = list(
RPS_EMOTE_SCISSORS = image(icon = 'icons/obj/items.dmi', icon_state = "bscissor"),
RPS_EMOTE_PAPER = image(icon = 'icons/obj/bureaucracy.dmi', icon_state = "paper"),
RPS_EMOTE_ROCK = image(icon = 'icons/obj/toy.dmi', icon_state = "pet_rock")
)
return show_radial_menu(user, user, move_icons)
/// A status effect that can have a certain amount of "bonus" duration added, which extends the duration every tick,
/// although there is a maximum amount of bonus time that can be active at any given time.
/datum/status_effect/limited_bonus
@@ -218,26 +320,11 @@
tick_interval = 4
/// The number of people the gun has locked on to. Caps at 10 for sanity.
var/locks = 0
/// What direction the owner was in when using the scope.
var/owner_dir = 0
/datum/status_effect/lwap_scope/on_creation(mob/living/new_owner, stored_dir = 0)
owner_dir = stored_dir
return ..()
/datum/status_effect/lwap_scope/tick()
locks = 0
var/turf/owner_turf = get_turf(owner)
var/scope_turf
for(var/turf/T in RANGE_EDGE_TURFS(7, owner_turf))
if(get_dir(owner, T) != owner_dir)
continue
if(T in range(owner, 6))
continue
scope_turf = T
break
if(scope_turf)
for(var/mob/living/L in range(10, scope_turf))
for(var/atom/movable/screen/fullscreen/stretch/cursor_catcher/scope/our_scope in owner.client.screen)
for(var/mob/living/L in range(10, our_scope.given_turf))
if(locks >= LWAP_LOCK_CAP)
return
if(L == owner || L.stat == DEAD || isslime(L) || ismonkeybasic(L)) //xenobio moment
+13 -1
View File
@@ -133,11 +133,13 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
if(limited_stock > 0)
limited_stock--
log_game("[key_name(user)] purchased [name]. [name] was discounted to [cost].")
user.create_log(MISC_LOG, "Uplink purchase: [name] was discounted to [cost]tc")
if(!user.mind.special_role)
message_admins("[key_name_admin(user)] purchased [name] (discounted to [cost]), as a non antagonist.")
else
log_game("[key_name(user)] purchased [name].")
user.create_log(MISC_LOG, "Uplink purchase: [name] for [cost]tc")
if(!user.mind.special_role)
message_admins("[key_name_admin(user)] purchased [name], as a non antagonist.")
@@ -603,7 +605,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/datum/uplink_item/device_tools/bonerepair
name = "Prototype Nanite Autoinjector"
desc = "Stolen prototype full body repair nanites. On injection it will shut down body systems as it revitilizes limbs and organs."
desc = "Stolen prototype full body repair nanites. On injection it will shut down body systems as it revitilizes limbs and organs. Heals organics organs, cybernetic organs, and limbs to fully operational conditions."
reference = "NCAI"
item = /obj/item/reagent_containers/hypospray/autoinjector/nanocalcium
cost = 10
@@ -853,6 +855,16 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
item = /obj/item/autosurgeon/organ/syndicate/razorwire
cost = 20
/datum/uplink_item/cyber_implants/scope_eyes
name = "Hardened Kaleido Optics Eyes Autoimplanter"
desc = "These cybernetic eye implants will let you zoom in on far away objects. \
Many users find it disorienting, and find it hard to interact with things near them when active. \
This pair has been hardened for special operations personnel."
reference = "KOE"
item = /obj/item/autosurgeon/organ/syndicate/scope_eyes
cost = 20
// POINTLESS BADASSERY
/datum/uplink_item/badass
+50 -24
View File
@@ -1,11 +1,12 @@
/datum/wires/nuclearbomb
holder_type = /obj/machinery/nuclearbomb
labelled = TRUE
randomize = TRUE
wire_count = 7 // 3 actual, 4 duds.
wire_count = 5
proper_name = "Nuclear bomb"
/datum/wires/nuclearbomb/New(atom/_holder)
wires = list(WIRE_BOMB_LIGHT, WIRE_BOMB_TIMING, WIRE_BOMB_SAFETY)
wires = list(WIRE_NUKE_SAFETY, WIRE_NUKE_DETONATOR, WIRE_NUKE_DISARM, WIRE_NUKE_LIGHT, WIRE_NUKE_CONTROL)
return ..()
/datum/wires/nuclearbomb/interactable(mob/user)
@@ -18,39 +19,64 @@
. = ..()
var/obj/machinery/nuclearbomb/N = holder
. += "The device is [N.timing ? "shaking!" : "still."]"
. += "The device is [N.safety ? "quiet" : "whirring"]."
. += "The lights are [N.lighthack ? "static" : "functional"]."
. += "The control panel is [is_cut(WIRE_NUKE_CONTROL) ? "turned off" : "functional"]."
. += "The disarm controls are [is_cut(WIRE_NUKE_DISARM) || is_cut(WIRE_NUKE_CONTROL) ? "disabled" : "functional"]."
. += "The safety controls are [is_cut(WIRE_NUKE_SAFETY) || is_cut(WIRE_NUKE_CONTROL) ? "disabled" : "functional"]."
. += "The lights are [is_cut(WIRE_NUKE_LIGHT) ? "static" : "functional"]."
/datum/wires/nuclearbomb/on_pulse(wire)
var/obj/machinery/nuclearbomb/N = holder
switch(wire)
if(WIRE_BOMB_LIGHT)
N.lighthack = !N.lighthack
addtimer(CALLBACK(N, TYPE_PROC_REF(/obj/machinery/nuclearbomb, reset_lighthack_callback)), 10 SECONDS)
if(WIRE_NUKE_SAFETY)
if(!is_cut(WIRE_NUKE_CONTROL))
N.audible_message("<span class='notice'>The safety controls flicker.</span>", hearing_distance = 1)
if(WIRE_BOMB_TIMING)
if(WIRE_NUKE_DETONATOR)
if(N.timing)
message_admins("[key_name_admin(usr)] pulsed a nuclear bomb's detonation wire, causing it to explode (<A href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[holder.x];Y=[holder.y];Z=[holder.z]'>JMP</a>)")
if(!N.training)
message_admins("[key_name_admin(usr)] pulsed a nuclear bomb's detonator wire, causing it to explode (<a href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[holder.x];Y=[holder.y];Z=[holder.z]'>JMP</a>)")
N.explode()
else
N.audible_message("<span class='warning'>[N] whirrs ominously.</span>", hearing_distance = 1)
if(WIRE_BOMB_SAFETY)
N.safety = !N.safety
addtimer(CALLBACK(N, TYPE_PROC_REF(/obj/machinery/nuclearbomb, reset_safety_callback)), 10 SECONDS)
if(WIRE_NUKE_DISARM)
if(N.timing && is_cut(WIRE_NUKE_CONTROL))
if(!is_cut(WIRE_NUKE_LIGHT))
N.icon_state = N.sprite_prefix + "nuclearbomb1"
N.timing = FALSE
N.audible_message("<span class='boldnotice'>The timer on [N] stops!</span>", hearing_distance = 1)
N.update_icon(UPDATE_OVERLAYS)
if(!N.training)
GLOB.bomb_set = FALSE
if(!N.is_syndicate && !N.training)
SSsecurity_level.set_level(N.previous_level)
else if(N.timing && !is_cut(WIRE_NUKE_CONTROL))
N.audible_message("<span class='boldnotice'>The disarm controls flash with an error. You need to disable the control panel first!</span>", hearing_distance = 1)
else if(!is_cut(WIRE_NUKE_CONTROL))
N.audible_message("<span class='notice'>The disarm controls flicker.</span>", hearing_distance = 1)
if(WIRE_NUKE_LIGHT)
N.audible_message("<span class='notice'>The lights on [N] flicker.</span>", hearing_distance = 1)
flick(N.sprite_prefix + "nuclearbombc", N)
if(WIRE_NUKE_CONTROL)
N.audible_message("<span class='notice'>[N]'s control panel flickers.</span>", hearing_distance = 1)
/datum/wires/nuclearbomb/on_cut(wire, mend)
var/obj/machinery/nuclearbomb/N = holder
switch(wire)
if(WIRE_BOMB_SAFETY)
if(N.timing)
message_admins("[key_name_admin(usr)] cut a nuclear bomb's timing wire, causing it to explode (<A href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[holder.x];Y=[holder.y];Z=[holder.z]'>JMP</a>)")
if(WIRE_NUKE_DETONATOR)
if(N.timing && !mend)
if(!N.training)
message_admins("[key_name_admin(usr)] cut a nuclear bomb's detonator wire, causing it to explode (<a href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[holder.x];Y=[holder.y];Z=[holder.z]'>JMP</a>)")
N.explode()
if(WIRE_BOMB_TIMING)
if(!N.lighthack)
if(N.icon_state == "nuclearbomb2")
N.icon_state = "nuclearbomb1"
N.timing = FALSE
GLOB.bomb_set = FALSE
if(WIRE_BOMB_LIGHT)
N.lighthack = !N.lighthack
if(WIRE_NUKE_LIGHT)
if(!mend)
N.icon_state = N.sprite_prefix + "nuclearbomb0"
if(mend)
if(N.timing)
N.icon_state = N.sprite_prefix + "nuclearbomb2"
else
N.icon_state = N.sprite_prefix + "nuclearbomb1"
N.update_icon(UPDATE_OVERLAYS)
+6 -1
View File
@@ -2,6 +2,8 @@
/datum/wires
/// TRUE if the wires will be different every time a new wire datum is created.
var/randomize = FALSE
/// TRUE if the wires are labelled for every user
var/labelled = FALSE
/// The atom the wires belong too. For example: an airlock.
var/atom/holder
/// The holder type; used to make sure that the holder is the correct type.
@@ -104,7 +106,8 @@
if(ishuman(user))
var/mob/living/carbon/human/H = user
var/obj/item/organ/internal/eyes/eyes = H.get_int_organ(/obj/item/organ/internal/eyes)
if(eyes && HAS_TRAIT(H, TRAIT_COLORBLIND)) // Check if the human has colorblindness.
var/obj/item/clothing/glasses/glasses = H.get_item_by_slot(SLOT_HUD_GLASSES)
if(eyes && HAS_TRAIT(H, TRAIT_COLORBLIND) && (!glasses || !glasses.correct_wires)) // Check if the human has colorblindness.
replace_colors = eyes.replace_colours // Get the colorblind replacement colors list.
var/list/wires_list = list()
@@ -281,6 +284,8 @@
var/can_probably_see_wires = FALSE
var/obj/item/held_item = user.get_active_hand()
var/obj/item/offhand = user.get_inactive_hand()
if(labelled)
can_probably_see_wires = TRUE
if(istype(held_item) && HAS_TRAIT(held_item, TRAIT_SHOW_WIRE_INFO))
can_probably_see_wires = TRUE
if(istype(offhand) && HAS_TRAIT(offhand, TRAIT_SHOW_WIRE_INFO))
@@ -106,6 +106,10 @@
name = "\improper Firing Range"
icon_state = "firingrange"
/area/station/security/defusal
name = "\improper Defusal Workshop"
icon_state = "defusal"
// Checkpoints
/area/station/security/checkpoint
+1
View File
@@ -1164,6 +1164,7 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
if(curturf)
.["Jump to turf"] = "?_src_=holder;adminplayerobservecoodjump=1;X=[curturf.x];Y=[curturf.y];Z=[curturf.z]"
.["Add reagent"] = "?_src_=vars;addreagent=[UID()]"
.["Edit reagents"] = "?_src_=vars;editreagents=[UID()]"
.["Trigger explosion"] = "?_src_=vars;explode=[UID()]"
.["Trigger EM pulse"] = "?_src_=vars;emp=[UID()]"
+17 -16
View File
@@ -199,7 +199,8 @@
Moved(old_loc, direction, TRUE)
/atom/movable/Move(atom/newloc, direct = 0, movetime)
if(!loc || !newloc) return 0
if(!loc || !newloc)
return FALSE
var/atom/oldloc = loc
if(loc != newloc)
@@ -321,7 +322,7 @@
Moved(old_loc, NONE)
return 1
return TRUE
/atom/movable/proc/onTransitZ(old_z,new_z)
for(var/item in src) // Notify contents of Z-transition. This can be overridden if we know the items contents do not care.
@@ -348,36 +349,36 @@
//Called whenever an object moves and by mobs when they attempt to move themselves through space
//And when an object or action applies a force on src, see newtonian_move() below
//Return 0 to have src start/keep drifting in a no-grav area and 1 to stop/not start drifting
//Mobs should return 1 if they should be able to move of their own volition, see client/Move() in mob_movement.dm
//return FALSE to have src start/keep drifting in a no-grav area and TRUE to stop/not start drifting
//Mobs should return TRUE if they should be able to move of their own volition, see client/Move() in mob_movement.dm
//movement_dir == 0 when stopping or any dir when trying to move
/atom/movable/proc/Process_Spacemove(movement_dir = 0)
if(has_gravity(src))
return 1
return TRUE
if(pulledby && !pulledby.pulling)
return 1
return TRUE
if(throwing)
return 1
return TRUE
if(locate(/obj/structure/lattice) in range(1, get_turf(src))) //Not realistic but makes pushing things in space easier
return 1
return TRUE
return 0
return FALSE
/atom/movable/proc/newtonian_move(direction) //Only moves the object if it's under no gravity
if(!loc || Process_Spacemove(0))
inertia_dir = 0
return 0
return FALSE
inertia_dir = direction
if(!direction)
return 1
return TRUE
inertia_last_loc = loc
SSspacedrift.processing[src] = src
return 1
return TRUE
//called when src is thrown into hit_atom
/atom/movable/proc/throw_impact(atom/hit_atom, throwingdatum)
@@ -397,7 +398,7 @@
/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = INFINITY, dodgeable = TRUE, block_movement = TRUE)
if(!target || (flags & NODROP) || speed <= 0)
return 0
return FALSE
if(pulledby)
pulledby.stop_pulling()
@@ -500,8 +501,8 @@
last_move = buckled_mob.last_move
inertia_dir = last_move
buckled_mob.inertia_dir = last_move
return 0
return 1
return FALSE
return TRUE
/atom/movable/proc/force_pushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction)
return FALSE
@@ -521,7 +522,7 @@
/atom/movable/CanPass(atom/movable/mover, turf/target, height=1.5)
if(mover in buckled_mobs)
return 1
return TRUE
return ..()
/atom/movable/proc/get_spacemove_backup()
-2
View File
@@ -339,8 +339,6 @@
~~~~~~~~~~~~~~~~~~~~~*/
/obj/mecha/proc/diag_hud_set_mechhealth()
var/image/holder = hud_list[DIAG_MECH_HUD]
var/icon/I = icon(icon, icon_state, dir)
holder.pixel_y = I.Height() - world.icon_size
holder.icon_state = "huddiag[RoundDiagBar(obj_integrity/max_integrity)]"
/obj/mecha/proc/diag_hud_set_mechcell()
+7 -7
View File
@@ -29,18 +29,17 @@
H.set_species(has_primitive_form, keep_missing_bodyparts = TRUE)
new /obj/effect/temp_visual/monkeyify(H.loc)
sleep(22)
addtimer(CALLBACK(src, PROC_REF(finish_monkeyize), H, !has_primitive_form), 2.2 SECONDS)
/datum/mutation/monkey/proc/finish_monkeyize(mob/living/carbon/human/H, should_gib)
H.invisibility = initial(H.invisibility)
if(!has_primitive_form) //If the pre-change mob in question has no primitive set, this is going to be messy.
if(should_gib) //If the pre-change mob in question has no primitive set, this is going to be messy.
H.gib()
return
REMOVE_TRAITS_IN(H, TRANSFORMING_TRAIT)
to_chat(H, "<B>You are now a [H.dna.species.name].</B>")
return H
/datum/mutation/monkey/deactivate(mob/living/carbon/human/H)
..()
if(!istype(H))
@@ -63,11 +62,13 @@
H.set_species(has_greater_form, keep_missing_bodyparts = TRUE)
new /obj/effect/temp_visual/monkeyify/humanify(H.loc)
sleep(22)
addtimer(CALLBACK(src, PROC_REF(finish_unmonkeyize), H, !has_greater_form), 2.2 SECONDS)
/datum/mutation/monkey/proc/finish_unmonkeyize(mob/living/carbon/human/H, should_gib)
REMOVE_TRAITS_IN(H, TRANSFORMING_TRAIT)
H.invisibility = initial(H.invisibility)
if(!has_greater_form) //If the pre-change mob in question has no primitive set, this is going to be messy.
if(should_gib) //If the pre-change mob in question has no primitive set, this is going to be messy.
H.gib()
return
@@ -76,4 +77,3 @@
to_chat(H, "<B>You are now a [H.dna.species.name].</B>")
return H
+40 -9
View File
@@ -394,6 +394,9 @@
return
var/atom/movable/the_item = targets[1]
if(!user.Adjacent(the_item))
to_chat(user, "<span class='danger'>You need to be next to [the_item] for this!</span>")
return FALSE
if(ishuman(the_item))
var/mob/living/carbon/human/H = the_item
var/obj/item/organ/external/limb = H.get_organ(user.zone_selected)
@@ -412,15 +415,14 @@
revert_cast()
return FALSE
user.visible_message("<span class='danger'>[user] begins stuffing [the_item]'s [limb.name] into [user.p_their()] gaping maw!</span>")
var/oldloc = H.loc
if(!do_mob(user,H,EAT_MOB_DELAY))
if(!do_mob(user, H, EAT_MOB_DELAY))
to_chat(user, "<span class='danger'>You were interrupted before you could eat [the_item]!</span>")
else
if(!limb || !H)
return
if(H.loc != oldloc)
to_chat(user, "<span class='danger'>\The [limb] moved away from your mouth!</span>")
return
if(!user.Adjacent(the_item))
to_chat(user, "<span class='danger'>You need to be next to [the_item] for this!</span>")
return FALSE
user.visible_message("<span class='danger'>[user] [pick("chomps","bites")] off [the_item]'s [limb]!</span>")
playsound(user.loc, 'sound/items/eatfood.ogg', 50, 0)
@@ -476,6 +478,7 @@
invocation_type = "none"
action_icon_state = "genetic_jump"
var/leap_distance = 10
/datum/spell/leap/create_new_targeting()
return new /datum/spell_targeting/self
@@ -508,15 +511,25 @@
user.layer = 9
user.flying = TRUE
for(var/i=0, i<10, i++)
for(var/i in 1 to leap_distance)
var/turf/hit_turf = get_step(user, user.dir)
var/atom/hit_atom = get_blocking_atom(hit_turf)
if(hit_atom)
hit_atom.hit_by_thrown_mob(user, damage = 10)
break
step(user, user.dir)
if(i < 5) user.pixel_y += 8
else user.pixel_y -= 8
if(i < 6)
user.pixel_y += 8
else
user.pixel_y -= 8
sleep(1)
user.flying = prevFlying
user.pixel_y = 0 // In case leap was varedited to be longer or shorter
if(HAS_TRAIT(user, TRAIT_FAT) && prob(66))
user.visible_message("<span class='danger'>[user.name]</b> crashes due to [user.p_their()] heavy weight!</span>")
user.visible_message("<span class='danger'><b>[user.name]</b> crashes due to [user.p_their()] heavy weight!</span>")
//playsound(user.loc, 'zhit.wav', 50, 1)
user.AdjustWeakened(20 SECONDS)
user.AdjustStunned(10 SECONDS)
@@ -539,6 +552,24 @@
container.pixel_x = 0
container.pixel_y = 0
/datum/spell/leap/proc/get_blocking_atom(turf/turf_to_check)
if(!turf_to_check)
return FALSE
if(turf_to_check.density)
return turf_to_check
for(var/atom/movable/hit_thing in turf_to_check)
if(isliving(hit_thing))
var/mob/living/hit_mob = hit_thing
return hit_mob.density
if(isobj(hit_thing))
var/obj/hit_obj = hit_thing
return hit_obj.density
return FALSE
////////////////////////////////////////////////////////////////////////
// WAS: /datum/bioEffect/polymorphism
+2 -2
View File
@@ -438,14 +438,14 @@
/proc/get_nuke_code()
var/nukecode = "ERROR"
for(var/obj/machinery/nuclearbomb/bomb in GLOB.machines)
for(var/obj/machinery/nuclearbomb/bomb in GLOB.nuke_list)
if(bomb && bomb.r_code && is_station_level(bomb.z))
nukecode = bomb.r_code
return nukecode
/proc/get_nuke_status()
var/nuke_status = NUKE_MISSING
for(var/obj/machinery/nuclearbomb/bomb in GLOB.machines)
for(var/obj/machinery/nuclearbomb/bomb in GLOB.nuke_list)
if(is_station_level(bomb.z))
nuke_status = NUKE_CORE_MISSING
if(bomb.core)
@@ -3,7 +3,62 @@
#define MIND_DEVICE_MESSAGE 1
#define MIND_DEVICE_CONTROL 2
//AGENT VEST
#define BATON_STUN 0
#define BATON_SLEEP 1
#define BATON_CUFF 2
#define BATON_PROBE 3
#define BATON_MODES 4
/*
CONTENTS:
1. AGENT GEAR
2. SCIENTIST GEAR
3. ENGINEERING TOOLS
4. MEDICAL TOOLS
5. JANITORIAL TOOLS
6. STRUCTURES
*/
// Setting up abductor exclusivity.
/obj/item/abductor
name = "generic abductor item"
icon = 'icons/obj/abductor.dmi'
desc = "You are not supposed to be able to see this. If you can see this, please make an issue report on GitHub."
/obj/item/abductor/proc/AbductorCheck(user)
if(isabductor(user))
return TRUE
to_chat(user, "<span class='warning'>You can't figure how this works!</span>")
return FALSE
/obj/item/abductor/proc/ScientistCheck(user)
if(!AbductorCheck(user))
return FALSE
var/mob/living/carbon/human/H = user
var/datum/species/abductor/S = H.dna.species
if(S.scientist)
return TRUE
to_chat(user, "<span class='warning'>You're not trained to use this!</span>")
return FALSE
/////////////////////////////////////////
/////////////// AGENT GEAR //////////////
/////////////////////////////////////////
/obj/item/clothing/head/helmet/abductor
name = "agent headgear"
desc = "Abduct with style - spiky style. Prevents digital tracking."
icon_state = "alienhelmet"
item_state = "alienhelmet"
blockTracking = 1
origin_tech = "materials=7;magnets=4;abductor=3"
flags = BLOCKHAIR
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE
sprite_sheets = list(
"Vox" = 'icons/mob/clothing/species/vox/head.dmi'
)
/obj/item/clothing/suit/armor/abductor/vest
name = "agent vest"
desc = "A vest outfitted with advanced stealth technology. It has two modes - combat and stealth."
@@ -129,113 +184,6 @@
break
return ..()
/obj/item/abductor
icon = 'icons/obj/abductor.dmi'
/obj/item/abductor/proc/AbductorCheck(user)
if(isabductor(user))
return TRUE
to_chat(user, "<span class='warning'>You can't figure how this works!</span>")
return FALSE
/obj/item/abductor/proc/ScientistCheck(user)
if(!AbductorCheck(user))
return FALSE
var/mob/living/carbon/human/H = user
var/datum/species/abductor/S = H.dna.species
if(S.scientist)
return TRUE
to_chat(user, "<span class='warning'>You're not trained to use this!</span>")
return FALSE
/obj/item/abductor/gizmo
name = "science tool"
desc = "A dual-mode tool for retrieving specimens and scanning appearances. Scanning can be done through cameras."
icon_state = "gizmo_scan"
item_state = "gizmo"
origin_tech = "engineering=7;magnets=4;bluespace=4;abductor=3"
var/mode = GIZMO_SCAN
var/mob/living/marked = null
var/obj/machinery/abductor/console/console
/obj/item/abductor/gizmo/attack_self(mob/user)
if(!ScientistCheck(user))
return
if(!console)
to_chat(user, "<span class='warning'>The device is not linked to a console!</span>")
return
if(mode == GIZMO_SCAN)
mode = GIZMO_MARK
icon_state = "gizmo_mark"
else
mode = GIZMO_SCAN
icon_state = "gizmo_scan"
to_chat(user, "<span class='notice'>You switch the device to [mode==GIZMO_SCAN? "SCAN": "MARK"] MODE</span>")
/obj/item/abductor/gizmo/attack(mob/living/M, mob/user)
if(!ScientistCheck(user))
return
if(!console)
to_chat(user, "<span class='warning'>The device is not linked to console!</span>")
return
switch(mode)
if(GIZMO_SCAN)
scan(M, user)
if(GIZMO_MARK)
mark(M, user)
/obj/item/abductor/gizmo/afterattack(atom/target, mob/living/user, flag, params)
if(flag)
return
if(!ScientistCheck(user))
return
if(!console)
to_chat(user, "<span class='warning'>The device is not linked to console!</span>")
return
switch(mode)
if(GIZMO_SCAN)
scan(target, user)
if(GIZMO_MARK)
mark(target, user)
/obj/item/abductor/gizmo/proc/scan(atom/target, mob/living/user)
if(ishuman(target))
console.AddSnapshot(target)
to_chat(user, "<span class='notice'>You scan [target] and add [target.p_them()] to the database.</span>")
/obj/item/abductor/gizmo/proc/mark(atom/target, mob/living/user)
if(marked == target)
to_chat(user, "<span class='warning'>This specimen is already marked!</span>")
return
if(ishuman(target))
if(isabductor(target))
marked = target
to_chat(user, "<span class='notice'>You mark [target] for future retrieval.</span>")
else
prepare(target,user)
else
prepare(target,user)
/obj/item/abductor/gizmo/proc/prepare(atom/target, mob/living/user)
if(get_dist(target,user)>1)
to_chat(user, "<span class='warning'>You need to be next to the specimen to prepare it for transport!</span>")
return
to_chat(user, "<span class='notice'>You begin preparing [target] for transport...</span>")
if(do_after(user, 100, target = target))
marked = target
to_chat(user, "<span class='notice'>You finish preparing [target] for transport.</span>")
/obj/item/abductor/gizmo/Destroy()
if(console)
console.gizmo = null
return ..()
/obj/item/abductor/silencer
name = "abductor silencer"
desc = "A compact device used to shut down communications equipment."
@@ -277,75 +225,6 @@
R.listening = FALSE // Prevents the radio from buzzing due to the EMP, preserving possible stealthiness.
R.emp_act(1)
/obj/item/abductor/mind_device
name = "mental interface device"
desc = "A dual-mode tool for directly communicating with sentient brains. It can be used to send a direct message to a target, or to send a command to a test subject with a charged gland."
icon_state = "mind_device_message"
item_state = "silencer"
var/mode = MIND_DEVICE_MESSAGE
/obj/item/abductor/mind_device/attack_self(mob/user)
if(!ScientistCheck(user))
return
if(mode == MIND_DEVICE_MESSAGE)
mode = MIND_DEVICE_CONTROL
icon_state = "mind_device_control"
else
mode = MIND_DEVICE_MESSAGE
icon_state = "mind_device_message"
to_chat(user, "<span class='notice'>You switch the device to [mode == MIND_DEVICE_MESSAGE ? "TRANSMISSION" : "COMMAND"] MODE</span>")
/obj/item/abductor/mind_device/afterattack(atom/target, mob/living/user, flag, params)
if(!ScientistCheck(user))
return
switch(mode)
if(MIND_DEVICE_CONTROL)
mind_control(target, user)
if(MIND_DEVICE_MESSAGE)
mind_message(target, user)
/obj/item/abductor/mind_device/proc/mind_control(atom/target, mob/living/user)
if(iscarbon(target))
var/mob/living/carbon/C = target
var/obj/item/organ/internal/heart/gland/G = C.get_organ_slot("heart")
if(!istype(G))
to_chat(user, "<span class='warning'>Your target does not have an experimental gland!</span>")
return
if(!G.mind_control_uses)
to_chat(user, "<span class='warning'>Your target's gland is spent!</span>")
return
if(G.active_mind_control)
to_chat(user, "<span class='warning'>Your target is already under a mind-controlling influence!</span>")
return
var/command = tgui_input_text(user, "Enter the command for your target to follow. Uses Left: [G.mind_control_uses], Duration: [DisplayTimeText(G.mind_control_duration)]", "Enter command")
if(!command)
return
if(QDELETED(user) || user.get_active_hand() != src || loc != user)
return
if(QDELETED(G))
return
G.mind_control(command, user)
to_chat(user, "<span class='notice'>You send the command to your target.</span>")
/obj/item/abductor/mind_device/proc/mind_message(atom/target, mob/living/user)
if(isliving(target))
var/mob/living/L = target
if(L.stat == DEAD)
to_chat(user, "<span class='warning'>Your target is dead!</span>")
return
var/message = tgui_input_text(user, "Write a message to send to your target's brain.", "Enter message")
if(!message)
return
if(QDELETED(L) || L.stat == DEAD)
return
to_chat(L, "<span class='italics'>You hear a voice in your head saying: </span><span class='abductor'>[message]</span>")
to_chat(user, "<span class='notice'>You send the message to your target.</span>")
log_say("[key_name(user)] sent an abductor mind message to [key_name(L)]: '[message]'", user)
/obj/item/gun/energy/alien
name = "alien pistol"
desc = "A complicated gun that fires bursts of high-intensity radiation."
@@ -357,41 +236,6 @@
trigger_guard = TRIGGER_GUARD_ALLOW_ALL
can_holster = TRUE
/obj/item/paper/abductor
name = "Dissection Guide"
icon_state = "alienpaper_words"
info = {"<b>Dissection for Dummies</b><br>
<br>
1.Acquire fresh specimen.<br>
2.Put the specimen on operating table.<br>
3.Apply scalpel to the chest, preparing for experimental dissection.<br>
4.Apply scalpel to specimen's torso.<br>
5.Clamp bleeders on specimen's torso with a hemostat.<br>
6.Retract skin of specimen's torso with a retractor.<br>
7.Saw through the specimen's torso with a saw.<br>
8.Apply retractor again to specimen's torso.<br>
9.Search through the specimen's torso with your hands to remove any superfluous organs.<br>
10.Insert replacement gland (Retrieve one from gland storage).<br>
11.Cauterize the patient's torso with a cautery.<br>
12.Consider dressing the specimen back to not disturb the habitat. <br>
13.Put the specimen in the experiment machinery.<br>
14.Choose one of the machine options. The target will be analyzed and teleported to the selected drop-off point.<br>
15.You will receive one supply credit, and the subject will be counted towards your quota.<br>
<br>
Congratulations! You are now trained for invasive xenobiology research!"}
/obj/item/paper/abductor/update_icon_state()
return
/obj/item/paper/abductor/AltClick()
return
#define BATON_STUN 0
#define BATON_SLEEP 1
#define BATON_CUFF 2
#define BATON_PROBE 3
#define BATON_MODES 4
/obj/item/abductor_baton
name = "advanced baton"
desc = "A quad-mode baton used for incapacitation and restraining of specimens."
@@ -590,6 +434,281 @@ Congratulations! You are now trained for invasive xenobiology research!"}
/obj/item/radio/headset/abductor/screwdriver_act()
return// Stops humans from disassembling abductor headsets.
/////////////////////////////////////////
///////////// SCIENTIST GEAR ////////////
/////////////////////////////////////////
/obj/item/abductor/gizmo
name = "science tool"
desc = "A dual-mode tool for retrieving specimens and scanning appearances. Scanning can be done through cameras."
icon_state = "gizmo_scan"
item_state = "gizmo"
origin_tech = "engineering=7;magnets=4;bluespace=4;abductor=3"
var/mode = GIZMO_SCAN
var/mob/living/marked = null
var/obj/machinery/abductor/console/console
/obj/item/abductor/gizmo/attack_self(mob/user)
if(!ScientistCheck(user))
return
if(!console)
to_chat(user, "<span class='warning'>The device is not linked to a console!</span>")
return
if(mode == GIZMO_SCAN)
mode = GIZMO_MARK
icon_state = "gizmo_mark"
else
mode = GIZMO_SCAN
icon_state = "gizmo_scan"
to_chat(user, "<span class='notice'>You switch the device to [mode==GIZMO_SCAN? "SCAN": "MARK"] MODE</span>")
/obj/item/abductor/gizmo/attack(mob/living/M, mob/user)
if(!ScientistCheck(user))
return
if(!console)
to_chat(user, "<span class='warning'>The device is not linked to console!</span>")
return
switch(mode)
if(GIZMO_SCAN)
scan(M, user)
if(GIZMO_MARK)
mark(M, user)
/obj/item/abductor/gizmo/afterattack(atom/target, mob/living/user, flag, params)
if(flag)
return
if(!ScientistCheck(user))
return
if(!console)
to_chat(user, "<span class='warning'>The device is not linked to console!</span>")
return
switch(mode)
if(GIZMO_SCAN)
scan(target, user)
if(GIZMO_MARK)
mark(target, user)
/obj/item/abductor/gizmo/proc/scan(atom/target, mob/living/user)
if(ishuman(target))
console.AddSnapshot(target)
to_chat(user, "<span class='notice'>You scan [target] and add [target.p_them()] to the database.</span>")
/obj/item/abductor/gizmo/proc/mark(atom/target, mob/living/user)
if(marked == target)
to_chat(user, "<span class='warning'>This specimen is already marked!</span>")
return
if(ishuman(target))
if(isabductor(target))
marked = target
to_chat(user, "<span class='notice'>You mark [target] for future retrieval.</span>")
else
prepare(target,user)
else
prepare(target,user)
/obj/item/abductor/gizmo/proc/prepare(atom/target, mob/living/user)
if(get_dist(target,user)>1)
to_chat(user, "<span class='warning'>You need to be next to the specimen to prepare it for transport!</span>")
return
to_chat(user, "<span class='notice'>You begin preparing [target] for transport...</span>")
if(do_after(user, 100, target = target))
marked = target
to_chat(user, "<span class='notice'>You finish preparing [target] for transport.</span>")
/obj/item/abductor/gizmo/Destroy()
if(console)
console.gizmo = null
return ..()
/obj/item/abductor/mind_device
name = "mental interface device"
desc = "A dual-mode tool for directly communicating with sentient brains. It can be used to send a direct message to a target, or to send a command to a test subject with a charged gland."
icon_state = "mind_device_message"
item_state = "silencer"
var/mode = MIND_DEVICE_MESSAGE
/obj/item/abductor/mind_device/attack_self(mob/user)
if(!ScientistCheck(user))
return
if(mode == MIND_DEVICE_MESSAGE)
mode = MIND_DEVICE_CONTROL
icon_state = "mind_device_control"
else
mode = MIND_DEVICE_MESSAGE
icon_state = "mind_device_message"
to_chat(user, "<span class='notice'>You switch the device to [mode == MIND_DEVICE_MESSAGE ? "TRANSMISSION" : "COMMAND"] MODE</span>")
/obj/item/abductor/mind_device/afterattack(atom/target, mob/living/user, flag, params)
if(!ScientistCheck(user))
return
switch(mode)
if(MIND_DEVICE_CONTROL)
mind_control(target, user)
if(MIND_DEVICE_MESSAGE)
mind_message(target, user)
/obj/item/abductor/mind_device/proc/mind_control(atom/target, mob/living/user)
if(iscarbon(target))
var/mob/living/carbon/C = target
var/obj/item/organ/internal/heart/gland/G = C.get_organ_slot("heart")
if(!istype(G))
to_chat(user, "<span class='warning'>Your target does not have an experimental gland!</span>")
return
if(!G.mind_control_uses)
to_chat(user, "<span class='warning'>Your target's gland is spent!</span>")
return
if(G.active_mind_control)
to_chat(user, "<span class='warning'>Your target is already under a mind-controlling influence!</span>")
return
var/command = tgui_input_text(user, "Enter the command for your target to follow. Uses Left: [G.mind_control_uses], Duration: [DisplayTimeText(G.mind_control_duration)]", "Enter command")
if(!command)
return
if(QDELETED(user) || user.get_active_hand() != src || loc != user)
return
if(QDELETED(G))
return
G.mind_control(command, user)
to_chat(user, "<span class='notice'>You send the command to your target.</span>")
/obj/item/abductor/mind_device/proc/mind_message(atom/target, mob/living/user)
if(isliving(target))
var/mob/living/L = target
if(L.stat == DEAD)
to_chat(user, "<span class='warning'>Your target is dead!</span>")
return
var/message = tgui_input_text(user, "Write a message to send to your target's brain.", "Enter message")
if(!message)
return
if(QDELETED(L) || L.stat == DEAD)
return
to_chat(L, "<span class='italics'>You hear a voice in your head saying: </span><span class='abductor'>[message]</span>")
to_chat(user, "<span class='notice'>You send the message to your target.</span>")
log_say("[key_name(user)] sent an abductor mind message to [key_name(L)]: '[message]'", user)
/obj/item/paper/abductor
name = "Dissection Guide"
icon_state = "alienpaper_words"
info = {"<b>Dissection for Dummies</b><br>
<br>
1.Acquire fresh specimen.<br>
2.Put the specimen on operating table.<br>
3.Apply scalpel to the chest, preparing for experimental dissection.<br>
4.Apply scalpel to specimen's torso.<br>
5.Clamp bleeders on specimen's torso with a hemostat.<br>
6.Retract skin of specimen's torso with a retractor.<br>
7.Saw through the specimen's torso with a saw.<br>
8.Apply retractor again to specimen's torso.<br>
9.Search through the specimen's torso with your hands to remove any superfluous organs.<br>
10.Insert replacement gland (Retrieve one from gland storage).<br>
11.Cauterize the patient's torso with a cautery.<br>
12.Consider dressing the specimen back to not disturb the habitat. <br>
13.Put the specimen in the experiment machinery.<br>
14.Choose one of the machine options. The target will be analyzed and teleported to the selected drop-off point.<br>
15.You will receive one supply credit, and the subject will be counted towards your quota.<br>
<br>
Congratulations! You are now trained for invasive xenobiology research!"}
/obj/item/paper/abductor/update_icon_state()
return
/obj/item/paper/abductor/AltClick()
return
/////////////////////////////////////////
/////////// ENGINEERING TOOLS ///////////
/////////////////////////////////////////
/obj/item/screwdriver/abductor
name = "alien screwdriver"
desc = "An ultrasonic screwdriver."
icon = 'icons/obj/abductor.dmi'
icon_state = "screwdriver"
usesound = 'sound/items/pshoom.ogg'
toolspeed = 0.1
random_color = FALSE
/obj/item/wrench/abductor
name = "alien wrench"
desc = "A polarized wrench. It causes anything placed between the jaws to turn."
icon = 'icons/obj/abductor.dmi'
icon_state = "wrench"
usesound = 'sound/effects/empulse.ogg'
toolspeed = 0.1
origin_tech = "materials=5;engineering=5;abductor=3"
/obj/item/weldingtool/abductor
name = "alien welding tool"
desc = "An alien welding tool. Whatever fuel it uses, it never runs out."
icon = 'icons/obj/abductor.dmi'
icon_state = "welder"
toolspeed = 0.1
w_class = WEIGHT_CLASS_SMALL
light_intensity = 0
origin_tech = "plasmatech=5;engineering=5;abductor=3"
requires_fuel = FALSE
refills_over_time = TRUE
low_fuel_changes_icon = FALSE
/obj/item/crowbar/abductor
name = "alien crowbar"
desc = "A hard-light crowbar. It appears to pry by itself, without any effort required."
icon = 'icons/obj/abductor.dmi'
icon_state = "crowbar"
usesound = 'sound/weapons/sonic_jackhammer.ogg'
toolspeed = 0.1
w_class = WEIGHT_CLASS_SMALL
origin_tech = "combat=4;engineering=4;abductor=3"
/obj/item/wirecutters/abductor
name = "alien wirecutters"
desc = "Extremely sharp wirecutters, made out of a silvery-green metal."
icon = 'icons/obj/abductor.dmi'
icon_state = "cutters"
toolspeed = 0.1
origin_tech = "materials=5;engineering=4;abductor=3"
random_color = FALSE
/obj/item/wirecutters/abductor/Initialize(mapload)
. = ..()
ADD_TRAIT(src, TRAIT_SHOW_WIRE_INFO, ROUNDSTART_TRAIT)
/obj/item/multitool/abductor
name = "alien multitool"
desc = "An omni-technological interface."
icon = 'icons/obj/abductor.dmi'
icon_state = "multitool"
toolspeed = 0.1
w_class = WEIGHT_CLASS_SMALL
origin_tech = "magnets=5;engineering=5;abductor=3"
/obj/item/multitool/abductor/Initialize(mapload)
. = ..()
ADD_TRAIT(src, TRAIT_SHOW_WIRE_INFO, ROUNDSTART_TRAIT)
/obj/item/storage/belt/military/abductor
name = "agent belt"
desc = "A belt used by abductor agents."
icon = 'icons/obj/abductor.dmi'
icon_state = "belt"
item_state = "security"
/obj/item/storage/belt/military/abductor/full/populate_contents()
new /obj/item/screwdriver/abductor(src)
new /obj/item/wrench/abductor(src)
new /obj/item/weldingtool/abductor(src)
new /obj/item/crowbar/abductor(src)
new /obj/item/wirecutters/abductor(src)
new /obj/item/multitool/abductor(src)
new /obj/item/stack/cable_coil(src, 30, COLOR_WHITE)
/////////////////////////////////////////
/////////// MEDICAL TOOLS ///////////////
/////////////////////////////////////////
/obj/item/scalpel/alien
name = "alien scalpel"
desc = "It's a gleaming sharp knife made out of silvery-green metal."
@@ -641,7 +760,7 @@ Congratulations! You are now trained for invasive xenobiology research!"}
/obj/item/FixOVein/alien
name = "alien FixOVein"
desc = "Bloodless aliens would totally know how to stop internal bleeding...right?"
desc = "Bloodless aliens would totally know how to stop internal bleeding... Right?"
icon = 'icons/obj/abductor.dmi'
origin_tech = "materials=2;biotech=2;abductor=2"
toolspeed = 0.25
@@ -653,21 +772,89 @@ Congratulations! You are now trained for invasive xenobiology research!"}
origin_tech = "materials=2;biotech=2;abductor=2"
toolspeed = 0.25
/obj/item/clothing/head/helmet/abductor
name = "agent headgear"
desc = "Abduct with style - spiky style. Prevents digital tracking."
icon_state = "alienhelmet"
item_state = "alienhelmet"
blockTracking = 1
origin_tech = "materials=7;magnets=4;abductor=3"
flags = BLOCKHAIR
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE
/////////////////////////////////////////
//////////// JANITORIAL TOOLS ///////////
/////////////////////////////////////////
/obj/item/mop/advanced/abductor
name = "alien mop"
desc = "A collapsible mop clearly used by aliens to clean up any evidence of a close encounter. The head produces a constant supply of water when run over a surface, seemingly out of nowhere."
icon = 'icons/obj/abductor.dmi'
icon_state = "mop_abductor"
mopcap = 100
origin_tech = "materials=3;engineering=3;abductor=3"
refill_rate = 50
refill_reagent = "water"
mopspeed = 10
sprite_sheets = list(
"Vox" = 'icons/mob/clothing/species/vox/head.dmi'
/obj/item/soap/syndie/abductor
name = "alien soap"
desc = "Even bloodless aliens need to wash the grime off. Smells like gunpowder."
icon = 'icons/obj/abductor.dmi'
icon_state = "soap_abductor"
/obj/item/lightreplacer/bluespace/abductor
name = "alien light replacer"
desc = "It's important to keep all the mysterious lights on a UFO functional when flying over backwater country."
icon = 'icons/obj/abductor.dmi'
icon_state = "lightreplacer_abductor"
origin_tech = "magnets=3;engineering=4;abductor=3"
max_uses = 40
uses = 20
/obj/item/melee/flyswatter/abductor
name = "alien flyswatter"
desc = "For killing alien insects, obviously."
icon = 'icons/obj/abductor.dmi'
icon_state = "flyswatter_abductor"
item_state = "flyswatter_abductor"
origin_tech = "abductor=1"
force = 2 // Twice as powerful thanks to alien technology!
throwforce = 2
/obj/item/reagent_containers/spray/cleaner/safety/abductor // Essentially an Advanced Space Cleaner, but abductor-themed. For the implant.
name = "alien space cleaner"
desc = "An alien spray bottle contaning alien-brand non-foaming space cleaner! It only accepts space cleaner."
icon = 'icons/obj/abductor.dmi'
icon_state = "cleaner_abductor"
item_state = "cleaner_abductor"
volume = 500
spray_maxrange = 3
spray_currentrange = 3
list_reagents = list("cleaner" = 500)
/obj/item/storage/belt/janitor/abductor
name = "alien janibelt"
desc = "A belt used to hold out-of-this-world cleaning supplies! Used by abductors to keep their ships clean."
icon = 'icons/obj/abductor.dmi'
icon_state = "janibelt_abductor"
item_state = "security"
storage_slots = 7
can_hold = list(
/obj/item/grenade/chem_grenade/cleaner,
/obj/item/lightreplacer,
/obj/item/flashlight,
/obj/item/reagent_containers/spray,
/obj/item/soap,
/obj/item/holosign_creator/janitor,
/obj/item/melee/flyswatter,
/obj/item/storage/bag/trash,
/obj/item/push_broom,
/obj/item/door_remote/janikeyring,
/obj/item/mop/advanced/abductor
)
// Operating Table / Beds / Lockers
/obj/item/storage/belt/janitor/abductor/full/populate_contents()
new /obj/item/mop/advanced/abductor(src)
new /obj/item/soap/syndie/abductor(src)
new /obj/item/lightreplacer/bluespace/abductor(src)
new /obj/item/storage/bag/trash/bluespace(src)
new /obj/item/melee/flyswatter/abductor(src)
new /obj/item/reagent_containers/spray/cleaner/safety/abductor(src)
new /obj/item/holosign_creator/janitor(src)
/////////////////////////////////////////
/////////////// STRUCTURES //////////////
/////////////////////////////////////////
/obj/structure/bed/abductor
name = "resting contraption"
desc = "This looks similar to contraptions from earth. Could aliens be stealing our technology?"
@@ -50,7 +50,6 @@
/datum/outfit/abductor/scientist
name = "Abductor Scientist"
backpack_contents = list(
/obj/item/abductor/gizmo = 1
)
@@ -84,7 +84,7 @@
if(declaring_war)
to_chat(user, "You are already in the process of declaring war! Make your mind up.")
return FALSE
if(length(GLOB.player_list) < CHALLENGE_MIN_PLAYERS)
if(length(get_living_players(exclude_nonhuman = FALSE, exclude_offstation = TRUE)) < CHALLENGE_MIN_PLAYERS)
to_chat(user, "The enemy crew is too small to be worth declaring war on.")
return FALSE
if(!is_admin_level(user.z))
+153 -62
View File
@@ -15,7 +15,7 @@ GLOBAL_VAR(bomb_set)
name = "\improper Nuclear Fission Explosive"
desc = "Uh oh. RUN!!!!"
icon = 'icons/obj/nuclearbomb.dmi'
icon_state = "nuclearbomb0"
icon_state = "nuclearbomb1"
density = TRUE
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
flags_2 = NO_MALF_EFFECT_2 | CRITICAL_ATOM_2
@@ -25,8 +25,6 @@ GLOBAL_VAR(bomb_set)
/// Are our bolts *supposed* to be in the floor, may not actually cause anchoring if the bolts are cut
var/extended = TRUE
/// If true, prevents the lights on the nuke
var/lighthack = FALSE
/// Countdown to boom
var/timeleft = 120
/// Are we counting down?
@@ -55,6 +53,10 @@ GLOBAL_VAR(bomb_set)
var/core_stage = NUKE_CORE_EVERYTHING_FINE
///How many sheets of various metals we need to fix it
var/sheets_to_fix = 5
/// Is this a training bomb?
var/training = FALSE
/// Prefix to add, if any, on icon states for this bomb
var/sprite_prefix = ""
///Bombs Internal Radio
var/obj/item/radio/radio
@@ -70,9 +72,10 @@ GLOBAL_VAR(bomb_set)
. = ..()
r_code = rand(10000, 99999) // Creates a random code upon object spawn.
wires = new/datum/wires/nuclearbomb(src)
ADD_TRAIT(src, TRAIT_OBSCURED_WIRES, ROUNDSTART_TRAIT)
previous_level = SSsecurity_level.get_current_level_as_text()
GLOB.poi_list |= src
if(!training)
GLOB.poi_list |= src
GLOB.nuke_list |= src
core = new /obj/item/nuke_core/plutonium(src)
STOP_PROCESSING(SSobj, core) //Let us not irradiate the vault by default.
update_icon(UPDATE_OVERLAYS)
@@ -81,14 +84,26 @@ GLOBAL_VAR(bomb_set)
radio.follow_target = src
radio.config(list("Special Ops" = 0))
/obj/machinery/nuclearbomb/syndicate/Initialize()
. = ..()
wires.labelled = FALSE
ADD_TRAIT(src, TRAIT_OBSCURED_WIRES, ROUNDSTART_TRAIT)
GLOB.syndi_nuke_list |= src
/obj/machinery/nuclearbomb/Destroy()
SStgui.close_uis(wires)
QDEL_NULL(wires)
QDEL_NULL(core)
QDEL_NULL(radio)
GLOB.poi_list.Remove(src)
if(!training)
GLOB.poi_list.Remove(src)
GLOB.nuke_list.Remove(src)
return ..()
/obj/machinery/nuclearbomb/syndicate/Destroy()
GLOB.syndi_nuke_list.Remove(src)
. = ..()
/obj/machinery/nuclearbomb/process()
if(timing)
GLOB.bomb_set = TRUE // So long as there is one nuke timing, it means one nuke is armed.
@@ -99,6 +114,8 @@ GLOBAL_VAR(bomb_set)
/obj/machinery/nuclearbomb/examine(mob/user)
. = ..()
if(training)
. += "<span class='notice'><b>Alt-Click</b> to reset the bomb.</span>"
if(!panel_open)
. += "<span class='notice'>The outer panel is <b>screwed shut</b>.</span>"
switch(removal_stage)
@@ -126,15 +143,15 @@ GLOBAL_VAR(bomb_set)
underlays.Cut()
set_light(0)
if(!lighthack)
underlays += emissive_appearance(icon, "nuclearbomb_lightmask")
if(!wires.is_cut(WIRE_NUKE_LIGHT))
underlays += emissive_appearance(icon, sprite_prefix + "nukelights_lightmask")
set_light(1, LIGHTING_MINIMUM_POWER)
if(panel_open)
. += "hackpanel_open"
. += sprite_prefix + "hackpanel_open"
if(anchored) // Using anchored due to removal_stage deanchoring having multiple steps
. += "nukebolts"
. += sprite_prefix + "nukebolts"
// Selected stage lets us show the open core, even if the front panel is closed
var/selected_stage = removal_stage
@@ -151,6 +168,12 @@ GLOBAL_VAR(bomb_set)
/obj/machinery/nuclearbomb/attackby(obj/item/O as obj, mob/user as mob, params)
if(istype(O, /obj/item/disk/nuclear))
if(extended)
if(auth)
to_chat(user, "<span class='warning'>There's already a disk in the slot!</span>")
return
if((istype(O, /obj/item/disk/nuclear/training) && !training) || (training && !istype(O, /obj/item/disk/nuclear/training)))
to_chat(user, "<span class='warning'>[O] doesn't fit into [src]!</span>")
return
if(!user.drop_item())
to_chat(user, "<span class='notice'>[O] is stuck to your hand!</span>")
return
@@ -212,12 +235,15 @@ GLOBAL_VAR(bomb_set)
if(!I.tool_use_check(user, 0))
return
if(removal_stage == NUKE_COVER_OFF)
user.visible_message("[user] starts forcing open the bolt covers on [src].", "You start forcing open the anchoring bolt covers with [I]...")
user.visible_message("<span class='notice'>[user] starts forcing open the bolt covers on [src].</span>", "<span class='notice'>You start forcing open the anchoring bolt covers with [I]...</span>")
if(!I.use_tool(src, user, 15, volume = I.tool_volume) || removal_stage != NUKE_COVER_OFF)
return
user.visible_message("[user] forces open the bolt covers on [src].", "You force open the bolt covers.")
user.visible_message("<span class='notice'>[user] forces open the bolt covers on [src].</span>", "<span class='notice'>You force open the bolt covers.</span>")
removal_stage = NUKE_COVER_OPEN
if(removal_stage == NUKE_CORE_EVERYTHING_FINE)
if(training)
to_chat(user, "<span class='notice'>This is where you'd take off the plate to access the internal core, but this training bomb doesn't have one.</span>")
return
user.visible_message("<span class='notice'>[user] starts removing [src]'s outer core plate...</span>", "<span class='notice'>You start removing [src]'s outer core plate...</span>")
if(!I.use_tool(src, user, 4 SECONDS, volume = I.tool_volume) || removal_stage != NUKE_CORE_EVERYTHING_FINE)
return
@@ -235,10 +261,10 @@ GLOBAL_VAR(bomb_set)
if(core)
START_PROCESSING(SSobj, core)
if(removal_stage == NUKE_UNWRENCHED)
user.visible_message("[user] begins lifting [src] off of the anchors.", "You begin lifting the device off the anchors...")
user.visible_message("<span class='notice'>[user] begins lifting [src] off of the anchors.</span>", "<span class='notice'>You begin lifting the device off the anchors...</span>")
if(!I.use_tool(src, user, 8 SECONDS, volume = I.tool_volume) || removal_stage != NUKE_UNWRENCHED)
return
user.visible_message("[user] crowbars [src] off of the anchors. It can now be moved.", "You jam the crowbar under the nuclear device and lift it off its anchors. You can now move it!")
user.visible_message("<span class='notice'>[user] crowbars [src] off of the anchors. It can now be moved.</span>", "<span class='notice'>You jam the crowbar under the nuclear device and lift it off its anchors. You can now move it!</span>")
anchored = FALSE
removal_stage = NUKE_MOBILE
update_icon(UPDATE_OVERLAYS)
@@ -251,10 +277,10 @@ GLOBAL_VAR(bomb_set)
. = TRUE
if(!I.tool_use_check(user, 0))
return
user.visible_message("[user] begins unwrenching the anchoring bolts on [src].", "You begin unwrenching the anchoring bolts...")
user.visible_message("<span class='notice'>[user] begins unwrenching the anchoring bolts on [src].</span>", "<span class='notice'>You begin unwrenching the anchoring bolts...</span>")
if(!I.use_tool(src, user, 50, volume = I.tool_volume) || removal_stage != NUKE_SEALANT_OPEN)
return
user.visible_message("[user] unwrenches the anchoring bolts on [src].", "You unwrench the anchoring bolts.")
user.visible_message("<span class='notice'>[user] unwrenches the anchoring bolts on [src].</span>", "<span class='notice'>You unwrench the anchoring bolts.</span>")
removal_stage = NUKE_UNWRENCHED
update_icon(UPDATE_OVERLAYS)
@@ -273,23 +299,23 @@ GLOBAL_VAR(bomb_set)
if(auth || (istype(I, /obj/item/screwdriver/nuke) && !is_syndicate))
if(!panel_open)
panel_open = TRUE
to_chat(user, "You unscrew the control panel of [src].")
to_chat(user, "<span class='notice'>You unscrew the control panel of [src].</span>")
anchor_stage = removal_stage
removal_stage = core_stage
else
panel_open = FALSE
to_chat(user, "You screw the control panel of [src] back on.")
to_chat(user, "<span class='notice'>You screw the control panel of [src] back on.</span>")
core_stage = removal_stage
removal_stage = anchor_stage
else
if(!panel_open)
to_chat(user, "[src] emits a buzzing noise, the panel staying locked in.")
to_chat(user, "<span class='warning'>[src] emits a buzzing noise, the panel staying locked in.</span>")
if(panel_open)
panel_open = FALSE
to_chat(user, "You screw the control panel of [src] back on.")
to_chat(user, "<span class='notice'>You screw the control panel of [src] back on.</span>")
core_stage = removal_stage
removal_stage = anchor_stage
flick("nuclearbombc", src)
flick(sprite_prefix + "nuclearbombc", src)
update_icon(UPDATE_OVERLAYS)
/obj/machinery/nuclearbomb/wirecutter_act(mob/user, obj/item/I)
@@ -397,6 +423,8 @@ GLOBAL_VAR(bomb_set)
/obj/machinery/nuclearbomb/proc/is_auth(mob/user)
if(auth)
if(istype(auth, /obj/item/disk/nuclear/training) && !training)
return FALSE
return TRUE
else if(user.can_admin_interact())
return TRUE
@@ -409,6 +437,9 @@ GLOBAL_VAR(bomb_set)
. = TRUE
if(exploded)
return
if(wires.is_cut(WIRE_NUKE_CONTROL))
to_chat(usr, "<span class='warning'>The control panel isn't responding! Something must be wrong with its wiring!</span>")
return FALSE
switch(action)
if("deploy")
if(removal_stage != NUKE_MOBILE)
@@ -416,9 +447,9 @@ GLOBAL_VAR(bomb_set)
visible_message("<span class='warning'>With a steely snap, bolts slide out of [src] and anchor it to the flooring!</span>")
else
visible_message("<span class='warning'>[src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.</span>")
if(!lighthack)
flick("nuclearbombc", src)
icon_state = "nuclearbomb1"
if(!wires.is_cut(WIRE_NUKE_LIGHT))
flick(sprite_prefix + "nuclearbombc", src)
icon_state = sprite_prefix + "nuclearbomb1"
update_icon(UPDATE_OVERLAYS)
extended = TRUE
return
@@ -433,6 +464,8 @@ GLOBAL_VAR(bomb_set)
else
var/obj/item/I = usr.get_active_hand()
if(istype(I, /obj/item/disk/nuclear))
if((istype(I, /obj/item/disk/nuclear/training) && !training) || (training && !istype(I, /obj/item/disk/nuclear/training)))
return
usr.drop_item()
I.forceMove(src)
auth = I
@@ -491,43 +524,57 @@ GLOBAL_VAR(bomb_set)
return
timeleft = time
if("toggle_safety")
if(wires.is_cut(WIRE_NUKE_SAFETY))
to_chat(usr, "<span class='warning'>The safety isn't responding! Something must be wrong with its wiring!</span>")
return FALSE
safety = !(safety)
if(safety)
if(!is_syndicate)
if(!is_syndicate && !training)
SSsecurity_level.set_level(previous_level)
timing = FALSE
GLOB.bomb_set = FALSE
if(!training)
GLOB.bomb_set = FALSE
if("toggle_armed")
if(safety)
to_chat(usr, "<span class='notice'>The safety is still on.</span>")
return
if(!core)
if(!core && !training)
to_chat(usr, "<span class='danger'>[src]'s screen blinks red! There is no plutonium core in [src]!</span>")
return
timing = !(timing)
if(timing)
if(!lighthack)
icon_state = "nuclearbomb2"
if(!timing)
if(wires.is_cut(WIRE_NUKE_DETONATOR))
to_chat(usr, "<span class='warning'>[src] isn't arming! Something must be wrong with its wiring!</span>")
return FALSE
timing = TRUE
if(!wires.is_cut(WIRE_NUKE_LIGHT))
icon_state = sprite_prefix + "nuclearbomb2"
update_icon(UPDATE_OVERLAYS)
if(!safety)
if(!safety && !training)
message_admins("[key_name_admin(usr)] engaged a nuclear bomb [ADMIN_JMP(src)]")
if(!is_syndicate && SSsecurity_level.get_current_level_as_number() != SEC_LEVEL_EPSILON)
SSsecurity_level.set_level(SEC_LEVEL_DELTA)
GLOB.bomb_set = TRUE // There can still be issues with this resetting when there are multiple bombs. Not a big deal though for Nuke
if(SSsecurity_level.get_current_level_as_number() == SEC_LEVEL_EPSILON)
radio.autosay("<span class='reallybig'>The Nuclear Bomb has been armed, retreat from the station immediately!</span>", name, "Special Ops")
else
else if(!training)
GLOB.bomb_set = TRUE
else
if(!is_syndicate)
if(wires.is_cut(WIRE_NUKE_DISARM))
to_chat(usr, "<span class='warning'>[src] isn't disarming! Something must be wrong with its wiring!</span>")
return FALSE
timing = FALSE
if(!is_syndicate && !training)
SSsecurity_level.set_level(previous_level)
GLOB.bomb_set = FALSE
if(!lighthack)
icon_state = "nuclearbomb1"
if(!training)
GLOB.bomb_set = FALSE
if(!wires.is_cut(WIRE_NUKE_LIGHT))
icon_state = sprite_prefix + "nuclearbomb1"
update_icon(UPDATE_OVERLAYS)
/obj/machinery/nuclearbomb/blob_act(obj/structure/blob/B)
if(training)
qdel(src)
return
if(exploded)
return
if(timing) //boom
@@ -567,16 +614,19 @@ GLOBAL_VAR(bomb_set)
/obj/machinery/nuclearbomb/proc/explode()
if(training)
atom_say("You've triggered the detonate wire. You are dead.")
return
if(safety)
timing = FALSE
return
exploded = TRUE
yes_code = FALSE
safety = TRUE
if(!lighthack)
icon_state = "nuclearbomb3"
if(!wires.is_cut(WIRE_NUKE_LIGHT))
icon_state = sprite_prefix + "nuclearbomb3"
update_icon(UPDATE_OVERLAYS)
playsound(src,'sound/machines/alarm.ogg',100,0,5)
playsound(src, 'sound/machines/alarm.ogg', 100, FALSE, 5)
if(SSticker && SSticker.mode)
SSticker.mode.explosion_in_progress = TRUE
SSticker.event_blackbox(outcome = ROUND_END_NUCLEAR)
@@ -618,23 +668,6 @@ GLOBAL_VAR(bomb_set)
return
return
/obj/machinery/nuclearbomb/proc/reset_lighthack_callback()
lighthack = !lighthack
/obj/machinery/nuclearbomb/proc/reset_safety_callback()
safety = !safety
if(safety == 1)
if(!is_syndicate)
SSsecurity_level.set_level(previous_level)
visible_message("<span class='notice'>[src] quiets down.</span>")
if(!lighthack)
if(icon_state == "nuclearbomb2")
icon_state = "nuclearbomb1"
update_icon(UPDATE_OVERLAYS)
else
visible_message("<span class='notice'>[src] emits a quiet whirling noise!</span>")
//==========DAT FUKKEN DISK===============
/obj/item/disk/nuclear
name = "nuclear authentication disk"
@@ -645,6 +678,8 @@ GLOBAL_VAR(bomb_set)
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
/// Is the disk restricted to the station? If true, also respawns the disk when deleted
var/restricted_to_station = TRUE
/// Is this a training disk?
var/training = FALSE
/obj/item/disk/nuclear/unrestricted
name = "unrestricted nuclear authentication disk"
@@ -655,7 +690,9 @@ GLOBAL_VAR(bomb_set)
..()
if(restricted_to_station)
START_PROCESSING(SSobj, src)
GLOB.poi_list |= src
if(!training)
GLOB.poi_list |= src
GLOB.nad_list |= src
/obj/item/disk/nuclear/process()
if(!restricted_to_station)
@@ -682,26 +719,32 @@ GLOBAL_VAR(bomb_set)
/obj/item/disk/nuclear/Destroy(force)
var/turf/diskturf = get_turf(src)
if(training)
return ..()
if(force)
message_admins("[src] has been !!force deleted!! in ([diskturf ? "[diskturf.x], [diskturf.y] ,[diskturf.z] - <A href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[diskturf.x];Y=[diskturf.y];Z=[diskturf.z]'>JMP</a>":"nonexistent location"]).")
message_admins("[src] has been !!force deleted!! in ([diskturf ? "[diskturf.x], [diskturf.y] ,[diskturf.z] - <a href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[diskturf.x];Y=[diskturf.y];Z=[diskturf.z]'>JMP</a>":"nonexistent location"]).")
log_game("[src] has been !!force deleted!! in ([diskturf ? "[diskturf.x], [diskturf.y] ,[diskturf.z]":"nonexistent location"]).")
GLOB.poi_list.Remove(src)
GLOB.nad_list.Remove(src)
STOP_PROCESSING(SSobj, src)
return ..()
if(!restricted_to_station) // Non-restricted NADs should be allowed to be deleted, otherwise it becomes a restricted NAD when teleported
message_admins("[src] (unrestricted) has been deleted in ([diskturf ? "[diskturf.x], [diskturf.y] ,[diskturf.z] - <A href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[diskturf.x];Y=[diskturf.y];Z=[diskturf.z]'>JMP</a>":"nonexistent location"]). It will not respawn.")
message_admins("[src] (unrestricted) has been deleted in ([diskturf ? "[diskturf.x], [diskturf.y] ,[diskturf.z] - <a href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[diskturf.x];Y=[diskturf.y];Z=[diskturf.z]'>JMP</a>":"nonexistent location"]). It will not respawn.")
log_game("[src] (unrestricted) has been deleted in ([diskturf ? "[diskturf.x], [diskturf.y] ,[diskturf.z]":"nonexistent location"]). It will not respawn.")
GLOB.poi_list.Remove(src)
GLOB.nad_list.Remove(src)
STOP_PROCESSING(SSobj, src)
return ..()
var/turf/new_spawn = find_respawn()
if(new_spawn)
GLOB.poi_list.Remove(src)
GLOB.nad_list.Remove(src)
var/obj/item/disk/nuclear/NEWDISK = new(new_spawn)
transfer_fingerprints_to(NEWDISK)
message_admins("[src] has been destroyed at ([diskturf.x], [diskturf.y], [diskturf.z] - <A href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[diskturf.x];Y=[diskturf.y];Z=[diskturf.z]'>JMP</a>). Moving it to ([NEWDISK.x], [NEWDISK.y], [NEWDISK.z] - <A href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[NEWDISK.x];Y=[NEWDISK.y];Z=[NEWDISK.z]'>JMP</a>).")
message_admins("[src] has been destroyed at ([diskturf.x], [diskturf.y], [diskturf.z] - <a href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[diskturf.x];Y=[diskturf.y];Z=[diskturf.z]'>JMP</a>). Moving it to ([NEWDISK.x], [NEWDISK.y], [NEWDISK.z] - <a href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[NEWDISK.x];Y=[NEWDISK.y];Z=[NEWDISK.z]'>JMP</a>).")
log_game("[src] has been destroyed in ([diskturf.x], [diskturf.y], [diskturf.z]). Moving it to ([NEWDISK.x], [NEWDISK.y], [NEWDISK.z]).")
..()
return QDEL_HINT_HARDDEL_NOW // We want this to be deleted ASAP, but we want refs properly cleared too
@@ -720,6 +763,54 @@ GLOBAL_VAR(bomb_set)
if(length(open_turfs))
return pick(open_turfs)
/// MARK: TRAINING NUKE
/obj/machinery/nuclearbomb/training
name = "training nuclear bomb"
desc = "A fake nuke used to practice nuclear device operations. \
The '1' key on the keypad appears to be significantly more worn than the other keys."
icon_state = "t_nuclearbomb1"
resistance_flags = null
training = TRUE
sprite_prefix = "t_"
/obj/machinery/nuclearbomb/training/Initialize()
. = ..()
r_code = 11111 //Uuh.. one!
qdel(core)
/obj/machinery/nuclearbomb/training/process()
if(timing)
timeleft = max(timeleft - 2, 0) // 2 seconds per process()
if(timeleft <= 0)
INVOKE_ASYNC(src, PROC_REF(training_detonation))
/obj/machinery/nuclearbomb/training/blob_act(obj/structure/blob/B)
qdel(src)
/obj/machinery/nuclearbomb/training/AltClick(mob/user)
. = ..()
to_chat(user, "<span class='notice'>You hit the reset button on [src].</span>")
training_reset()
/obj/machinery/nuclearbomb/training/proc/training_detonation()
atom_say("Nuclear device detonated. Resetting...")
training_reset()
/obj/machinery/nuclearbomb/training/proc/training_reset()
if(auth)
auth.forceMove(get_turf(src))
new /obj/machinery/nuclearbomb/training(get_turf(src))
qdel(src)
/obj/item/disk/nuclear/training
name = "training authentication disk"
desc = "The code is 11111."
icon_state = "trainingdisk"
resistance_flags = null
restricted_to_station = FALSE
training = TRUE
#undef NUKE_INTACT
#undef NUKE_COVER_OFF
#undef NUKE_COVER_OPEN
+3 -3
View File
@@ -96,15 +96,15 @@
/obj/item/pinpointer/proc/scandisk()
if(!the_disk)
the_disk = locate() in GLOB.poi_list
the_disk = locate() in GLOB.nad_list
/obj/item/pinpointer/proc/scanbomb()
if(!syndicate)
if(!the_bomb)
the_bomb = locate() in GLOB.poi_list
the_bomb = locate() in GLOB.nuke_list
else
if(!the_s_bomb)
the_s_bomb = locate() in GLOB.poi_list
the_s_bomb = locate() in GLOB.syndi_nuke_list
/obj/item/pinpointer/proc/point_at_target(atom/target)
if(!target)
+5
View File
@@ -106,6 +106,11 @@
protected_jobs = list("Captain")
location_override = "the Captain's Office"
/datum/theft_objective/nukedisc/check_special_completion(obj/item/I)
if(istype(I, /obj/item/disk/nuclear/training)) //Haha no
return FALSE
return TRUE
/datum/theft_objective/reactive
name = "any type of reactive armor"
typepath = /obj/item/clothing/suit/armor/reactive
+3 -5
View File
@@ -389,11 +389,9 @@
card_icon = "wheel_of_fortune"
/datum/tarot/wheel_of_fortune/activate(mob/living/target)
var/list/static/bad_vendors = list(
/obj/machinery/economy/vending/liberationstation,
/obj/machinery/economy/vending/toyliberationstation,
/obj/machinery/economy/vending/wallmed
)
var/list/static/bad_vendors = typesof(/obj/machinery/economy/vending/liberationstation)\
+ typesof(/obj/machinery/economy/vending/toyliberationstation)\
+ typesof(/obj/machinery/economy/vending/wallmed) // Future proofing in case we add more subtypes of disallowed vendors
var/turf/target_turf = get_turf(target)
var/vendorpath = pick(subtypesof(/obj/machinery/economy/vending) - bad_vendors)
new vendorpath(target_turf)
+5 -6
View File
@@ -41,10 +41,8 @@
/obj/item/organ/internal/cyberimp/arm/combat/centcom
)
/datum/outfit/job/ntnavyofficer/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
/datum/outfit/job/ntnavyofficer/on_mind_initialize(mob/living/carbon/human/H)
. = ..()
if(visualsOnly)
return
H.mind.offstation_role = TRUE
// CC Officials who lead ERTs, Death Squads, etc.
@@ -97,10 +95,8 @@
/obj/item/organ/internal/cyberimp/arm/combat/centcom
)
/datum/outfit/job/ntspecops/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
/datum/outfit/job/ntspecops/on_mind_initialize(mob/living/carbon/human/H)
. = ..()
if(visualsOnly)
return
H.mind.offstation_role = TRUE
/datum/job/ntspecops/solgovspecops
@@ -121,4 +117,7 @@
if(istype(I))
apply_to_card(I, H, get_centcom_access(name), name, "lifetimeid")
H.sec_hud_set_ID()
/datum/outfit/job/ntspecops/solgovspecops/on_mind_initialize(mob/living/carbon/human/H)
. = ..()
H.mind.offstation_role = TRUE
+14
View File
@@ -216,6 +216,7 @@
gear_leftovers += G
/datum/outfit/job/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
. = ..()
if(visualsOnly)
return
@@ -280,3 +281,16 @@
PDA.ownjob = C.assignment
PDA.ownrank = C.rank
PDA.name = "PDA-[H.real_name] ([PDA.ownjob])"
/datum/outfit/job/on_mind_initialize(mob/living/carbon/human/H)
. = ..()
var/obj/item/card/id/id = H.wear_id
if(!id)
return
var/datum/job/J = SSjobs.GetJobType(jobtype)
if(!J)
J = SSjobs.GetJob(H.job)
id.assignment = H.mind.role_alt_title ? H.mind.role_alt_title : J.title
if(!H.mind.initial_account)
return
id.associated_account_number = H.mind.initial_account.account_number
+13 -10
View File
@@ -202,6 +202,9 @@
singlemutcheck(H, GLOB.soberblock, MUTCHK_FORCED)
H.dna.default_blocks.Add(GLOB.soberblock)
H.check_mutations = 1
/datum/outfit/job/bartender/on_mind_initialize(mob/living/carbon/human/H)
. = ..()
ADD_TRAIT(H.mind, TRAIT_TABLE_LEAP, ROUNDSTART_TRAIT)
ADD_TRAIT(H.mind, TRAIT_SLEIGHT_OF_HAND, ROUNDSTART_TRAIT)
@@ -236,12 +239,10 @@
/obj/item/paper/chef=1,\
/obj/item/book/manual/wiki/chef_recipes=1)
/datum/outfit/job/chef/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
..()
if(visualsOnly)
return
/datum/outfit/job/chef/on_mind_initialize(mob/living/carbon/human/H)
. = ..()
var/datum/martial_art/cqc/under_siege/justacook = new
justacook.teach(H)
justacook.teach(H) // requires mind
ADD_TRAIT(H.mind, TRAIT_TABLE_LEAP, ROUNDSTART_TRAIT)
@@ -419,12 +420,14 @@
if(visualsOnly)
return
if(H.mind)
H.mind.AddSpell(new /datum/spell/aoe/conjure/build/mime_wall(null))
H.mind.AddSpell(new /datum/spell/mime/speak(null))
H.mind.miming = 1
qdel(H.GetComponent(/datum/component/footstep))
/datum/outfit/job/mime/on_mind_initialize(mob/living/carbon/human/H)
. = ..()
H.mind.AddSpell(new /datum/spell/aoe/conjure/build/mime_wall(null))
H.mind.AddSpell(new /datum/spell/mime/speak(null))
H.mind.miming = TRUE
/datum/job/janitor
title = "Janitor"
flag = JOB_JANITOR
@@ -488,7 +491,7 @@
/datum/outfit/job/librarian/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
..()
if(!H.mind)
if(visualsOnly)
return
for(var/la in GLOB.all_languages)
var/datum/language/new_language = GLOB.all_languages[la]
+4 -3
View File
@@ -32,11 +32,12 @@
if(visualsOnly)
return
if(istype(H.mind))
ADD_TRAIT(H.mind, TRAIT_HOLY, ROUNDSTART_TRAIT)
INVOKE_ASYNC(src, PROC_REF(religion_pick), H)
/datum/outfit/job/chaplain/on_mind_initialize(mob/living/carbon/human/H)
. = ..()
ADD_TRAIT(H.mind, TRAIT_HOLY, ROUNDSTART_TRAIT)
/datum/outfit/job/chaplain/proc/religion_pick(mob/living/carbon/human/user)
var/obj/item/storage/bible/B = new /obj/item/storage/bible(get_turf(user))
B.customisable = TRUE // Only the initial bible is customisable
+4 -1
View File
@@ -55,8 +55,11 @@
U.implant(H)
U.hidden_uplink.uses = 2500
H.faction += "syndicate"
/datum/outfit/job/syndicateofficer/on_mind_initialize(mob/living/carbon/human/H)
. = ..()
var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS]
opshud.join_hud(H.mind.current)
H.mind.offstation_role = TRUE
set_antag_hud(H.mind.current, "hudoperative")
H.regenerate_icons()
INVOKE_ASYNC(H, TYPE_PROC_REF(/mob/living/carbon/human, regenerate_icons))
@@ -300,20 +300,7 @@
emagged = FALSE
setMenuState(ui.user, COMM_SCREEN_MAIN)
if("RestartNanoMob")
if(SSmob_hunt)
if(SSmob_hunt.manual_reboot())
var/loading_msg = pick("Respawning spawns", "Reticulating splines", "Flipping hat",
"Capturing all of them", "Fixing minor text issues", "Being the very best",
"Nerfing this", "Not communicating with playerbase", "Coding a ripoff in a 2D spaceman game")
to_chat(ui.user, "<span class='notice'>Restarting Nano-Mob Hunter GO! game server. [loading_msg]...</span>")
else
to_chat(ui.user, "<span class='warning'>Nano-Mob Hunter GO! game server reboot failed due to recent restart. Please wait before re-attempting.</span>")
else
to_chat(ui.user, "<span class='danger'>Nano-Mob Hunter GO! game server is offline for extended maintenance. Contact your Central Command administrators for more info if desired.</span>")
// ADMIN CENTCOMM ONLY STUFF
if("send_to_cc_announcement_page")
if(!ADMIN_CHECK(ui.user))
return
+3 -2
View File
@@ -301,8 +301,9 @@
if(occupant_typecache)
occupant_typecache = typecacheof(occupant_typecache)
/obj/machinery/suit_storage_unit/Destroy()
dump_contents()
/obj/machinery/suit_storage_unit/Destroy(force)
if(!force)
dump_contents()
SStgui.close_uis(wires)
QDEL_NULL(wires)
return ..()
-2
View File
@@ -1301,7 +1301,6 @@
icon_panel = "wide_vendor"
category = VENDOR_TYPE_SUPPLIES
products = list(/obj/item/pda =10,
/obj/item/cartridge/mob_hunt_game = 25,
/obj/item/cartridge/medical = 10,
/obj/item/cartridge/chemistry = 10,
/obj/item/cartridge/engineering = 10,
@@ -1314,7 +1313,6 @@
/obj/item/cartridge/mime = 1)
prices = list(/obj/item/pda = 300,
/obj/item/cartridge/mob_hunt_game = 50,
/obj/item/cartridge/medical = 200,
/obj/item/cartridge/chemistry = 150,
/obj/item/cartridge/engineering = 100,
+62 -14
View File
@@ -16,8 +16,16 @@
wreckage = /obj/structure/mecha_wreckage/ripley
var/list/cargo = new
var/cargo_capacity = 15
/// How many goliath hides does the Ripley have? Does not stack with other armor
var/hides = 0
/// How many drake hides does the Ripley have? Does not stack with other armor
var/drake_hides = 0
/// How many plates does the Ripley have? Does not stack with other armor
var/plates = 0
/obj/mecha/working/ripley/Move()
. = ..()
if(.)
@@ -33,10 +41,14 @@
ore.forceMove(ore_box)
/obj/mecha/working/ripley/Destroy()
for(var/i=1, i <= hides, i++)
new /obj/item/stack/sheet/animalhide/goliath_hide(loc) //If a goliath-plated ripley gets killed, all the plates drop
for(var/i in 1 to hides)
new /obj/item/stack/sheet/animalhide/goliath_hide(get_turf(src)) //If a armor-plated ripley gets killed, all the armor drop
for(var/i in 1 to plates)
new /obj/item/stack/sheet/animalhide/armor_plate(get_turf(src))
for(var/i in 1 to drake_hides)
new /obj/item/stack/sheet/animalhide/ashdrake(get_turf(src))
for(var/atom/movable/A in cargo)
A.forceMove(loc)
A.forceMove(get_turf(src))
step_rand(A)
cargo.Cut()
return ..()
@@ -55,22 +67,58 @@
/obj/mecha/working/ripley/update_desc()
. = ..()
if(!hides) // Just in case if hides are somehow removed
if(!hides && !plates && !drake_hides) // Just in case if armor is removed
desc = initial(desc)
return
if(hides == 3)
desc = "Autonomous Power Loader Unit. It's wearing a fearsome carapace entirely composed of goliath hide plates - its pilot must be an experienced monster hunter."
else
desc = "Autonomous Power Loader Unit. Its armour is enhanced with some goliath hide plates."
// Goliath hides
if(hides)
if(hides == HIDES_COVERED_FULL)
desc = "Autonomous Power Loader Unit. It's wearing a fearsome carapace entirely composed of goliath hide plates - its pilot must be an experienced monster hunter."
else
desc = "Autonomous Power Loader Unit. Its armour is enhanced with some goliath hide plates."
return
// Metal plates
if(plates)
if(plates == PLATES_COVERED_FULL)
desc = "Autonomous Power Loader Unit. Its armor is completely lined with metal plating."
else
desc = "Autonomous Power Loader Unit. Its armor is reinforced with some metal plating."
return
// Drake hides
if(drake_hides)
if(drake_hides == DRAKE_HIDES_COVERED_FULL)
desc = "Autonomous Power Loader Unit. Its every corner is covered in ancient hide, creating a powerful shield. The pilot of this exosuit must be prepared for battles on the level of legend."
if(drake_hides == DRAKE_HIDES_COVERED_MODERATE)
desc = "Autonomous Power Loader Unit. Its armor is adorned with dragon hide plates, instilling fear in its enemies and guarding its pilot."
if(drake_hides == DRAKE_HIDES_COVERED_SLIGHT)
desc = "Autonomous Power Loader Unit. The armor of this exosuit only touches the mythical: a few plates of dragon hide adorn its plating like rare warrior trophies."
return
/obj/mecha/working/ripley/update_overlays()
. = ..()
if(!hides)
return
if(hides == 3)
. += occupant ? "ripley-g-full" : "ripley-g-full-open"
else
. += occupant ? "ripley-g" : "ripley-g-open"
// hides
if(hides)
if(hides == HIDES_COVERED_FULL)
. += occupant ? "ripley-g-full" : "ripley-g-full-open"
else
. += occupant ? "ripley-g" : "ripley-g-open"
//plates
if(plates)
if(plates == PLATES_COVERED_FULL)
. += occupant ? "ripley-m-full" : "ripley-m-full-open"
else
. += occupant ? "ripley-m" : "ripley-m-open"
//drake hides
if(drake_hides)
if(drake_hides == DRAKE_HIDES_COVERED_FULL)
. += occupant ? "ripley-d-full" : "ripley-d-full-open"
else if(drake_hides == DRAKE_HIDES_COVERED_MODERATE)
. += occupant ? "ripley-d-2" : "ripley-d-2-open"
else if(drake_hides == DRAKE_HIDES_COVERED_SLIGHT)
. += occupant ? "ripley-d" : "ripley-d-open"
/obj/mecha/working/ripley/firefighter
desc = "A standard APLU chassis that was refitted with additional thermal protection and a cistern."
+1
View File
@@ -1,2 +1,3 @@
/obj/mecha/working
internal_damage_threshold = 60
@@ -228,3 +228,6 @@
/obj/effect/turf_decal/raven/nine
icon_state = "RAVEN9"
/obj/effect/turf_decal/blue_corner
icon_state = "darkbluecorners"
@@ -19,41 +19,3 @@
for(var/j in 1 to steps_amt)
sleep(1)
step(expl,direct)
/obj/effect/explosion
name = "explosive particles"
icon = 'icons/effects/96x96.dmi'
icon_state = "explosion"
opacity = TRUE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
pixel_x = -32
pixel_y = -32
/obj/effect/explosion/New()
..()
QDEL_IN(src, 10)
/datum/effect_system/explosion
/datum/effect_system/explosion/set_up(loca)
if(isturf(loca))
location = loca
else
location = get_turf(loca)
/datum/effect_system/explosion/start()
new/obj/effect/explosion(location)
var/datum/effect_system/expl_particles/P = new/datum/effect_system/expl_particles()
P.set_up(10, 0, location)
P.start()
/datum/effect_system/explosion/smoke
/datum/effect_system/explosion/smoke/proc/create_smoke()
var/datum/effect_system/smoke_spread/S = new
S.set_up(5, FALSE, location, null)
S.start()
/datum/effect_system/explosion/smoke/start()
..()
addtimer(CALLBACK(src, PROC_REF(create_smoke)), 5)
-3
View File
@@ -678,8 +678,5 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/newplayer_start) //Without this you sp
var/turf/simulated/T = get_turf(src)
T.burn_tile()
/obj/effect/landmark/battle_mob_point
name = "Nanomob Battle Avatar Spawn Point"
/obj/effect/landmark/free_golem_spawn
name = "Free Golem Spawn Point"
@@ -0,0 +1,64 @@
/obj/effect/temp_visual/explosion
name = "boom"
icon = 'icons/effects/96x96.dmi'
icon_state = "explosion2"
duration = 6 SECONDS
/// Smoke wave particle holder
var/obj/effect/abstract/particle_holder/smoke_wave
/// Explosion smoke particle holder
var/obj/effect/abstract/particle_holder/explosion_smoke
/// Sparks particle holder
var/obj/effect/abstract/particle_holder/sparks
/obj/effect/temp_visual/explosion/Initialize(mapload, radius, color, small = FALSE, large = FALSE)
. = ..()
set_light(radius, radius, LIGHT_COLOR_ORANGE)
generate_particles(radius, small, large)
var/image/I = image(icon, src, icon_state, 10, -32, -32)
var/matrix/rotate = matrix()
rotate.Turn(rand(0, 359))
I.transform = rotate
overlays += I // We use an overlay so the explosion and light source are both in the correct location plus so the particles don't rotate with the explosion
icon_state = null
/// Generate the particles
/obj/effect/temp_visual/explosion/proc/generate_particles(radius, small = FALSE, large = FALSE)
if(small)
smoke_wave = new(src, /particles/smoke_wave/small)
else
smoke_wave = new(src, /particles/smoke_wave)
if(large)
explosion_smoke = new(src, /particles/explosion_smoke/deva)
else if(small)
explosion_smoke = new(src, /particles/explosion_smoke/small)
else
explosion_smoke = new(src, /particles/explosion_smoke)
sparks = new(src, /particles/sparks_outwards)
if(large)
smoke_wave.particles.velocity = generator(GEN_CIRCLE, 6 * radius, 6 * radius)
else if(small)
smoke_wave.particles.velocity = generator(GEN_CIRCLE, 3 * radius, 3 * radius)
else
smoke_wave.particles.velocity = generator(GEN_CIRCLE, 5 * radius, 5 * radius)
explosion_smoke.layer = layer + 0.1
sparks.particles.velocity = generator(GEN_CIRCLE, 8 * radius, 8 * radius)
// The reason for these timers is to set the count to 0
// This causes any particle systems to not spawn in new particles, but not delete the currently existing ones
addtimer(CALLBACK(src, PROC_REF(set_count_short)), 1 SECONDS)
/obj/effect/temp_visual/explosion/proc/set_count_short()
remove_light()
explosion_smoke.particles.count = 0
sparks.particles.count = 0
smoke_wave.particles.count = 0
/obj/effect/temp_visual/explosion/Destroy()
QDEL_NULL(smoke_wave)
QDEL_NULL(explosion_smoke)
QDEL_NULL(sparks)
return ..()
@@ -231,16 +231,12 @@
layer = ABOVE_MOB_LAYER
duration = 4
/obj/effect/temp_visual/explosion
/obj/effect/temp_visual/pka_explosion
name = "explosion"
icon = 'icons/effects/96x96.dmi'
icon_state = "explosion"
icon_state = "explosionfast"
pixel_x = -32
pixel_y = -32
duration = 8
/obj/effect/temp_visual/explosion/fast
icon_state = "explosionfast"
duration = 4
/obj/effect/temp_visual/heart
+10 -10
View File
@@ -1,5 +1,3 @@
//TODO: Flash range does nothing currently
#define CREAK_DELAY 5 SECONDS //Time taken for the creak to play after explosion, if applicable.
#define DEVASTATION_PROB 30 //The probability modifier for devistation, maths!
#define HEAVY_IMPACT_PROB 5 //ditto
@@ -74,6 +72,10 @@
var/turf/M_turf = get_turf(M)
if(M_turf && M_turf.z == z0)
var/dist = get_dist(M_turf, epicenter)
if(isliving(M) && dist <= flash_range)
var/mob/living/to_flash = M
var/is_very_close_to_the_explosion = flash_range > (dist * 2)
to_flash.flash_eyes(is_very_close_to_the_explosion * 2, is_very_close_to_the_explosion, is_very_close_to_the_explosion) // Gets past sunglasses
var/baseshakeamount
if(orig_max_distance - dist > 0)
baseshakeamount = sqrt((orig_max_distance - dist) * 0.1)
@@ -107,14 +109,12 @@
if(creaking_explosion) // 5 seconds after the bang, the station begins to creak
addtimer(CALLBACK(M, TYPE_PROC_REF(/mob, playsound_local), epicenter, null, rand(FREQ_LOWER, FREQ_UPPER), 1, frequency, null, null, FALSE, hull_creaking_sound, 0), CREAK_DELAY)
if(heavy_impact_range > 1)
var/datum/effect_system/explosion/E
if(smoke)
E = new /datum/effect_system/explosion/smoke
else
E = new
E.set_up(epicenter)
E.start()
if(devastation_range > 0)
new /obj/effect/temp_visual/explosion(epicenter, max_range, FALSE, TRUE)
else if(heavy_impact_range > 0)
new /obj/effect/temp_visual/explosion(epicenter, max_range, FALSE, FALSE)
else if(light_impact_range > 0)
new /obj/effect/temp_visual/explosion(epicenter, max_range, TRUE, FALSE)
var/list/affected_turfs = spiral_range_turfs(max_range, epicenter)
@@ -0,0 +1,231 @@
/* CONTENTS:
0. generic define gripper
1. UNIVERSAL GRIPPER
2. MEDICAL GRIPPER
3. SERVICE GRIPPER
4. ENGINEERING GRIPPER
*/
// Generic gripper. This should never appear anywhere.
/obj/item/gripper
name = "generic gripper item"
desc = "If you can see this, make an issue report to Github. Something has gone wrong!"
icon = 'icons/obj/device.dmi'
icon_state = "gripper"
actions_types = list(/datum/action/item_action/drop_gripped_item)
/// Set to TRUE to allow interaction with light fixtures and cell-containing machinery.
var/engineering_machine_interaction = FALSE
/// Set to TRUE to allow the gripper to shake people awake/help them up.
var/can_help_up = FALSE
/// Defines what items the gripper can carry.
var/list/can_hold = list()
/// Set to TRUE to allow ANY item to be held, bypassing can_hold checks.
var/can_hold_all_items = FALSE
/// The item currently being held.
var/obj/item/gripped_item
/obj/item/gripper/examine(mob/user)
. = ..()
if(!gripped_item)
. += "<span class='notice'>[src] is empty.</span>"
return
. += "<span class='notice'>[src] is currently holding [gripped_item].</span>"
/obj/item/gripper/examine_more(mob/user)
. = ..()
. += {"Cyborg grippers are well-developed, and despite some anatomical differences that manifest in some models, they can be used just as effectively as a regular hand with enough practice.
Companies like Nanotrasen use software to limit the items that a cyborg can manipulate to a specific pre-defined list, \
as part of their multi-layered protections to try and eliminate the chance of a hypothetical synthetic uprising, not wishing to see a repeat of the IPC uprising in 2525."}
/obj/item/gripper/Initialize(mapload)
. = ..()
can_hold = typecacheof(can_hold)
/obj/item/gripper/ui_action_click(mob/user)
drop_gripped_item(user)
/obj/item/gripper/proc/drop_gripped_item(mob/user, silent = FALSE)
if(!gripped_item)
to_chat(user, "<span class='warning'>[src] is empty.</span>")
return
if(!silent)
to_chat(user, "<span class='warning'>You drop [gripped_item].</span>")
gripped_item.forceMove(get_turf(src))
gripped_item = null
/obj/item/gripper/attack_self(mob/user)
if(!gripped_item)
to_chat(user, "<span class='warning'>[src] is empty.</span>")
return
gripped_item.attack_self(user)
/obj/item/gripper/attack(mob/living/carbon/M, mob/living/carbon/user)
return
// This is required to ensure that the forceMove checks on some objects don't rip the gripper out of the borg's inventory and toss it on the floor. That would hurt, a lot!
/obj/item/gripper/forceMove(atom/destination)
return
/obj/item/gripper/afterattack(atom/target, mob/living/user, proximity, params)
//Target is invalid or we are not adjacent.
if(!target || !proximity)
return FALSE
// Shake people awake, get them on their feet.
if(ishuman(target) && can_help_up)
var/mob/living/carbon/human/pickup_target = target
if(!IS_HORIZONTAL(pickup_target))
return
pickup_target.AdjustSleeping(-10 SECONDS)
pickup_target.AdjustParalysis(-6 SECONDS)
pickup_target.AdjustStunned(-6 SECONDS)
pickup_target.AdjustWeakened(-6 SECONDS)
pickup_target.AdjustKnockDown(-6 SECONDS)
pickup_target.adjustStaminaLoss(-10)
pickup_target.resting = FALSE
pickup_target.stand_up()
playsound(user.loc, 'sound/weapons/thudswoosh.ogg', 50, TRUE, -1)
user.visible_message(
"<span class='notice'>[user] shakes [pickup_target] trying to wake [pickup_target.p_them()] up!</span>",
"<span class='notice'>You shake [pickup_target] trying to wake [pickup_target.p_them()] up!</span>"
)
return FALSE
//Already have an item.
if(gripped_item)
//Pass the attack on to the target. This might delete/relocate gripped_item.
if(!target.attackby(gripped_item, user, params))
// If the attackby didn't resolve or delete the target or gripped_item, afterattack
// (Certain things, such as mountable frames, rely on afterattack)
gripped_item?.afterattack(target, user, 1, params)
//If gripped_item either didn't get deleted, or it failed to be transfered to its target
if(!gripped_item && length(contents))
gripped_item = contents[1]
return FALSE
else if(gripped_item && !contents.len)
gripped_item = null
//Check that we're not pocketing a mob.
else if(isitem(target))
var/obj/item/I = target
// Make sure the item is something the gripper can hold
if(can_hold_all_items || is_type_in_typecache(I, can_hold))
to_chat(user, "<span class='notice'>You collect [I].</span>")
I.forceMove(src)
gripped_item = I
return TRUE
to_chat(user, "<span class='warning'>You hold your gripper over [target], but no matter how hard you try, you cannot make yourself grab it.</span>")
return FALSE
// Everything past this point requires being able to engineer.
if(!engineering_machine_interaction)
return
// APC cells.
if(istype(target, /obj/machinery/power/apc))
var/obj/machinery/power/apc/A = target
if(A.opened && A.cell)
gripped_item = A.cell
A.cell.add_fingerprint(user)
A.cell.update_icon()
A.cell.forceMove(src)
A.cell = null
A.charging = APC_NOT_CHARGING
A.update_icon()
user.visible_message("<span class='warning'>[user] removes the power cell from [A]!</span>", "<span class='warning'>You remove the power cell.</span>")
// Cell Chargers
else if(istype(target, /obj/machinery/cell_charger))
var/obj/machinery/cell_charger/cell_charger = target
if(cell_charger.charging)
gripped_item = cell_charger.charging
cell_charger.charging.add_fingerprint(user)
cell_charger.charging.forceMove(src)
cell_charger.removecell()
// Putting lights in fixtures.
else if(istype(target, /obj/machinery/light))
var/obj/machinery/light/light = target
var/obj/item/light/L = light.drop_light_tube()
L.forceMove(src)
gripped_item = L
user.visible_message("<span class='notice'>[user] removes the light from the fixture.</span>", "<span class='notice'>You dislodge the light from the fixture.</span>")
return TRUE
////////////////////////////////
// MARK: UNIVERSAL GRIPPER
////////////////////////////////
/// Universal gripper. Not supplied to any cyborg by default. Could be varedited onto a borg for event stuff. Functions almost like a real hand!
/obj/item/gripper/universal
name = "cyborg gripper"
desc = "A grasping tool for cyborgs. This one is not restricted by any restraining software, allowing it to handle any object the user wishes."
// It's UNIVERSAL so it has all functions enabled.
engineering_machine_interaction = TRUE
can_help_up = TRUE
can_hold_all_items = TRUE
////////////////////////////////
// MARK: MEDICAL GRIPPER
////////////////////////////////
// For medical borgs, for doing medical stuff!
// Not giving this anything to hold yet, but stuff may be added in the future. Organs/implants are currently viewed as too strong to hold.
/obj/item/gripper/medical
name = "medical gripper"
desc = "A grasping tool for cyborgs. This one is covered with hygenic medical-grade silicone rubber. \
Use it to help patients up once surgery is complete, or to substitute for hands in surgical operations."
can_help_up = TRUE
// REMOVE actions_types from here if you add a can_hold list for this gripper!
actions_types = list()
////////////////////////////////
// MARK: SERVICE GRIPPER
////////////////////////////////
// For service borgs. To make them slightly better at their job.
/obj/item/gripper/service
name = "service gripper"
desc = "A grasping tool for cyborgs. This version is made from hygenic easy-clean material. Maybe some day you'll be able to grab food with it..."
// For waking up drunkards.
can_help_up = TRUE
// Everything in this list is currently for either playing games or otherwise assisting the crew in mundane, non-impactful ways.
can_hold = list(
/obj/item/deck,
/obj/item/cardhand,
/obj/item/coin,
/obj/item/paper,
/obj/item/photo,
/obj/item/toy/plushie
)
////////////////////////////////
// MARK: ENGINEERING GRIPPER
////////////////////////////////
// For engineering and sabotage borgs, and drones.
/obj/item/gripper/engineering
name = "engineering gripper"
desc = "A grasping tool for cyborgs. This version can hold a wide variety of constructon components for use in engineering work."
engineering_machine_interaction = TRUE
can_hold = list(
/obj/item/firealarm_electronics,
/obj/item/airalarm_electronics,
/obj/item/airlock_electronics,
/obj/item/firelock_electronics,
/obj/item/intercom_electronics,
/obj/item/apc_electronics,
/obj/item/tracker_electronics,
/obj/item/stock_parts,
/obj/item/vending_refill,
/obj/item/mounted/frame,
/obj/item/assembly/prox_sensor,
/obj/item/assembly/igniter,
/obj/item/rack_parts,
/obj/item/camera_assembly,
/obj/item/tank,
/obj/item/circuitboard,
/obj/item/stack/ore/bluespace_crystal,
/obj/item/stack/tile/light,
/obj/item/light
)
@@ -486,3 +486,24 @@
return
for(var/obj/item/reagent_containers/borghypo/F in R.module.modules)
F.emag_act()
/obj/item/borg/upgrade/abductor_jani
name = "janitorial cyborg abductor upgrade"
desc = "An experimental upgrade that replaces a janitorial cyborg's tools with the abductor versions."
icon_state = "abductor_mod"
origin_tech = "biotech=6;materials=6;abductor=3"
require_module = TRUE
module_type = /obj/item/robot_module/janitor
items_to_replace = list(
/obj/item/mop/advanced/cyborg = /obj/item/mop/advanced/abductor,
/obj/item/soap = /obj/item/soap/syndie/abductor,
/obj/item/lightreplacer/cyborg = /obj/item/lightreplacer/bluespace/abductor,
/obj/item/melee/flyswatter = /obj/item/melee/flyswatter/abductor
)
items_to_add = list(
/obj/item/reagent_containers/spray/cleaner/safety/abductor
)
special_rechargables = list(
/obj/item/reagent_containers/spray/cleaner/safety/abductor,
/obj/item/lightreplacer/bluespace/abductor
)
@@ -178,7 +178,7 @@ GLOBAL_LIST_INIT(sinew_recipes, list (
/obj/item/stack/sheet/animalhide/goliath_hide
name = "goliath hide plates"
desc = "Pieces of a goliath's rocky hide, these might be able to make your suit a bit more durable to attack from the local fauna."
desc = "Pieces of a goliath's rocky hide, these might be able to make your miner equipment such as suits, plasmaman helmets, borgs and Ripley class exosuits a bit more durable to attack from the local fauna."
icon = 'icons/obj/stacks/organic.dmi'
icon_state = "goliath_hide"
item_state = "goliath_hide"
@@ -198,41 +198,80 @@ GLOBAL_LIST_INIT(sinew_recipes, list (
if(is_type_in_typecache(target, goliath_platable_armor_typecache))
var/obj/item/clothing/C = target
var/datum/armor/current_armor = C.armor
if(current_armor.getRating(MELEE) < 60)
C.armor = current_armor.setRating(melee_value = min(current_armor.getRating(MELEE) + 10, 60))
if(current_armor.getRating(MELEE) < 75)
if(!use(1))
to_chat(user, "<span class='notice'>You dont have enough [src] for this!</span>")
return
C.armor = current_armor.setRating(melee_value = min(current_armor.getRating(MELEE) + 15, 75))
to_chat(user, "<span class='info'>You strengthen [target], improving its resistance against melee attacks.</span>")
use(1)
else
to_chat(user, "<span class='warning'>You can't improve [C] any further!</span>")
else if(istype(target, /obj/mecha/working/ripley))
var/obj/mecha/working/ripley/D = target
if(D.hides < 3)
if(D.hides < HIDES_COVERED_FULL && !D.plates && !D.drake_hides)
if(!use(1))
to_chat(user, "<span class='notice'>You dont have enough [src] for this!</span>")
return
D.hides++
D.armor = D.armor.setRating(melee_value = min(D.armor.getRating(MELEE) + 10, 70))
D.armor = D.armor.setRating(bullet_value = min(D.armor.getRating(BULLET) + 5, 50))
D.armor = D.armor.setRating(laser_value = min(D.armor.getRating(LASER) + 5, 50))
to_chat(user, "<span class='info'>You strengthen [target], improving its resistance against melee attacks.</span>")
D.armor = D.armor.setRating(melee_value = min(D.armor.getRating(MELEE) + 25, 115))
D.armor = D.armor.setRating(bullet_value = min(D.armor.getRating(BULLET) + 7, 60))
D.armor = D.armor.setRating(laser_value = min(D.armor.getRating(LASER) + 7, 60))
to_chat(user, "<span class='info'>You strengthen [target], improving its resistance against attacks.</span>")
D.update_appearance(UPDATE_DESC|UPDATE_OVERLAYS)
use(1)
else
to_chat(user, "<span class='warning'>You can't improve [D] any further!</span>")
else if(isrobot(target))
var/mob/living/silicon/robot/R = target
if(istype(R.module, /obj/item/robot_module/miner))
var/datum/armor/current_armor = R.armor
if(current_armor.getRating(MELEE) < 60)
R.armor = current_armor.setRating(melee_value = min(current_armor.getRating(MELEE) + 10, 60))
if(current_armor.getRating(MELEE) < 75)
if(!use(1))
to_chat(user, "<span class='notice'>You dont have enough [src] for this!</span>")
return
R.armor = current_armor.setRating(melee_value = min(current_armor.getRating(MELEE) + 15, 75))
to_chat(user, "<span class='info'>You strengthen [target], improving its resistance against melee attacks.</span>")
use(1)
else
to_chat(user, "<span class='warning'>You can't improve [R] any further!</span>")
else
to_chat(user, "<span class='warning'>[R]'s armor can not be improved!</span>")
/obj/item/stack/sheet/animalhide/armor_plate
name = "armor plate"
desc = "This piece of metal can be attached to the mech itself, enhancing its protective characteristics. Unfortunately, only working class exosuits have notches for such armor."
icon = 'icons/mecha/mecha_equipment.dmi'
icon_state = "armor_plate"
item_state = "armor_plate"
singular_name = "armor plate"
flags = NOBLUDGEON
w_class = WEIGHT_CLASS_NORMAL
layer = MOB_LAYER
/obj/item/stack/sheet/animalhide/armor_plate/afterattack(atom/target, mob/user, proximity_flag)
if(!proximity_flag)
return
if(istype(target, /obj/mecha/working/ripley))
var/obj/mecha/working/ripley/D = target
if(D.plates < PLATES_COVERED_FULL && !D.hides && !D.drake_hides)
if(!use(1))
to_chat(user, "<span class='notice'>You dont have enough [src] for this!</span>")
return
use(1)
D.plates++
D.armor = D.armor.setRating(melee_value = min(D.armor.getRating(MELEE) + 10, 70))
D.armor = D.armor.setRating(bullet_value = min(D.armor.getRating(BULLET) + 4, 50))
D.armor = D.armor.setRating(laser_value = min(D.armor.getRating(LASER) + 4, 50))
to_chat(user, "<span class='info'>You strengthen [target], improving its resistance against attacks.</span>")
D.update_appearance(UPDATE_DESC|UPDATE_OVERLAYS)
else
to_chat(user, "<span class='warning'>You can't improve [D] any further!</span>")
/obj/item/stack/sheet/animalhide/armor_plate/attackby(obj/item/W, mob/user, params)
return // no steel leather for ya
/obj/item/stack/sheet/animalhide/ashdrake
name = "ash drake hide"
desc = "The strong, scaled hide of an ash drake."
desc = "The strong, scaled hide of an ash drake. Can be attached to the mech itself, greatly enhancing its protective characteristics. Unfortunately, only working class exosuits have notches for such armor."
icon = 'icons/obj/stacks/organic.dmi'
icon_state = "dragon_hide"
item_state = "dragon_hide"
@@ -242,9 +281,30 @@ GLOBAL_LIST_INIT(sinew_recipes, list (
layer = MOB_LAYER
dynamic_icon_state = TRUE
/obj/item/stack/sheet/animalhide/ashdrake/afterattack(atom/target, mob/user, proximity_flag)
if(!proximity_flag)
return
if(istype(target, /obj/mecha/working/ripley))
var/obj/mecha/working/ripley/D = target
if(D.drake_hides < DRAKE_HIDES_COVERED_FULL && !D.hides && !D.plates)
if(!use(1))
to_chat(user, "<span class='notice'>You dont have enough [src] for this!</span>")
return
use(1)
D.drake_hides++
D.max_integrity += 50
D.obj_integrity += 50
D.armor = D.armor.setRating(melee_value = min(D.armor.getRating(MELEE) + 45, 175)) // 77.7% melee armor maximum
D.armor = D.armor.setRating(bullet_value = min(D.armor.getRating(BULLET) + 7, 60))
D.armor = D.armor.setRating(laser_value = min(D.armor.getRating(LASER) + 7, 60))
to_chat(user, "<span class='info'>You strengthen [target], improving its resistance against attacks.</span>")
D.update_appearance(UPDATE_DESC|UPDATE_OVERLAYS)
else
to_chat(user, "<span class='warning'>You can't improve [D] any further!</span>")
//Step one - dehairing.
/obj/item/stack/sheet/animalhide/attackby(obj/item/W as obj, mob/user as mob, params)
/obj/item/stack/sheet/animalhide/attackby(obj/item/W, mob/user, params)
if(W.sharp)
user.visible_message("[user] starts cutting hair off \the [src].", "<span class='notice'>You start cutting the hair off \the [src]...</span>", "<span class='italics'>You hear the sound of a knife rubbing against flesh.</span>")
if(do_after(user, 50 * W.toolspeed, target = src))
@@ -215,6 +215,7 @@ GLOBAL_LIST_INIT(wood_recipes, list(
new /datum/stack_recipe("rake", /obj/item/cultivator/rake, 5, time = 1 SECONDS),
new /datum/stack_recipe("wooden bucket", /obj/item/reagent_containers/glass/bucket/wooden, 3, time = 1 SECONDS),
new /datum/stack_recipe("firebrand", /obj/item/match/firebrand, 2, time = 10 SECONDS),
new /datum/stack_recipe("notice board", /obj/item/mounted/noticeboard, 5, time = 5 SECONDS),
null,
new /datum/stack_recipe("wood floor tile", /obj/item/stack/tile/wood, 1, 4, 20),
new /datum/stack_recipe_list("wood structures", list(
-10
View File
@@ -35,16 +35,6 @@
toolspeed = 0.5
resistance_flags = FIRE_PROOF | ACID_PROOF
/obj/item/crowbar/abductor
name = "alien crowbar"
desc = "A hard-light crowbar. It appears to pry by itself, without any effort required."
icon = 'icons/obj/abductor.dmi'
usesound = 'sound/weapons/sonic_jackhammer.ogg'
icon_state = "crowbar"
toolspeed = 0.1
w_class = WEIGHT_CLASS_SMALL
origin_tech = "combat=4;engineering=4;abductor=3"
/obj/item/crowbar/small
name = "miniature titanium crowbar"
desc = "A tiny, lightweight titanium crowbar. It fits handily in your pocket."
@@ -171,19 +171,6 @@
. = ..()
ADD_TRAIT(src, TRAIT_SHOW_WIRE_INFO, ROUNDSTART_TRAIT) // Drones are linked to the station
/obj/item/multitool/abductor
name = "alien multitool"
desc = "An omni-technological interface."
icon = 'icons/obj/abductor.dmi'
icon_state = "multitool"
toolspeed = 0.1
w_class = WEIGHT_CLASS_SMALL
origin_tech = "magnets=5;engineering=5;abductor=3"
/obj/item/multitool/abductor/Initialize(mapload)
. = ..()
ADD_TRAIT(src, TRAIT_SHOW_WIRE_INFO, ROUNDSTART_TRAIT)
#undef PROXIMITY_NONE
#undef PROXIMITY_ON_SCREEN
#undef PROXIMITY_NEAR
@@ -90,15 +90,6 @@
return BRUTELOSS
/obj/item/screwdriver/abductor
name = "alien screwdriver"
desc = "An ultrasonic screwdriver."
icon = 'icons/obj/abductor.dmi'
icon_state = "screwdriver"
usesound = 'sound/items/pshoom.ogg'
toolspeed = 0.1
random_color = FALSE
/obj/item/screwdriver/power
name = "hand drill"
desc = "A simple hand drill with a screwdriver bit attached."
-13
View File
@@ -275,19 +275,6 @@
materials = list(MAT_METAL = 200, MAT_GLASS = 50)
low_fuel_changes_icon = FALSE
/obj/item/weldingtool/abductor
name = "alien welding tool"
desc = "An alien welding tool. Whatever fuel it uses, it never runs out."
icon = 'icons/obj/abductor.dmi'
icon_state = "welder"
toolspeed = 0.1
w_class = WEIGHT_CLASS_SMALL
light_intensity = 0
origin_tech = "plasmatech=5;engineering=5;abductor=3"
requires_fuel = FALSE
refills_over_time = TRUE
low_fuel_changes_icon = FALSE
/obj/item/weldingtool/hugetank
name = "upgraded welding tool"
desc = "An upgraded welder based off the industrial welder."
@@ -98,19 +98,6 @@
random_color = FALSE
resistance_flags = FIRE_PROOF | ACID_PROOF
/obj/item/wirecutters/abductor
name = "alien wirecutters"
desc = "Extremely sharp wirecutters, made out of a silvery-green metal."
icon = 'icons/obj/abductor.dmi'
icon_state = "cutters"
toolspeed = 0.1
origin_tech = "materials=5;engineering=4;abductor=3"
random_color = FALSE
/obj/item/wirecutters/abductor/Initialize(mapload)
. = ..()
ADD_TRAIT(src, TRAIT_SHOW_WIRE_INFO, ROUNDSTART_TRAIT)
/obj/item/wirecutters/cyborg
name = "wirecutters"
desc = "This cuts wires."
-9
View File
@@ -54,15 +54,6 @@
toolspeed = 0.5
resistance_flags = FIRE_PROOF | ACID_PROOF
/obj/item/wrench/abductor
name = "alien wrench"
desc = "A polarized wrench. It causes anything placed between the jaws to turn."
icon = 'icons/obj/abductor.dmi'
icon_state = "wrench"
usesound = 'sound/effects/empulse.ogg'
toolspeed = 0.1
origin_tech = "materials=5;engineering=5;abductor=3"
/obj/item/wrench/power
name = "hand drill"
desc = "A simple powered drill with a bolt bit."
+39 -3
View File
@@ -13,14 +13,19 @@
var/obj/item/assembly/nadeassembly = null
var/assemblyattacher
var/notify_admins = TRUE
/// C4 overlay to put on target
var/mutable_appearance/plastic_overlay
/// Target of the overlay, not neccicarly the thing the C4 is attached to!
var/atom/plastic_overlay_target
/obj/item/grenade/plastic/Initialize(mapload)
. = ..()
image_overlay = image('icons/obj/grenade.dmi', "[item_state]2")
plastic_overlay = mutable_appearance(icon, "[item_state]2", HIGH_OBJ_LAYER)
/obj/item/grenade/plastic/Destroy()
QDEL_NULL(nadeassembly)
target = null
plastic_overlay_target = null
return ..()
/obj/item/grenade/plastic/attackby(obj/item/I, mob/user, params)
@@ -74,7 +79,7 @@
return
to_chat(user, "<span class='notice'>You start planting [src].[isnull(nadeassembly) ? " The timer is set to [det_time]..." : ""]</span>")
if(do_after(user, 5 SECONDS * toolspeed, target = AM))
if(do_after(user, 1.5 SECONDS * toolspeed, target = AM))
if(!user.unEquip(src))
return
target = AM
@@ -84,7 +89,26 @@
message_admins("[ADMIN_LOOKUPFLW(user)] planted [name] on [target.name] at ([target.x],[target.y],[target.z] - <a href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[target.x];Y=[target.y];Z=[target.z]'>JMP</a>) with [det_time] second fuse", 0, 1)
log_game("[key_name(user)] planted [name] on [target.name] at ([target.x],[target.y],[target.z]) with [det_time] second fuse")
AddComponent(/datum/component/persistent_overlay, image_overlay, target)
plastic_overlay.layer = HIGH_OBJ_LAYER
if(isturf(target) || istype(target, /obj/machinery/door))
plastic_overlay_target = new /obj/effect/plastic(get_turf(user))
else
plastic_overlay_target = target
if(isliving(target))
plastic_overlay.layer = ABOVE_ALL_MOB_LAYER
if(plastic_overlay_target != target)
switch(plastic_overlay_target.x - target.x)
if(-1)
plastic_overlay.pixel_x += 32
if(1)
plastic_overlay.pixel_x -= 32
switch(plastic_overlay_target.y - target.y)
if(-1)
plastic_overlay.pixel_y += 32
if(1)
plastic_overlay.pixel_y -= 32
plastic_overlay_target.add_overlay(plastic_overlay)
if(!nadeassembly)
to_chat(user, "<span class='notice'>You plant the bomb. Timer counting down from [det_time].</span>")
addtimer(CALLBACK(src, PROC_REF(prime)), det_time SECONDS)
@@ -146,6 +170,10 @@
/obj/item/grenade/plastic/c4/prime()
var/turf/location
if(plastic_overlay_target && !QDELETED(plastic_overlay_target))
plastic_overlay_target.cut_overlay(plastic_overlay, TRUE)
if(istype(plastic_overlay_target, /obj/effect/plastic))
qdel(plastic_overlay_target)
if(target)
if(!QDELETED(target))
location = get_turf(target)
@@ -211,6 +239,10 @@
/obj/item/grenade/plastic/c4/thermite/prime()
var/turf/location
if(plastic_overlay_target && !QDELETED(plastic_overlay_target))
plastic_overlay_target.cut_overlay(plastic_overlay, TRUE)
if(istype(plastic_overlay_target, /obj/effect/plastic))
qdel(plastic_overlay_target)
if(target)
if(!QDELETED(target))
location = get_turf(target)
@@ -235,3 +267,7 @@
M.adjust_fire_stacks(2)
M.IgniteMob()
qdel(src)
//Used so the effect is visable for overlay purposes, but not show on right click with a broken sprite
/obj/effect/plastic
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
@@ -457,22 +457,6 @@
new /obj/item/grenade/empgrenade(src) // Two of each
new /obj/item/grenade/syndieminibomb(src) // One minibomb
/obj/item/storage/belt/military/abductor
name = "agent belt"
desc = "A belt used by abductor agents."
icon = 'icons/obj/abductor.dmi'
icon_state = "belt"
item_state = "security"
/obj/item/storage/belt/military/abductor/full/populate_contents()
new /obj/item/screwdriver/abductor(src)
new /obj/item/wrench/abductor(src)
new /obj/item/weldingtool/abductor(src)
new /obj/item/crowbar/abductor(src)
new /obj/item/wirecutters/abductor(src)
new /obj/item/multitool/abductor(src)
new /obj/item/stack/cable_coil(src, 30, COLOR_WHITE)
/obj/item/storage/belt/military/assault
name = "assault belt"
desc = "A tactical assault belt."
+5
View File
@@ -242,6 +242,8 @@
origin_tech = "magnets=1"
/// The reference to the envelope that is currently stored in the mail scanner. It will be cleared upon confirming a correct delivery
var/obj/item/envelope/saved
/// How far away can the scanner scan mail or people
var/scanner_range = 7
/obj/item/mail_scanner/examine(mob/user)
. = ..()
@@ -251,6 +253,9 @@
return
/obj/item/mail_scanner/afterattack(atom/A, mob/user)
if(get_dist(A, user) > scanner_range)
to_chat(user, "<span class='warning'>The scanner doesn't reach that far!</span>")
return
if(istype(A, /obj/item/envelope))
var/obj/item/envelope/envelope = A
if(envelope.has_been_scanned)
@@ -57,8 +57,9 @@
break
// Fix for #383 - C4 deleting fridges with corpses
/obj/structure/closet/Destroy()
dump_contents()
/obj/structure/closet/Destroy(force)
if(!force)
dump_contents()
return ..()
/obj/structure/closet/CanPass(atom/movable/mover, turf/target, height=0)
@@ -20,6 +20,7 @@
L.unbuckle_mob()
L.forceMove(src)
ADD_TRAIT(L, TRAIT_MUTE, STATUE_MUTE)
ADD_TRAIT(L, TRAIT_EMOTE_MUTE, STATUE_MUTE)
max_integrity = max(L.health + 100, 100) //stoning damaged mobs will result in easier to shatter statues
intialTox = L.getToxLoss()
intialFire = L.getFireLoss()
@@ -50,6 +51,7 @@
M.adjustFireLoss(intialFire - M.getFireLoss())
M.adjustBruteLoss(intialBrute - M.getBruteLoss())
M.setOxyLoss(intialOxy)
M.Stun(2.5 SECONDS) // No using items inside a statue
if(timer <= 0)
dump_contents()
STOP_PROCESSING(SSobj, src)
@@ -69,6 +71,7 @@
for(var/mob/living/M in src)
M.forceMove(loc)
REMOVE_TRAIT(M, TRAIT_MUTE, STATUE_MUTE)
REMOVE_TRAIT(M, TRAIT_EMOTE_MUTE, STATUE_MUTE)
M.take_overall_damage((M.health - obj_integrity - 100),0) //any new damage the statue incurred is transfered to the mob
..()
@@ -120,7 +123,7 @@
/obj/structure/closet/statue/indestructible
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
timer = 240 SECONDS_TO_LIFE_CYCLES
timer = 120 SECONDS_TO_LIFE_CYCLES
/obj/structure/closet/statue/indestructible/ex_act(severity)
return //No delimbing them
@@ -113,7 +113,7 @@
M.gib()
for(var/obj/mecha/E in range(30, T))
E.take_damage(E.max_integrity)
explosion(get_turf(src), 25, 35, 45, 55, 1, 1, 60, 0, 0)
explosion(get_turf(src), 25, 35, 45, 55, 1, 1, 60, 0)
STOP_PROCESSING(SSobj, src)
qdel(src)
+1 -1
View File
@@ -90,7 +90,7 @@
else if(mybag)
mybag.attackby(I, user, params)
else
to_chat(usr, "<span class='warning'>You cannot interface your modules [src]!</span>")
to_chat(usr, "<span class='warning'>You cannot interface your modules with [src]!</span>")
/obj/structure/janitorialcart/crowbar_act(mob/living/user, obj/item/I)
. = TRUE
@@ -24,6 +24,9 @@
return ..()
/obj/structure/mopbucket/attackby(obj/item/W as obj, mob/user as mob, params)
if(W.is_robot_module())
to_chat(user, "<span class='warning'>You cannot interface your modules with [src]!</span>")
return
if(istype(W, /obj/item/mop))
var/obj/item/mop/M = W
if(M.reagents.total_volume < M.reagents.maximum_volume)
+125 -64
View File
@@ -1,82 +1,143 @@
#define MAX_NOTICES 5
/obj/item/mounted/noticeboard
name = "notice board"
desc = "A board for pinning important notices upon."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "noticeboard"
w_class = WEIGHT_CLASS_BULKY
/obj/item/mounted/noticeboard/do_build(turf/on_wall, mob/user)
new /obj/structure/noticeboard(get_turf(user), get_dir(on_wall, user), building = TRUE)
qdel(src)
/obj/structure/noticeboard
name = "notice board"
desc = "A board for pinning important notices upon."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "nboard00"
icon_state = "noticeboard-5"
density = FALSE
anchored = TRUE
max_integrity = 150
var/notices = 0
/obj/structure/noticeboard/Initialize()
..()
for(var/obj/item/I in loc)
if(notices > 4) break
if(istype(I, /obj/item/paper))
I.loc = src
notices++
icon_state = "nboard0[notices]"
/obj/structure/noticeboard/New(turf/loc, direction, building = FALSE)
. = ..()
if(building)
setDir(direction)
set_pixel_offsets_from_dir(-32, 32, -30, 30)
update_icon(UPDATE_ICON_STATE)
//attaching papers!!
/obj/structure/noticeboard/attackby(obj/item/O as obj, mob/user as mob, params)
if(istype(O, /obj/item/paper))
if(notices < 5)
O.add_fingerprint(user)
add_fingerprint(user)
user.drop_item()
O.loc = src
/obj/structure/noticeboard/Initialize()
. = ..()
for(var/obj/item/paper in loc)
if(notices >= MAX_NOTICES)
break
if(istype(paper, /obj/item/paper))
paper.loc = src
notices++
icon_state = "nboard0[notices]" //update sprite
to_chat(user, "<span class='notice'>You pin the paper to the noticeboard.</span>")
else
to_chat(user, "<span class='notice'>You reach to pin your paper to the board but hesitate. You are certain your paper will not be seen among the many others already attached.</span>")
update_icon(UPDATE_ICON_STATE)
/obj/structure/noticeboard/update_icon_state()
if(notices)
icon_state = "noticeboard-[notices]"
return
icon_state = "noticeboard"
/obj/structure/noticeboard/attack_hand(mob/user)
ui_interact(user)
/obj/structure/noticeboard/attack_ghost(mob/user)
ui_interact(user)
/obj/structure/noticeboard/ui_state(mob/user)
return GLOB.default_state
/obj/structure/noticeboard/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Noticeboard", name)
ui.set_autoupdate(FALSE)
ui.open()
/obj/structure/noticeboard/ui_data(mob/user)
var/list/data = list()
var/list/pinned_papers = list()
for(var/obj/item/paper/paper in src)
pinned_papers += list(list(
"name" = paper.name,
"contents" = paper.info,
"ref" = paper.UID(),
))
data["papers"] = pinned_papers
return data
/obj/structure/noticeboard/ui_act(action, params, datum/tgui/ui)
if(..())
return
. = TRUE
add_fingerprint(usr)
switch(action)
if("interact")
if(usr.stat || usr.restrained())
return
var/obj/item/paper/paper = locate(params["paper"])
if(!paper && paper.loc != src)
return
var/obj/item/held_item = usr.get_active_hand()
if(is_pen(held_item))
paper.attackby(held_item, usr)
return
else
usr.put_in_hands(paper)
paper.add_fingerprint(usr)
notices--
to_chat(usr, "<span class='notice'>You take a [paper.name] out of [src].</span>")
update_icon(UPDATE_ICON_STATE)
if("showFull")
var/obj/item/paper/paper = locate(params["paper"])
if(!paper && paper.loc != src)
return
paper.show_content(usr)
return
/obj/structure/noticeboard/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/paper))
if(notices >= MAX_NOTICES)
to_chat(user, "<span class='notice'>You reach to pin your paper to the board but hesitate. You are certain your paper will not be seen among the many others already attached.</span>")
return
if(!user.drop_item())
return
I.forceMove(src)
notices++
to_chat(user, "<span class='notice'>You pin the paper to the noticeboard.</span>")
update_icon(UPDATE_ICON_STATE)
add_fingerprint(user)
SStgui.update_uis(src)
return
return ..()
/obj/structure/noticeboard/attack_hand(user as mob)
var/dat = "<b>Noticeboard</b><br>"
for(var/obj/item/paper/P in src)
dat += "<a href='byond://?src=[UID()];read=\ref[P]'>[P.name]</a> <a href='byond://?src=[UID()];write=\ref[P]'>Write</a> <a href='byond://?src=[UID()];remove=\ref[P]'>Remove</a><br>"
user << browse("<!DOCTYPE html><meta charset='utf-8'><head><title>Notices</title></head>[dat]","window=noticeboard")
onclose(user, "noticeboard")
/obj/structure/noticeboard/wrench_act(mob/living/user, obj/item/I)
if(user.a_intent != INTENT_HELP)
return
. = TRUE
if(!(flags & NODECONSTRUCT))
WRENCH_UNANCHOR_WALL_MESSAGE
I.play_tool_sound(user, I.tool_volume)
deconstruct(TRUE)
/obj/structure/noticeboard/deconstruct(disassembled = TRUE)
if(!(flags & NODECONSTRUCT))
new /obj/item/stack/sheet/metal (loc, 1)
if(flags & NODECONSTRUCT)
return
if(notices)
for(var/I in contents)
var/obj/item/paper/notice = I
notice.forceMove(loc)
new /obj/item/mounted/noticeboard(loc)
qdel(src)
/obj/structure/noticeboard/Topic(href, href_list)
..()
usr.set_machine(src)
if(href_list["remove"])
if((usr.stat || usr.restrained())) //For when a player is handcuffed while they have the notice window open
return
var/obj/item/P = locate(href_list["remove"])
if(P && P.loc == src)
P.loc = get_turf(src) //dump paper on the floor because you're a clumsy fuck
P.add_fingerprint(usr)
add_fingerprint(usr)
notices--
icon_state = "nboard0[notices]"
if(href_list["write"])
if((usr.stat || usr.restrained())) //For when a player is handcuffed while they have the notice window open
return
var/obj/item/P = locate(href_list["write"])
if((P && P.loc == src)) //ifthe paper's on the board
if(is_pen(usr.r_hand)) //and you're holding a pen
add_fingerprint(usr)
P.attackby(usr.r_hand, usr) //then do ittttt
else
if(is_pen(usr.l_hand)) //check other hand for pen
add_fingerprint(usr)
P.attackby(usr.l_hand, usr)
else
to_chat(usr, "<span class='notice'>You'll need something to write with!</span>")
if(href_list["read"])
var/obj/item/paper/P = locate(href_list["read"])
if(P && P.loc == src)
P.show_content(usr)
return
#undef MAX_NOTICES

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