Merge remote-tracking branch 'citadel/master' into combat_rework
This commit is contained in:
@@ -23380,7 +23380,7 @@
|
||||
/obj/structure/extinguisher_cabinet{
|
||||
pixel_y = -32
|
||||
},
|
||||
/obj/item/paper/guides/cogstation/letter_sec,
|
||||
/obj/item/paper/fluff/cogstation/secsolars,
|
||||
/turf/open/floor/plasteel,
|
||||
/area/security/main)
|
||||
"aYJ" = (
|
||||
@@ -27342,13 +27342,16 @@
|
||||
/turf/open/floor/plasteel,
|
||||
/area/security/courtroom)
|
||||
"bhA" = (
|
||||
/obj/machinery/disposal/bin,
|
||||
/obj/effect/turf_decal/delivery,
|
||||
/obj/structure/disposalpipe/trunk{
|
||||
dir = 4
|
||||
/obj/item/stack/cable_coil/red,
|
||||
/obj/item/multitool,
|
||||
/obj/item/wrench,
|
||||
/obj/item/stack/sheet/metal/five{
|
||||
pixel_x = 6;
|
||||
pixel_y = -6
|
||||
},
|
||||
/turf/open/floor/plasteel,
|
||||
/area/quartermaster/sorting)
|
||||
/obj/item/paper/fluff/cogstation/letter_arrd,
|
||||
/turf/open/floor/plating,
|
||||
/area/maintenance/disposal)
|
||||
"bhB" = (
|
||||
/obj/structure/table/wood,
|
||||
/obj/item/stack/packageWrap,
|
||||
@@ -28343,6 +28346,7 @@
|
||||
/obj/effect/turf_decal/tile/yellow{
|
||||
dir = 4
|
||||
},
|
||||
/obj/item/paper/guides/cogstation/letter_atmos,
|
||||
/turf/open/floor/plasteel/dark/corner{
|
||||
dir = 1
|
||||
},
|
||||
@@ -34940,15 +34944,19 @@
|
||||
},
|
||||
/area/maintenance/disposal)
|
||||
"bxz" = (
|
||||
/obj/item/stack/cable_coil/red,
|
||||
/obj/item/multitool,
|
||||
/obj/item/wrench,
|
||||
/obj/item/stack/sheet/metal/five{
|
||||
pixel_x = 6;
|
||||
pixel_y = -6
|
||||
/obj/effect/turf_decal/tile/yellow{
|
||||
dir = 4
|
||||
},
|
||||
/turf/open/floor/plating,
|
||||
/area/maintenance/disposal)
|
||||
/obj/machinery/computer/station_alert,
|
||||
/obj/structure/sign/poster/official/safety_eye_protection{
|
||||
pixel_y = 32
|
||||
},
|
||||
/obj/effect/turf_decal/tile/red{
|
||||
dir = 1
|
||||
},
|
||||
/obj/item/paper/guides/cogstation/letter_eng,
|
||||
/turf/open/floor/plasteel,
|
||||
/area/engine/break_room)
|
||||
"bxA" = (
|
||||
/obj/machinery/announcement_system,
|
||||
/turf/open/floor/plasteel/dark,
|
||||
@@ -43875,14 +43883,19 @@
|
||||
/turf/open/floor/plasteel/dark,
|
||||
/area/science/robotics/lab)
|
||||
"bQq" = (
|
||||
/obj/machinery/atmospherics/components/unary/vent_pump/on,
|
||||
/obj/structure/cable{
|
||||
icon_state = "4-8"
|
||||
/obj/effect/turf_decal/tile/yellow{
|
||||
dir = 1
|
||||
},
|
||||
/obj/effect/landmark/event_spawn,
|
||||
/obj/machinery/atmospherics/pipe/simple/orange/hidden{
|
||||
dir = 8
|
||||
/obj/effect/turf_decal/tile/yellow,
|
||||
/obj/structure/table/wood,
|
||||
/obj/machinery/airalarm{
|
||||
pixel_y = 24
|
||||
},
|
||||
/obj/item/modular_computer/laptop/preset/civilian,
|
||||
/obj/effect/turf_decal/tile/blue{
|
||||
dir = 4
|
||||
},
|
||||
/obj/item/paper/guides/cogstation/letter_atmos,
|
||||
/turf/open/floor/plasteel,
|
||||
/area/engine/break_room)
|
||||
"bQr" = (
|
||||
@@ -51737,27 +51750,17 @@
|
||||
/turf/open/floor/plasteel,
|
||||
/area/engine/atmos)
|
||||
"cfU" = (
|
||||
/obj/structure/table,
|
||||
/obj/effect/turf_decal/tile/purple{
|
||||
dir = 4
|
||||
/obj/machinery/atmospherics/components/unary/vent_pump/on,
|
||||
/obj/structure/cable{
|
||||
icon_state = "4-8"
|
||||
},
|
||||
/obj/effect/turf_decal/tile/purple{
|
||||
/obj/effect/landmark/event_spawn,
|
||||
/obj/machinery/atmospherics/pipe/simple/orange/hidden{
|
||||
dir = 8
|
||||
},
|
||||
/obj/effect/turf_decal/tile/yellow{
|
||||
dir = 1
|
||||
},
|
||||
/obj/effect/turf_decal/tile/yellow,
|
||||
/obj/item/clothing/gloves/color/latex,
|
||||
/obj/item/book/manual/wiki/cit/chem_recipies,
|
||||
/obj/item/book/manual/wiki/cit/chemistry{
|
||||
pixel_x = 2;
|
||||
pixel_y = -3
|
||||
},
|
||||
/obj/item/reagent_containers/dropper,
|
||||
/obj/machinery/atmospherics/pipe/manifold/orange/hidden,
|
||||
/turf/open/floor/plasteel/white,
|
||||
/area/medical/chemistry)
|
||||
/obj/item/beacon,
|
||||
/turf/open/floor/plasteel,
|
||||
/area/engine/break_room)
|
||||
"cfV" = (
|
||||
/obj/machinery/door/airlock/external{
|
||||
name = "Atmospherics External Airlock";
|
||||
@@ -57026,18 +57029,18 @@
|
||||
/turf/open/floor/plasteel,
|
||||
/area/engine/break_room)
|
||||
"cqt" = (
|
||||
/obj/effect/turf_decal/tile/yellow{
|
||||
/obj/machinery/disposal/bin,
|
||||
/obj/effect/turf_decal/delivery,
|
||||
/obj/structure/disposalpipe/trunk{
|
||||
dir = 4
|
||||
},
|
||||
/obj/machinery/computer/station_alert,
|
||||
/obj/structure/sign/poster/official/safety_eye_protection{
|
||||
pixel_y = 32
|
||||
},
|
||||
/obj/effect/turf_decal/tile/red{
|
||||
dir = 1
|
||||
/obj/structure/noticeboard/qm{
|
||||
dir = 4;
|
||||
icon_state = "nboard00";
|
||||
pixel_x = -32
|
||||
},
|
||||
/turf/open/floor/plasteel,
|
||||
/area/engine/break_room)
|
||||
/area/quartermaster/sorting)
|
||||
"cqu" = (
|
||||
/obj/effect/turf_decal/tile/yellow{
|
||||
dir = 4
|
||||
@@ -57106,20 +57109,28 @@
|
||||
/turf/open/floor/plasteel,
|
||||
/area/engine/break_room)
|
||||
"cqz" = (
|
||||
/obj/structure/table,
|
||||
/obj/effect/turf_decal/tile/purple{
|
||||
dir = 4
|
||||
},
|
||||
/obj/effect/turf_decal/tile/purple{
|
||||
dir = 8
|
||||
},
|
||||
/obj/effect/turf_decal/tile/yellow{
|
||||
dir = 1
|
||||
},
|
||||
/obj/effect/turf_decal/tile/yellow,
|
||||
/obj/structure/table/wood,
|
||||
/obj/machinery/airalarm{
|
||||
pixel_y = 24
|
||||
/obj/item/clothing/gloves/color/latex,
|
||||
/obj/item/book/manual/wiki/cit/chem_recipies,
|
||||
/obj/item/book/manual/wiki/cit/chemistry{
|
||||
pixel_x = 2;
|
||||
pixel_y = -3
|
||||
},
|
||||
/obj/item/modular_computer/laptop/preset/civilian,
|
||||
/obj/effect/turf_decal/tile/blue{
|
||||
dir = 4
|
||||
},
|
||||
/turf/open/floor/plasteel,
|
||||
/area/engine/break_room)
|
||||
/obj/machinery/atmospherics/pipe/manifold/orange/hidden,
|
||||
/obj/item/paper/fluff/cogstation/chemists,
|
||||
/obj/item/reagent_containers/dropper,
|
||||
/turf/open/floor/plasteel/white,
|
||||
/area/medical/chemistry)
|
||||
"cqA" = (
|
||||
/obj/structure/cable{
|
||||
icon_state = "1-2"
|
||||
@@ -96465,7 +96476,7 @@ bBQ
|
||||
csV
|
||||
bIe
|
||||
bYB
|
||||
cfU
|
||||
cqz
|
||||
bIM
|
||||
cvt
|
||||
cmS
|
||||
@@ -109285,7 +109296,7 @@ asR
|
||||
aSK
|
||||
aSr
|
||||
aeI
|
||||
cqt
|
||||
bxz
|
||||
bwP
|
||||
cBn
|
||||
cBH
|
||||
@@ -110315,7 +110326,7 @@ aUf
|
||||
aeI
|
||||
bnp
|
||||
cmO
|
||||
bQq
|
||||
cfU
|
||||
cmm
|
||||
cri
|
||||
cdH
|
||||
@@ -111598,7 +111609,7 @@ aRR
|
||||
cpj
|
||||
aSr
|
||||
aeI
|
||||
cqz
|
||||
bQq
|
||||
cqI
|
||||
bQM
|
||||
cdl
|
||||
@@ -114945,7 +114956,7 @@ bbV
|
||||
bjf
|
||||
bkh
|
||||
blu
|
||||
bbV
|
||||
ciI
|
||||
ccZ
|
||||
cgs
|
||||
cxo
|
||||
@@ -116742,7 +116753,7 @@ cPH
|
||||
bfU
|
||||
bFD
|
||||
bgO
|
||||
bhA
|
||||
cqt
|
||||
bUQ
|
||||
cvj
|
||||
cDg
|
||||
@@ -117990,7 +118001,7 @@ bwb
|
||||
aMs
|
||||
cAb
|
||||
cAl
|
||||
bxz
|
||||
bhA
|
||||
bgP
|
||||
bzO
|
||||
caD
|
||||
|
||||
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
@@ -0,0 +1,224 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"a" = (
|
||||
/turf/template_noop,
|
||||
/area/template_noop)
|
||||
"b" = (
|
||||
/turf/closed/wall/mineral/titanium,
|
||||
/area/shuttle/arrival)
|
||||
"c" = (
|
||||
/obj/machinery/door/airlock/titanium{
|
||||
name = "Arrivals Shuttle Airlock"
|
||||
},
|
||||
/obj/structure/fans/tiny,
|
||||
/turf/open/floor/mineral/titanium/blue,
|
||||
/area/shuttle/arrival)
|
||||
"d" = (
|
||||
/obj/effect/spawner/structure/window/shuttle,
|
||||
/turf/open/floor/plating,
|
||||
/area/shuttle/arrival)
|
||||
"e" = (
|
||||
/obj/structure/closet/wardrobe/black,
|
||||
/turf/open/floor/mineral/titanium/blue,
|
||||
/area/shuttle/arrival)
|
||||
"f" = (
|
||||
/turf/open/floor/mineral/titanium/blue,
|
||||
/area/shuttle/arrival)
|
||||
"g" = (
|
||||
/obj/machinery/computer/arcade,
|
||||
/turf/open/floor/mineral/titanium/blue,
|
||||
/area/shuttle/arrival)
|
||||
"h" = (
|
||||
/obj/structure/closet/wardrobe/grey,
|
||||
/obj/machinery/light/small{
|
||||
dir = 1
|
||||
},
|
||||
/turf/open/floor/mineral/titanium/blue,
|
||||
/area/shuttle/arrival)
|
||||
"i" = (
|
||||
/obj/structure/closet/wardrobe/green,
|
||||
/turf/open/floor/mineral/titanium/blue,
|
||||
/area/shuttle/arrival)
|
||||
"j" = (
|
||||
/obj/machinery/requests_console{
|
||||
department = "Arrival shuttle";
|
||||
name = "Arrivals Shuttle console";
|
||||
pixel_y = 30
|
||||
},
|
||||
/obj/machinery/light{
|
||||
dir = 1
|
||||
},
|
||||
/turf/open/floor/mineral/titanium/blue,
|
||||
/area/shuttle/arrival)
|
||||
"k" = (
|
||||
/obj/structure/shuttle/engine/heater{
|
||||
dir = 4
|
||||
},
|
||||
/obj/structure/window/reinforced{
|
||||
dir = 8
|
||||
},
|
||||
/turf/open/floor/plating/airless,
|
||||
/area/shuttle/arrival)
|
||||
"m" = (
|
||||
/obj/machinery/light{
|
||||
dir = 1
|
||||
},
|
||||
/obj/structure/closet/wardrobe/mixed,
|
||||
/turf/open/floor/mineral/titanium/blue,
|
||||
/area/shuttle/arrival)
|
||||
"n" = (
|
||||
/obj/docking_port/mobile/arrivals{
|
||||
name = "Snaxi Arrivals Shuttle"
|
||||
},
|
||||
/obj/structure/shuttle/engine/propulsion/burst/right{
|
||||
dir = 4
|
||||
},
|
||||
/turf/open/floor/plating/airless,
|
||||
/area/shuttle/arrival)
|
||||
"o" = (
|
||||
/obj/structure/table,
|
||||
/obj/item/storage/firstaid/regular,
|
||||
/obj/machinery/light/small,
|
||||
/turf/open/floor/mineral/titanium/blue,
|
||||
/area/shuttle/arrival)
|
||||
"p" = (
|
||||
/obj/structure/table,
|
||||
/obj/item/storage/toolbox/emergency,
|
||||
/turf/open/floor/mineral/titanium/blue,
|
||||
/area/shuttle/arrival)
|
||||
"q" = (
|
||||
/obj/machinery/light,
|
||||
/turf/open/floor/mineral/titanium/blue,
|
||||
/area/shuttle/arrival)
|
||||
"r" = (
|
||||
/obj/structure/chair/comfy/shuttle{
|
||||
dir = 8
|
||||
},
|
||||
/turf/open/floor/mineral/titanium,
|
||||
/area/shuttle/arrival)
|
||||
"s" = (
|
||||
/obj/item/radio/intercom{
|
||||
name = "Station Intercom (General)";
|
||||
pixel_y = -29
|
||||
},
|
||||
/obj/machinery/light,
|
||||
/turf/open/floor/mineral/titanium/blue,
|
||||
/area/shuttle/arrival)
|
||||
"x" = (
|
||||
/obj/structure/closet/emcloset,
|
||||
/turf/open/floor/mineral/titanium/blue,
|
||||
/area/shuttle/arrival)
|
||||
"z" = (
|
||||
/obj/structure/shuttle/engine/propulsion/burst/right{
|
||||
dir = 4
|
||||
},
|
||||
/turf/open/floor/plating/airless,
|
||||
/area/shuttle/arrival)
|
||||
|
||||
(1,1,1) = {"
|
||||
a
|
||||
b
|
||||
d
|
||||
d
|
||||
d
|
||||
b
|
||||
a
|
||||
"}
|
||||
(2,1,1) = {"
|
||||
b
|
||||
b
|
||||
r
|
||||
r
|
||||
r
|
||||
b
|
||||
b
|
||||
"}
|
||||
(3,1,1) = {"
|
||||
b
|
||||
h
|
||||
f
|
||||
f
|
||||
f
|
||||
o
|
||||
b
|
||||
"}
|
||||
(4,1,1) = {"
|
||||
b
|
||||
i
|
||||
r
|
||||
r
|
||||
r
|
||||
p
|
||||
b
|
||||
"}
|
||||
(5,1,1) = {"
|
||||
b
|
||||
e
|
||||
f
|
||||
f
|
||||
f
|
||||
x
|
||||
b
|
||||
"}
|
||||
(6,1,1) = {"
|
||||
b
|
||||
m
|
||||
r
|
||||
r
|
||||
r
|
||||
q
|
||||
b
|
||||
"}
|
||||
(7,1,1) = {"
|
||||
d
|
||||
g
|
||||
f
|
||||
f
|
||||
f
|
||||
f
|
||||
d
|
||||
"}
|
||||
(8,1,1) = {"
|
||||
c
|
||||
f
|
||||
r
|
||||
r
|
||||
r
|
||||
f
|
||||
c
|
||||
"}
|
||||
(9,1,1) = {"
|
||||
c
|
||||
f
|
||||
f
|
||||
f
|
||||
f
|
||||
f
|
||||
c
|
||||
"}
|
||||
(10,1,1) = {"
|
||||
b
|
||||
j
|
||||
r
|
||||
r
|
||||
r
|
||||
s
|
||||
b
|
||||
"}
|
||||
(11,1,1) = {"
|
||||
b
|
||||
k
|
||||
k
|
||||
k
|
||||
k
|
||||
k
|
||||
b
|
||||
"}
|
||||
(12,1,1) = {"
|
||||
b
|
||||
z
|
||||
z
|
||||
n
|
||||
z
|
||||
z
|
||||
b
|
||||
"}
|
||||
@@ -342,11 +342,6 @@
|
||||
},
|
||||
/turf/open/floor/plasteel/dark,
|
||||
/area/shuttle/syndicate/eva)
|
||||
"aN" = (
|
||||
/obj/machinery/portable_atmospherics/canister/oxygen,
|
||||
/obj/effect/turf_decal/bot_white,
|
||||
/turf/open/floor/plasteel/dark,
|
||||
/area/shuttle/syndicate/eva)
|
||||
"aO" = (
|
||||
/obj/structure/chair/comfy/shuttle{
|
||||
dir = 4;
|
||||
@@ -385,8 +380,9 @@
|
||||
/turf/open/floor/mineral/plastitanium,
|
||||
/area/shuttle/syndicate/eva)
|
||||
"aS" = (
|
||||
/obj/structure/tank_dispenser/oxygen,
|
||||
/obj/effect/turf_decal/bot_white,
|
||||
/obj/vehicle/ridden/atv/snowmobile,
|
||||
/obj/item/key,
|
||||
/turf/open/floor/plasteel/dark,
|
||||
/area/shuttle/syndicate/eva)
|
||||
"aT" = (
|
||||
@@ -1172,15 +1168,37 @@
|
||||
},
|
||||
/turf/closed/wall/r_wall/syndicate,
|
||||
/area/shuttle/syndicate/armory)
|
||||
"gZ" = (
|
||||
/obj/effect/turf_decal/bot_white,
|
||||
/obj/vehicle/ridden/atv/snowmobile,
|
||||
/obj/item/key,
|
||||
/turf/open/floor/plasteel/dark,
|
||||
/area/shuttle/syndicate/airlock)
|
||||
"pd" = (
|
||||
/obj/machinery/porta_turret/syndicate/shuttle{
|
||||
dir = 5
|
||||
},
|
||||
/turf/closed/wall/r_wall/syndicate,
|
||||
/area/shuttle/syndicate/bridge)
|
||||
"vv" = (
|
||||
/obj/structure/reagent_dispensers/fueltank,
|
||||
"qk" = (
|
||||
/obj/effect/turf_decal/tile/neutral{
|
||||
dir = 1
|
||||
},
|
||||
/obj/effect/turf_decal/tile/neutral,
|
||||
/obj/effect/turf_decal/tile/neutral{
|
||||
dir = 4
|
||||
},
|
||||
/obj/effect/turf_decal/tile/neutral{
|
||||
dir = 8
|
||||
},
|
||||
/obj/effect/turf_decal/bot_white,
|
||||
/obj/vehicle/ridden/atv/snowmobile,
|
||||
/obj/item/key,
|
||||
/turf/open/floor/plasteel/dark,
|
||||
/area/shuttle/syndicate/airlock)
|
||||
"vv" = (
|
||||
/obj/effect/turf_decal/bot_white,
|
||||
/obj/structure/tank_dispenser/oxygen,
|
||||
/turf/open/floor/plasteel/dark,
|
||||
/area/shuttle/syndicate/eva)
|
||||
"In" = (
|
||||
@@ -1195,6 +1213,14 @@
|
||||
},
|
||||
/turf/closed/wall/r_wall/syndicate,
|
||||
/area/shuttle/syndicate/medical)
|
||||
"Sz" = (
|
||||
/obj/effect/turf_decal/tile/neutral,
|
||||
/obj/effect/turf_decal/tile/neutral{
|
||||
dir = 8
|
||||
},
|
||||
/obj/structure/reagent_dispensers/fueltank,
|
||||
/turf/open/floor/plasteel/dark,
|
||||
/area/shuttle/syndicate/armory)
|
||||
|
||||
(1,1,1) = {"
|
||||
aa
|
||||
@@ -1330,7 +1356,7 @@ ac
|
||||
ad
|
||||
aa
|
||||
ax
|
||||
aN
|
||||
aS
|
||||
aS
|
||||
aU
|
||||
aZ
|
||||
@@ -1480,7 +1506,7 @@ ac
|
||||
In
|
||||
aa
|
||||
aB
|
||||
aO
|
||||
gZ
|
||||
aO
|
||||
aX
|
||||
bc
|
||||
@@ -1505,7 +1531,7 @@ ac
|
||||
aa
|
||||
aa
|
||||
aB
|
||||
aP
|
||||
qk
|
||||
aP
|
||||
aP
|
||||
aP
|
||||
@@ -1530,7 +1556,7 @@ aa
|
||||
aa
|
||||
aa
|
||||
aB
|
||||
aP
|
||||
qk
|
||||
aP
|
||||
aP
|
||||
aP
|
||||
@@ -1587,7 +1613,7 @@ bd
|
||||
aB
|
||||
bm
|
||||
bB
|
||||
bG
|
||||
Sz
|
||||
bQ
|
||||
bX
|
||||
ci
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"a" = (
|
||||
/turf/closed/wall/mineral/titanium,
|
||||
/area/shuttle/snowtaxi)
|
||||
"b" = (
|
||||
/obj/structure/shuttle/engine/propulsion/burst{
|
||||
dir = 4
|
||||
},
|
||||
/obj/structure/window/reinforced{
|
||||
dir = 8
|
||||
},
|
||||
/obj/structure/fans/tiny/invisible,
|
||||
/turf/open/floor/plating,
|
||||
/area/shuttle/snowtaxi)
|
||||
"c" = (
|
||||
/obj/machinery/door/airlock/titanium{
|
||||
name = "Mining Shuttle Airlock"
|
||||
},
|
||||
/obj/effect/mapping_helpers/airlock/cyclelink_helper,
|
||||
/obj/structure/fans/tiny,
|
||||
/turf/open/floor/plating,
|
||||
/area/shuttle/snowtaxi)
|
||||
"e" = (
|
||||
/obj/effect/spawner/structure/window/shuttle,
|
||||
/obj/structure/fans/tiny/invisible,
|
||||
/turf/open/floor/plating,
|
||||
/area/shuttle/snowtaxi)
|
||||
"f" = (
|
||||
/obj/machinery/light{
|
||||
dir = 1
|
||||
},
|
||||
/obj/structure/chair/comfy/shuttle{
|
||||
dir = 8
|
||||
},
|
||||
/turf/open/floor/mineral/titanium,
|
||||
/area/shuttle/snowtaxi)
|
||||
"g" = (
|
||||
/obj/machinery/door/airlock/titanium{
|
||||
name = "Mining Shuttle Airlock"
|
||||
},
|
||||
/obj/docking_port/mobile{
|
||||
dwidth = 3;
|
||||
height = 4;
|
||||
id = "snow_taxi";
|
||||
name = "snow taxi";
|
||||
port_direction = 8;
|
||||
width = 6
|
||||
},
|
||||
/obj/effect/mapping_helpers/airlock/cyclelink_helper{
|
||||
dir = 1
|
||||
},
|
||||
/obj/structure/fans/tiny,
|
||||
/turf/open/floor/plating,
|
||||
/area/shuttle/snowtaxi)
|
||||
"i" = (
|
||||
/obj/machinery/light,
|
||||
/obj/machinery/computer/shuttle/snow_taxi{
|
||||
dir = 4
|
||||
},
|
||||
/turf/open/floor/mineral/titanium,
|
||||
/area/shuttle/snowtaxi)
|
||||
"j" = (
|
||||
/obj/structure/chair/comfy/shuttle{
|
||||
dir = 1
|
||||
},
|
||||
/turf/open/floor/mineral/titanium,
|
||||
/area/shuttle/snowtaxi)
|
||||
"k" = (
|
||||
/turf/open/floor/mineral/titanium,
|
||||
/area/shuttle/snowtaxi)
|
||||
"l" = (
|
||||
/obj/effect/spawner/structure/window/shuttle,
|
||||
/obj/structure/fans/tiny/invisible,
|
||||
/turf/open/floor/plating/airless,
|
||||
/area/shuttle/snowtaxi)
|
||||
"u" = (
|
||||
/obj/structure/chair/comfy/shuttle,
|
||||
/turf/open/floor/mineral/titanium,
|
||||
/area/shuttle/snowtaxi)
|
||||
|
||||
(1,1,1) = {"
|
||||
a
|
||||
e
|
||||
e
|
||||
a
|
||||
"}
|
||||
(2,1,1) = {"
|
||||
a
|
||||
f
|
||||
i
|
||||
a
|
||||
"}
|
||||
(3,1,1) = {"
|
||||
e
|
||||
u
|
||||
j
|
||||
l
|
||||
"}
|
||||
(4,1,1) = {"
|
||||
c
|
||||
k
|
||||
k
|
||||
g
|
||||
"}
|
||||
(5,1,1) = {"
|
||||
a
|
||||
u
|
||||
j
|
||||
a
|
||||
"}
|
||||
(6,1,1) = {"
|
||||
a
|
||||
b
|
||||
b
|
||||
a
|
||||
"}
|
||||
@@ -0,0 +1 @@
|
||||
#define FORCE_MAP "_maps/snaxi.json"
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"map_name":"Snow Taxi",
|
||||
"map_path":"map_files/Snaxi",
|
||||
"map_file":[
|
||||
"IcemoonUnderground_Below.dmm",
|
||||
"IcemoonUnderground_Above.dmm",
|
||||
"Snaxi.dmm"
|
||||
],
|
||||
"station_ruin_budget":0,
|
||||
"space_ruin_levels":0,
|
||||
"space_empty_levels":0,
|
||||
"shuttles":{
|
||||
"cargo":"cargo_box",
|
||||
"ferry":"ferry_fancy",
|
||||
"whiteship":"whiteship_box",
|
||||
"emergency":"emergency_box"
|
||||
},
|
||||
"traits":[
|
||||
{
|
||||
"Up":1,
|
||||
"Station":0,
|
||||
"Mining":true,
|
||||
"Linkage":null,
|
||||
"Gravity":true,
|
||||
"Ice Ruins Underground":true,
|
||||
"Baseturf":"/turf/open/lava/plasma/ice_moon"
|
||||
},
|
||||
{
|
||||
"Down":-1,
|
||||
"Up":1,
|
||||
"Station":0,
|
||||
"Mining":true,
|
||||
"Linkage":null,
|
||||
"Gravity":true,
|
||||
"Ice Ruins Underground":true,
|
||||
"Baseturf":"/turf/open/openspace/icemoon"
|
||||
},
|
||||
{
|
||||
"Down":-1,
|
||||
"Mining":true,
|
||||
"Linkage":null,
|
||||
"Gravity":true,
|
||||
"Ice Ruins":true,
|
||||
"Weather_Snowstorm":true,
|
||||
"Baseturf":"/turf/open/floor/plating/asteroid/snow/icemoon"
|
||||
}
|
||||
],
|
||||
"minetype":"none"
|
||||
}
|
||||
@@ -1,24 +1,34 @@
|
||||
// Flags for the item_flags var on /obj/item
|
||||
|
||||
#define BEING_REMOVED (1<<0)
|
||||
#define IN_INVENTORY (1<<1) //is this item equipped into an inventory slot or hand of a mob? used for tooltips
|
||||
#define FORCE_STRING_OVERRIDE (1<<2) //used for tooltips
|
||||
#define NEEDS_PERMIT (1<<3) //Used by security bots to determine if this item is safe for public use.
|
||||
///is this item equipped into an inventory slot or hand of a mob? used for tooltips
|
||||
#define IN_INVENTORY (1<<1)
|
||||
///used for tooltips
|
||||
#define FORCE_STRING_OVERRIDE (1<<2)
|
||||
///Used by security bots to determine if this item is safe for public use.
|
||||
#define NEEDS_PERMIT (1<<3)
|
||||
#define SLOWS_WHILE_IN_HAND (1<<4)
|
||||
#define NO_MAT_REDEMPTION (1<<5) //Stops you from putting things like an RCD or other items into an ORM or protolathe for materials.
|
||||
#define DROPDEL (1<<6) //When dropped, it calls qdel on itself
|
||||
#define NOBLUDGEON (1<<7) //when an item has this it produces no "X has been hit by Y with Z" message in the default attackby()
|
||||
#define ABSTRACT (1<<8) //for all things that are technically items but used for various different stuff
|
||||
#define IMMUTABLE_SLOW (1<<9) //When players should not be able to change the slowdown of the item (Speed potions, ect)
|
||||
#define SURGICAL_TOOL (1<<10) //Tool commonly used for surgery: won't attack targets in an active surgical operation on help intent (in case of mistakes)
|
||||
#define NO_UNIFORM_REQUIRED (1<<11) //Can be worn on certain slots (currently belt and id) that would otherwise require an uniform.
|
||||
#define NO_ATTACK_CHAIN_SOFT_STAMCRIT (1<<12) //Entirely blocks melee_attack_chain() if user is soft stamcritted. Uses getStaminaLoss() to check at this point in time. THIS DOES NOT BLOCK RANGED AFTERATTACK()S, ONLY MELEE RANGE AFTERATTACK()S.
|
||||
///Stops you from putting things like an RCD or other items into an ORM or protolathe for materials.
|
||||
#define NO_MAT_REDEMPTION (1<<5)
|
||||
///When dropped, it calls qdel on itself
|
||||
#define DROPDEL (1<<6)
|
||||
///when an item has this it produces no "X has been hit by Y with Z" message in the default attackby()
|
||||
#define NOBLUDGEON (1<<7)
|
||||
///for all things that are technically items but used for various different stuff
|
||||
#define ABSTRACT (1<<8)
|
||||
///When players should not be able to change the slowdown of the item (Speed potions, ect)
|
||||
#define IMMUTABLE_SLOW (1<<9)
|
||||
///Tool commonly used for surgery: won't attack targets in an active surgical operation on help intent (in case of mistakes)
|
||||
#define SURGICAL_TOOL (1<<10)
|
||||
///Can be worn on certain slots (currently belt and id) that would otherwise require an uniform.
|
||||
#define NO_UNIFORM_REQUIRED (1<<11)
|
||||
///Damage when attacking people is not affected by combat mode.
|
||||
#define NO_COMBAT_MODE_FORCE_MODIFIER (1<<12)
|
||||
/// This item can be used to parry. Only a basic check used to determine if we should proceed with parry chain at all.
|
||||
#define ITEM_CAN_PARRY (1<<13)
|
||||
/// This item can be used in the directional blocking system. Only a basic check used to determine if we should proceed with directional block handling at all.
|
||||
#define ITEM_CAN_BLOCK (1<<14)
|
||||
|
||||
|
||||
// Flags for the clothing_flags var on /obj/item/clothing
|
||||
|
||||
#define LAVAPROTECT (1<<0)
|
||||
|
||||
@@ -72,10 +72,18 @@
|
||||
#define CHECK_STAMCRIT(mob) ((mob.combat_flags & COMBAT_FLAG_HARD_STAMCRIT)? HARD_STAMCRIT : ((mob.combat_flags & COMBAT_FLAG_SOFT_STAMCRIT)? SOFT_STAMCRIT : NOT_STAMCRIT))
|
||||
|
||||
//stamina stuff
|
||||
#define STAMINA_SOFTCRIT 100 //softcrit for stamina damage. prevents standing up, prevents performing actions that cost stamina, etc, but doesn't force a rest or stop movement
|
||||
#define STAMINA_CRIT 140 //crit for stamina damage. forces a rest, and stops movement until stamina goes back to stamina softcrit
|
||||
#define STAMINA_SOFTCRIT_TRADITIONAL 0 //same as STAMINA_SOFTCRIT except for the more traditional health calculations
|
||||
#define STAMINA_CRIT_TRADITIONAL -40 //ditto, but for STAMINA_CRIT
|
||||
///Threshold over which attacks start being hindered.
|
||||
#define STAMINA_NEAR_SOFTCRIT 90
|
||||
///softcrit for stamina damage. prevents standing up, some actions that cost stamina, etc, but doesn't force a rest or stop movement
|
||||
#define STAMINA_SOFTCRIT 100
|
||||
///sanity cap to prevent stamina actions (that are still performable) from sending you into crit.
|
||||
#define STAMINA_NEAR_CRIT 130
|
||||
///crit for stamina damage. forces a rest, and stops movement until stamina goes back to stamina softcrit
|
||||
#define STAMINA_CRIT 140
|
||||
///same as STAMINA_SOFTCRIT except for the more traditional health calculations
|
||||
#define STAMINA_SOFTCRIT_TRADITIONAL 0
|
||||
///ditto, but for STAMINA_CRIT
|
||||
#define STAMINA_CRIT_TRADITIONAL -40
|
||||
|
||||
#define CRAWLUNDER_DELAY 30 //Delay for crawling under a standing mob
|
||||
|
||||
@@ -181,6 +189,9 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
|
||||
#define EGUN_SELFCHARGE 1
|
||||
#define EGUN_SELFCHARGE_BORG 2
|
||||
|
||||
///Time to spend without clicking on other things required for your shots to become accurate.
|
||||
#define GUN_AIMING_TIME (2 SECONDS)
|
||||
|
||||
//Object/Item sharpness
|
||||
#define IS_BLUNT 0
|
||||
#define IS_SHARP 1
|
||||
@@ -248,6 +259,21 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
|
||||
#define STAM_COST_W_CLASS_MULT 1.25
|
||||
#define STAM_COST_THROW_MULT 2
|
||||
|
||||
///Multiplier of the (STAMINA_NEAR_CRIT - user current stamina loss) : (STAMINA_NEAR_CRIT - STAMINA_SOFTCRIT) ratio used in damage penalties when stam soft-critted.
|
||||
#define STAM_CRIT_ITEM_ATTACK_PENALTY 0.66
|
||||
/// changeNext_move penalty multiplier of the above.
|
||||
#define STAM_CRIT_ITEM_ATTACK_DELAY 1.75
|
||||
/// Damage penalty when fighting prone.
|
||||
#define LYING_DAMAGE_PENALTY 0.5
|
||||
/// Added delay when firing guns stam-softcritted. Summed with a hardset CLICK_CD_RANGE delay, similar to STAM_CRIT_DAMAGE_DELAY otherwise.
|
||||
#define STAM_CRIT_GUN_DELAY 2.75
|
||||
|
||||
/**
|
||||
* should the current-attack-damage be lower than the item force multiplied by this value,
|
||||
* a "inefficiently" prefix will be added to the message.
|
||||
*/
|
||||
#define INEFFICIENT_ATTACK_MSG_THRESHOLD 0.7
|
||||
|
||||
|
||||
//bullet_act() return values
|
||||
#define BULLET_ACT_HIT "HIT" //It's a successful hit, whatever that means in the context of the thing it's hitting.
|
||||
|
||||
@@ -36,4 +36,5 @@ GLOBAL_LIST_INIT(default_weight_class_to_volume, list(
|
||||
#define STORAGE_VOLUME_BACKPACK (DEFAULT_VOLUME_NORMAL * 7)
|
||||
#define STORAGE_VOLUME_DUFFLEBAG (DEFAULT_VOLUME_NORMAL * 10)
|
||||
#define STORAGE_VOLUME_BAG_OF_HOLDING (DEFAULT_VOLUME_NORMAL * 20)
|
||||
|
||||
#define STORAGE_VOLUME_CHEMISTRY_BAG (DEFAULT_VOLUME_TINY * 50)
|
||||
#define STORAGE_VOLUME_PILL_BOTTLE (DEFAULT_VOLUME_TINY * 7)
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
next_move = world.time + ((num+next_move_adjust)*next_move_modifier)
|
||||
|
||||
/mob/living/changeNext_move(num)
|
||||
last_click_move = next_move
|
||||
var/mod = next_move_modifier
|
||||
var/adj = next_move_adjust
|
||||
for(var/i in status_effects)
|
||||
|
||||
@@ -10,10 +10,6 @@
|
||||
/obj/item/proc/melee_attack_chain(mob/user, atom/target, params, flags, damage_multiplier = 1)
|
||||
if(isliving(user))
|
||||
var/mob/living/L = user
|
||||
if(item_flags & NO_ATTACK_CHAIN_SOFT_STAMCRIT)
|
||||
if(IS_STAMCRIT(L))
|
||||
to_chat(L, "<span class='warning'>You are too exhausted to swing [src]!</span>")
|
||||
return
|
||||
if(!CHECK_MOBILITY(L, MOBILITY_USE) && !(flags & ATTACKCHAIN_PARRY_COUNTERATTACK))
|
||||
to_chat(L, "<span class='warning'>You are unable to swing [src] right now!</span>")
|
||||
return
|
||||
@@ -59,8 +55,10 @@
|
||||
/mob/living/attackby(obj/item/I, mob/living/user, params, attackchain_flags, damage_multiplier)
|
||||
if(..())
|
||||
return TRUE
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
return I.attack(src, user, attackchain_flags, damage_multiplier)
|
||||
I.attack_delay_done = FALSE //Should be set TRUE in pre_attacked_by()
|
||||
. = I.attack(src, user, attackchain_flags, damage_multiplier)
|
||||
if(!I.attack_delay_done) //Otherwise, pre_attacked_by() should handle it.
|
||||
user.changeNext_move(I.click_delay)
|
||||
|
||||
/obj/item/proc/attack(mob/living/M, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1)
|
||||
if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK, M, user) & COMPONENT_ITEM_NO_ATTACK)
|
||||
@@ -68,11 +66,6 @@
|
||||
SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK, M, user)
|
||||
if(item_flags & NOBLUDGEON)
|
||||
return
|
||||
|
||||
if(IS_STAMCRIT(user)) // CIT CHANGE - makes it impossible to attack in stamina softcrit
|
||||
to_chat(user, "<span class='warning'>You're too exhausted.</span>") // CIT CHANGE - ditto
|
||||
return // CIT CHANGE - ditto
|
||||
|
||||
if(force && damtype != STAMINA && HAS_TRAIT(user, TRAIT_PACIFISM))
|
||||
to_chat(user, "<span class='warning'>You don't want to harm other living beings!</span>")
|
||||
return
|
||||
@@ -91,7 +84,9 @@
|
||||
log_combat(user, M, "attacked", src.name, "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])")
|
||||
add_fingerprint(user)
|
||||
|
||||
user.adjustStaminaLossBuffered(getweight(user, STAM_COST_ATTACK_MOB_MULT))//CIT CHANGE - makes attacking things cause stamina loss
|
||||
var/weight = getweight(user, STAM_COST_ATTACK_MOB_MULT) //CIT CHANGE - makes attacking things cause stamina loss
|
||||
if(weight)
|
||||
user.adjustStaminaLossBuffered(weight)
|
||||
|
||||
//the equivalent of the standard version of attack() but for object targets.
|
||||
/obj/item/proc/attack_obj(obj/O, mob/living/user)
|
||||
@@ -99,13 +94,12 @@
|
||||
return
|
||||
if(item_flags & NOBLUDGEON)
|
||||
return
|
||||
if(IS_STAMCRIT(user)) // CIT CHANGE - makes it impossible to attack in stamina softcrit
|
||||
to_chat(user, "<span class='warning'>You're too exhausted.</span>") // CIT CHANGE - ditto
|
||||
return // CIT CHANGE - ditto
|
||||
user.adjustStaminaLossBuffered(getweight(user, STAM_COST_ATTACK_OBJ_MULT))//CIT CHANGE - makes attacking things cause stamina loss
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
user.do_attack_animation(O)
|
||||
O.attacked_by(src, user)
|
||||
if(!O.attacked_by(src, user))
|
||||
user.changeNext_move(click_delay)
|
||||
var/weight = getweight(user, STAM_COST_ATTACK_OBJ_MULT)
|
||||
if(weight)
|
||||
user.adjustStaminaLossBuffered(weight)//CIT CHANGE - makes attacking things cause stamina loss
|
||||
|
||||
/atom/movable/proc/attacked_by()
|
||||
return
|
||||
@@ -113,9 +107,18 @@
|
||||
/obj/attacked_by(obj/item/I, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1)
|
||||
var/totitemdamage = I.force * damage_multiplier
|
||||
var/bad_trait
|
||||
if(!SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
totitemdamage *= 0.5
|
||||
|
||||
var/stamloss = user.getStaminaLoss()
|
||||
var/next_move_mult = 1
|
||||
if(stamloss > STAMINA_NEAR_SOFTCRIT) //The more tired you are, the less damage you do.
|
||||
var/penalty = (stamloss - STAMINA_NEAR_SOFTCRIT)/(STAMINA_NEAR_CRIT - STAMINA_NEAR_SOFTCRIT)*STAM_CRIT_ITEM_ATTACK_PENALTY
|
||||
totitemdamage *= 1 - penalty
|
||||
next_move_mult += penalty*STAM_CRIT_ITEM_ATTACK_DELAY
|
||||
user.changeNext_move(I.click_delay*next_move_mult)
|
||||
|
||||
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
bad_trait = SKILL_COMBAT_MODE //blacklist combat skills.
|
||||
|
||||
if(I.used_skills && user.mind)
|
||||
if(totitemdamage)
|
||||
totitemdamage = user.mind.item_action_skills_mod(I, totitemdamage, I.skill_difficulty, SKILL_ATTACK_OBJ, bad_trait)
|
||||
@@ -123,11 +126,13 @@
|
||||
if(!(I.used_skills[skill] & SKILL_TRAIN_ATTACK_OBJ))
|
||||
continue
|
||||
user.mind.auto_gain_experience(skill, I.skill_gain)
|
||||
|
||||
if(totitemdamage)
|
||||
visible_message("<span class='danger'>[user] has hit [src] with [I]!</span>", null, null, COMBAT_MESSAGE_RANGE)
|
||||
//only witnesses close by and the victim see a hit message.
|
||||
log_combat(user, src, "attacked", I)
|
||||
take_damage(totitemdamage, I.damtype, "melee", 1)
|
||||
return TRUE
|
||||
|
||||
/mob/living/attacked_by(obj/item/I, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1)
|
||||
var/list/block_return = list()
|
||||
@@ -135,7 +140,7 @@
|
||||
if((user != src) && mob_run_block(I, totitemdamage, "the [I.name]", ((attackchain_flags & ATTACKCHAIN_PARRY_COUNTERATTACK)? ATTACK_TYPE_PARRY_COUNTERATTACK : NONE) | ATTACK_TYPE_MELEE, I.armour_penetration, user, null, block_return) & BLOCK_SUCCESS)
|
||||
return FALSE
|
||||
totitemdamage = block_calculate_resultant_damage(totitemdamage, block_return)
|
||||
send_item_attack_message(I, user)
|
||||
send_item_attack_message(I, user, null, totitemdamage)
|
||||
I.do_stagger_action(src, user, totitemdamage)
|
||||
if(I.force)
|
||||
apply_damage(totitemdamage, I.damtype)
|
||||
@@ -151,19 +156,37 @@
|
||||
/mob/living/simple_animal/attacked_by(obj/item/I, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1)
|
||||
if(I.force < force_threshold || I.damtype == STAMINA)
|
||||
playsound(loc, 'sound/weapons/tap.ogg', I.get_clamped_volume(), 1, -1)
|
||||
user.changeNext_move(I.click_delay) //pre_attacked_by not called
|
||||
else
|
||||
return ..()
|
||||
|
||||
/mob/living/proc/pre_attacked_by(obj/item/I, mob/living/user)
|
||||
. = I.force
|
||||
if(!.)
|
||||
return
|
||||
|
||||
var/stamloss = user.getStaminaLoss()
|
||||
var/stam_mobility_mult = 1
|
||||
var/next_move_mult = 1
|
||||
if(stamloss > STAMINA_NEAR_SOFTCRIT) //The more tired you are, the less damage you do.
|
||||
var/penalty = (stamloss - STAMINA_NEAR_SOFTCRIT)/(STAMINA_NEAR_CRIT - STAMINA_NEAR_SOFTCRIT)*STAM_CRIT_ITEM_ATTACK_PENALTY
|
||||
stam_mobility_mult -= penalty
|
||||
next_move_mult += penalty*STAM_CRIT_ITEM_ATTACK_DELAY
|
||||
if(stam_mobility_mult > LYING_DAMAGE_PENALTY && !CHECK_MOBILITY(user, MOBILITY_STAND)) //damage penalty for fighting prone, doesn't stack with the above.
|
||||
stam_mobility_mult = LYING_DAMAGE_PENALTY
|
||||
. *= stam_mobility_mult
|
||||
user.changeNext_move(I.click_delay*next_move_mult)
|
||||
I.attack_delay_done = TRUE
|
||||
|
||||
var/bad_trait
|
||||
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
. *= 0.5
|
||||
bad_trait = SKILL_COMBAT_MODE //blacklist combat skills.
|
||||
if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
. *= 1.5
|
||||
if(!CHECK_MOBILITY(user, MOBILITY_STAND))
|
||||
. *= 0.5
|
||||
if(!(I.item_flags & NO_COMBAT_MODE_FORCE_MODIFIER))
|
||||
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
bad_trait = SKILL_COMBAT_MODE //blacklist combat skills.
|
||||
if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE))
|
||||
. *= 0.5
|
||||
else if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
. *= 1.5
|
||||
|
||||
if(!user.mind || !I.used_skills)
|
||||
return
|
||||
if(.)
|
||||
@@ -173,7 +196,6 @@
|
||||
continue
|
||||
user.mind.auto_gain_experience(skill, I.skill_gain)
|
||||
|
||||
|
||||
// Proximity_flag is 1 if this afterattack was called on something adjacent, in your square, or on your person.
|
||||
// Click parameters is the params string from byond Click() code, see that documentation.
|
||||
/obj/item/proc/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
@@ -187,10 +209,12 @@
|
||||
else
|
||||
return clamp(w_class * 6, 10, 100) // Multiply the item's weight class by 6, then clamp the value between 10 and 100
|
||||
|
||||
/mob/living/proc/send_item_attack_message(obj/item/I, mob/living/user, hit_area)
|
||||
/mob/living/proc/send_item_attack_message(obj/item/I, mob/living/user, hit_area, current_force)
|
||||
var/message_verb = "attacked"
|
||||
if(I.attack_verb && I.attack_verb.len)
|
||||
message_verb = "[pick(I.attack_verb)]"
|
||||
if(current_force < I.force * INEFFICIENT_ATTACK_MSG_THRESHOLD)
|
||||
message_verb = "inefficiently [message_verb]"
|
||||
else if(!I.force)
|
||||
return
|
||||
var/message_hit_area = ""
|
||||
@@ -217,6 +241,8 @@
|
||||
bad_trait = SKILL_COMBAT_MODE
|
||||
if(used_skills && user.mind)
|
||||
. = user.mind.item_action_skills_mod(src, ., skill_difficulty, trait, bad_trait, FALSE)
|
||||
var/total_health = user.getStaminaLoss()
|
||||
. = clamp(., 0, STAMINA_NEAR_CRIT - total_health)
|
||||
|
||||
/// How long this staggers for. 0 and negatives supported.
|
||||
/obj/item/proc/melee_stagger_duration(force_override)
|
||||
|
||||
@@ -307,7 +307,11 @@ SUBSYSTEM_DEF(research)
|
||||
for(var/A in subtypesof(/obj/item/seeds))
|
||||
var/obj/item/seeds/S = A
|
||||
var/list/L = list()
|
||||
L[TECHWEB_POINT_TYPE_GENERIC] = 50 + initial(S.rarity) * 2
|
||||
//First we get are yield and rarity and times it by two
|
||||
//Then we subtract production and maturation, making it so faster growing plants are better for RnD
|
||||
//Then we add in lifespan and potency,
|
||||
//A basic seed can be worth 268 points if its the best it can be.
|
||||
L[TECHWEB_POINT_TYPE_GENERIC] = 50 + initial(S.rarity) * 2 + initial(S.yield) * 2 - initial(S.maturation) - initial(S.production) + initial(S.lifespan) + initial(S.potency)
|
||||
techweb_point_items[S] = L
|
||||
|
||||
return ..()
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/datum/component/decal
|
||||
dupe_mode = COMPONENT_DUPE_ALLOWED
|
||||
can_transfer = TRUE
|
||||
var/cleanable
|
||||
var/description
|
||||
var/mutable_appearance/pic
|
||||
|
||||
var/first_dir // This only stores the dir arg from init
|
||||
|
||||
/datum/component/decal/Initialize(_icon, _icon_state, _dir, _cleanable=CLEAN_GOD, _color, _layer=TURF_LAYER, _description, _alpha=255)
|
||||
if(!isatom(parent) || !generate_appearance(_icon, _icon_state, _dir, _layer, _color, _alpha))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
first_dir = _dir
|
||||
description = _description
|
||||
cleanable = _cleanable
|
||||
|
||||
apply()
|
||||
|
||||
/datum/component/decal/RegisterWithParent()
|
||||
. = ..()
|
||||
if(first_dir)
|
||||
RegisterSignal(parent, COMSIG_ATOM_DIR_CHANGE, .proc/rotate_react)
|
||||
if(cleanable)
|
||||
RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_react)
|
||||
if(description)
|
||||
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/examine)
|
||||
|
||||
/datum/component/decal/UnregisterFromParent()
|
||||
. = ..()
|
||||
UnregisterSignal(parent, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_COMPONENT_CLEAN_ACT, COMSIG_PARENT_EXAMINE))
|
||||
|
||||
/datum/component/decal/Destroy()
|
||||
remove()
|
||||
return ..()
|
||||
|
||||
/datum/component/decal/PreTransfer()
|
||||
remove()
|
||||
|
||||
/datum/component/decal/PostTransfer()
|
||||
remove()
|
||||
apply()
|
||||
|
||||
/datum/component/decal/proc/generate_appearance(_icon, _icon_state, _dir, _layer, _color, _alpha)
|
||||
if(!_icon || !_icon_state)
|
||||
return FALSE
|
||||
// It has to be made from an image or dir breaks because of a byond bug
|
||||
var/temp_image = image(_icon, null, _icon_state, _layer, _dir)
|
||||
pic = new(temp_image)
|
||||
pic.color = _color
|
||||
pic.alpha = _alpha
|
||||
return TRUE
|
||||
|
||||
/datum/component/decal/proc/apply(atom/thing)
|
||||
var/atom/master = thing || parent
|
||||
master.add_overlay(pic, TRUE)
|
||||
if(isitem(master))
|
||||
addtimer(CALLBACK(master, /obj/item/.proc/update_slot_icon), 0, TIMER_UNIQUE)
|
||||
|
||||
/datum/component/decal/proc/remove(atom/thing)
|
||||
var/atom/master = thing || parent
|
||||
master.cut_overlay(pic, TRUE)
|
||||
if(isitem(master))
|
||||
addtimer(CALLBACK(master, /obj/item/.proc/update_slot_icon), 0, TIMER_UNIQUE)
|
||||
|
||||
/datum/component/decal/proc/rotate_react(datum/source, old_dir, new_dir)
|
||||
if(old_dir == new_dir)
|
||||
return
|
||||
remove()
|
||||
pic.dir = turn(pic.dir, dir2angle(old_dir) - dir2angle(new_dir))
|
||||
apply()
|
||||
|
||||
/datum/component/decal/proc/clean_react(datum/source, strength)
|
||||
if(strength >= cleanable)
|
||||
qdel(src)
|
||||
|
||||
/datum/component/decal/proc/examine(datum/source, mob/user, list/examine_list)
|
||||
examine_list += description
|
||||
@@ -1,13 +0,0 @@
|
||||
/datum/component/decal/blood
|
||||
dupe_mode = COMPONENT_DUPE_UNIQUE
|
||||
|
||||
/datum/component/decal/blood/Initialize(_icon, _icon_state, _dir, _cleanable=CLEAN_STRENGTH_BLOOD, _color, _layer=ABOVE_OBJ_LAYER)
|
||||
if(!isitem(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
. = ..()
|
||||
RegisterSignal(parent, COMSIG_ATOM_GET_EXAMINE_NAME, .proc/get_examine_name)
|
||||
|
||||
/datum/component/decal/blood/proc/get_examine_name(datum/source, mob/user, list/override)
|
||||
var/atom/A = parent
|
||||
|
||||
return COMPONENT_EXNAME_CHANGED
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
var/mob/living/owner = parent
|
||||
if(owner.stat != DEAD)
|
||||
START_PROCESSING(SSdcs, src)
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
RegisterSignal(parent, COMSIG_ADD_MOOD_EVENT, .proc/add_event)
|
||||
RegisterSignal(parent, COMSIG_CLEAR_MOOD_EVENT, .proc/clear_event)
|
||||
@@ -40,12 +40,12 @@
|
||||
hud.show_hud(hud.hud_version)
|
||||
|
||||
/datum/component/mood/Destroy()
|
||||
STOP_PROCESSING(SSdcs, src)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
unmodify_hud()
|
||||
return ..()
|
||||
|
||||
/datum/component/mood/proc/stop_processing()
|
||||
STOP_PROCESSING(SSdcs, src)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
|
||||
/datum/component/mood/proc/print_mood(mob/user)
|
||||
var/msg = "<span class='info'>*---------*\n<EM>Your current mood</EM>\n"
|
||||
@@ -138,7 +138,7 @@
|
||||
else
|
||||
screen_obj.icon_state = "mood[mood_level]"
|
||||
|
||||
/datum/component/mood/process() //Called on SSdcs process
|
||||
/datum/component/mood/process() //Called on SSobj process
|
||||
if(QDELETED(parent)) // workaround to an obnoxious sneaky periodical runtime.
|
||||
qdel(src)
|
||||
return
|
||||
@@ -345,7 +345,7 @@
|
||||
|
||||
///Called when parent is revived.
|
||||
/datum/component/mood/proc/on_revive(datum/source, full_heal)
|
||||
START_PROCESSING(SSdcs, src)
|
||||
START_PROCESSING(SSobj, src)
|
||||
if(!full_heal)
|
||||
return
|
||||
remove_temp_moods()
|
||||
|
||||
@@ -62,7 +62,9 @@
|
||||
orbiters[orbiter] = TRUE
|
||||
orbiter.orbiting = src
|
||||
RegisterSignal(orbiter, COMSIG_MOVABLE_MOVED, .proc/orbiter_move_react)
|
||||
|
||||
var/matrix/initial_transform = matrix(orbiter.transform)
|
||||
orbiters[orbiter] = initial_transform
|
||||
|
||||
// Head first!
|
||||
if(pre_rotation)
|
||||
@@ -79,8 +81,6 @@
|
||||
|
||||
orbiter.SpinAnimation(rotation_speed, -1, clockwise, rotation_segments, parallel = FALSE)
|
||||
|
||||
//we stack the orbits up client side, so we can assign this back to normal server side without it breaking the orbit
|
||||
orbiter.transform = initial_transform
|
||||
orbiter.forceMove(get_turf(parent))
|
||||
to_chat(orbiter, "<span class='notice'>Now orbiting [parent].</span>")
|
||||
|
||||
@@ -89,6 +89,8 @@
|
||||
return
|
||||
UnregisterSignal(orbiter, COMSIG_MOVABLE_MOVED)
|
||||
orbiter.SpinAnimation(0, 0)
|
||||
if(istype(orbiters[orbiter],/matrix)) //This is ugly.
|
||||
orbiter.transform = orbiters[orbiter]
|
||||
orbiters -= orbiter
|
||||
orbiter.stop_orbit(src)
|
||||
orbiter.orbiting = null
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
/obj/item/reagent_containers/hypospray/medipen, /obj/item/reagent_containers/dropper,
|
||||
/obj/item/implanter, /obj/item/screwdriver, /obj/item/weldingtool/mini,
|
||||
/obj/item/firing_pin, /obj/item/gun/ballistic/automatic/pistol, /obj/item/gun/ballistic/automatic/magrifle/pistol,
|
||||
/obj/item/toy/plush/snakeplushie
|
||||
/obj/item/toy/plush/snakeplushie, /obj/item/gun/energy/e_gun/mini
|
||||
))
|
||||
|
||||
/datum/component/storage/concrete/pockets/shoes/clown/Initialize()
|
||||
@@ -68,7 +68,7 @@
|
||||
/obj/item/scalpel, /obj/item/reagent_containers/syringe, /obj/item/dnainjector,
|
||||
/obj/item/reagent_containers/hypospray/medipen, /obj/item/reagent_containers/dropper,
|
||||
/obj/item/implanter, /obj/item/screwdriver, /obj/item/weldingtool/mini,
|
||||
/obj/item/firing_pin, /obj/item/bikehorn, /obj/item/gun/ballistic/automatic/pistol))
|
||||
/obj/item/firing_pin, /obj/item/bikehorn, /obj/item/gun/ballistic/automatic/pistol, /obj/item/gun/energy/e_gun/mini))
|
||||
|
||||
/datum/component/storage/concrete/pockets/pocketprotector
|
||||
max_items = 3
|
||||
|
||||
@@ -163,24 +163,24 @@
|
||||
if(-4 to -2) // glancing blow at best
|
||||
user.visible_message("<span class='warning'>[user] lands a weak [tackle_word] on [target], briefly knocking [target.p_them()] off-balance!</span>", "<span class='userdanger'>You land a weak [tackle_word] on [target], briefly knocking [target.p_them()] off-balance!</span>", target)
|
||||
to_chat(target, "<span class='userdanger'>[user] lands a weak [tackle_word] on you, briefly knocking you off-balance!</span>")
|
||||
|
||||
user.Knockdown(30)
|
||||
target.adjustStaminaLoss(15)
|
||||
target.apply_status_effect(STATUS_EFFECT_TASED_WEAK, 6 SECONDS)
|
||||
|
||||
if(-1 to 0) // decent hit, both parties are about equally inconvenienced
|
||||
user.visible_message("<span class='warning'>[user] lands a passable [tackle_word] on [target], sending them both tumbling!</span>", "<span class='userdanger'>You land a passable [tackle_word] on [target], sending you both tumbling!</span>", target)
|
||||
to_chat(target, "<span class='userdanger'>[user] lands a passable [tackle_word] on you, sending you both tumbling!</span>")
|
||||
|
||||
target.adjustStaminaLoss(stamina_cost)
|
||||
target.adjustStaminaLoss(stamina_cost * 1.5)
|
||||
target.Paralyze(5)
|
||||
user.Knockdown(20)
|
||||
target.Knockdown(25)
|
||||
target.Knockdown(30)
|
||||
|
||||
if(1 to 2) // solid hit, tackler has a slight advantage
|
||||
user.visible_message("<span class='warning'>[user] lands a solid [tackle_word] on [target], knocking them both down hard!</span>", "<span class='userdanger'>You land a solid [tackle_word] on [target], knocking you both down hard!</span>", target)
|
||||
to_chat(target, "<span class='userdanger'>[user] lands a solid [tackle_word] on you, knocking you both down hard!</span>")
|
||||
|
||||
target.adjustStaminaLoss(30)
|
||||
target.adjustStaminaLoss(40)
|
||||
target.Paralyze(5)
|
||||
user.Knockdown(10)
|
||||
target.Knockdown(20)
|
||||
@@ -192,9 +192,9 @@
|
||||
user.SetKnockdown(0)
|
||||
user.set_resting(FALSE, TRUE, FALSE)
|
||||
user.forceMove(get_turf(target))
|
||||
target.adjustStaminaLoss(40)
|
||||
target.Paralyze(5)
|
||||
target.Knockdown(30)
|
||||
target.adjustStaminaLoss(50)
|
||||
target.Paralyze(3) //Otherwise the victim can just instantly get out of the grab.
|
||||
target.DefaultCombatKnockdown(20) //So they cant get up instantly.
|
||||
if(ishuman(target) && iscarbon(user))
|
||||
target.grabbedby(user)
|
||||
|
||||
@@ -205,9 +205,9 @@
|
||||
user.SetKnockdown(0)
|
||||
user.set_resting(FALSE, TRUE, FALSE)
|
||||
user.forceMove(get_turf(target))
|
||||
target.adjustStaminaLoss(40)
|
||||
target.Paralyze(5)
|
||||
target.Knockdown(30)
|
||||
target.adjustStaminaLoss(65)
|
||||
target.Paralyze(10)
|
||||
target.DefaultCombatKnockdown(20)
|
||||
if(ishuman(target) && iscarbon(user))
|
||||
target.grabbedby(user)
|
||||
target.grippedby(user, instant = TRUE)
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/datum/element/decal
|
||||
element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH
|
||||
id_arg_index = 2
|
||||
var/cleanable
|
||||
var/description
|
||||
var/mutable_appearance/pic
|
||||
var/list/num_decals_per_atom
|
||||
|
||||
var/first_dir // This stores the direction of the decal compared to the parent facing NORTH
|
||||
|
||||
/datum/element/decal/Attach(datum/target, _icon, _icon_state, _dir, _cleanable=CLEAN_GOD, _color, _layer=TURF_LAYER, _description, _alpha=255)
|
||||
. = ..()
|
||||
if(. == ELEMENT_INCOMPATIBLE || !_icon || !_icon_state || !isatom(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
var/atom/A = target
|
||||
if(!pic)
|
||||
// It has to be made from an image or dir breaks because of a byond bug
|
||||
var/temp_image = image(_icon, null, _icon_state, _layer, _dir)
|
||||
pic = new(temp_image)
|
||||
pic.color = _color
|
||||
pic.alpha = _alpha
|
||||
first_dir = _dir
|
||||
description = _description
|
||||
cleanable = _cleanable
|
||||
|
||||
LAZYINITLIST(num_decals_per_atom)
|
||||
|
||||
if(!num_decals_per_atom[A])
|
||||
if(first_dir)
|
||||
RegisterSignal(A, COMSIG_ATOM_DIR_CHANGE, .proc/rotate_react)
|
||||
if(cleanable)
|
||||
RegisterSignal(A, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_react)
|
||||
if(description)
|
||||
RegisterSignal(A, COMSIG_PARENT_EXAMINE, .proc/examine)
|
||||
|
||||
apply(A, TRUE)
|
||||
|
||||
num_decals_per_atom[A]++
|
||||
|
||||
/datum/element/decal/Detach(datum/target)
|
||||
var/atom/A = target
|
||||
remove(A, A.dir)
|
||||
UnregisterSignal(A, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_COMPONENT_CLEAN_ACT, COMSIG_PARENT_EXAMINE))
|
||||
LAZYREMOVE(num_decals_per_atom, A)
|
||||
return ..()
|
||||
|
||||
/datum/element/decal/proc/remove(atom/target, old_dir)
|
||||
pic.dir = first_dir == NORTH ? target.dir : turn(first_dir, dir2angle(old_dir))
|
||||
for(var/i in 1 to num_decals_per_atom[target])
|
||||
target.cut_overlay(pic, TRUE)
|
||||
if(isitem(target))
|
||||
addtimer(CALLBACK(target, /obj/item/.proc/update_slot_icon), 0, TIMER_UNIQUE)
|
||||
|
||||
/datum/element/decal/proc/apply(atom/target, init = FALSE)
|
||||
pic.dir = first_dir == NORTH ? target.dir : turn(first_dir, dir2angle(target.dir))
|
||||
if(init)
|
||||
target.add_overlay(pic, TRUE)
|
||||
else
|
||||
for(var/i in 1 to num_decals_per_atom[target])
|
||||
target.add_overlay(pic, TRUE)
|
||||
if(isitem(target))
|
||||
addtimer(CALLBACK(target, /obj/item/.proc/update_slot_icon), 0, TIMER_UNIQUE)
|
||||
|
||||
/datum/element/decal/proc/rotate_react(datum/source, old_dir, new_dir)
|
||||
if(old_dir == new_dir)
|
||||
return
|
||||
remove(source, old_dir)
|
||||
apply(source)
|
||||
|
||||
/datum/element/decal/proc/clean_react(datum/source, strength)
|
||||
if(strength >= cleanable)
|
||||
Detach(source)
|
||||
|
||||
/datum/element/decal/proc/examine(datum/source, mob/user, list/examine_list)
|
||||
examine_list += description
|
||||
@@ -4,7 +4,7 @@
|
||||
var/list/user_by_item = list()
|
||||
|
||||
/datum/element/earhealing/New()
|
||||
START_PROCESSING(SSdcs, src)
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/datum/element/earhealing/Attach(datum/target)
|
||||
. = ..()
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/datum/element/photosynthesis
|
||||
element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH
|
||||
id_arg_index = 2
|
||||
///how much brute damage (or integrity, for objects) is healed (taken if positive) at maximum luminosity. (if lum_minus were 0)
|
||||
var/light_bruteheal = -1
|
||||
///how much burn damage is restored/taken at maximum luminosity. Mobs only.
|
||||
var/light_burnheal = -1
|
||||
///how much tox damage is restored/taken at maximum luminosity. Mobs only.
|
||||
var/light_toxheal = -1
|
||||
///how much oxy damage is restored/taken at maximum luminosity. Mobs only.
|
||||
var/light_oxyheal = -1
|
||||
///how nutrition recovery/expenses factor, not affected by bonus_lum and malus_lum. Mobs only.
|
||||
var/light_nutrition_gain = 4
|
||||
///A value subtracted to the lum count, which allows targets to wilt or heal in the darkness.
|
||||
var/lum_minus = 0.5
|
||||
///the minimum lum count over which where the target damage is adjusted.
|
||||
var/bonus_lum = 0.2
|
||||
///the maximum lum count under which the target damage is inversely adjusted.
|
||||
var/malus_lum = 0
|
||||
///List of atoms this element is attached to. Doubles as a multiplier if the same element is attached multiple times to a target multiple times.
|
||||
var/list/attached_atoms
|
||||
|
||||
/datum/element/photosynthesis/Attach(datum/target, brute = -1, burn = -1, tox = -1, oxy = -1, nutri = 4, minus = 0.5, bonus = 0.2, malus = 0)
|
||||
. = ..()
|
||||
if(. == ELEMENT_INCOMPATIBLE || !(isliving(target) || (isobj(target) && light_bruteheal)))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
light_bruteheal = brute
|
||||
light_burnheal = burn
|
||||
light_toxheal = tox
|
||||
light_oxyheal = oxy
|
||||
light_nutrition_gain = nutri
|
||||
lum_minus = minus
|
||||
bonus_lum = bonus
|
||||
malus_lum = malus
|
||||
|
||||
if(!attached_atoms)
|
||||
attached_atoms = list()
|
||||
START_PROCESSING(SSobj, src)
|
||||
attached_atoms[target]++
|
||||
|
||||
/datum/element/photosynthesis/Detach(datum/target)
|
||||
attached_atoms[target]--
|
||||
if(!attached_atoms[target])
|
||||
attached_atoms -= target
|
||||
if(!length(attached_atoms))
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
attached_atoms = null
|
||||
return ..()
|
||||
|
||||
/datum/element/photosynthesis/process()
|
||||
for(var/A in attached_atoms)
|
||||
var/atom/movable/AM = A
|
||||
var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing
|
||||
if(isturf(AM.loc)) //else, there's considered to be no light
|
||||
var/turf/T = AM.loc
|
||||
light_amount = (T.get_lumcount() - lum_minus)
|
||||
|
||||
if(isliving(AM))
|
||||
var/mob/living/L = AM
|
||||
if(L.stat == DEAD)
|
||||
continue
|
||||
if(light_nutrition_gain)
|
||||
L.adjust_nutrition(light_amount * light_nutrition_gain * attached_atoms[AM], NUTRITION_LEVEL_FULL)
|
||||
if(light_amount > bonus_lum || light_amount < malus_lum)
|
||||
var/mult = ((light_amount > bonus_lum) ? 1 : -1) * attached_atoms[AM]
|
||||
if(light_bruteheal)
|
||||
L.adjustBruteLoss(light_bruteheal * mult)
|
||||
if(light_burnheal)
|
||||
L.adjustFireLoss(light_burnheal * mult)
|
||||
if(light_toxheal)
|
||||
L.adjustToxLoss(light_toxheal * mult)
|
||||
if(light_oxyheal)
|
||||
L.adjustOxyLoss(light_oxyheal * mult)
|
||||
|
||||
else if(light_amount > bonus_lum || light_amount < malus_lum)
|
||||
var/obj/O = AM
|
||||
var/damage = light_bruteheal * ((light_amount > bonus_lum) ? 1 : -1) * attached_atoms[AM]
|
||||
if(damage < 0 && O.obj_integrity < O.max_integrity)
|
||||
O.obj_integrity = min(O.obj_integrity + damage, O.max_integrity) //Till we get a obj heal proc...
|
||||
else
|
||||
O.take_damage(damage, BRUTE, FALSE, FALSE, null, 100)
|
||||
@@ -170,6 +170,11 @@
|
||||
port_id = "snowdin"
|
||||
can_be_bought = FALSE
|
||||
|
||||
/datum/map_template/shuttle/snow_taxi
|
||||
port_id = "snow"
|
||||
can_be_bought = FALSE
|
||||
suffix = "taxi"
|
||||
|
||||
// Shuttles start here:
|
||||
|
||||
/datum/map_template/shuttle/emergency/backup
|
||||
@@ -557,6 +562,10 @@
|
||||
suffix = "cog"
|
||||
name = "arrival shuttle (Cog)"
|
||||
|
||||
/datum/map_template/shuttle/arrival/snaxi
|
||||
suffix = "snaxi"
|
||||
name = "arrival shuttle (Snaxi)"
|
||||
|
||||
/datum/map_template/shuttle/aux_base/default
|
||||
suffix = "default"
|
||||
name = "auxilliary base (Default)"
|
||||
|
||||
@@ -191,7 +191,7 @@
|
||||
/datum/mind/proc/skill_html_readout()
|
||||
var/list/out = list("<center><h1>Skills</h1></center><hr>")
|
||||
out += "<table style=\"width:100%\"><tr><th><b>Skill</b><th><b>Value</b></tr>"
|
||||
for(var/path in skill_holder.skills|skill_holder.skill_value_mods|skill_holder.skill_level_mods)
|
||||
for(var/path in GLOB.skill_datums)
|
||||
var/datum/skill/S = GLOB.skill_datums[path]
|
||||
var/skill_value = get_skill_value(path)
|
||||
var/skill_level = get_skill_level(path, round = TRUE)
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
area_type = /area
|
||||
protected_areas = list(/area/maintenance, /area/ai_monitored/turret_protected/ai_upload, /area/ai_monitored/turret_protected/ai_upload_foyer,
|
||||
/area/ai_monitored/turret_protected/ai, /area/storage/emergency/starboard, /area/storage/emergency/port, /area/shuttle, /area/security/prison, /area/ruin, /area/space/nearstation)
|
||||
/area/ai_monitored/turret_protected/ai, /area/storage/emergency/starboard, /area/storage/emergency/port, /area/shuttle, /area/security/prison, /area/ruin, /area/space/nearstation, /area/icemoon)
|
||||
target_trait = ZTRAIT_STATION
|
||||
|
||||
immunity_type = "rad"
|
||||
|
||||
@@ -200,4 +200,7 @@
|
||||
name = "Tiny Freighter"
|
||||
|
||||
/area/shuttle/caravan/freighter3
|
||||
name = "Tiny Freighter"
|
||||
name = "Tiny Freighter"
|
||||
|
||||
/area/shuttle/snowtaxi
|
||||
name = "Snow Taxi"
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
targetitem = /obj/item/gun/energy/e_gun/hos
|
||||
difficulty = 10
|
||||
excludefromjob = list("Head Of Security")
|
||||
altitems = list(/obj/item/gun/ballistic/revolver/mws)
|
||||
altitems = list(/obj/item/gun/ballistic/revolver/mws, /obj/item/choice_beacon/hosgun) //We now look for eather the alt verson of the hos gun or the beacon picker.
|
||||
|
||||
/datum/objective_item/steal/handtele
|
||||
name = "a hand teleporter."
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
return ..()
|
||||
|
||||
/obj/machinery/porta_turret_cover/attacked_by(obj/item/I, mob/user, attackchain_flags = NONE, damage_multiplier = 1)
|
||||
parent_turret.attacked_by(I, user, attackchain_flags, damage_multiplier)
|
||||
return parent_turret.attacked_by(I, user)
|
||||
|
||||
/obj/machinery/porta_turret_cover/attack_alien(mob/living/carbon/alien/humanoid/user)
|
||||
parent_turret.attack_alien(user)
|
||||
|
||||
@@ -100,44 +100,61 @@
|
||||
eat(AM)
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/recycler/proc/eat(atom/AM0, sound=TRUE)
|
||||
/obj/machinery/recycler/proc/eat(atom/AM0)
|
||||
if(stat & (BROKEN|NOPOWER) || safety_mode)
|
||||
return
|
||||
|
||||
var/list/to_eat
|
||||
|
||||
to_eat = AM0.GetAllContentsIgnoring(GLOB.typecache_mob)
|
||||
to_eat = list(AM0)
|
||||
|
||||
var/items_recycled = 0
|
||||
var/buzz = FALSE
|
||||
for(var/i in to_eat)
|
||||
var/atom/movable/AM = i
|
||||
if(QDELETED(AM))
|
||||
continue
|
||||
var/obj/item/bodypart/head/as_head = AM
|
||||
var/obj/item/mmi/as_mmi = AM
|
||||
var/brain_holder = istype(AM, /obj/item/organ/brain) || (istype(as_head) && as_head.brain) || (istype(as_mmi) && as_mmi.brain) || isbrain(AM) || istype(AM, /obj/item/dullahan_relay)
|
||||
var/brain_holder = istype(AM, /obj/item/organ/brain) || (istype(as_head) && as_head.brain) || (istype(as_mmi) && as_mmi.brain) || istype(AM, /obj/item/dullahan_relay)
|
||||
if(brain_holder)
|
||||
emergency_stop(AM)
|
||||
else if(isliving(AM))
|
||||
if((obj_flags & EMAGGED)||((!allowed(AM))&&(!ishuman(AM))))
|
||||
crush_living(AM)
|
||||
if(obj_flags & EMAGGED)
|
||||
continue
|
||||
else
|
||||
emergency_stop(AM)
|
||||
return
|
||||
else if(isliving(AM))
|
||||
if((obj_flags & EMAGGED)||((!allowed(AM))&&(!ishuman(AM))))
|
||||
to_eat += crush_living(AM)
|
||||
else
|
||||
emergency_stop(AM)
|
||||
return
|
||||
else if(isitem(AM))
|
||||
var/obj/O = AM
|
||||
if(O.resistance_flags & INDESTRUCTIBLE)
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
||||
buzz = TRUE
|
||||
O.forceMove(loc)
|
||||
else
|
||||
recycle_item(AM)
|
||||
to_eat += recycle_item(AM)
|
||||
items_recycled++
|
||||
else
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
||||
buzz = TRUE
|
||||
AM.forceMove(loc)
|
||||
|
||||
if(items_recycled && sound)
|
||||
if(items_recycled)
|
||||
playsound(src, item_recycle_sound, 50, 1)
|
||||
if(buzz)
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
||||
|
||||
/obj/machinery/recycler/proc/recycle_item(obj/item/I)
|
||||
|
||||
. = list()
|
||||
for(var/A in I)
|
||||
var/atom/movable/AM = A
|
||||
AM.forceMove(loc)
|
||||
if(AM.loc == loc)
|
||||
. += AM
|
||||
|
||||
I.forceMove(loc)
|
||||
var/obj/item/grown/log/L = I
|
||||
if(istype(L))
|
||||
@@ -172,6 +189,7 @@
|
||||
|
||||
/obj/machinery/recycler/proc/crush_living(mob/living/L)
|
||||
|
||||
. = list()
|
||||
L.forceMove(loc)
|
||||
|
||||
if(issilicon(L))
|
||||
@@ -193,7 +211,7 @@
|
||||
if(eat_victim_items)
|
||||
for(var/obj/item/I in L.get_equipped_items(TRUE))
|
||||
if(L.dropItemToGround(I))
|
||||
eat(I, sound=FALSE)
|
||||
. += I
|
||||
|
||||
// Instantly lie down, also go unconscious from the pain, before you die.
|
||||
L.Unconscious(100)
|
||||
|
||||
@@ -9,7 +9,7 @@ GLOBAL_LIST_EMPTY(allConsoles)
|
||||
#define NO_NEW_MESSAGE 0
|
||||
#define NORMAL_MESSAGE_PRIORITY 1
|
||||
#define HIGH_MESSAGE_PRIORITY 2
|
||||
#define EXTREME_MESSAGE_PRIORITY 3 // not implemented, will probably require some hacking... everything needs to have a hidden feature in this game.
|
||||
#define EXTREME_MESSAGE_PRIORITY 3 // is implimented, does require hacking. everything needs to have a hidden feature in this game.
|
||||
|
||||
/obj/machinery/requests_console
|
||||
name = "requests console"
|
||||
@@ -48,9 +48,9 @@ GLOBAL_LIST_EMPTY(allConsoles)
|
||||
var/announceAuth = FALSE //Will be set to 1 when you authenticate yourself for announcements
|
||||
var/msgVerified = "" //Will contain the name of the person who verified it
|
||||
var/msgStamped = "" //If a message is stamped, this will contain the stamp name
|
||||
var/message = "";
|
||||
var/dpt = ""; //the department which will be receiving the message
|
||||
var/priority = -1 ; //Priority of the message being sent
|
||||
var/message = ""
|
||||
var/dpt = "" //the department which will be receiving the message
|
||||
var/priority = NORMAL_MESSAGE_PRIORITY //Priority of the message being sent. why is the default -1??
|
||||
var/obj/item/radio/Radio
|
||||
var/emergency //If an emergency has been called by this device. Acts as both a cooldown and lets the responder know where it the emergency was triggered from
|
||||
var/receive_ore_updates = FALSE //If ore redemption machines will send an update when it receives new ores.
|
||||
@@ -62,16 +62,17 @@ GLOBAL_LIST_EMPTY(allConsoles)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/requests_console/update_icon_state()
|
||||
if(stat & NOPOWER)
|
||||
if(CHECK_BITFIELD(stat, NOPOWER))
|
||||
set_light(0)
|
||||
else
|
||||
set_light(1.4,0.7,"#34D352")//green light
|
||||
set_light(1.4, 0.7, "#34D352")//green light
|
||||
|
||||
if(open)
|
||||
if(!hackState)
|
||||
icon_state="req_comp_open"
|
||||
else
|
||||
icon_state="req_comp_rewired"
|
||||
else if(stat & NOPOWER)
|
||||
else if(CHECK_BITFIELD(stat, NOPOWER))
|
||||
if(icon_state != "req_comp_off")
|
||||
icon_state = "req_comp_off"
|
||||
else
|
||||
@@ -122,7 +123,7 @@ GLOBAL_LIST_EMPTY(allConsoles)
|
||||
GLOB.req_console_information += department
|
||||
|
||||
Radio = new /obj/item/radio(src)
|
||||
Radio.listening = 0
|
||||
Radio.listening = FALSE
|
||||
|
||||
/obj/machinery/requests_console/Destroy()
|
||||
QDEL_NULL(Radio)
|
||||
@@ -131,164 +132,173 @@ GLOBAL_LIST_EMPTY(allConsoles)
|
||||
|
||||
/obj/machinery/requests_console/ui_interact(mob/user)
|
||||
. = ..()
|
||||
if(open) //no.
|
||||
return
|
||||
|
||||
var/dat = ""
|
||||
if(!open)
|
||||
switch(screen)
|
||||
if(1) //req. assistance
|
||||
dat += "Which department do you need assistance from?<BR><BR>"
|
||||
dat += "<table width='100%'>"
|
||||
for(var/dpt in GLOB.req_console_assistance)
|
||||
if (dpt != department)
|
||||
dat += "<tr>"
|
||||
dat += "<td width='55%'>[dpt]</td>"
|
||||
dat += "<td width='45%'><A href='?src=[REF(src)];write=[ckey(dpt)]'>Normal</A> <A href='?src=[REF(src)];write=[ckey(dpt)];priority=2'>High</A>"
|
||||
if(hackState)
|
||||
dat += "<A href='?src=[REF(src)];write=[ckey(dpt)];priority=3'>EXTREME</A>"
|
||||
dat += "</td>"
|
||||
dat += "</tr>"
|
||||
dat += "</table>"
|
||||
dat += "<BR><A href='?src=[REF(src)];setScreen=0'><< Back</A><BR>"
|
||||
switch(screen)
|
||||
if(1) //req. assistance
|
||||
dat += "Which department do you need assistance from?<br><br>"
|
||||
dat += "<table width='100%'>"
|
||||
for(var/dpt in GLOB.req_console_assistance)
|
||||
if(dpt == department)
|
||||
continue
|
||||
dat += "<tr>"
|
||||
dat += "<td width='55%'>[dpt]</td>"
|
||||
dat += "<td width='45%'>"
|
||||
dat += "<a href='?src=[REF(src)];write=[ckey(dpt)];priority=1'>Normal</a>"
|
||||
dat += "<a href='?src=[REF(src)];write=[ckey(dpt)];priority=2'>High</a>"
|
||||
if(hackState)
|
||||
dat += "<a href='?src=[REF(src)];write=[ckey(dpt)];priority=3'>EXTREME</a>"
|
||||
dat += "</td>"
|
||||
dat += "</tr>"
|
||||
dat += "</table>"
|
||||
dat += "<br><A href='?src=[REF(src)];setScreen=0'><< Back</A><br>"
|
||||
|
||||
if(2) //req. supplies
|
||||
dat += "Which department do you need supplies from?<BR><BR>"
|
||||
dat += "<table width='100%'>"
|
||||
for(var/dpt in GLOB.req_console_supplies)
|
||||
if (dpt != department)
|
||||
dat += "<tr>"
|
||||
dat += "<td width='55%'>[dpt]</td>"
|
||||
dat += "<td width='45%'><A href='?src=[REF(src)];write=[ckey(dpt)]'>Normal</A> <A href='?src=[REF(src)];write=[ckey(dpt)];priority=2'>High</A>"
|
||||
if(hackState)
|
||||
dat += "<A href='?src=[REF(src)];write=[ckey(dpt)];priority=3'>EXTREME</A>"
|
||||
dat += "</td>"
|
||||
dat += "</tr>"
|
||||
dat += "</table>"
|
||||
dat += "<BR><A href='?src=[REF(src)];setScreen=0'><< Back</A><BR>"
|
||||
if(2) //req. supplies
|
||||
dat += "Which department do you need supplies from?<br><br>"
|
||||
dat += "<table width='100%'>"
|
||||
for(var/dpt in GLOB.req_console_supplies)
|
||||
if(dpt == department)
|
||||
continue
|
||||
|
||||
if(3) //relay information
|
||||
dat += "Which department would you like to send information to?<BR><BR>"
|
||||
dat += "<table width='100%'>"
|
||||
for(var/dpt in GLOB.req_console_information)
|
||||
if (dpt != department)
|
||||
dat += "<tr>"
|
||||
dat += "<td width='55%'>[dpt]</td>"
|
||||
dat += "<td width='45%'><A href='?src=[REF(src)];write=[ckey(dpt)]'>Normal</A> <A href='?src=[REF(src)];write=[ckey(dpt)];priority=2'>High</A>"
|
||||
if(hackState)
|
||||
dat += "<A href='?src=[REF(src)];write=[ckey(dpt)];priority=3'>EXTREME</A>"
|
||||
dat += "</td>"
|
||||
dat += "</tr>"
|
||||
dat += "</table>"
|
||||
dat += "<BR><A href='?src=[REF(src)];setScreen=0'><< Back</A><BR>"
|
||||
dat += "<tr>"
|
||||
dat += "<td width='55%'>[dpt]</td>"
|
||||
dat += "<td width='45%'>"
|
||||
dat += "<a href='?src=[REF(src)];write=[ckey(dpt)];priority=1'>Normal</a>"
|
||||
dat += "<a href='?src=[REF(src)];write=[ckey(dpt)];priority=2'>High</a>"
|
||||
if(hackState)
|
||||
dat += "<a href='?src=[REF(src)];write=[ckey(dpt)];priority=3'>EXTREME</a>"
|
||||
dat += "</td>"
|
||||
dat += "</tr>"
|
||||
dat += "</table>"
|
||||
dat += "<br><A href='?src=[REF(src)];setScreen=0'><< Back</A><br>"
|
||||
|
||||
if(6) //sent successfully
|
||||
dat += "<span class='good'>Message sent.</span><BR><BR>"
|
||||
dat += "<A href='?src=[REF(src)];setScreen=0'>Continue</A><BR>"
|
||||
if(3) //relay information
|
||||
dat += "Which department would you like to send information to?<br><br>"
|
||||
dat += "<table width='100%'>"
|
||||
for(var/dpt in GLOB.req_console_information)
|
||||
if(dpt == department)
|
||||
continue
|
||||
dat += "<tr>"
|
||||
dat += "<td width='55%'>[dpt]</td>"
|
||||
dat += "<td width='45%'>"
|
||||
dat += "<a href='?src=[REF(src)];write=[ckey(dpt)];priority=1'>Normal</a>"
|
||||
dat += "<a href='?src=[REF(src)];write=[ckey(dpt)];priority=2'>High</a>"
|
||||
if(hackState)
|
||||
dat += "<a href='?src=[REF(src)];write=[ckey(dpt)];priority=3'>EXTREME</a>"
|
||||
dat += "</td>"
|
||||
dat += "</tr>"
|
||||
dat += "</table>"
|
||||
dat += "<br><a href='?src=[REF(src)];setScreen=0'><< Back</a><br>"
|
||||
|
||||
if(7) //unsuccessful; not sent
|
||||
dat += "<span class='bad'>An error occurred.</span><BR><BR>"
|
||||
dat += "<A href='?src=[REF(src)];setScreen=0'>Continue</A><BR>"
|
||||
if(6) //sent successfully
|
||||
dat += "<span class='good'>Message sent.</span><br><br>"
|
||||
dat += "<a href='?src=[REF(src)];setScreen=0'>Continue</a><br>"
|
||||
|
||||
if(8) //view messages
|
||||
for (var/obj/machinery/requests_console/Console in GLOB.allConsoles)
|
||||
if (Console.department == department)
|
||||
Console.newmessagepriority = NO_NEW_MESSAGE
|
||||
Console.update_icon()
|
||||
if(7) //unsuccessful; not sent
|
||||
dat += "<span class='bad'>An error occurred.</span><br><br>"
|
||||
dat += "<a href='?src=[REF(src)];setScreen=0'>Continue</a><br>"
|
||||
|
||||
newmessagepriority = NO_NEW_MESSAGE
|
||||
update_icon()
|
||||
var/messageComposite = ""
|
||||
for(var/msg in messages) // This puts more recent messages at the *top*, where they belong.
|
||||
messageComposite = "<div class='block'>[msg]</div>" + messageComposite
|
||||
dat += messageComposite
|
||||
dat += "<BR><A href='?src=[REF(src)];setScreen=0'><< Back to Main Menu</A><BR>"
|
||||
if(8) //view messages
|
||||
for(var/obj/machinery/requests_console/Console in GLOB.allConsoles)
|
||||
if(Console.department == department)
|
||||
Console.newmessagepriority = NO_NEW_MESSAGE
|
||||
Console.update_icon()
|
||||
|
||||
if(9) //authentication before sending
|
||||
dat += "<B>Message Authentication</B><BR><BR>"
|
||||
dat += "<b>Message for [dpt]: </b>[message]<BR><BR>"
|
||||
dat += "<div class='notice'>You may authenticate your message now by scanning your ID or your stamp</div><BR>"
|
||||
dat += "<b>Validated by:</b> [msgVerified ? msgVerified : "<i>Not Validated</i>"]<br>"
|
||||
dat += "<b>Stamped by:</b> [msgStamped ? msgStamped : "<i>Not Stamped</i>"]<br><br>"
|
||||
dat += "<A href='?src=[REF(src)];department=[dpt]'>Send Message</A><BR>"
|
||||
dat += "<BR><A href='?src=[REF(src)];setScreen=0'><< Discard Message</A><BR>"
|
||||
newmessagepriority = NO_NEW_MESSAGE
|
||||
update_icon()
|
||||
var/messageComposite = ""
|
||||
for(var/msg in messages) // This puts more recent messages at the *top*, where they belong.
|
||||
messageComposite = "<div class='block'>[msg]</div>" + messageComposite
|
||||
dat += messageComposite
|
||||
dat += "<br><a href='?src=[REF(src)];setScreen=0'><< Back to Main Menu</a><br>"
|
||||
|
||||
if(10) //send announcement
|
||||
dat += "<h3>Station-wide Announcement</h3>"
|
||||
if(announceAuth)
|
||||
dat += "<div class='notice'>Authentication accepted</div><BR>"
|
||||
else
|
||||
dat += "<div class='notice'>Swipe your card to authenticate yourself</div><BR>"
|
||||
dat += "<b>Message: </b>[message ? message : "<i>No Message</i>"]<BR>"
|
||||
dat += "<A href='?src=[REF(src)];writeAnnouncement=1'>[message ? "Edit" : "Write"] Message</A><BR><BR>"
|
||||
if ((announceAuth || IsAdminGhost(user)) && message)
|
||||
dat += "<A href='?src=[REF(src)];sendAnnouncement=1'>Announce Message</A><BR>"
|
||||
else
|
||||
dat += "<span class='linkOff'>Announce Message</span><BR>"
|
||||
dat += "<BR><A href='?src=[REF(src)];setScreen=0'><< Back</A><BR>"
|
||||
if(9) //authentication before sending
|
||||
dat += "<b>Message Authentication</b> <br><br>"
|
||||
dat += "<b>Message for [dpt]:</b> [message] <br><br>"
|
||||
dat += "<div class='notice'>You may authenticate your message now by scanning your ID or your stamp</div> <br>"
|
||||
|
||||
dat += "<b>Validated by:</b> [msgVerified ? "<span class='good'><b>[msgVerified]</b></span>" : "<i>Not Validated</i>"] <br>"
|
||||
dat += "<b>Stamped by:</b> [msgStamped ? "<span class='boldnotice'>[msgStamped]</span>" : "<i>Not Stamped</i>"] <br><br>"
|
||||
|
||||
dat += "<a href='?src=[REF(src)];department=[dpt]'>Send Message</a> <br><br>"
|
||||
dat += "<a href='?src=[REF(src)];setScreen=0'><< Discard Message</a> <br>"
|
||||
|
||||
else //main menu
|
||||
screen = 0
|
||||
announceAuth = FALSE
|
||||
if (newmessagepriority == NORMAL_MESSAGE_PRIORITY)
|
||||
dat += "<div class='notice'>There are new messages</div><BR>"
|
||||
if (newmessagepriority == HIGH_MESSAGE_PRIORITY)
|
||||
dat += "<div class='notice'>There are new <b>PRIORITY</b> messages</div><BR>"
|
||||
if (newmessagepriority == EXTREME_MESSAGE_PRIORITY)
|
||||
dat += "<div class='notice'>There are new <b>EXTREME PRIORITY</b> messages</div><BR>"
|
||||
dat += "<A href='?src=[REF(src)];setScreen=8'>View Messages</A><BR><BR>"
|
||||
if(10) //send announcement
|
||||
dat += "<h3>Station-wide Announcement</h3>"
|
||||
if(announceAuth)
|
||||
dat += "<div class='notice'>Authentication accepted</div><br>"
|
||||
else
|
||||
dat += "<div class='notice'>Swipe your card to authenticate yourself</div> <br>"
|
||||
dat += "<b>Message: </b>[message ? message : "<i>No Message</i>"] <br>"
|
||||
dat += "<a href='?src=[REF(src)];writeAnnouncement=1'>[message ? "Edit" : "Write"] Message</a> <br><br>"
|
||||
if((announceAuth || IsAdminGhost(user)) && message)
|
||||
dat += "<a href='?src=[REF(src)];sendAnnouncement=1'>Announce Message</a> <br>"
|
||||
else
|
||||
dat += "<span class='linkOff'>Announce Message</span> <br>"
|
||||
dat += "<br><a href='?src=[REF(src)];setScreen=0'><< Back</a> <br>"
|
||||
|
||||
dat += "<A href='?src=[REF(src)];setScreen=1'>Request Assistance</A><BR>"
|
||||
dat += "<A href='?src=[REF(src)];setScreen=2'>Request Supplies</A><BR>"
|
||||
dat += "<A href='?src=[REF(src)];setScreen=3'>Relay Anonymous Information</A><BR><BR>"
|
||||
else //main menu
|
||||
screen = 0
|
||||
announceAuth = FALSE
|
||||
if(newmessagepriority == NORMAL_MESSAGE_PRIORITY)
|
||||
dat += "<div class='notice'>There are new messages</div><br>"
|
||||
if(newmessagepriority == HIGH_MESSAGE_PRIORITY)
|
||||
dat += "<div class='notice'>There are new <b>PRIORITY</b> messages</div><br>"
|
||||
if(newmessagepriority == EXTREME_MESSAGE_PRIORITY)
|
||||
dat += "<div class='notice'>There are new <b>EXTREME PRIORITY</b> messages</div><br>"
|
||||
|
||||
if(!emergency)
|
||||
dat += "<A href='?src=[REF(src)];emergency=1'>Emergency: Security</A><BR>"
|
||||
dat += "<A href='?src=[REF(src)];emergency=2'>Emergency: Engineering</A><BR>"
|
||||
dat += "<A href='?src=[REF(src)];emergency=3'>Emergency: Medical</A><BR><BR>"
|
||||
else
|
||||
dat += "<B><font color='red'>[emergency] has been dispatched to this location.</font></B><BR><BR>"
|
||||
dat += "<a href='?src=[REF(src)];setScreen=8'>View Messages</a> <br><br>"
|
||||
|
||||
if(announcementConsole)
|
||||
dat += "<A href='?src=[REF(src)];setScreen=10'>Send Station-wide Announcement</A><BR><BR>"
|
||||
if (silent)
|
||||
dat += "Speaker <A href='?src=[REF(src)];setSilent=0'>OFF</A>"
|
||||
else
|
||||
dat += "Speaker <A href='?src=[REF(src)];setSilent=1'>ON</A>"
|
||||
var/datum/browser/popup = new(user, "req_console", "[department] Requests Console", 450, 440)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
return
|
||||
dat += "<a href='?src=[REF(src)];setScreen=1'>Request Assistance</a> <br>"
|
||||
dat += "<a href='?src=[REF(src)];setScreen=2'>Request Supplies</a> <br>"
|
||||
dat += "<a href='?src=[REF(src)];setScreen=3'>Relay Anonymous Information</a> <br><br>"
|
||||
|
||||
if(!emergency)
|
||||
dat += "<a href='?src=[REF(src)];emergency=1'>Emergency: Security</a> <br>"
|
||||
dat += "<a href='?src=[REF(src)];emergency=2'>Emergency: Engineering</a> <br>"
|
||||
dat += "<a href='?src=[REF(src)];emergency=3'>Emergency: Medical</a> <br><br>"
|
||||
else
|
||||
dat += "<b><div class='bad'>[emergency] has been dispatched to this location.</div></b> <br><br>"
|
||||
|
||||
if(announcementConsole)
|
||||
dat += "<a href='?src=[REF(src)];setScreen=10'>Send Station-wide Announcement</a> <br><br>"
|
||||
if(silent)
|
||||
dat += "Speaker <a href='?src=[REF(src)];setSilent=0'>OFF</a>"
|
||||
else
|
||||
dat += "Speaker <a href='?src=[REF(src)];setSilent=1'>ON</a>"
|
||||
|
||||
var/datum/browser/popup = new(user, "req_console", "[department] Requests Console", 450, 440)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/requests_console/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
usr.set_machine(src)
|
||||
add_fingerprint(usr)
|
||||
|
||||
|
||||
if(href_list["write"])
|
||||
dpt = ckey(reject_bad_text(href_list["write"])) //write contains the string of the receiving department's name
|
||||
var/new_message = stripped_input(usr, "Write your message:", "Awaiting Input", "", MAX_MESSAGE_LEN)
|
||||
if(new_message)
|
||||
message = new_message
|
||||
screen = 9
|
||||
if (text2num(href_list["priority"]) < 2)
|
||||
priority = -1
|
||||
else
|
||||
priority = text2num(href_list["priority"])
|
||||
priority = text2num(href_list["priority"])
|
||||
else
|
||||
dpt = "";
|
||||
msgVerified = ""
|
||||
msgStamped = ""
|
||||
screen = 0
|
||||
priority = -1
|
||||
priority = NORMAL_MESSAGE_PRIORITY //:salt:
|
||||
|
||||
if(href_list["writeAnnouncement"])
|
||||
var/new_message = reject_bad_text(stripped_input(usr, "Write your message:", "Awaiting Input", "", MAX_MESSAGE_LEN))
|
||||
if(new_message)
|
||||
message = new_message
|
||||
if (text2num(href_list["priority"]) < 2)
|
||||
priority = -1
|
||||
else
|
||||
priority = text2num(href_list["priority"])
|
||||
priority = text2num(href_list["priority"])
|
||||
else
|
||||
message = ""
|
||||
announceAuth = FALSE
|
||||
@@ -296,106 +306,116 @@ GLOBAL_LIST_EMPTY(allConsoles)
|
||||
|
||||
if(href_list["sendAnnouncement"])
|
||||
if(!announcementConsole)
|
||||
updateUsrDialog()
|
||||
return
|
||||
if(isliving(usr))
|
||||
var/mob/living/L = usr
|
||||
message = L.treat_message(message)
|
||||
minor_announce(message, "[department] Announcement:")
|
||||
GLOB.news_network.SubmitArticle(message, department, "Station Announcements", null)
|
||||
usr.log_talk(message, LOG_SAY, tag="station announcement from [src]")
|
||||
usr.log_talk(message, LOG_SAY, tag = "station announcement from [src]")
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] has made a station announcement from [src] at [AREACOORD(usr)].")
|
||||
announceAuth = FALSE
|
||||
message = ""
|
||||
screen = 0
|
||||
|
||||
if(href_list["emergency"])
|
||||
if(!emergency)
|
||||
var/radio_freq
|
||||
switch(text2num(href_list["emergency"]))
|
||||
if(1) //Security
|
||||
radio_freq = FREQ_SECURITY
|
||||
emergency = "Security"
|
||||
if(2) //Engineering
|
||||
radio_freq = FREQ_ENGINEERING
|
||||
emergency = "Engineering"
|
||||
if(3) //Medical
|
||||
radio_freq = FREQ_MEDICAL
|
||||
emergency = "Medical"
|
||||
if(radio_freq)
|
||||
Radio.set_frequency(radio_freq)
|
||||
Radio.talk_into(src,"[emergency] emergency in [department]!!",radio_freq)
|
||||
update_icon()
|
||||
addtimer(CALLBACK(src, .proc/clear_emergency), 3000)
|
||||
if(emergency) //already has an emergency? do not continue
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
if( href_list["department"] && message )
|
||||
var/log_msg = message
|
||||
var/radio_freq
|
||||
switch(text2num(href_list["emergency"]))
|
||||
if(1) //Security
|
||||
radio_freq = FREQ_SECURITY
|
||||
emergency = "Security"
|
||||
if(2) //Engineering
|
||||
radio_freq = FREQ_ENGINEERING
|
||||
emergency = "Engineering"
|
||||
if(3) //Medical
|
||||
radio_freq = FREQ_MEDICAL
|
||||
emergency = "Medical"
|
||||
if(radio_freq)
|
||||
Radio.set_frequency(radio_freq)
|
||||
Radio.talk_into(src, "[emergency] emergency in [department]!!", radio_freq)
|
||||
update_icon()
|
||||
addtimer(CALLBACK(src, .proc/clear_emergency), 5 MINUTES)
|
||||
|
||||
if(href_list["department"] && message)
|
||||
var/sending = message
|
||||
sending += "<br>"
|
||||
if (msgVerified)
|
||||
sending += msgVerified
|
||||
sending += "<br>"
|
||||
if (msgStamped)
|
||||
sending += msgStamped
|
||||
sending += "<br>"
|
||||
screen = 7 //if it's successful, this will get overrwritten (7 = unsufccessfull, 6 = successfull)
|
||||
if (sending)
|
||||
var/pass = FALSE
|
||||
var/datum/data_rc_msg/log = new(href_list["department"], department, log_msg, msgStamped, msgVerified, priority)
|
||||
for (var/obj/machinery/telecomms/message_server/MS in GLOB.telecomms_list)
|
||||
if (MS.toggled)
|
||||
MS.rc_msgs += log
|
||||
pass = TRUE
|
||||
if(msgVerified)
|
||||
sending += "<span class='good'><b>[msgVerified]</b></span> <br>"
|
||||
if(msgStamped)
|
||||
sending += "<span class='boldnotice'>[msgStamped]</span> <br>"
|
||||
//so you're telling me is you cheated, by making fail happen, then quickly replacing it with 6
|
||||
|
||||
if(pass)
|
||||
var/radio_freq = 0
|
||||
switch(href_list["department"])
|
||||
if("bridge")
|
||||
radio_freq = FREQ_COMMAND
|
||||
if("medbay")
|
||||
radio_freq = FREQ_MEDICAL
|
||||
if("science")
|
||||
radio_freq = FREQ_SCIENCE
|
||||
if("engineering")
|
||||
radio_freq = FREQ_ENGINEERING
|
||||
if("security")
|
||||
radio_freq = FREQ_SECURITY
|
||||
if("cargobay" || "mining")
|
||||
radio_freq = FREQ_SUPPLY
|
||||
Radio.set_frequency(radio_freq)
|
||||
var/authentic
|
||||
if(msgVerified || msgStamped)
|
||||
authentic = " (Authenticated)"
|
||||
var/workingServer = FALSE
|
||||
var/datum/data_rc_msg/log = new(href_list["department"], department, message, msgStamped, msgVerified, priority)
|
||||
for(var/obj/machinery/telecomms/message_server/MS in GLOB.telecomms_list)
|
||||
if(MS.on) //on does the calculations. why would this server still work even though the apc is off??
|
||||
LAZYADD(MS.rc_msgs, log)
|
||||
workingServer = TRUE
|
||||
|
||||
var/alert = ""
|
||||
for (var/obj/machinery/requests_console/Console in GLOB.allConsoles)
|
||||
if (ckey(Console.department) == ckey(href_list["department"]))
|
||||
switch(priority)
|
||||
if(2) //High priority
|
||||
alert = "PRIORITY Alert in [department][authentic]"
|
||||
Console.createmessage(src, alert, sending, 2, 1)
|
||||
if(3) // Extreme Priority
|
||||
alert = "EXTREME PRIORITY Alert from [department][authentic]"
|
||||
Console.createmessage(src, alert , sending, 3, 1)
|
||||
else // Normal priority
|
||||
alert = "Message from [department][authentic]"
|
||||
Console.createmessage(src, alert , sending, 1, 1)
|
||||
screen = 6
|
||||
if(!workingServer)
|
||||
screen = 7
|
||||
say("NOTICE: No server detected! Please contact your local engineering team.")
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
if(radio_freq)
|
||||
Radio.talk_into(src, "[alert]: <i>[message]</i>", radio_freq)
|
||||
var/radio_freq = 0
|
||||
switch(href_list["department"])
|
||||
if("bridge")
|
||||
radio_freq = FREQ_COMMAND
|
||||
if("medbay")
|
||||
radio_freq = FREQ_MEDICAL
|
||||
if("science")
|
||||
radio_freq = FREQ_SCIENCE
|
||||
if("engineering")
|
||||
radio_freq = FREQ_ENGINEERING
|
||||
if("security")
|
||||
radio_freq = FREQ_SECURITY
|
||||
if("cargobay" || "mining")
|
||||
radio_freq = FREQ_SUPPLY
|
||||
Radio.set_frequency(radio_freq)
|
||||
|
||||
switch(priority)
|
||||
if(2)
|
||||
messages += "<span class='bad'>High Priority</span><BR><b>To:</b> [dpt]<BR>[sending]"
|
||||
else
|
||||
messages += "<b>To: [dpt]</b><BR>[sending]"
|
||||
var/authentic = ""
|
||||
if(msgVerified || msgStamped)
|
||||
authentic = " (Authenticated)"
|
||||
|
||||
var/alert = ""
|
||||
for(var/obj/machinery/requests_console/C in GLOB.allConsoles)
|
||||
if(ckey(C.department) != ckey(href_list["department"]))
|
||||
continue
|
||||
switch(priority)
|
||||
if(HIGH_MESSAGE_PRIORITY) //High priority
|
||||
alert = "PRIORITY Alert from [department][authentic]"
|
||||
C.createmessage(src, alert, sending, HIGH_MESSAGE_PRIORITY)
|
||||
if(EXTREME_MESSAGE_PRIORITY) // Extreme Priority
|
||||
alert = "EXTREME PRIORITY Alert from [department][authentic]"
|
||||
C.createmessage(src, alert, sending, EXTREME_MESSAGE_PRIORITY)
|
||||
else // Normal priority
|
||||
alert = "Message from [department][authentic]"
|
||||
C.createmessage(src, alert, sending, NORMAL_MESSAGE_PRIORITY)
|
||||
screen = 6 //if it ever gets here that means (c.department == href_ls["dept"])
|
||||
|
||||
if(radio_freq)
|
||||
Radio.talk_into(src, "[alert]: <i>[message]</i>", radio_freq)
|
||||
//log to (this)
|
||||
switch(priority)
|
||||
if(HIGH_MESSAGE_PRIORITY)
|
||||
messages += "<span class='bad'>High Priority</span><br><b>To:</b> [dpt]<br>[sending]"
|
||||
if(EXTREME_MESSAGE_PRIORITY)
|
||||
messages += "<span class='bad'>!!!Extreme Priority!!!</span><br><b>To:</b> [dpt]<br>[sending]"
|
||||
else
|
||||
say("NOTICE: No server detected!")
|
||||
messages += "<b>To:</b> [dpt]<br>[sending]"
|
||||
|
||||
|
||||
//Handle screen switching
|
||||
switch(text2num(href_list["setScreen"]))
|
||||
if(null) //skip
|
||||
updateUsrDialog()
|
||||
return
|
||||
if(1) //req. assistance
|
||||
screen = 1
|
||||
if(2) //req. supplies
|
||||
@@ -423,16 +443,14 @@ GLOBAL_LIST_EMPTY(allConsoles)
|
||||
msgVerified = ""
|
||||
msgStamped = ""
|
||||
message = ""
|
||||
priority = -1
|
||||
priority = NORMAL_MESSAGE_PRIORITY // :salt:
|
||||
screen = 0
|
||||
|
||||
//Handle silencing the console
|
||||
switch( href_list["setSilent"] )
|
||||
if(null) //skip
|
||||
if("1")
|
||||
silent = TRUE
|
||||
else
|
||||
silent = FALSE
|
||||
if(href_list["setSilent"] == "1")
|
||||
silent = TRUE
|
||||
else
|
||||
silent = FALSE
|
||||
|
||||
updateUsrDialog()
|
||||
return
|
||||
@@ -457,31 +475,32 @@ GLOBAL_LIST_EMPTY(allConsoles)
|
||||
linkedsender = source
|
||||
capitalize(title)
|
||||
switch(priority)
|
||||
if(2) //High priority
|
||||
if(HIGH_MESSAGE_PRIORITY) //High priority
|
||||
if(newmessagepriority < HIGH_MESSAGE_PRIORITY)
|
||||
newmessagepriority = HIGH_MESSAGE_PRIORITY
|
||||
update_icon()
|
||||
if(!silent)
|
||||
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
say(title)
|
||||
messages += "<span class='bad'>High Priority</span><BR><b>From:</b> [linkedsender]<BR>[message]"
|
||||
messages += "<span class='bad'>High Priority</span><br><b>From:</b> [linkedsender]<br>[message]" //the fuck is this not being sent
|
||||
|
||||
if(3) // Extreme Priority
|
||||
if(EXTREME_MESSAGE_PRIORITY) // Extreme Priority
|
||||
if(newmessagepriority < EXTREME_MESSAGE_PRIORITY)
|
||||
newmessagepriority = EXTREME_MESSAGE_PRIORITY
|
||||
update_icon()
|
||||
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
say(title)
|
||||
messages += "<span class='bad'>!!!Extreme Priority!!!</span><BR><b>From:</b> [linkedsender]<BR>[message]"
|
||||
//we ignore the silent option because this is !!!IMPORTANT!!!
|
||||
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
say(title)
|
||||
messages += "<span class='bad'><b>!!!Extreme Priority!!!</span></b><br><b>From:</b> [linkedsender]<br>[message]"
|
||||
|
||||
else // Normal priority
|
||||
if(newmessagepriority < NORMAL_MESSAGE_PRIORITY)
|
||||
newmessagepriority = NORMAL_MESSAGE_PRIORITY
|
||||
update_icon()
|
||||
if(!src.silent)
|
||||
if(!silent)
|
||||
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
say(title)
|
||||
messages += "<b>From:</b> [linkedsender]<BR>[message]"
|
||||
messages += "<b>From:</b> [linkedsender]<br>[message]"
|
||||
|
||||
/obj/machinery/requests_console/attackby(obj/item/O, mob/user, params)
|
||||
if(istype(O, /obj/item/crowbar))
|
||||
@@ -505,23 +524,26 @@ GLOBAL_LIST_EMPTY(allConsoles)
|
||||
to_chat(user, "<span class='warning'>You must open the maintenance panel first!</span>")
|
||||
return
|
||||
|
||||
var/obj/item/card/id/ID = O.GetID()
|
||||
if(ID)
|
||||
if(istype(O, /obj/item/card/id))
|
||||
var/obj/item/card/id/ID = O.GetID()
|
||||
if(!ID)
|
||||
return
|
||||
if(screen == 9)
|
||||
msgVerified = "<font color='green'><b>Verified by [ID.registered_name] ([ID.assignment])</b></font>"
|
||||
msgVerified = "Verified by [ID.registered_name] ([ID.assignment])"
|
||||
updateUsrDialog()
|
||||
if(screen == 10)
|
||||
if (ACCESS_RC_ANNOUNCE in ID.access)
|
||||
if(ACCESS_RC_ANNOUNCE in ID.access)
|
||||
announceAuth = TRUE
|
||||
else
|
||||
announceAuth = FALSE
|
||||
to_chat(user, "<span class='warning'>You are not authorized to send announcements!</span>")
|
||||
updateUsrDialog()
|
||||
return
|
||||
if (istype(O, /obj/item/stamp))
|
||||
|
||||
if(istype(O, /obj/item/stamp))
|
||||
if(screen == 9)
|
||||
var/obj/item/stamp/T = O
|
||||
msgStamped = "<span class='boldnotice'>Stamped with the [T.name]</span>"
|
||||
msgStamped = "Stamped with the [T.name]"
|
||||
updateUsrDialog()
|
||||
return
|
||||
return ..()
|
||||
|
||||
@@ -1,215 +1,164 @@
|
||||
|
||||
/*
|
||||
The log console for viewing the entire telecomms
|
||||
network log
|
||||
*/
|
||||
|
||||
/obj/machinery/computer/telecomms/server
|
||||
name = "telecommunications server monitoring console"
|
||||
icon_screen = "comm_logs"
|
||||
desc = "Has full access to all details and record of the telecommunications network it's monitoring."
|
||||
circuit = /obj/item/circuitboard/computer/comm_server
|
||||
req_access = list(ACCESS_TCOMSAT)
|
||||
|
||||
var/screen = 0 // the screen number:
|
||||
var/list/servers = list() // the servers located by the computer
|
||||
var/obj/machinery/telecomms/server/SelectedServer
|
||||
var/list/machinelist = list() // the servers located by the computer
|
||||
var/obj/machinery/telecomms/server/SelectedMachine = null
|
||||
|
||||
var/network = "NULL" // the network to probe
|
||||
var/temp = "" // temporary feedback messages
|
||||
var/notice = ""
|
||||
var/universal_translate = FALSE // set to TRUE(1) if it can translate nonhuman speech
|
||||
|
||||
var/universal_translate = 0 // set to 1 if it can translate nonhuman speech
|
||||
/obj/machinery/computer/telecomms/server/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "tcommsserver", "Telecomms Server Monitor", 575, 400, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
req_access = list(ACCESS_TCOMSAT)
|
||||
circuit = /obj/item/circuitboard/computer/comm_server
|
||||
/obj/machinery/computer/telecomms/server/ui_data(mob/user)
|
||||
var/list/data_out = list()
|
||||
data_out["network"] = network
|
||||
data_out["notice"] = notice
|
||||
|
||||
/obj/machinery/computer/telecomms/server/ui_interact(mob/user)
|
||||
. = ..()
|
||||
var/dat = "<TITLE>Telecommunication Server Monitor</TITLE><center><b>Telecommunications Server Monitor</b></center>"
|
||||
data_out["servers"] = list()
|
||||
for(var/obj/machinery/telecomms/server/T in machinelist)
|
||||
var/list/data = list(
|
||||
name = T.name,
|
||||
id = T.id,
|
||||
ref = REF(T)
|
||||
)
|
||||
data_out["servers"] += list(data)
|
||||
data_out["servers"] = sortList(data_out["servers"]) //a-z sort
|
||||
|
||||
switch(screen)
|
||||
if(!SelectedMachine) //null is bad.
|
||||
data_out["selected"] = null //but in js, null is good.
|
||||
return data_out
|
||||
|
||||
data_out["selected"] = list(
|
||||
name = SelectedMachine.name,
|
||||
id = SelectedMachine.id,
|
||||
status = SelectedMachine.on,
|
||||
traffic = SelectedMachine.totaltraffic, //note: total traffic, not traffic!
|
||||
ref = REF(SelectedMachine)
|
||||
)
|
||||
data_out["selected_logs"] = list()
|
||||
|
||||
// --- Main Menu ---
|
||||
if(!LAZYLEN(SelectedMachine.log_entries))
|
||||
return data_out
|
||||
|
||||
for(var/datum/comm_log_entry/C in SelectedMachine.log_entries)
|
||||
var/list/data = list()
|
||||
data["name"] = C.name //name of the file
|
||||
data["ref"] = REF(C)
|
||||
data["input_type"] = C.input_type //type of input ("Speech File" | "Execution Error").
|
||||
|
||||
if(0)
|
||||
dat += "<br>[temp]<br>"
|
||||
dat += "<br>Current Network: <a href='?src=[REF(src)];network=1'>[network]</a><br>"
|
||||
if(servers.len)
|
||||
dat += "<br>Detected Telecommunication Servers:<ul>"
|
||||
for(var/obj/machinery/telecomms/T in servers)
|
||||
dat += "<li><a href='?src=[REF(src)];viewserver=[T.id]'>[REF(T)] [T.name]</a> ([T.id])</li>"
|
||||
dat += "</ul>"
|
||||
dat += "<br><a href='?src=[REF(src)];operation=release'>\[Flush Buffer\]</a>"
|
||||
if(C.input_type == "Speech File") //there is a reason why this is not a switch.
|
||||
data["source"] = list(
|
||||
name = C.parameters["name"], //name of the mob | obj
|
||||
job = C.parameters["job"] //job of the mob | obj
|
||||
)
|
||||
|
||||
// -- Determine race of orator --
|
||||
var/mobtype = C.parameters["mobtype"]
|
||||
var/race // The actual race of the mob
|
||||
|
||||
if(ispath(mobtype, /mob/living/carbon/human) || ispath(mobtype, /mob/living/brain))
|
||||
race = "Humanoid"
|
||||
else if(ispath(mobtype, /mob/living/simple_animal/slime))
|
||||
race = "Slime" // NT knows a lot about slimes, but not aliens. Can identify slimes
|
||||
else if(ispath(mobtype, /mob/living/carbon/monkey))
|
||||
race = "Monkey"
|
||||
else if(ispath(mobtype, /mob/living/silicon) || C.parameters["job"] == "AI")
|
||||
race = "Artificial Life" // sometimes M gets deleted prematurely for AIs... just check the job
|
||||
else if(isobj(mobtype))
|
||||
race = "Machinery"
|
||||
else if(ispath(mobtype, /mob/living/simple_animal))
|
||||
race = "Domestic Animal"
|
||||
else
|
||||
dat += "<br>No servers detected. Scan for servers: <a href='?src=[REF(src)];operation=scan'>\[Scan\]</a>"
|
||||
race = "Unidentifiable"
|
||||
|
||||
data["race"] = race
|
||||
// based on [/atom/movable/proc/lang_treat]
|
||||
var/message = C.parameters["message"]
|
||||
var/language = C.parameters["language"]
|
||||
|
||||
// --- Viewing Server ---
|
||||
if(universal_translate || user.has_language(language))
|
||||
message = message
|
||||
else if(!user.has_language(language))
|
||||
var/datum/language/D = GLOB.language_datum_instances[language]
|
||||
message = D.scramble(message)
|
||||
else if(language)
|
||||
message = "(unintelligible)"
|
||||
|
||||
if(1)
|
||||
dat += "<br>[temp]<br>"
|
||||
dat += "<center><a href='?src=[REF(src)];operation=mainmenu'>\[Main Menu\]</a> <a href='?src=[REF(src)];operation=refresh'>\[Refresh\]</a></center>"
|
||||
dat += "<br>Current Network: [network]"
|
||||
dat += "<br>Selected Server: [SelectedServer.id]"
|
||||
data["message"] = message
|
||||
|
||||
if(SelectedServer.totaltraffic >= 1024)
|
||||
dat += "<br>Total recorded traffic: [round(SelectedServer.totaltraffic / 1024)] Terrabytes<br><br>"
|
||||
else
|
||||
dat += "<br>Total recorded traffic: [SelectedServer.totaltraffic] Gigabytes<br><br>"
|
||||
else if(C.input_type == "Execution Error")
|
||||
data["message"] = C.parameters["message"]
|
||||
else
|
||||
data["message"] = "(unintelligible)"
|
||||
|
||||
data_out["selected_logs"] += list(data)
|
||||
return data_out
|
||||
|
||||
dat += "Stored Logs: <ol>"
|
||||
|
||||
var/i = 0
|
||||
for(var/datum/comm_log_entry/C in SelectedServer.log_entries)
|
||||
i++
|
||||
|
||||
|
||||
// If the log is a speech file
|
||||
if(C.input_type == "Speech File")
|
||||
dat += "<li><font color = #008F00>[C.name]</font> <font color = #FF0000><a href='?src=[REF(src)];delete=[i]'>\[X\]</a></font><br>"
|
||||
|
||||
// -- Determine race of orator --
|
||||
|
||||
var/mobtype = C.parameters["mobtype"]
|
||||
var/race // The actual race of the mob
|
||||
|
||||
if(ispath(mobtype, /mob/living/carbon/human) || ispath(mobtype, /mob/living/brain))
|
||||
race = "Humanoid"
|
||||
|
||||
// NT knows a lot about slimes, but not aliens. Can identify slimes
|
||||
else if(ispath(mobtype, /mob/living/simple_animal/slime))
|
||||
race = "Slime"
|
||||
|
||||
else if(ispath(mobtype, /mob/living/carbon/monkey))
|
||||
race = "Monkey"
|
||||
|
||||
// sometimes M gets deleted prematurely for AIs... just check the job
|
||||
else if(ispath(mobtype, /mob/living/silicon) || C.parameters["job"] == "AI")
|
||||
race = "Artificial Life"
|
||||
|
||||
else if(isobj(mobtype))
|
||||
race = "Machinery"
|
||||
|
||||
else if(ispath(mobtype, /mob/living/simple_animal))
|
||||
race = "Domestic Animal"
|
||||
|
||||
else
|
||||
race = "<i>Unidentifiable</i>"
|
||||
|
||||
dat += "<u><font color = #18743E>Data type</font></u>: [C.input_type]<br>"
|
||||
dat += "<u><font color = #18743E>Source</font></u>: [C.parameters["name"]] (Job: [C.parameters["job"]])<br>"
|
||||
dat += "<u><font color = #18743E>Class</font></u>: [race]<br>"
|
||||
var/message = C.parameters["message"]
|
||||
var/language = C.parameters["language"]
|
||||
|
||||
// based on [/atom/movable/proc/lang_treat]
|
||||
if (universal_translate || user.has_language(language))
|
||||
message = "\"[message]\""
|
||||
else if (!user.has_language(language))
|
||||
var/datum/language/D = GLOB.language_datum_instances[language]
|
||||
message = "\"[D.scramble(message)]\""
|
||||
else if (language)
|
||||
message = "<i>(unintelligible)</i>"
|
||||
|
||||
dat += "<u><font color = #18743E>Contents</font></u>: [message]<br>"
|
||||
dat += "</li><br>"
|
||||
|
||||
else if(C.input_type == "Execution Error")
|
||||
dat += "<li><font color = #990000>[C.name]</font> <a href='?src=[REF(src)];delete=[i]'>\[X\]</a><br>"
|
||||
dat += "<u><font color = #787700>Error</font></u>: \"[C.parameters["message"]]\"<br>"
|
||||
dat += "</li><br>"
|
||||
|
||||
else
|
||||
dat += "<li><font color = #000099>[C.name]</font> <a href='?src=[REF(src)];delete=[i]'>\[X\]</a><br>"
|
||||
dat += "<u><font color = #18743E>Data type</font></u>: [C.input_type]<br>"
|
||||
dat += "<u><font color = #18743E>Contents</font></u>: <i>(unintelligible)</i><br>"
|
||||
dat += "</li><br>"
|
||||
|
||||
|
||||
dat += "</ol>"
|
||||
|
||||
|
||||
|
||||
user << browse(dat, "window=comm_monitor;size=575x400")
|
||||
onclose(user, "server_control")
|
||||
|
||||
temp = ""
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/computer/telecomms/server/Topic(href, href_list)
|
||||
/obj/machinery/computer/telecomms/server/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
|
||||
add_fingerprint(usr)
|
||||
usr.set_machine(src)
|
||||
|
||||
if(href_list["viewserver"])
|
||||
screen = 1
|
||||
for(var/obj/machinery/telecomms/T in servers)
|
||||
if(T.id == href_list["viewserver"])
|
||||
SelectedServer = T
|
||||
break
|
||||
|
||||
if(href_list["operation"])
|
||||
switch(href_list["operation"])
|
||||
|
||||
if("release")
|
||||
servers = list()
|
||||
screen = 0
|
||||
|
||||
if("mainmenu")
|
||||
screen = 0
|
||||
|
||||
if("scan")
|
||||
if(servers.len > 0)
|
||||
temp = "<font color = #D70B00>- FAILED: CANNOT PROBE WHEN BUFFER FULL -</font color>"
|
||||
|
||||
else
|
||||
for(var/obj/machinery/telecomms/server/T in urange(25, src))
|
||||
if(T.network == network)
|
||||
servers.Add(T)
|
||||
|
||||
if(!servers.len)
|
||||
temp = "<font color = #D70B00>- FAILED: UNABLE TO LOCATE SERVERS IN \[[network]\] -</font color>"
|
||||
else
|
||||
temp = "<font color = #336699>- [servers.len] SERVERS PROBED & BUFFERED -</font color>"
|
||||
|
||||
screen = 0
|
||||
|
||||
if(href_list["delete"])
|
||||
|
||||
if(!src.allowed(usr) && !(obj_flags & EMAGGED))
|
||||
to_chat(usr, "<span class='danger'>ACCESS DENIED.</span>")
|
||||
switch(action)
|
||||
if("mainmenu")
|
||||
SelectedMachine = null
|
||||
notice = ""
|
||||
return
|
||||
if("release")
|
||||
machinelist = list()
|
||||
notice = ""
|
||||
return
|
||||
if("network") //network change, flush the selected machine and buffer
|
||||
var/newnet = sanitize(sanitize_text(params["value"], network))
|
||||
if(length(newnet) > 15) //i'm looking at you, you href fuckers
|
||||
notice = "FAILED: Network tag string too lengthy"
|
||||
return
|
||||
network = newnet
|
||||
SelectedMachine = null
|
||||
machinelist = list()
|
||||
return
|
||||
if("probe")
|
||||
if(LAZYLEN(machinelist) > 0)
|
||||
notice = "FAILED: Cannot probe when buffer full"
|
||||
return
|
||||
|
||||
for(var/obj/machinery/telecomms/T in GLOB.telecomms_list) //telecomms just went global!
|
||||
if(T.network == network)
|
||||
LAZYADD(machinelist, T)
|
||||
|
||||
if(SelectedServer)
|
||||
if(!LAZYLEN(machinelist))
|
||||
notice = "FAILED: Unable to locate network entities in \[[network]\]"
|
||||
return
|
||||
if("viewmachine")
|
||||
for(var/obj/machinery/telecomms/T in machinelist)
|
||||
if(T.id == params["value"])
|
||||
SelectedMachine = T
|
||||
break
|
||||
if("delete")
|
||||
if(!src.allowed(usr) && !CHECK_BITFIELD(obj_flags, EMAGGED))
|
||||
to_chat(usr, "<span class='danger'>ACCESS DENIED.</span>")
|
||||
return
|
||||
|
||||
var/datum/comm_log_entry/D = SelectedServer.log_entries[text2num(href_list["delete"])]
|
||||
|
||||
temp = "<font color = #336699>- DELETED ENTRY: [D.name] -</font color>"
|
||||
|
||||
SelectedServer.log_entries.Remove(D)
|
||||
if(!SelectedMachine)
|
||||
notice = "ALERT: No server detected. Server may be nonresponsive."
|
||||
return
|
||||
var/datum/comm_log_entry/D = locate(params["value"])
|
||||
if(!istype(D))
|
||||
notice = "NOTICE: Object not found"
|
||||
return
|
||||
notice = "Deleted entry: [D.name]"
|
||||
LAZYREMOVE(SelectedMachine.log_entries, D)
|
||||
qdel(D)
|
||||
|
||||
else
|
||||
temp = "<font color = #D70B00>- FAILED: NO SELECTED MACHINE -</font color>"
|
||||
|
||||
if(href_list["network"])
|
||||
|
||||
var/newnet = stripped_input(usr, "Which network do you want to view?", "Comm Monitor", network)
|
||||
|
||||
if(newnet && ((usr in range(1, src)) || hasSiliconAccessInArea(usr)))
|
||||
if(length(newnet) > 15)
|
||||
temp = "<font color = #D70B00>- FAILED: NETWORK TAG STRING TOO LENGHTLY -</font color>"
|
||||
|
||||
else
|
||||
|
||||
network = newnet
|
||||
screen = 0
|
||||
servers = list()
|
||||
temp = "<font color = #336699>- NEW NETWORK TAG SET IN ADDRESS \[[network]\] -</font color>"
|
||||
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/telecomms/server/attackby()
|
||||
. = ..()
|
||||
updateUsrDialog()
|
||||
@@ -3,241 +3,360 @@
|
||||
Lets you read PDA and request console messages.
|
||||
*/
|
||||
|
||||
#define LINKED_SERVER_NONRESPONSIVE (!linkedServer || (linkedServer.stat & (NOPOWER|BROKEN)))
|
||||
|
||||
// The monitor itself.
|
||||
/obj/machinery/computer/message_monitor
|
||||
name = "message monitor console"
|
||||
desc = "Used to monitor the crew's PDA messages, as well as request console messages."
|
||||
icon_screen = "comm_logs"
|
||||
circuit = /obj/item/circuitboard/computer/message_monitor
|
||||
//Server linked to.
|
||||
|
||||
//Servers, and server linked to.
|
||||
var/network = "tcommsat" // the network to probe
|
||||
var/list/machinelist = list() // the servers located by the computer
|
||||
var/obj/machinery/telecomms/message_server/linkedServer = null
|
||||
|
||||
//Sparks effect - For emag
|
||||
var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread
|
||||
|
||||
//Messages - Saves me time if I want to change something.
|
||||
var/noserver = "<span class='alert'>ALERT: No server detected.</span>"
|
||||
var/incorrectkey = "<span class='warning'>ALERT: Incorrect decryption key!</span>"
|
||||
var/defaultmsg = "<span class='notice'>Welcome. Please select an option.</span>"
|
||||
var/rebootmsg = "<span class='warning'>%$&(�: Critical %$$@ Error // !RestArting! <lOadiNg backUp iNput ouTput> - ?pLeaSe wAit!</span>"
|
||||
var/noserver = "ALERT: No server detected. Server may be nonresponsive."
|
||||
var/incorrectkey = "ALERT: Incorrect decryption key!"
|
||||
var/rebootmsg = "%$�(�:SYS&EM INTRN@L ACfES VIOL�TIa█ DEtE₡TED! Ree3ARcinG A█ BAaKUP RdST�RE PbINT \[0xcff32ca/ - PLfASE aAIT"
|
||||
|
||||
//Computer properties
|
||||
var/screen = 0 // 0 = Main menu, 1 = Message Logs, 2 = Hacked screen, 3 = Custom Message
|
||||
var/hacking = FALSE // Is it being hacked into by the AI/Cyborg
|
||||
var/message = "<span class='notice'>System bootup complete. Please select an option.</span>" // The message that shows on the main menu.
|
||||
var/auth = FALSE // Are they authenticated?
|
||||
var/optioncount = 7
|
||||
var/message = "" // The message that shows on the main menu.
|
||||
var/auth = FALSE // Are they authenticated?
|
||||
|
||||
// Custom Message Properties
|
||||
var/customsender = "System Administrator"
|
||||
var/obj/item/pda/customrecepient = null
|
||||
var/customsender = "System Administrator"
|
||||
var/customjob = "Admin"
|
||||
var/custommessage = "This is a test, please ignore."
|
||||
|
||||
light_color = LIGHT_COLOR_GREEN
|
||||
|
||||
/obj/machinery/computer/message_monitor/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE,\
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "telepdalog", name, 727, 510, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/message_monitor/ui_static_data(mob/user)
|
||||
var/list/data_out = list()
|
||||
|
||||
if(!linkedServer || !auth) // no need building this if the usr isn't authenticated
|
||||
return data_out
|
||||
|
||||
data_out["recon_logs"] = list()
|
||||
var/i1 = 0
|
||||
for(var/datum/data_rc_msg/rc in linkedServer.rc_msgs)
|
||||
i1++
|
||||
if(i1 > 3000)
|
||||
break
|
||||
var/list/data = list(
|
||||
sender = rc.send_dpt,
|
||||
recipient = rc.rec_dpt,
|
||||
message = rc.message,
|
||||
stamp = rc.stamp,
|
||||
auth = rc.id_auth,
|
||||
priority = rc.priority,
|
||||
ref = REF(rc)
|
||||
)
|
||||
data_out["recon_logs"] += list(data)
|
||||
|
||||
data_out["message_logs"] = list()
|
||||
var/i2 = 0
|
||||
for(var/datum/data_pda_msg/pda in linkedServer.pda_msgs)
|
||||
i2++
|
||||
if(i2 > 3000)
|
||||
break
|
||||
var/list/data = list(
|
||||
sender = pda.sender,
|
||||
recipient = pda.recipient,
|
||||
message = pda.message,
|
||||
picture = pda.picture ? TRUE : FALSE,
|
||||
ref = REF(pda)
|
||||
)
|
||||
data_out["message_logs"] += list(data)
|
||||
|
||||
return data_out
|
||||
|
||||
/obj/machinery/computer/message_monitor/ui_data(mob/user)
|
||||
var/list/data_out = list()
|
||||
|
||||
data_out["notice"] = message
|
||||
data_out["authenticated"] = auth
|
||||
data_out["network"] = network
|
||||
|
||||
var/mob/living/silicon/S = user
|
||||
if(istype(S) && S.hack_software)
|
||||
data_out["canhack"] = TRUE
|
||||
|
||||
data_out["hacking"] = (hacking || CHECK_BITFIELD(obj_flags, EMAGGED))
|
||||
if(hacking)
|
||||
data_out["borg"] = ((isAI(user) || iscyborg(user)) && !CHECK_BITFIELD(obj_flags, EMAGGED)) //even borgs can't read emag
|
||||
return data_out
|
||||
|
||||
data_out["servers"] = list()
|
||||
for(var/obj/machinery/telecomms/message_server/T in machinelist)
|
||||
var/list/data = list(
|
||||
name = T.name,
|
||||
id = T.id,
|
||||
ref = REF(T)
|
||||
)
|
||||
data_out["servers"] += list(data) // This /might/ cause an oom. Too bad!
|
||||
data_out["servers"] = sortList(data_out["servers"]) //a-z sort
|
||||
|
||||
data_out["fake_message"] = list(
|
||||
sender = customsender,
|
||||
job = customjob,
|
||||
message = custommessage,
|
||||
recepient = (customrecepient ? "[customrecepient.owner] ([customrecepient.ownjob])" : null)
|
||||
)
|
||||
|
||||
if(!linkedServer)
|
||||
data_out["selected"] = null
|
||||
return data_out
|
||||
|
||||
data_out["selected"] = list(
|
||||
name = linkedServer.name,
|
||||
id = linkedServer.id,
|
||||
ref = REF(linkedServer),
|
||||
status = (linkedServer.on && (linkedServer.toggled != FALSE)) // returns true if server is running
|
||||
)
|
||||
return data_out
|
||||
|
||||
/obj/machinery/computer/message_monitor/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("mainmenu") //deselect
|
||||
linkedServer = null
|
||||
auth = FALSE
|
||||
message = ""
|
||||
return
|
||||
if("release") //release server listing
|
||||
machinelist = list()
|
||||
message = ""
|
||||
return
|
||||
if("network") //network change, flush the selected machine and buffer, and de-auth them, if blank, return default
|
||||
var/newnet = sanitize(sanitize_text(params["value"], network))
|
||||
if(length(newnet) > 15) //i'm looking at you, you href fuckers
|
||||
message = "FAILED: Network tag string too lengthy"
|
||||
return
|
||||
network = newnet
|
||||
linkedServer = null
|
||||
machinelist = list()
|
||||
auth = FALSE
|
||||
message = "NOTICE: Network change detected. Server disconnected, please re-authenticate."
|
||||
return
|
||||
if("probe") //probe network for the pda serbs
|
||||
if(LAZYLEN(machinelist) > 0)
|
||||
message = "FAILED: Cannot probe when buffer full"
|
||||
return
|
||||
|
||||
for(var/obj/machinery/telecomms/message_server/T in GLOB.telecomms_list)
|
||||
if(T.network == network)
|
||||
LAZYADD(machinelist, T)
|
||||
|
||||
if(!LAZYLEN(machinelist))
|
||||
message = "FAILED: Unable to locate network entities in \[[network]\]"
|
||||
return
|
||||
if("viewmachine") //selected but not authorized
|
||||
for(var/obj/machinery/telecomms/message_server/T in machinelist)
|
||||
if(T.id == params["value"])
|
||||
linkedServer = T
|
||||
break
|
||||
|
||||
if("auth")
|
||||
if(!(linkedServer.on && (linkedServer.toggled != FALSE)))
|
||||
message = noserver
|
||||
return
|
||||
if(auth)
|
||||
auth = FALSE
|
||||
update_static_data(usr) //make sure it's cleared!
|
||||
return
|
||||
var/dkey = stripped_input(usr, "Please enter the decryption key.")
|
||||
if(dkey && dkey == "")
|
||||
return
|
||||
if(linkedServer.decryptkey == dkey)
|
||||
auth = TRUE
|
||||
else
|
||||
message = incorrectkey
|
||||
update_static_data(usr)
|
||||
if("change_auth")
|
||||
if(!auth)
|
||||
message = "WARNING: Auth failed! Please log in to change the password!"
|
||||
return
|
||||
else if(!(linkedServer.on && (linkedServer.toggled != FALSE)))
|
||||
message = noserver
|
||||
return
|
||||
|
||||
var/dkey = stripped_input(usr, "Please enter the old decryption key.")
|
||||
if(dkey && dkey != "")
|
||||
if(linkedServer.decryptkey == dkey)
|
||||
var/newkey = stripped_input(usr, "Please enter the new key (3 - 20 characters max):")
|
||||
if(!ISINRANGE(length(newkey), 3, 20))
|
||||
message = "NOTICE: Decryption key length too long/short!"
|
||||
return
|
||||
if(newkey && newkey != "")
|
||||
linkedServer.decryptkey = newkey
|
||||
message = "NOTICE: Decryption key set."
|
||||
return
|
||||
message = incorrectkey
|
||||
|
||||
if("hack")
|
||||
if(!(linkedServer.on && (linkedServer.toggled != FALSE)))
|
||||
message = noserver
|
||||
return
|
||||
|
||||
var/mob/living/silicon/S = usr
|
||||
if(istype(S) && S.hack_software)
|
||||
hacking = TRUE
|
||||
//Time it takes to bruteforce is dependant on the password length.
|
||||
addtimer(CALLBACK(src, .proc/BruteForce, usr), (10 SECONDS) * length(linkedServer.decryptkey))
|
||||
|
||||
if("del_log")
|
||||
if(!auth)
|
||||
message = "WARNING: Auth failed! Delete aborted!"
|
||||
return
|
||||
else if(!(linkedServer.on && (linkedServer.toggled != FALSE)))
|
||||
message = noserver
|
||||
return
|
||||
|
||||
var/datum/data_ref = locate(params["ref"])
|
||||
if(istype(data_ref, /datum/data_rc_msg))
|
||||
LAZYREMOVE(linkedServer.rc_msgs, data_ref)
|
||||
message = "NOTICE: Log Deleted!"
|
||||
else if(istype(data_ref, /datum/data_pda_msg))
|
||||
LAZYREMOVE(linkedServer.pda_msgs, data_ref)
|
||||
message = "NOTICE: Log Deleted!"
|
||||
else
|
||||
message = "NOTICE: Log not found! It may have already been deleted"
|
||||
update_static_data(usr)
|
||||
|
||||
if("clear_log")
|
||||
if(!auth)
|
||||
message = "WARNING: Auth failed! Delete aborted!"
|
||||
return
|
||||
else if(!(linkedServer.on && (linkedServer.toggled != FALSE)))
|
||||
message = noserver
|
||||
return
|
||||
|
||||
var/what = params["value"]
|
||||
if(what == "pda_logs")
|
||||
linkedServer.pda_msgs = list()
|
||||
if(what == "rc_msgs")
|
||||
linkedServer.rc_msgs = list()
|
||||
update_static_data(usr)
|
||||
if("fake")
|
||||
if(!auth)
|
||||
message = "WARNING: Auth failed!"
|
||||
return
|
||||
else if(!(linkedServer.on && (linkedServer.toggled != FALSE)))
|
||||
message = noserver
|
||||
return
|
||||
|
||||
if("reset" in params)
|
||||
ResetMessage()
|
||||
return
|
||||
if("send" in params)
|
||||
if(isnull(customrecepient))
|
||||
message = "NOTICE: No recepient selected!"
|
||||
return
|
||||
if(length(custommessage) <= 0 || custommessage == "")
|
||||
message = "NOTICE: No message entered!"
|
||||
return
|
||||
if(length(customjob) <= 0 || customjob == "")
|
||||
customjob = "Admin"
|
||||
return
|
||||
if(length(customsender) <= 0 || customsender == "")
|
||||
customsender = "UNKNOWN"
|
||||
//sanitize text!!!
|
||||
var/datum/signal/subspace/pda/signal = new(src, list(
|
||||
"name" = sanitize(customsender),
|
||||
"job" = sanitize(customjob),
|
||||
"message" = sanitize(custommessage),
|
||||
"emojis" = TRUE,
|
||||
"targets" = list("[customrecepient.owner] ([customrecepient.ownjob])")
|
||||
))
|
||||
// this will log the signal and transmit it to the target
|
||||
linkedServer.receive_information(signal, null)
|
||||
usr.log_message("(PDA: [name] | [usr.real_name]) sent \"[sanitize(custommessage)]\" to [signal.format_target()]", LOG_PDA)
|
||||
message = ""
|
||||
return
|
||||
// Do not check if it's blank yet
|
||||
// But do check if it's above our set limit (for people who manualy send hrefs at us!)
|
||||
if("sender" in params)
|
||||
var/S = params["sender"]
|
||||
if(length(S) > MAX_NAME_LEN)
|
||||
message = "FAILED: Job string too lengthy"
|
||||
return
|
||||
customsender = S
|
||||
return
|
||||
if("job" in params)
|
||||
var/J = params["job"]
|
||||
if(length(J) > 100)
|
||||
message = "FAILED: Job string too lengthy"
|
||||
return
|
||||
|
||||
customjob = J
|
||||
return
|
||||
if("message" in params)
|
||||
var/M = params["message"]
|
||||
if(length(M) > MAX_MESSAGE_LEN)
|
||||
message = "FAILED: Message string too lengthy"
|
||||
return
|
||||
custommessage = M
|
||||
return
|
||||
|
||||
if("recepient" in params)
|
||||
// Get out list of viable PDAs
|
||||
var/list/obj/item/pda/sendPDAs = get_viewable_pdas()
|
||||
if(GLOB.PDAs && LAZYLEN(GLOB.PDAs) > 0)
|
||||
customrecepient = input(usr, "Select a PDA from the list.") as null|anything in sortNames(sendPDAs)
|
||||
else
|
||||
customrecepient = null
|
||||
return
|
||||
if("refresh")
|
||||
update_static_data(usr)
|
||||
|
||||
/obj/machinery/computer/message_monitor/attackby(obj/item/O, mob/living/user, params)
|
||||
if(istype(O, /obj/item/screwdriver) && (obj_flags & EMAGGED))
|
||||
//Stops people from just unscrewing the monitor and putting it back to get the console working again.
|
||||
if(istype(O, /obj/item/screwdriver) && CHECK_BITFIELD(obj_flags, EMAGGED))
|
||||
//Stops people from just unscrewing the monitor and putting it back to get the console working again.
|
||||
//Why this though, you should make it emag to a board level. (i wont do it)
|
||||
to_chat(user, "<span class='warning'>It is too hot to mess with!</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/message_monitor/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
if(CHECK_BITFIELD(obj_flags, EMAGGED))
|
||||
return
|
||||
if(isnull(linkedServer))
|
||||
to_chat(user, "<span class='notice'>A no server error appears on the screen.</span>")
|
||||
return
|
||||
obj_flags |= EMAGGED
|
||||
screen = 2
|
||||
ENABLE_BITFIELD(obj_flags, EMAGGED)
|
||||
spark_system.set_up(5, 0, src)
|
||||
spark_system.start()
|
||||
var/obj/item/paper/monitorkey/MK = new(loc, linkedServer)
|
||||
// Will help make emagging the console not so easy to get away with.
|
||||
MK.info += "<br><br><font color='red'>�%@%(*$%&(�&?*(%&�/{}</font>"
|
||||
var/time = 100 * length(linkedServer.decryptkey)
|
||||
addtimer(CALLBACK(src, .proc/UnmagConsole), time)
|
||||
message = rebootmsg
|
||||
addtimer(CALLBACK(src, .proc/UnmagConsole), (10 SECONDS) * length(linkedServer.decryptkey))
|
||||
//message = rebootmsg
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/message_monitor/New()
|
||||
. = ..()
|
||||
GLOB.telecomms_list += src
|
||||
|
||||
/obj/machinery/computer/message_monitor/Initialize()
|
||||
..()
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/machinery/computer/message_monitor/LateInitialize()
|
||||
//Is the server isn't linked to a server, and there's a server available, default it to the first one in the list.
|
||||
if(!linkedServer)
|
||||
for(var/obj/machinery/telecomms/message_server/S in GLOB.telecomms_list)
|
||||
linkedServer = S
|
||||
break
|
||||
|
||||
/obj/machinery/computer/message_monitor/Destroy()
|
||||
GLOB.telecomms_list -= src
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/computer/message_monitor/ui_interact(mob/living/user)
|
||||
. = ..()
|
||||
//If the computer is being hacked or is emagged, display the reboot message.
|
||||
if(hacking || (obj_flags & EMAGGED))
|
||||
message = rebootmsg
|
||||
var/dat = "<center><font color='blue'[message]</font></center>"
|
||||
|
||||
if(auth)
|
||||
dat += "<h4><dd><A href='?src=[REF(src)];auth=1'>	<font color='green'>\[Authenticated\]</font></a>	/"
|
||||
dat += " Server Power: <A href='?src=[REF(src)];active=1'>[linkedServer && linkedServer.toggled ? "<font color='green'>\[On\]</font>":"<font color='red'>\[Off\]</font>"]</a></h4>"
|
||||
else
|
||||
dat += "<h4><dd><A href='?src=[REF(src)];auth=1'>	<font color='red'>\[Unauthenticated\]</font></a>	/"
|
||||
dat += " Server Power: <u>[linkedServer && linkedServer.toggled ? "<font color='green'>\[On\]</font>":"<font color='red'>\[Off\]</font>"]</u></h4>"
|
||||
|
||||
if(hacking || (obj_flags & EMAGGED))
|
||||
screen = 2
|
||||
else if(!auth || LINKED_SERVER_NONRESPONSIVE)
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
screen = 0
|
||||
|
||||
switch(screen)
|
||||
//Main menu
|
||||
if(0)
|
||||
//	 = TAB
|
||||
var/i = 0
|
||||
dat += "<dd><A href='?src=[REF(src)];find=1'>	[++i]. Link To A Server</a></dd>"
|
||||
if(auth)
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
dat += "<dd><A>	ERROR: Server not found!</A><br></dd>"
|
||||
else
|
||||
dat += "<dd><A href='?src=[REF(src)];view_logs=1'>	[++i]. View Message Logs </a><br></dd>"
|
||||
dat += "<dd><A href='?src=[REF(src)];view_requests=1'>	[++i]. View Request Console Logs </a></br></dd>"
|
||||
dat += "<dd><A href='?src=[REF(src)];clear_logs=1'>	[++i]. Clear Message Logs</a><br></dd>"
|
||||
dat += "<dd><A href='?src=[REF(src)];clear_requests=1'>	[++i]. Clear Request Console Logs</a><br></dd>"
|
||||
dat += "<dd><A href='?src=[REF(src)];pass=1'>	[++i]. Set Custom Key</a><br></dd>"
|
||||
dat += "<dd><A href='?src=[REF(src)];msg=1'>	[++i]. Send Admin Message</a><br></dd>"
|
||||
else
|
||||
for(var/n = ++i; n <= optioncount; n++)
|
||||
dat += "<dd><font color='blue'>	[n]. ---------------</font><br></dd>"
|
||||
var/mob/living/silicon/S = usr
|
||||
if(istype(S) && S.hack_software)
|
||||
//Malf/Traitor AIs can bruteforce into the system to gain the Key.
|
||||
dat += "<dd><A href='?src=[REF(src)];hack=1'><i><font color='Red'>*&@#. Bruteforce Key</font></i></font></a><br></dd>"
|
||||
else
|
||||
dat += "<br>"
|
||||
|
||||
//Bottom message
|
||||
if(!auth)
|
||||
dat += "<br><hr><dd><span class='notice'>Please authenticate with the server in order to show additional options.</span>"
|
||||
else
|
||||
dat += "<br><hr><dd><span class='warning'>Reg, #514 forbids sending messages to a Head of Staff containing Erotic Rendering Properties.</span>"
|
||||
|
||||
//Message Logs
|
||||
if(1)
|
||||
var/index = 0
|
||||
dat += "<center><A href='?src=[REF(src)];back=1'>Back</a> - <A href='?src=[REF(src)];refresh=1'>Refresh</a></center><hr>"
|
||||
dat += "<table border='1' width='100%'><tr><th width = '5%'>X</th><th width='15%'>Sender</th><th width='15%'>Recipient</th><th width='300px' word-wrap: break-word>Message</th></tr>"
|
||||
for(var/datum/data_pda_msg/pda in linkedServer.pda_msgs)
|
||||
index++
|
||||
if(index > 3000)
|
||||
break
|
||||
// Del - Sender - Recepient - Message
|
||||
// X - Al Green - Your Mom - WHAT UP!?
|
||||
dat += "<tr><td width = '5%'><center><A href='?src=[REF(src)];delete_logs=[REF(pda)]' style='color: rgb(255,0,0)'>X</a></center></td><td width='15%'>[pda.sender]</td><td width='15%'>[pda.recipient]</td><td width='300px'>[pda.message][pda.picture ? " <a href='byond://?src=[REF(pda)];photo=1'>(Photo)</a>":""]</td></tr>"
|
||||
dat += "</table>"
|
||||
//Hacking screen.
|
||||
if(2)
|
||||
if(isAI(user) || iscyborg(user))
|
||||
dat += "Brute-forcing for server key.<br> It will take 20 seconds for every character that the password has."
|
||||
dat += "In the meantime, this console can reveal your true intentions if you let someone access it. Make sure no humans enter the room during that time."
|
||||
else
|
||||
//It's the same message as the one above but in binary. Because robots understand binary and humans don't... well I thought it was clever.
|
||||
dat += {"01000010011100100111010101110100011001010010110<br>
|
||||
10110011001101111011100100110001101101001011011100110011<br>
|
||||
10010000001100110011011110111001000100000011100110110010<br>
|
||||
10111001001110110011001010111001000100000011010110110010<br>
|
||||
10111100100101110001000000100100101110100001000000111011<br>
|
||||
10110100101101100011011000010000001110100011000010110101<br>
|
||||
10110010100100000001100100011000000100000011100110110010<br>
|
||||
10110001101101111011011100110010001110011001000000110011<br>
|
||||
00110111101110010001000000110010101110110011001010111001<br>
|
||||
00111100100100000011000110110100001100001011100100110000<br>
|
||||
10110001101110100011001010111001000100000011101000110100<br>
|
||||
00110000101110100001000000111010001101000011001010010000<br>
|
||||
00111000001100001011100110111001101110111011011110111001<br>
|
||||
00110010000100000011010000110000101110011001011100010000<br>
|
||||
00100100101101110001000000111010001101000011001010010000<br>
|
||||
00110110101100101011000010110111001110100011010010110110<br>
|
||||
10110010100101100001000000111010001101000011010010111001<br>
|
||||
10010000001100011011011110110111001110011011011110110110<br>
|
||||
00110010100100000011000110110000101101110001000000111001<br>
|
||||
00110010101110110011001010110000101101100001000000111100<br>
|
||||
10110111101110101011100100010000001110100011100100111010<br>
|
||||
10110010100100000011010010110111001110100011001010110111<br>
|
||||
00111010001101001011011110110111001110011001000000110100<br>
|
||||
10110011000100000011110010110111101110101001000000110110<br>
|
||||
00110010101110100001000000111001101101111011011010110010<br>
|
||||
10110111101101110011001010010000001100001011000110110001<br>
|
||||
10110010101110011011100110010000001101001011101000010111<br>
|
||||
00010000001001101011000010110101101100101001000000111001<br>
|
||||
10111010101110010011001010010000001101110011011110010000<br>
|
||||
00110100001110101011011010110000101101110011100110010000<br>
|
||||
00110010101101110011101000110010101110010001000000111010<br>
|
||||
00110100001100101001000000111001001101111011011110110110<br>
|
||||
10010000001100100011101010111001001101001011011100110011<br>
|
||||
10010000001110100011010000110000101110100001000000111010<br>
|
||||
001101001011011010110010100101110"}
|
||||
|
||||
//Fake messages
|
||||
if(3)
|
||||
dat += "<center><A href='?src=[REF(src)];back=1'>Back</a> - <A href='?src=[REF(src)];Reset=1'>Reset</a></center><hr>"
|
||||
|
||||
dat += {"<table border='1' width='100%'>
|
||||
<tr><td width='20%'><A href='?src=[REF(src)];select=Sender'>Sender</a></td>
|
||||
<td width='20%'><A href='?src=[REF(src)];select=RecJob'>Sender's Job</a></td>
|
||||
<td width='20%'><A href='?src=[REF(src)];select=Recepient'>Recipient</a></td>
|
||||
<td width='300px' word-wrap: break-word><A href='?src=[REF(src)];select=Message'>Message</a></td></tr>"}
|
||||
//Sender - Sender's Job - Recepient - Message
|
||||
//Al Green- Your Dad - Your Mom - WHAT UP!?
|
||||
|
||||
dat += {"<tr><td width='20%'>[customsender]</td>
|
||||
<td width='20%'>[customjob]</td>
|
||||
<td width='20%'>[customrecepient ? customrecepient.owner : "NONE"]</td>
|
||||
<td width='300px'>[custommessage]</td></tr>"}
|
||||
dat += "</table><br><center><A href='?src=[REF(src)];select=Send'>Send</a>"
|
||||
|
||||
//Request Console Logs
|
||||
if(4)
|
||||
|
||||
var/index = 0
|
||||
/* data_rc_msg
|
||||
X - 5%
|
||||
var/rec_dpt = "Unspecified" //name of the person - 15%
|
||||
var/send_dpt = "Unspecified" //name of the sender- 15%
|
||||
var/message = "Blank" //transferred message - 300px
|
||||
var/stamp = "Unstamped" - 15%
|
||||
var/id_auth = "Unauthenticated" - 15%
|
||||
var/priority = "Normal" - 10%
|
||||
*/
|
||||
dat += "<center><A href='?src=[REF(src)];back=1'>Back</a> - <A href='?src=[REF(src)];refresh=1'>Refresh</a></center><hr>"
|
||||
dat += {"<table border='1' width='100%'><tr><th width = '5%'>X</th><th width='15%'>Sending Dep.</th><th width='15%'>Receiving Dep.</th>
|
||||
<th width='300px' word-wrap: break-word>Message</th><th width='15%'>Stamp</th><th width='15%'>ID Auth.</th><th width='15%'>Priority.</th></tr>"}
|
||||
for(var/datum/data_rc_msg/rc in linkedServer.rc_msgs)
|
||||
index++
|
||||
if(index > 3000)
|
||||
break
|
||||
// Del - Sender - Recepient - Message
|
||||
// X - Al Green - Your Mom - WHAT UP!?
|
||||
dat += {"<tr><td width = '5%'><center><A href='?src=[REF(src)];delete_requests=[REF(rc)]' style='color: rgb(255,0,0)'>X</a></center></td><td width='15%'>[rc.send_dpt]</td>
|
||||
<td width='15%'>[rc.rec_dpt]</td><td width='300px'>[rc.message]</td><td width='15%'>[rc.stamp]</td><td width='15%'>[rc.id_auth]</td><td width='15%'>[rc.priority]</td></tr>"}
|
||||
dat += "</table>"
|
||||
|
||||
message = defaultmsg
|
||||
var/datum/browser/popup = new(user, "hologram_console", name, 700, 700)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/message_monitor/proc/BruteForce(mob/user)
|
||||
if(isnull(linkedServer))
|
||||
to_chat(user, "<span class='warning'>Could not complete brute-force: Linked Server Disconnected!</span>")
|
||||
@@ -245,10 +364,11 @@
|
||||
var/currentKey = linkedServer.decryptkey
|
||||
to_chat(user, "<span class='warning'>Brute-force completed! The key is '[currentKey]'.</span>")
|
||||
hacking = FALSE
|
||||
screen = 0 // Return the screen back to normal
|
||||
message = ""
|
||||
|
||||
/obj/machinery/computer/message_monitor/proc/UnmagConsole()
|
||||
obj_flags &= ~EMAGGED
|
||||
DISABLE_BITFIELD(obj_flags, EMAGGED)
|
||||
message = ""
|
||||
|
||||
/obj/machinery/computer/message_monitor/proc/ResetMessage()
|
||||
customsender = "System Administrator"
|
||||
@@ -256,199 +376,12 @@
|
||||
custommessage = "This is a test, please ignore."
|
||||
customjob = "Admin"
|
||||
|
||||
/obj/machinery/computer/message_monitor/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr))
|
||||
//Authenticate
|
||||
if (href_list["auth"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
auth = FALSE
|
||||
screen = 0
|
||||
else
|
||||
var/dkey = trim(input(usr, "Please enter the decryption key.") as text|null)
|
||||
if(dkey && dkey != "")
|
||||
if(linkedServer.decryptkey == dkey)
|
||||
auth = TRUE
|
||||
else
|
||||
message = incorrectkey
|
||||
|
||||
//Turn the server on/off.
|
||||
if (href_list["active"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
linkedServer.toggled = !linkedServer.toggled
|
||||
//Find a server
|
||||
if (href_list["find"])
|
||||
var/list/message_servers = list()
|
||||
for (var/obj/machinery/telecomms/message_server/M in GLOB.telecomms_list)
|
||||
message_servers += M
|
||||
|
||||
if(message_servers.len > 1)
|
||||
linkedServer = input(usr, "Please select a server.", "Select a server.", null) as null|anything in message_servers
|
||||
message = "<span class='alert'>NOTICE: Server selected.</span>"
|
||||
else if(message_servers.len > 0)
|
||||
linkedServer = message_servers[1]
|
||||
message = "<span class='notice'>NOTICE: Only Single Server Detected - Server selected.</span>"
|
||||
else
|
||||
message = noserver
|
||||
|
||||
//View the logs - KEY REQUIRED
|
||||
if (href_list["view_logs"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
screen = 1
|
||||
|
||||
//Clears the logs - KEY REQUIRED
|
||||
if (href_list["clear_logs"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
linkedServer.pda_msgs = list()
|
||||
message = "<span class='notice'>NOTICE: Logs cleared.</span>"
|
||||
//Clears the request console logs - KEY REQUIRED
|
||||
if (href_list["clear_requests"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
linkedServer.rc_msgs = list()
|
||||
message = "<span class='notice'>NOTICE: Logs cleared.</span>"
|
||||
//Change the password - KEY REQUIRED
|
||||
if (href_list["pass"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
var/dkey = stripped_input(usr, "Please enter the decryption key.")
|
||||
if(dkey && dkey != "")
|
||||
if(linkedServer.decryptkey == dkey)
|
||||
var/newkey = trim(input(usr,"Please enter the new key (3 - 16 characters max):"))
|
||||
if(length(newkey) <= 3)
|
||||
message = "<span class='notice'>NOTICE: Decryption key too short!</span>"
|
||||
else if(length(newkey) > 16)
|
||||
message = "<span class='notice'>NOTICE: Decryption key too long!</span>"
|
||||
else if(newkey && newkey != "")
|
||||
linkedServer.decryptkey = newkey
|
||||
message = "<span class='notice'>NOTICE: Decryption key set.</span>"
|
||||
else
|
||||
message = incorrectkey
|
||||
|
||||
//Hack the Console to get the password
|
||||
if (href_list["hack"])
|
||||
var/mob/living/silicon/S = usr
|
||||
if(istype(S) && S.hack_software)
|
||||
hacking = TRUE
|
||||
screen = 2
|
||||
//Time it takes to bruteforce is dependant on the password length.
|
||||
spawn(100*length(linkedServer.decryptkey))
|
||||
if(src && linkedServer && usr)
|
||||
BruteForce(usr)
|
||||
//Delete the log.
|
||||
if (href_list["delete_logs"])
|
||||
//Are they on the view logs screen?
|
||||
if(screen == 1)
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else //if(istype(href_list["delete_logs"], /datum/data_pda_msg))
|
||||
linkedServer.pda_msgs -= locate(href_list["delete_logs"])
|
||||
message = "<span class='notice'>NOTICE: Log Deleted!</span>"
|
||||
//Delete the request console log.
|
||||
if (href_list["delete_requests"])
|
||||
//Are they on the view logs screen?
|
||||
if(screen == 4)
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else //if(istype(href_list["delete_logs"], /datum/data_pda_msg))
|
||||
linkedServer.rc_msgs -= locate(href_list["delete_requests"])
|
||||
message = "<span class='notice'>NOTICE: Log Deleted!</span>"
|
||||
//Create a custom message
|
||||
if (href_list["msg"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
screen = 3
|
||||
//Fake messaging selection - KEY REQUIRED
|
||||
if (href_list["select"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
screen = 0
|
||||
else
|
||||
switch(href_list["select"])
|
||||
|
||||
//Reset
|
||||
if("Reset")
|
||||
ResetMessage()
|
||||
|
||||
//Select Your Name
|
||||
if("Sender")
|
||||
customsender = stripped_input(usr, "Please enter the sender's name.") || customsender
|
||||
|
||||
//Select Receiver
|
||||
if("Recepient")
|
||||
//Get out list of viable PDAs
|
||||
var/list/obj/item/pda/sendPDAs = get_viewable_pdas()
|
||||
if(GLOB.PDAs && GLOB.PDAs.len > 0)
|
||||
customrecepient = input(usr, "Select a PDA from the list.") as null|anything in sortNames(sendPDAs)
|
||||
else
|
||||
customrecepient = null
|
||||
|
||||
//Enter custom job
|
||||
if("RecJob")
|
||||
customjob = stripped_input(usr, "Please enter the sender's job.") || customjob
|
||||
|
||||
//Enter message
|
||||
if("Message")
|
||||
custommessage = stripped_input(usr, "Please enter your message.") || custommessage
|
||||
|
||||
//Send message
|
||||
if("Send")
|
||||
if(isnull(customsender) || customsender == "")
|
||||
customsender = "UNKNOWN"
|
||||
|
||||
if(isnull(customrecepient))
|
||||
message = "<span class='notice'>NOTICE: No recepient selected!</span>"
|
||||
return attack_hand(usr)
|
||||
|
||||
if(isnull(custommessage) || custommessage == "")
|
||||
message = "<span class='notice'>NOTICE: No message entered!</span>"
|
||||
return attack_hand(usr)
|
||||
|
||||
var/datum/signal/subspace/pda/signal = new(src, list(
|
||||
"name" = "[customsender]",
|
||||
"job" = "[customjob]",
|
||||
"message" = custommessage,
|
||||
"emojis" = TRUE,
|
||||
"targets" = list("[customrecepient.owner] ([customrecepient.ownjob])")
|
||||
))
|
||||
// this will log the signal and transmit it to the target
|
||||
linkedServer.receive_information(signal, null)
|
||||
usr.log_message("(PDA: [name] | [usr.real_name]) sent \"[custommessage]\" to [signal.format_target()]", LOG_PDA)
|
||||
|
||||
|
||||
//Request Console Logs - KEY REQUIRED
|
||||
if(href_list["view_requests"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
message = noserver
|
||||
else if(auth)
|
||||
screen = 4
|
||||
|
||||
if (href_list["back"])
|
||||
screen = 0
|
||||
|
||||
return attack_hand(usr)
|
||||
|
||||
#undef LINKED_SERVER_NONRESPONSIVE
|
||||
|
||||
/obj/item/paper/monitorkey
|
||||
name = "monitor decryption key"
|
||||
|
||||
/obj/item/paper/monitorkey/Initialize(mapload, obj/machinery/telecomms/message_server/server)
|
||||
..()
|
||||
if (server)
|
||||
if(server)
|
||||
print(server)
|
||||
return INITIALIZE_HINT_NORMAL
|
||||
else
|
||||
@@ -460,7 +393,7 @@
|
||||
add_overlay("paper_words")
|
||||
|
||||
/obj/item/paper/monitorkey/LateInitialize()
|
||||
for (var/obj/machinery/telecomms/message_server/server in GLOB.telecomms_list)
|
||||
if (server.decryptkey)
|
||||
for(var/obj/machinery/telecomms/message_server/server in GLOB.telecomms_list)
|
||||
if(server.decryptkey)
|
||||
print(server)
|
||||
break
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/*
|
||||
Telecomms monitor tracks the overall trafficing of a telecommunications network
|
||||
and displays a heirarchy of linked machines.
|
||||
@@ -10,117 +9,98 @@
|
||||
icon_screen = "comm_monitor"
|
||||
desc = "Monitors the details of the telecommunications network it's synced with."
|
||||
|
||||
var/screen = 0 // the screen number:
|
||||
var/list/machinelist = list() // the machines located by the computer
|
||||
var/obj/machinery/telecomms/SelectedMachine
|
||||
var/obj/machinery/telecomms/SelectedMachine = null
|
||||
|
||||
var/network = "NULL" // the network to probe
|
||||
var/notice = ""
|
||||
|
||||
var/temp = "" // temporary feedback messages
|
||||
circuit = /obj/item/circuitboard/computer/comm_monitor
|
||||
|
||||
/obj/machinery/computer/telecomms/monitor/ui_interact(mob/user)
|
||||
. = ..()
|
||||
var/dat = "<TITLE>Telecommunications Monitor</TITLE><center><b>Telecommunications Monitor</b></center>"
|
||||
/obj/machinery/computer/telecomms/monitor/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE,\
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
|
||||
switch(screen)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "telemonitor", name, 575, 400, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/telecomms/monitor/ui_data(mob/user)
|
||||
var/list/data_out = list()
|
||||
data_out["network"] = network
|
||||
data_out["notice"] = notice
|
||||
|
||||
// --- Main Menu ---
|
||||
data_out["servers"] = list()
|
||||
for(var/obj/machinery/telecomms/T in machinelist)
|
||||
var/list/data = list(
|
||||
name = T.name,
|
||||
id = T.id,
|
||||
ref = REF(T)
|
||||
)
|
||||
data_out["servers"] += list(data)
|
||||
data_out["servers"] = sortList(data_out["servers"])
|
||||
|
||||
if(0)
|
||||
dat += "<br>[temp]<br><br>"
|
||||
dat += "<br>Current Network: <a href='?src=[REF(src)];network=1'>[network]</a><br>"
|
||||
if(machinelist.len)
|
||||
dat += "<br>Detected Network Entities:<ul>"
|
||||
for(var/obj/machinery/telecomms/T in machinelist)
|
||||
dat += "<li><a href='?src=[REF(src)];viewmachine=[T.id]'>[REF(T)] [T.name]</a> ([T.id])</li>"
|
||||
dat += "</ul>"
|
||||
dat += "<br><a href='?src=[REF(src)];operation=release'>\[Flush Buffer\]</a>"
|
||||
else
|
||||
dat += "<a href='?src=[REF(src)];operation=probe'>\[Probe Network\]</a>"
|
||||
if(!SelectedMachine) //null is bad.
|
||||
data_out["selected"] = null //but in js, null is good.
|
||||
return data_out
|
||||
|
||||
data_out["selected"] = list(
|
||||
name = SelectedMachine.name,
|
||||
id = SelectedMachine.id,
|
||||
status = SelectedMachine.on,
|
||||
traffic = SelectedMachine.traffic,
|
||||
netspeed = SelectedMachine.netspeed,
|
||||
freq_listening = SelectedMachine.freq_listening,
|
||||
long_range_link = SelectedMachine.long_range_link,
|
||||
ref = REF(SelectedMachine)
|
||||
)
|
||||
data_out["selected_servers"] = list()
|
||||
for(var/obj/machinery/telecomms/T in SelectedMachine.links)
|
||||
if(!T.hide)
|
||||
var/list/data = list(
|
||||
name = T.name,
|
||||
id = T.id,
|
||||
ref = REF(T)
|
||||
)
|
||||
data_out["selected_servers"] += list(data)
|
||||
|
||||
return data_out
|
||||
|
||||
// --- Viewing Machine ---
|
||||
|
||||
if(1)
|
||||
dat += "<br>[temp]<br>"
|
||||
dat += "<center><a href='?src=[REF(src)];operation=mainmenu'>\[Main Menu\]</a></center>"
|
||||
dat += "<br>Current Network: [network]<br>"
|
||||
dat += "Selected Network Entity: [SelectedMachine.name] ([SelectedMachine.id])<br>"
|
||||
dat += "Linked Entities: <ol>"
|
||||
for(var/obj/machinery/telecomms/T in SelectedMachine.links)
|
||||
if(!T.hide)
|
||||
dat += "<li><a href='?src=[REF(src)];viewmachine=[T.id]'>[REF(T.id)] [T.name]</a> ([T.id])</li>"
|
||||
dat += "</ol>"
|
||||
|
||||
|
||||
|
||||
user << browse(dat, "window=comm_monitor;size=575x400")
|
||||
onclose(user, "server_control")
|
||||
|
||||
temp = ""
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/computer/telecomms/monitor/Topic(href, href_list)
|
||||
/obj/machinery/computer/telecomms/monitor/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("mainmenu")
|
||||
SelectedMachine = null
|
||||
notice = ""
|
||||
return
|
||||
if("release")
|
||||
machinelist = list()
|
||||
notice = ""
|
||||
return
|
||||
if("network") //network change, flush the selected machine and buffer
|
||||
var/newnet = sanitize(sanitize_text(params["value"], network))
|
||||
if(length(newnet) > 15) //i'm looking at you, you href fuckers
|
||||
notice = "FAILED: Network tag string too lengthy"
|
||||
return
|
||||
network = newnet
|
||||
SelectedMachine = null
|
||||
machinelist = list()
|
||||
return
|
||||
if("probe")
|
||||
if(LAZYLEN(machinelist) > 0)
|
||||
notice = "FAILED: Cannot probe when buffer full"
|
||||
return
|
||||
|
||||
for(var/obj/machinery/telecomms/T in GLOB.telecomms_list)
|
||||
if(T.network == network)
|
||||
LAZYADD(machinelist, T)
|
||||
|
||||
|
||||
add_fingerprint(usr)
|
||||
usr.set_machine(src)
|
||||
|
||||
if(href_list["viewmachine"])
|
||||
screen = 1
|
||||
for(var/obj/machinery/telecomms/T in machinelist)
|
||||
if(T.id == href_list["viewmachine"])
|
||||
SelectedMachine = T
|
||||
break
|
||||
|
||||
if(href_list["operation"])
|
||||
switch(href_list["operation"])
|
||||
|
||||
if("release")
|
||||
machinelist = list()
|
||||
screen = 0
|
||||
|
||||
if("mainmenu")
|
||||
screen = 0
|
||||
|
||||
if("probe")
|
||||
if(machinelist.len > 0)
|
||||
temp = "<font color = #D70B00>- FAILED: CANNOT PROBE WHEN BUFFER FULL -</font color>"
|
||||
|
||||
else
|
||||
for(var/obj/machinery/telecomms/T in urange(25, src))
|
||||
if(T.network == network)
|
||||
machinelist.Add(T)
|
||||
|
||||
if(!machinelist.len)
|
||||
temp = "<font color = #D70B00>- FAILED: UNABLE TO LOCATE NETWORK ENTITIES IN \[[network]\] -</font color>"
|
||||
else
|
||||
temp = "<font color = #336699>- [machinelist.len] ENTITIES LOCATED & BUFFERED -</font color>"
|
||||
|
||||
screen = 0
|
||||
|
||||
|
||||
if(href_list["network"])
|
||||
|
||||
var/newnet = stripped_input(usr, "Which network do you want to view?", "Comm Monitor", network)
|
||||
if(newnet && ((usr in range(1, src)) || hasSiliconAccessInArea(usr)))
|
||||
if(length(newnet) > 15)
|
||||
temp = "<font color = #D70B00>- FAILED: NETWORK TAG STRING TOO LENGHTLY -</font color>"
|
||||
|
||||
else
|
||||
network = newnet
|
||||
screen = 0
|
||||
machinelist = list()
|
||||
temp = "<font color = #336699>- NEW NETWORK TAG SET IN ADDRESS \[[network]\] -</font color>"
|
||||
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/telecomms/monitor/attackby()
|
||||
. = ..()
|
||||
updateUsrDialog()
|
||||
if(!LAZYLEN(machinelist))
|
||||
notice = "FAILED: Unable to locate network entities in \[[network]\]"
|
||||
return
|
||||
if("viewmachine")
|
||||
for(var/obj/machinery/telecomms/T in machinelist)
|
||||
if(T.id == params["value"])
|
||||
SelectedMachine = T
|
||||
break
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
var/temp = "" // output message
|
||||
|
||||
/obj/machinery/telecomms/attackby(obj/item/P, mob/user, params)
|
||||
|
||||
var/icon_closed = initial(icon_state)
|
||||
var/icon_open = "[initial(icon_state)]_o"
|
||||
|
||||
if(!on)
|
||||
icon_closed = "[initial(icon_state)]_off"
|
||||
icon_open = "[initial(icon_state)]_o_off"
|
||||
@@ -27,78 +27,240 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/telecomms/ui_interact(mob/user)
|
||||
. = ..()
|
||||
// You need a multitool to use this, or be silicon
|
||||
if(!hasSiliconAccessInArea(user))
|
||||
// istype returns false if the value is null
|
||||
if(!istype(user.get_active_held_item(), /obj/item/multitool))
|
||||
return
|
||||
/obj/machinery/telecomms/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE,\
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
if(!canInteract(user))
|
||||
if(ui)
|
||||
ui.close() //haha no.
|
||||
return
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "teleinteract", "[name] Access", 520, 500, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/telecomms/ui_data(mob/user)
|
||||
. = list() //cpypaste from the vending bus
|
||||
.["notice"] = temp
|
||||
.["multitool"] = FALSE
|
||||
var/obj/item/multitool/P = get_multitool(user)
|
||||
var/dat
|
||||
dat = "<font face = \"Courier\"><HEAD><TITLE>[name]</TITLE></HEAD><center><H3>[name] Access</H3></center>"
|
||||
dat += "<br>[temp]<br>"
|
||||
dat += "<br>Power Status: <a href='?src=[REF(src)];input=toggle'>[toggled ? "On" : "Off"]</a>"
|
||||
if(on && toggled)
|
||||
if(id != "" && id)
|
||||
dat += "<br>Identification String: <a href='?src=[REF(src)];input=id'>[id]</a>"
|
||||
else
|
||||
dat += "<br>Identification String: <a href='?src=[REF(src)];input=id'>NULL</a>"
|
||||
dat += "<br>Network: <a href='?src=[REF(src)];input=network'>[network]</a>"
|
||||
dat += "<br>Prefabrication: [autolinkers.len ? "TRUE" : "FALSE"]"
|
||||
if(hide)
|
||||
dat += "<br>Shadow Link: ACTIVE</a>"
|
||||
if(P)
|
||||
.["multitool"] = TRUE
|
||||
.["multitool_buf"] = null //to clean the list!
|
||||
var/obj/machinery/telecomms/T = P.buffer
|
||||
if(istype(T))
|
||||
.["multitool_buf"] = list(
|
||||
name = T.name,
|
||||
id = T.id
|
||||
)
|
||||
|
||||
//Show additional options for certain machines.
|
||||
dat += Options_Menu()
|
||||
.["machine"] = list()
|
||||
.["machine"]["power"] = toggled
|
||||
.["machine"]["id"] = id
|
||||
.["machine"]["network"] = network
|
||||
.["machine"]["prefab"] = LAZYLEN(autolinkers) ? TRUE : FALSE
|
||||
.["machine"]["hidden"] = hide
|
||||
|
||||
dat += "<br>Linked Network Entities: <ol>"
|
||||
.["links"] = list()
|
||||
for(var/obj/machinery/telecomms/T in links)
|
||||
if(T.hide && !hide)
|
||||
continue
|
||||
var/list/data = list(
|
||||
name = T.name,
|
||||
id = T.id,
|
||||
ref = REF(T)
|
||||
)
|
||||
.["links"] += list(data)
|
||||
|
||||
var/i = 0
|
||||
for(var/obj/machinery/telecomms/T in links)
|
||||
i++
|
||||
if(T.hide && !hide)
|
||||
continue
|
||||
dat += "<li>[REF(T)] [T.name] ([T.id]) <a href='?src=[REF(src)];unlink=[i]'>\[X\]</a></li>"
|
||||
dat += "</ol>"
|
||||
.["freq_listening"] = freq_listening
|
||||
|
||||
dat += "<br>Filtering Frequencies: "
|
||||
/obj/machinery/telecomms/relay/ui_data(mob/user)
|
||||
. = ..()
|
||||
.["machine"]["isrelay"] = TRUE
|
||||
.["machine"]["broadcast"] = broadcasting
|
||||
.["machine"]["receiving"] = receiving
|
||||
|
||||
i = 0
|
||||
if(length(freq_listening))
|
||||
for(var/x in freq_listening)
|
||||
i++
|
||||
if(i < length(freq_listening))
|
||||
dat += "[format_frequency(x)] GHz<a href='?src=[REF(src)];delete=[x]'>\[X\]</a>; "
|
||||
else
|
||||
dat += "[format_frequency(x)] GHz<a href='?src=[REF(src)];delete=[x]'>\[X\]</a>"
|
||||
else
|
||||
dat += "NONE"
|
||||
/obj/machinery/telecomms/bus/ui_data(mob/user)
|
||||
. = ..()
|
||||
.["machine"]["isbus"] = TRUE
|
||||
.["machine"]["chang_frequency"] = change_frequency
|
||||
.["machine"]["chang_freq_value"] = change_freq_value
|
||||
|
||||
dat += "<br> <a href='?src=[REF(src)];input=freq'>\[Add Filter\]</a>"
|
||||
dat += "<hr>"
|
||||
|
||||
if(P)
|
||||
var/obj/machinery/telecomms/T = P.buffer
|
||||
if(istype(T))
|
||||
dat += "<br><br>MULTITOOL BUFFER: [T] ([T.id]) <a href='?src=[REF(src)];link=1'>\[Link\]</a> <a href='?src=[REF(src)];flush=1'>\[Flush\]"
|
||||
else
|
||||
dat += "<br><br>MULTITOOL BUFFER: <a href='?src=[REF(src)];buffer=1'>\[Add Machine\]</a>"
|
||||
|
||||
dat += "</font>"
|
||||
/obj/machinery/telecomms/ui_act(action, params, datum/tgui/ui)
|
||||
if(!canInteract(usr))
|
||||
if(ui)
|
||||
ui.close() //haha no.
|
||||
return
|
||||
temp = ""
|
||||
user << browse(dat, "window=tcommachine;size=520x500;can_resize=0")
|
||||
onclose(user, "tcommachine")
|
||||
return TRUE
|
||||
|
||||
switch(action)
|
||||
if("toggle")
|
||||
toggled = !toggled
|
||||
temp = "-% [src.name] has been [toggled ? "activated" : "deactivated"]. %-"
|
||||
update_power()
|
||||
return
|
||||
if("machine")
|
||||
if("id" in params)
|
||||
if(!canAccess(usr))
|
||||
return
|
||||
//if the text is blank, return the id it was using
|
||||
var/newid = sanitize_text(reject_bad_text(params["id"]), id) // reject_bad_text can return null!
|
||||
if(length(newid) > 255)
|
||||
temp = "-% Too many characters in new id tag. %-"
|
||||
return
|
||||
temp = "-% New ID assigned: \"[newid]\". %-"
|
||||
id = newid
|
||||
return
|
||||
if("network" in params)
|
||||
if(!canAccess(usr))
|
||||
return
|
||||
var/newnet = sanitize(sanitize_text(params["network"], network))
|
||||
if(length(newnet) > 15)
|
||||
temp = "-% Too many characters in new network tag. %-"
|
||||
return
|
||||
network = newnet
|
||||
links = list()
|
||||
temp = "-% New network tag assigned: \"[network]\" %-"
|
||||
return
|
||||
if("multitool")
|
||||
var/obj/item/multitool/P = get_multitool(usr)
|
||||
if("Link" in params)
|
||||
if(!canAccess(usr))
|
||||
return
|
||||
if(!istype(P))
|
||||
temp = "-% Unable to acquire buffer %-"
|
||||
return
|
||||
|
||||
var/obj/machinery/telecomms/T = P.buffer
|
||||
if(!istype(T) || T == src)
|
||||
temp = "-% Unable to acquire buffer %-"
|
||||
return
|
||||
|
||||
if(!(src in T.links))
|
||||
LAZYADD(T.links, src)
|
||||
|
||||
if(!(T in links))
|
||||
LAZYADD(links, T)
|
||||
temp = "-% Successfully linked with [REF(T)] [T.name] %-"
|
||||
|
||||
if("Flush" in params)
|
||||
if(!istype(P))
|
||||
temp = "-% Unable to acquire multitool %-"
|
||||
return
|
||||
|
||||
temp = "-% Buffer successfully flushed. %-"
|
||||
P.buffer = null
|
||||
|
||||
if("Add" in params)
|
||||
if(!canAccess(usr))
|
||||
return
|
||||
if(!istype(P))
|
||||
temp = "-% Unable to acquire multitool %-"
|
||||
return
|
||||
|
||||
P.buffer = src
|
||||
temp = "% Successfully stored [REF(P.buffer)] [P.buffer.name] in buffer %-"
|
||||
|
||||
if("unlink")
|
||||
var/obj/machinery/telecomms/T = locate(params["value"])
|
||||
if(!canAccess(usr))
|
||||
return
|
||||
if(!istype(T))
|
||||
temp = "-% Unable to locate machine to unlink from, try again. %-"
|
||||
return
|
||||
|
||||
temp = "-% Removed [REF(T)] [T.name] from linked entities. %-"
|
||||
if(T.links) //lazyrem makes blank list null, which is good but some might cause runtime ee's
|
||||
T.links.Remove(src)
|
||||
links.Remove(T)
|
||||
if("freq")
|
||||
if("add" in params)
|
||||
var/newfreq = input("Specify a new frequency to filter (GHz). Decimals assigned automatically.", src.name, null) as null|num
|
||||
if(!canAccess(usr) || !newfreq || isnull(newfreq))
|
||||
return
|
||||
|
||||
if(findtext(num2text(newfreq), ".")) // did they not read the text?
|
||||
newfreq *= 10 // shift the decimal one place
|
||||
|
||||
newfreq = sanitize_frequency(newfreq, TRUE) //sanitize
|
||||
if(newfreq == FREQ_SYNDICATE)
|
||||
temp = "-% Error: Interference preventing filtering frequency: \"[newfreq] GHz\" %-"
|
||||
return
|
||||
if(newfreq in freq_listening)
|
||||
temp = "-% Error: Frequency already filtered %-"
|
||||
return
|
||||
|
||||
LAZYADD(freq_listening, newfreq)
|
||||
temp = "-% New frequency filter assigned: \"[newfreq] GHz\" %-"
|
||||
|
||||
if("remove" in params)
|
||||
if(!canAccess(usr))
|
||||
return
|
||||
var/x = text2num(params["remove"])
|
||||
temp = "-% Removed frequency filter [x] %-"
|
||||
freq_listening.Remove(x)
|
||||
|
||||
/obj/machinery/telecomms/relay/ui_act(action, params)
|
||||
..()
|
||||
switch(action)
|
||||
if("relay")
|
||||
if("broadcast" in params)
|
||||
if(!canAccess(usr))
|
||||
return
|
||||
broadcasting = !broadcasting
|
||||
temp = "-% Broadcasting mode changed. %-"
|
||||
return
|
||||
if("receiving" in params)
|
||||
if(!canAccess(usr))
|
||||
return
|
||||
receiving = !receiving
|
||||
temp = "-% Receiving mode changed. %-"
|
||||
|
||||
/obj/machinery/telecomms/bus/ui_act(action, params)
|
||||
..()
|
||||
switch(action)
|
||||
if("frequency")
|
||||
if("toggle" in params)
|
||||
if(!canAccess(usr))
|
||||
return
|
||||
change_frequency = !change_frequency
|
||||
return
|
||||
if("adjust" in params)
|
||||
var/newfreq = text2num(params["adjust"])
|
||||
if(!canAccess(usr) || !newfreq)
|
||||
return
|
||||
// this should return true, unless the href is handcrafted
|
||||
if(findtext(num2text(newfreq), "."))
|
||||
newfreq *= 10 // shift the decimal one place
|
||||
|
||||
newfreq = sanitize_frequency(newfreq, TRUE)
|
||||
if(newfreq == FREQ_SYNDICATE)
|
||||
temp = "-% Error: Interference preventing filtering frequency: \"[newfreq] GHz\" %-"
|
||||
return
|
||||
|
||||
change_freq_value = newfreq
|
||||
temp = "-% New frequency to change to assigned: \"[newfreq] GHz\" %-"
|
||||
return
|
||||
|
||||
// Check if the user can use it.
|
||||
/obj/machinery/telecomms/proc/canInteract(mob/user)
|
||||
if(hasSiliconAccessInArea(user) || istype(user.get_active_held_item(), /obj/item/multitool))
|
||||
return TRUE
|
||||
return FALSE
|
||||
// Check if the user is nearby and has a multitool.
|
||||
/obj/machinery/telecomms/proc/canAccess(mob/user)
|
||||
if((canInteract(user) && in_range(user, src)) || hasSiliconAccessInArea(user))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
// Returns a multitool from a user depending on their mobtype.
|
||||
|
||||
/obj/machinery/telecomms/proc/get_multitool(mob/user)
|
||||
|
||||
var/obj/item/multitool/P = null
|
||||
// Let's double check
|
||||
if(!hasSiliconAccessInArea(user) && istype(user.get_active_held_item(), /obj/item/multitool))
|
||||
P = user.get_active_held_item()
|
||||
if(!canInteract(user))
|
||||
return null
|
||||
var/obj/item/multitool/P = user.get_active_held_item()
|
||||
// Is the ref not a null? and is it the actual type?
|
||||
if(istype(P))
|
||||
return P
|
||||
else if(isAI(user))
|
||||
var/mob/living/silicon/ai/U = user
|
||||
P = U.aiMulti
|
||||
@@ -106,170 +268,3 @@
|
||||
if(istype(user.get_active_held_item(), /obj/item/multitool))
|
||||
P = user.get_active_held_item()
|
||||
return P
|
||||
|
||||
// Additional Options for certain machines. Use this when you want to add an option to a specific machine.
|
||||
// Example of how to use below.
|
||||
|
||||
/obj/machinery/telecomms/proc/Options_Menu()
|
||||
return ""
|
||||
|
||||
// The topic for Additional Options. Use this for checking href links for your specific option.
|
||||
// Example of how to use below.
|
||||
/obj/machinery/telecomms/proc/Options_Topic(href, href_list)
|
||||
return
|
||||
|
||||
// RELAY
|
||||
|
||||
/obj/machinery/telecomms/relay/Options_Menu()
|
||||
var/dat = ""
|
||||
dat += "<br>Broadcasting: <A href='?src=[REF(src)];broadcast=1'>[broadcasting ? "YES" : "NO"]</a>"
|
||||
dat += "<br>Receiving: <A href='?src=[REF(src)];receive=1'>[receiving ? "YES" : "NO"]</a>"
|
||||
return dat
|
||||
|
||||
/obj/machinery/telecomms/relay/Options_Topic(href, href_list)
|
||||
|
||||
if(href_list["receive"])
|
||||
receiving = !receiving
|
||||
temp = "<font color = #666633>-% Receiving mode changed. %-</font color>"
|
||||
if(href_list["broadcast"])
|
||||
broadcasting = !broadcasting
|
||||
temp = "<font color = #666633>-% Broadcasting mode changed. %-</font color>"
|
||||
|
||||
// BUS
|
||||
|
||||
/obj/machinery/telecomms/bus/Options_Menu()
|
||||
var/dat = "<br>Change Signal Frequency: <A href='?src=[REF(src)];change_freq=1'>[change_frequency ? "YES ([change_frequency])" : "NO"]</a>"
|
||||
return dat
|
||||
|
||||
/obj/machinery/telecomms/bus/Options_Topic(href, href_list)
|
||||
|
||||
if(href_list["change_freq"])
|
||||
|
||||
var/newfreq = input(usr, "Specify a new frequency for new signals to change to. Enter null to turn off frequency changing. Decimals assigned automatically.", src, network) as null|num
|
||||
if(canAccess(usr))
|
||||
if(newfreq)
|
||||
if(findtext(num2text(newfreq), "."))
|
||||
newfreq *= 10 // shift the decimal one place
|
||||
if(newfreq < 10000)
|
||||
change_frequency = newfreq
|
||||
temp = "<font color = #666633>-% New frequency to change to assigned: \"[newfreq] GHz\" %-</font color>"
|
||||
else
|
||||
change_frequency = 0
|
||||
temp = "<font color = #666633>-% Frequency changing deactivated %-</font color>"
|
||||
|
||||
|
||||
/obj/machinery/telecomms/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(!hasSiliconAccessInArea(usr))
|
||||
if(!istype(usr.get_active_held_item(), /obj/item/multitool))
|
||||
return
|
||||
|
||||
var/obj/item/multitool/P = get_multitool(usr)
|
||||
|
||||
if(href_list["input"])
|
||||
switch(href_list["input"])
|
||||
|
||||
if("toggle")
|
||||
|
||||
toggled = !toggled
|
||||
temp = "<font color = #666633>-% [src] has been [toggled ? "activated" : "deactivated"].</font color>"
|
||||
update_power()
|
||||
|
||||
|
||||
if("id")
|
||||
var/newid = reject_bad_text(stripped_input(usr, "Specify the new ID for this machine", src, id, MAX_MESSAGE_LEN))
|
||||
if(newid && canAccess(usr))
|
||||
id = newid
|
||||
temp = "<font color = #666633>-% New ID assigned: \"[id]\" %-</font color>"
|
||||
|
||||
if("network")
|
||||
var/newnet = stripped_input(usr, "Specify the new network for this machine. This will break all current links.", src, network)
|
||||
if(newnet && canAccess(usr))
|
||||
|
||||
if(length(newnet) > 15)
|
||||
temp = "<font color = #666633>-% Too many characters in new network tag %-</font color>"
|
||||
|
||||
else
|
||||
for(var/obj/machinery/telecomms/T in links)
|
||||
T.links.Remove(src)
|
||||
|
||||
network = newnet
|
||||
links = list()
|
||||
temp = "<font color = #666633>-% New network tag assigned: \"[network]\" %-</font color>"
|
||||
|
||||
|
||||
if("freq")
|
||||
var/newfreq = input(usr, "Specify a new frequency to filter (GHz). Decimals assigned automatically.", src, network) as null|num
|
||||
if(newfreq && canAccess(usr))
|
||||
if(findtext(num2text(newfreq), "."))
|
||||
newfreq *= 10 // shift the decimal one place
|
||||
if(newfreq == FREQ_SYNDICATE)
|
||||
temp = "<font color = #FF0000>-% Error: Interference preventing filtering frequency: \"[newfreq] GHz\" %-</font color>"
|
||||
else
|
||||
if(!(newfreq in freq_listening) && newfreq < 10000)
|
||||
freq_listening.Add(newfreq)
|
||||
temp = "<font color = #666633>-% New frequency filter assigned: \"[newfreq] GHz\" %-</font color>"
|
||||
|
||||
if(href_list["delete"])
|
||||
|
||||
// changed the layout about to workaround a pesky runtime -- Doohl
|
||||
|
||||
var/x = text2num(href_list["delete"])
|
||||
temp = "<font color = #666633>-% Removed frequency filter [x] %-</font color>"
|
||||
freq_listening.Remove(x)
|
||||
|
||||
if(href_list["unlink"])
|
||||
|
||||
if(text2num(href_list["unlink"]) <= length(links))
|
||||
var/obj/machinery/telecomms/T = links[text2num(href_list["unlink"])]
|
||||
if(T)
|
||||
temp = "<font color = #666633>-% Removed [REF(T)] [T.name] from linked entities. %-</font color>"
|
||||
|
||||
// Remove link entries from both T and src.
|
||||
|
||||
if(T.links)
|
||||
T.links.Remove(src)
|
||||
links.Remove(T)
|
||||
|
||||
else
|
||||
temp = "<font color = #666633>-% Unable to locate machine to unlink from, try again. %-</font color>"
|
||||
|
||||
if(href_list["link"])
|
||||
|
||||
if(P)
|
||||
var/obj/machinery/telecomms/T = P.buffer
|
||||
if(istype(T) && T != src)
|
||||
if(!(src in T.links))
|
||||
T.links += src
|
||||
|
||||
if(!(T in links))
|
||||
links += T
|
||||
|
||||
temp = "<font color = #666633>-% Successfully linked with [REF(T)] [T.name] %-</font color>"
|
||||
|
||||
else
|
||||
temp = "<font color = #666633>-% Unable to acquire buffer %-</font color>"
|
||||
|
||||
if(href_list["buffer"])
|
||||
|
||||
P.buffer = src
|
||||
temp = "<font color = #666633>-% Successfully stored [REF(P.buffer)] [P.buffer.name] in buffer %-</font color>"
|
||||
|
||||
|
||||
if(href_list["flush"])
|
||||
|
||||
temp = "<font color = #666633>-% Buffer successfully flushed. %-</font color>"
|
||||
P.buffer = null
|
||||
|
||||
Options_Topic(href, href_list)
|
||||
|
||||
usr.set_machine(src)
|
||||
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/telecomms/proc/canAccess(mob/user)
|
||||
if(hasSiliconAccessInArea(user) || in_range(user, src))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
idle_power_usage = 50
|
||||
netspeed = 40
|
||||
circuit = /obj/item/circuitboard/machine/telecomms/bus
|
||||
var/change_frequency = 0
|
||||
var/change_frequency = FALSE
|
||||
var/change_freq_value = 0
|
||||
|
||||
/obj/machinery/telecomms/bus/RefreshParts()
|
||||
idle_power_usage = 50
|
||||
@@ -28,8 +29,8 @@
|
||||
if(!istype(signal) || !is_freq_listening(signal))
|
||||
return
|
||||
|
||||
if(change_frequency && signal.frequency != FREQ_SYNDICATE)
|
||||
signal.frequency = change_frequency
|
||||
if(change_frequency && (change_freq_value && signal.frequency != FREQ_SYNDICATE))
|
||||
signal.frequency = change_freq_value
|
||||
|
||||
if(!istype(machine_from, /obj/machinery/telecomms/processor) && machine_from != src) // Signal must be ready (stupid assuming machine), let's send it
|
||||
// send to one linked processor unit
|
||||
|
||||
@@ -140,11 +140,16 @@
|
||||
..()
|
||||
if(href_list["photo"])
|
||||
var/mob/M = usr
|
||||
M << browse_rsc(picture.picture_image, "pda_photo.png")
|
||||
M << browse("<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><title>PDA Photo</title></head>" \
|
||||
+ "<body style='overflow:hidden;margin:0;text-align:center'>" \
|
||||
+ "<img src='pda_photo.png' width='192' style='-ms-interpolation-mode:nearest-neighbor' />" \
|
||||
+ "</body></html>", "window=pdaphoto;size=[picture.psize_x]x[picture.psize_y];can-close=true")
|
||||
|
||||
M << browse_rsc(picture.picture_image, "pda_photo.png")
|
||||
|
||||
var/dat = "<div style='overflow: hidden; margin :0; text-align: center'>"
|
||||
dat += "<img src='pda_photo.png' width='192' style='-ms-interpolation-mode:nearest-neighbor' />"
|
||||
dat += "</div>"
|
||||
|
||||
var/datum/browser/popup = new(M, "pdaphoto", "PDA Photo", picture.psize_x, picture.psize_y)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
onclose(M, "pdaphoto")
|
||||
|
||||
/datum/data_rc_msg
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
totaltraffic += traffic // add current traffic to total traffic
|
||||
|
||||
// Delete particularly old logs
|
||||
if (log_entries.len >= 400)
|
||||
if(LAZYLEN(log_entries) >= 400) //[list].len is not safe
|
||||
log_entries.Cut(1, 2)
|
||||
|
||||
var/datum/comm_log_entry/log = new
|
||||
|
||||
@@ -117,9 +117,9 @@ GLOBAL_LIST_EMPTY(telecomms_list)
|
||||
icon_state = "[initial(icon_state)]_off"
|
||||
|
||||
/obj/machinery/telecomms/proc/update_power()
|
||||
|
||||
if(toggled)
|
||||
if(stat & (BROKEN|NOPOWER|EMPED)) // if powered, on. if not powered, off. if too damaged, off
|
||||
// if powered, on. if not powered, off. if too damaged, off
|
||||
if(CHECK_BITFIELD(stat, (BROKEN | NOPOWER | EMPED)))
|
||||
on = FALSE
|
||||
else
|
||||
on = TRUE
|
||||
@@ -137,11 +137,11 @@ GLOBAL_LIST_EMPTY(telecomms_list)
|
||||
|
||||
/obj/machinery/telecomms/emp_act(severity)
|
||||
. = ..()
|
||||
if(. & EMP_PROTECT_SELF)
|
||||
if(CHECK_BITFIELD(., EMP_PROTECT_SELF))
|
||||
return
|
||||
if(prob(100/severity))
|
||||
if(!(stat & EMPED))
|
||||
stat |= EMPED
|
||||
var/duration = (300 * 10)/severity
|
||||
if(prob(100 / severity))
|
||||
if(!CHECK_BITFIELD(stat, EMPED))
|
||||
ENABLE_BITFIELD(stat, EMPED)
|
||||
var/duration = (300 * 10) / severity
|
||||
spawn(rand(duration - 20, duration + 20)) // Takes a long time for the machines to reboot.
|
||||
stat &= ~EMPED
|
||||
DISABLE_BITFIELD(stat, EMPED)
|
||||
|
||||
@@ -5,44 +5,42 @@
|
||||
var/base_icon
|
||||
var/looky_helpy = TRUE
|
||||
|
||||
/datum/component/construction/mecha/examine(mob/user)
|
||||
/datum/component/construction/mecha/examine(datum/source, mob/user, list/examine_list)
|
||||
. = ..()
|
||||
if(looky_helpy)
|
||||
switch(steps[index]["key"])
|
||||
if(TOOL_WRENCH)
|
||||
. += "<span class='notice'>The mech could be <b>wrenched</b> into place.</span>"
|
||||
examine_list += "<span class='notice'>The mech could be <b>wrenched</b> into place.</span>"
|
||||
if(TOOL_SCREWDRIVER)
|
||||
. += "<span class='notice'>The mech could be <b>screwed</b> into place.</span>"
|
||||
examine_list += "<span class='notice'>The mech could be <b>screwed</b> into place.</span>"
|
||||
if(TOOL_WIRECUTTER)
|
||||
. += "<span class='notice'>The mech wires could be <b>trimmed</b> into place.</span>"
|
||||
examine_list += "<span class='notice'>The mech wires could be <b>trimmed</b> into place.</span>"
|
||||
if(/obj/item/stack/cable_coil)
|
||||
. += "<span class='notice'>The mech could use some <b>wiring</b>.</span>"
|
||||
examine_list += "<span class='notice'>The mech could use some <b>wiring</b>.</span>"
|
||||
if(/obj/item/circuitboard)
|
||||
. += "<span class='notice'>The mech could use a type of<b>circuitboard</b>.</span>"
|
||||
examine_list += "<span class='notice'>The mech could use a type of<b>circuitboard</b>.</span>"
|
||||
if(/obj/item/stock_parts/scanning_module)
|
||||
. += "<span class='notice'>The mech could use a <b>scanning stock part</b>.</span>"
|
||||
examine_list += "<span class='notice'>The mech could use a <b>scanning stock part</b>.</span>"
|
||||
if(/obj/item/stock_parts/capacitor)
|
||||
. += "<span class='notice'>The mech could use a <b>power based stock part</b>.</span>"
|
||||
examine_list += "<span class='notice'>The mech could use a <b>power based stock part</b>.</span>"
|
||||
if(/obj/item/stock_parts/cell)
|
||||
. += "<span class='notice'>The mech could use a <b>power source</b>.</span>"
|
||||
examine_list += "<span class='notice'>The mech could use a <b>power source</b>.</span>"
|
||||
if(/obj/item/stack/sheet/metal)
|
||||
. += "<span class='notice'>The mech could use some <b>sheets of metal</b>.</span>"
|
||||
examine_list += "<span class='notice'>The mech could use some <b>sheets of metal</b>.</span>"
|
||||
if(/obj/item/stack/sheet/plasteel)
|
||||
. += "<span class='notice'>The mech could use some <b>sheets of strong steel</b>.</span>"
|
||||
examine_list += "<span class='notice'>The mech could use some <b>sheets of strong steel</b>.</span>"
|
||||
if(/obj/item/bikehorn)
|
||||
. += "<span class='notice'>HONK IT!.</span>"
|
||||
examine_list += "<span class='notice'>HONK IT!.</span>"
|
||||
if(/obj/item/clothing/mask/gas/clown_hat)
|
||||
. += "<span class='notice'>GIVE IT CLOWN MAKEUP HONK!.</span>"
|
||||
examine_list += "<span class='notice'>GIVE IT CLOWN MAKEUP HONK!.</span>"
|
||||
if(/obj/item/clothing/shoes/clown_shoes)
|
||||
. += "<span class='notice'>GIVE IT GOOFY SHOES HONK HONK!.</span>"
|
||||
examine_list += "<span class='notice'>GIVE IT GOOFY SHOES HONK HONK!.</span>"
|
||||
if(/obj/item/mecha_parts/part)
|
||||
. += "<span class='notice'>The mech could use a mech <b>part</b>.</span>"
|
||||
examine_list += "<span class='notice'>The mech could use a mech <b>part</b>.</span>"
|
||||
if(/obj/item/stack/ore/bluespace_crystal)
|
||||
. += "<span class='notice'>The mech could use a <b>crystal</b> of sorts.</span>"
|
||||
examine_list += "<span class='notice'>The mech could use a <b>crystal</b> of sorts.</span>"
|
||||
if(/obj/item/assembly/signaler/anomaly)
|
||||
. += "<span class='notice'>The mech could use a <b>anomaly</b> of sorts.</span>"
|
||||
else
|
||||
return
|
||||
examine_list += "<span class='notice'>The mech could use a <b>anomaly</b> of sorts.</span>"
|
||||
|
||||
/datum/component/construction/mecha/spawn_result()
|
||||
if(!result)
|
||||
|
||||
@@ -46,4 +46,4 @@
|
||||
var/turf/T = loc
|
||||
if(!istype(T)) //you know this will happen somehow
|
||||
CRASH("Turf decal initialized in an object/nullspace")
|
||||
T.AddComponent(/datum/component/decal, icon, icon_state, dir, CLEAN_GOD, color, null, null, alpha)
|
||||
T.AddElement(/datum/element/decal, icon, icon_state, turn(dir, -dir2angle(T.dir)), CLEAN_GOD, color, null, null, alpha)
|
||||
|
||||
@@ -95,6 +95,56 @@
|
||||
icon_state = "warden_gaze"
|
||||
duration = 3
|
||||
|
||||
/obj/effect/temp_visual/ratvar/volt_hit
|
||||
name = "volt blast"
|
||||
layer = ABOVE_MOB_LAYER
|
||||
duration = 8
|
||||
icon_state = "volt_hit"
|
||||
light_range = 1.5
|
||||
light_power = 2
|
||||
light_color = LIGHT_COLOR_ORANGE
|
||||
var/mob/user
|
||||
var/damage = 20
|
||||
|
||||
/obj/effect/temp_visual/ratvar/volt_hit/Initialize(mapload, caster)
|
||||
. = ..()
|
||||
user = caster
|
||||
if(user)
|
||||
var/matrix/M = new
|
||||
M.Turn(Get_Angle(src, user))
|
||||
transform = M
|
||||
INVOKE_ASYNC(src, .proc/volthit)
|
||||
|
||||
/obj/effect/temp_visual/ratvar/volt_hit/proc/volthit()
|
||||
if(user)
|
||||
Beam(get_turf(user), "volt_ray", time=duration, maxdistance=8, beam_type=/obj/effect/ebeam/volt_ray)
|
||||
var/hit_amount = 0
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/mob/living/L in T)
|
||||
if(is_servant_of_ratvar(L))
|
||||
continue
|
||||
var/obj/item/I = L.anti_magic_check()
|
||||
if(I)
|
||||
L.visible_message("<span class='warning'>Strange energy flows into [L]'s [I.name]!</span>", \
|
||||
"<span class='userdanger'>Your [I.name] shields you from [src]!</span>")
|
||||
continue
|
||||
L.visible_message("<span class='warning'>[L] is struck by a [name]!</span>", "<span class='userdanger'>You're struck by a [name]!</span>")
|
||||
L.apply_damage(damage, BURN, "chest", L.run_armor_check("chest", "laser", "Your armor absorbs [src]!", "Your armor blocks part of [src]!", 0, "Your armor was penetrated by [src]!"))
|
||||
log_combat(user, L, "struck with a volt blast")
|
||||
hit_amount++
|
||||
for(var/obj/mecha/M in T)
|
||||
if(M.occupant)
|
||||
if(is_servant_of_ratvar(M.occupant))
|
||||
continue
|
||||
to_chat(M.occupant, "<span class='userdanger'>Your [M.name] is struck by a [name]!</span>")
|
||||
M.visible_message("<span class='warning'>[M] is struck by a [name]!</span>")
|
||||
M.take_damage(damage, BURN, 0, 0)
|
||||
hit_amount++
|
||||
if(hit_amount)
|
||||
playsound(src, 'sound/machines/defib_zap.ogg', damage*hit_amount, 1, -1)
|
||||
else
|
||||
playsound(src, "sparks", 50, 1)
|
||||
|
||||
/obj/effect/temp_visual/ratvar/ocular_warden/Initialize()
|
||||
. = ..()
|
||||
pixel_x = rand(-8, 8)
|
||||
|
||||
@@ -55,6 +55,15 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
/// How long, in deciseconds, this staggers for, if null it will autocalculate from w_class and force. Unlike total mass this supports 0 and negatives.
|
||||
var/stagger_force
|
||||
|
||||
/**
|
||||
* Set FALSE and then checked at the end of on mob/living/attackby(), set TRUE on living/pre_attacked_by().
|
||||
* Should it be FALSE by the end of the item/attack(), that means the item overrode the standard attack behaviour
|
||||
* and the user still needs the delay applied. We can't be using return values since that'll stop afterattack() from being triggered.
|
||||
*/
|
||||
var/attack_delay_done = FALSE
|
||||
///next_move click/attack delay of this item.
|
||||
var/click_delay = CLICK_CD_MELEE
|
||||
|
||||
var/slot_flags = 0 //This is used to determine on which slots an item can fit.
|
||||
pass_flags = PASSTABLE
|
||||
pressure_resistance = 4
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
to_chat(user, "<span class='notice'>You need to get closer!</span>")
|
||||
return
|
||||
if(use_paint(user) && isturf(F))
|
||||
F.AddComponent(/datum/component/decal, 'icons/turf/decals.dmi', stored_decal_total, stored_dir, CLEAN_STRONG, color, null, null, alpha)
|
||||
F.AddElement(/datum/element/decal, 'icons/turf/decals.dmi', stored_decal_total, turn(stored_dir, -dir2angle(F.dir)), CLEAN_STRONG, color, null, null, alpha)
|
||||
|
||||
/obj/item/airlock_painter/decal/attack_self(mob/user)
|
||||
if((ink) && (ink.charges >= 1))
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
. = ..()
|
||||
AddElement(/datum/element/update_icon_blocker)
|
||||
|
||||
/obj/item/gun/energy/chrono_gun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
|
||||
/obj/item/gun/energy/chrono_gun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
|
||||
if(field)
|
||||
field_disconnect(field)
|
||||
..()
|
||||
|
||||
@@ -293,6 +293,10 @@
|
||||
name = "Mining Shuttle (Computer Board)"
|
||||
build_path = /obj/machinery/computer/shuttle/mining
|
||||
|
||||
/obj/item/circuitboard/computer/snow_taxi
|
||||
name = "Snow Taxi (Computer Board)"
|
||||
build_path = /obj/machinery/computer/shuttle/snow_taxi
|
||||
|
||||
/obj/item/circuitboard/computer/white_ship
|
||||
name = "White Ship (Computer Board)"
|
||||
build_path = /obj/machinery/computer/shuttle/white_ship
|
||||
|
||||
@@ -292,6 +292,10 @@
|
||||
light_color = "#37FFF7"
|
||||
actions_types = list()
|
||||
|
||||
/obj/item/melee/transforming/energy/sword/cx/Initialize()
|
||||
icon_state_on = icon_state
|
||||
return ..()
|
||||
|
||||
/obj/item/melee/transforming/energy/sword/cx/ComponentInitialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/update_icon_updates_onmob)
|
||||
@@ -309,6 +313,7 @@
|
||||
if(!supress_message_text)
|
||||
to_chat(user, "<span class='notice'>[src] [active ? "is now active":"can now be concealed"].</span>")
|
||||
|
||||
|
||||
/obj/item/melee/transforming/energy/sword/cx/update_overlays()
|
||||
. = ..()
|
||||
var/mutable_appearance/blade_overlay = mutable_appearance(icon, "cxsword_blade")
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
|
||||
flags_1 = CONDUCT_1
|
||||
item_flags = NEEDS_PERMIT | NO_COMBAT_MODE_FORCE_MODIFIER //To avoid ambushing and oneshotting healthy crewmembers on force setting 3.
|
||||
attack_verb = list("whacked", "fisted", "power-punched")
|
||||
force = 20
|
||||
throwforce = 10
|
||||
@@ -13,7 +14,7 @@
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 40)
|
||||
resistance_flags = FIRE_PROOF
|
||||
var/click_delay = 1.5
|
||||
click_delay = CLICK_CD_MELEE * 1.5
|
||||
var/fisto_setting = 1
|
||||
var/gasperfist = 3
|
||||
var/obj/item/tank/internals/tank = null //Tank used for the gauntlet's piston-ram.
|
||||
@@ -70,42 +71,46 @@
|
||||
|
||||
|
||||
/obj/item/melee/powerfist/attack(mob/living/target, mob/living/user)
|
||||
if(!tank)
|
||||
to_chat(user, "<span class='warning'>\The [src] can't operate without a source of gas!</span>")
|
||||
return
|
||||
var/datum/gas_mixture/gasused = tank.air_contents.remove(gasperfist * fisto_setting)
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T)
|
||||
return
|
||||
T.assume_air(gasused)
|
||||
T.air_update_turf()
|
||||
if(!gasused)
|
||||
to_chat(user, "<span class='warning'>\The [src]'s tank is empty!</span>")
|
||||
target.apply_damage((force / 5), BRUTE)
|
||||
playsound(loc, 'sound/weapons/punch1.ogg', 50, 1)
|
||||
target.visible_message("<span class='danger'>[user]'s powerfist lets out a dull thunk as [user.p_they()] punch[user.p_es()] [target.name]!</span>", \
|
||||
"<span class='userdanger'>[user]'s punches you!</span>")
|
||||
return
|
||||
if(gasused.total_moles() < gasperfist * fisto_setting)
|
||||
to_chat(user, "<span class='warning'>\The [src]'s piston-ram lets out a weak hiss, it needs more gas!</span>")
|
||||
playsound(loc, 'sound/weapons/punch4.ogg', 50, 1)
|
||||
target.apply_damage((force / 2), BRUTE)
|
||||
target.visible_message("<span class='danger'>[user]'s powerfist lets out a weak hiss as [user.p_they()] punch[user.p_es()] [target.name]!</span>", \
|
||||
"<span class='userdanger'>[user]'s punch strikes with force!</span>")
|
||||
return
|
||||
target.apply_damage(force * fisto_setting, BRUTE)
|
||||
target.visible_message("<span class='danger'>[user]'s powerfist lets out a loud hiss as [user.p_they()] punch[user.p_es()] [target.name]!</span>", \
|
||||
"<span class='userdanger'>You cry out in pain as [user]'s punch flings you backwards!</span>")
|
||||
new /obj/effect/temp_visual/kinetic_blast(target.loc)
|
||||
playsound(loc, 'sound/weapons/resonator_blast.ogg', 50, 1)
|
||||
playsound(loc, 'sound/weapons/genhit2.ogg', 50, 1)
|
||||
if(HAS_TRAIT(user, TRAIT_PACIFISM))
|
||||
to_chat(user, "<span class='warning'>You don't want to harm other living beings!</span>")
|
||||
return FALSE
|
||||
if(!tank)
|
||||
to_chat(user, "<span class='warning'>\The [src] can't operate without a source of gas!</span>")
|
||||
return FALSE
|
||||
var/datum/gas_mixture/gasused = tank.air_contents.remove(gasperfist * fisto_setting)
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T)
|
||||
return FALSE
|
||||
var/totalitemdamage = target.pre_attacked_by(src, user)
|
||||
T.assume_air(gasused)
|
||||
T.air_update_turf()
|
||||
if(!gasused)
|
||||
to_chat(user, "<span class='warning'>\The [src]'s tank is empty!</span>")
|
||||
target.apply_damage((totalitemdamage / 5), BRUTE)
|
||||
playsound(loc, 'sound/weapons/punch1.ogg', 50, 1)
|
||||
target.visible_message("<span class='danger'>[user]'s powerfist lets out a dull thunk as [user.p_they()] punch[user.p_es()] [target.name]!</span>", \
|
||||
"<span class='userdanger'>[user]'s punches you!</span>")
|
||||
return
|
||||
if(gasused.total_moles() < gasperfist * fisto_setting)
|
||||
to_chat(user, "<span class='warning'>\The [src]'s piston-ram lets out a weak hiss, it needs more gas!</span>")
|
||||
playsound(loc, 'sound/weapons/punch4.ogg', 50, 1)
|
||||
target.apply_damage((totalitemdamage / 2), BRUTE)
|
||||
target.visible_message("<span class='danger'>[user]'s powerfist lets out a weak hiss as [user.p_they()] punch[user.p_es()] [target.name]!</span>", \
|
||||
"<span class='userdanger'>[user]'s punch strikes with force!</span>")
|
||||
return
|
||||
target.apply_damage(totalitemdamage * fisto_setting, BRUTE)
|
||||
target.visible_message("<span class='danger'>[user]'s powerfist lets out a loud hiss as [user.p_they()] punch[user.p_es()] [target.name]!</span>", \
|
||||
"<span class='userdanger'>You cry out in pain as [user]'s punch flings you backwards!</span>")
|
||||
new /obj/effect/temp_visual/kinetic_blast(target.loc)
|
||||
playsound(loc, 'sound/weapons/resonator_blast.ogg', 50, 1)
|
||||
playsound(loc, 'sound/weapons/genhit2.ogg', 50, 1)
|
||||
|
||||
var/atom/throw_target = get_edge_target_turf(target, get_dir(src, get_step_away(target, src)))
|
||||
var/atom/throw_target = get_edge_target_turf(target, get_dir(src, get_step_away(target, src)))
|
||||
target.throw_at(throw_target, 5 * fisto_setting, 0.5 + (fisto_setting / 2))
|
||||
|
||||
target.throw_at(throw_target, 5 * fisto_setting, 0.5 + (fisto_setting / 2))
|
||||
log_combat(user, target, "power fisted", src)
|
||||
|
||||
log_combat(user, target, "power fisted", src)
|
||||
|
||||
user.changeNext_move(CLICK_CD_MELEE * click_delay)
|
||||
|
||||
return
|
||||
var/weight = getweight(user, STAM_COST_ATTACK_MOB_MULT)
|
||||
if(weight)
|
||||
user.adjustStaminaLossBuffered(weight)
|
||||
return TRUE
|
||||
|
||||
@@ -382,14 +382,14 @@
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon_state = "bag"
|
||||
desc = "A bag for storing pills, patches, and bottles."
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
slot_flags = ITEM_SLOT_BELT|ITEM_SLOT_POCKET
|
||||
resistance_flags = FLAMMABLE
|
||||
|
||||
/obj/item/storage/bag/chemistry/ComponentInitialize()
|
||||
. = ..()
|
||||
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
|
||||
STR.max_combined_w_class = 200
|
||||
STR.max_items = 50
|
||||
STR.storage_flags = STORAGE_FLAGS_VOLUME_DEFAULT
|
||||
STR.max_volume = STORAGE_VOLUME_CHEMISTRY_BAG
|
||||
STR.insert_preposition = "in"
|
||||
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/pill, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/syringe/dart))
|
||||
|
||||
@@ -402,7 +402,7 @@
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon_state = "biobag"
|
||||
desc = "A bag for the safe transportation and disposal of biowaste and other biological materials."
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
slot_flags = ITEM_SLOT_BELT|ITEM_SLOT_POCKET
|
||||
resistance_flags = FLAMMABLE
|
||||
|
||||
/obj/item/storage/bag/bio/ComponentInitialize()
|
||||
|
||||
@@ -224,7 +224,7 @@
|
||||
. = ..()
|
||||
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
|
||||
STR.storage_flags = STORAGE_FLAGS_VOLUME_DEFAULT
|
||||
STR.max_volume = 14
|
||||
STR.max_volume = STORAGE_VOLUME_PILL_BOTTLE
|
||||
STR.allow_quick_gather = TRUE
|
||||
STR.click_gather = TRUE
|
||||
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/pill, /obj/item/dice))
|
||||
|
||||
@@ -174,7 +174,7 @@
|
||||
name = "\improper X-01 Multiphase energy gun box"
|
||||
desc = "A storage case for a high-tech energy firearm."
|
||||
|
||||
/obj/item/storage/secure/briefcase/mws_pack_hos/PopulateContents()
|
||||
/obj/item/storage/secure/briefcase/hos/multiphase_box/PopulateContents()
|
||||
new /obj/item/gun/energy/e_gun/hos(src)
|
||||
|
||||
// -----------------------------
|
||||
@@ -212,4 +212,4 @@
|
||||
return attack_self(user)
|
||||
|
||||
/obj/item/storage/secure/safe/HoS
|
||||
name = "head of security's safe"
|
||||
name = "head of security's safe"
|
||||
|
||||
@@ -141,7 +141,7 @@
|
||||
/obj/item/melee/baton/attack(mob/M, mob/living/carbon/human/user)
|
||||
var/interrupt = common_baton_melee(M, user, FALSE)
|
||||
if(!interrupt)
|
||||
..()
|
||||
return ..()
|
||||
|
||||
/obj/item/melee/baton/alt_pre_attack(atom/A, mob/living/user, params)
|
||||
. = common_baton_melee(A, user, TRUE) //return true (attackchain interrupt) if this also returns true. no harm-disarming.
|
||||
@@ -154,7 +154,7 @@
|
||||
if(turned_on && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
|
||||
clowning_around(user)
|
||||
if(IS_STAMCRIT(user)) //CIT CHANGE - makes it impossible to baton in stamina softcrit
|
||||
to_chat(user, "<span class='danger'>You're too exhausted for that.</span>")
|
||||
to_chat(user, "<span class='danger'>You're too exhausted to use [src] properly.</span>")
|
||||
return TRUE
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/L = M
|
||||
|
||||
@@ -835,11 +835,11 @@
|
||||
|
||||
/obj/item/toy/cards/deck/update_icon_state()
|
||||
switch(cards.len)
|
||||
if(INFINITY to original_size/2)
|
||||
if(original_size*0.5 to INFINITY)
|
||||
icon_state = "deck_[deckstyle]_full"
|
||||
if(original_size/2 to original_size/4)
|
||||
if(original_size*0.25 to original_size*0.5)
|
||||
icon_state = "deck_[deckstyle]_half"
|
||||
if(original_size/4 to 1)
|
||||
if(1 to original_size*0.25)
|
||||
icon_state = "deck_[deckstyle]_low"
|
||||
else
|
||||
icon_state = "deck_[deckstyle]_empty"
|
||||
|
||||
@@ -625,7 +625,7 @@
|
||||
force_wielded = 18
|
||||
throwforce = 20
|
||||
throw_speed = 4
|
||||
embedding = list("embedded_impact_pain_multiplier" = 3, "embed_chance" = 90)
|
||||
embedding = list("embedded_impact_pain_multiplier" = 1.5, "embed_chance" = 65)
|
||||
armour_penetration = 10
|
||||
custom_materials = list(/datum/material/iron=1150, /datum/material/glass=2075)
|
||||
hitsound = 'sound/weapons/bladeslice.ogg'
|
||||
@@ -710,6 +710,7 @@
|
||||
force_wielded = 19
|
||||
force_unwielded = 11
|
||||
throwforce = 21
|
||||
embedding = getEmbeddingBehavior(embed_chance = 75, embedded_pain_multiplier = 1.5) //plasmaglass spears are sharper
|
||||
icon_prefix = "spearplasma"
|
||||
qdel(tip)
|
||||
var/obj/item/twohanded/spear/S = locate() in parts_list
|
||||
@@ -724,6 +725,7 @@
|
||||
if(G)
|
||||
explosive = G
|
||||
name = "explosive lance"
|
||||
embedding = getEmbeddingBehavior(embed_chance = 0, embedded_pain_multiplier = 1)//elances should not be embeddable
|
||||
desc = "A makeshift spear with [G] attached to it."
|
||||
update_icon()
|
||||
|
||||
@@ -1249,14 +1251,13 @@
|
||||
|
||||
/obj/item/twohanded/electrostaff/attack(mob/living/target, mob/living/user)
|
||||
if(IS_STAMCRIT(user))//CIT CHANGE - makes it impossible to baton in stamina softcrit
|
||||
to_chat(user, "<span class='danger'>You're too exhausted for that.</span>")//CIT CHANGE - ditto
|
||||
to_chat(user, "<span class='danger'>You're too exhausted to use [src] properly.</span>")//CIT CHANGE - ditto
|
||||
return //CIT CHANGE - ditto
|
||||
if(on && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
|
||||
clowning_around(user) //ouch!
|
||||
return
|
||||
if(iscyborg(target))
|
||||
..()
|
||||
return
|
||||
return ..()
|
||||
if(target.mob_run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user, null, null) & BLOCK_SUCCESS) //No message; run_block() handles that
|
||||
playsound(target, 'sound/weapons/genhit.ogg', 50, 1)
|
||||
return FALSE
|
||||
|
||||
@@ -41,7 +41,7 @@ LINEN BINS
|
||||
return
|
||||
|
||||
/obj/item/bedsheet/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/wirecutters) || I.get_sharpness())
|
||||
if(!(flags_1 & HOLOGRAM_1) && (istype(I, /obj/item/wirecutters) || I.get_sharpness()))
|
||||
var/obj/item/stack/sheet/cloth/C = new (get_turf(src), 3)
|
||||
transfer_fingerprints_to(C)
|
||||
C.add_fingerprint(user)
|
||||
@@ -369,4 +369,4 @@ LINEN BINS
|
||||
/obj/structure/bedsheetbin/color
|
||||
sheet_types = list(/obj/item/bedsheet, /obj/item/bedsheet/blue, /obj/item/bedsheet/green, /obj/item/bedsheet/orange, \
|
||||
/obj/item/bedsheet/purple, /obj/item/bedsheet/red, /obj/item/bedsheet/yellow, /obj/item/bedsheet/brown, \
|
||||
/obj/item/bedsheet/black)
|
||||
/obj/item/bedsheet/black)
|
||||
|
||||
@@ -185,3 +185,16 @@
|
||||
desc = "A wall made out of a strange metal. The squares on it pulse in a predictable pattern."
|
||||
icon = 'icons/turf/walls/hierophant_wall.dmi'
|
||||
icon_state = "wall"
|
||||
|
||||
/turf/closed/indestructible/rock/glacierrock
|
||||
name = "unaturally hard ice wall"
|
||||
desc = "Ice, hardened over thousands of years, you're not breaking through this."
|
||||
icon = 'icons/turf/walls.dmi'
|
||||
icon_state = "snow_rock"
|
||||
|
||||
/turf/closed/indestructible/rock/glacierrock/blue
|
||||
name = "blue ice wall"
|
||||
desc = "The incredible compressive forces that formed this sturdy ice wall gave it a blue color."
|
||||
icon = 'icons/turf/walls.dmi'
|
||||
icon_state = "ice"
|
||||
canSmoothWith = list(/turf/closed/indestructible/rock/glacierrock/blue)
|
||||
|
||||
@@ -146,95 +146,3 @@
|
||||
|
||||
/turf/open/floor/plasteel/sepia
|
||||
icon_state = "sepia"
|
||||
|
||||
///////////////////////////////
|
||||
// Pre-Applied Decal Floors //
|
||||
//////////////////////////////
|
||||
|
||||
// Neutral
|
||||
/turf/open/floor/plasteel/neutral
|
||||
icon_state = "neutral_full"
|
||||
/turf/open/floor/plasteel/neutral/side
|
||||
icon_state = "neutral"
|
||||
/turf/open/floor/plasteel/neutral/corner
|
||||
icon_state = "neutral_corner"
|
||||
|
||||
// Dark Neutral
|
||||
/turf/open/floor/plasteel/dark/neutral
|
||||
icon_state = "dark_neutral_full"
|
||||
/turf/open/floor/plasteel/dark/neutral/checker
|
||||
icon_state = "dark_neutral_checker"
|
||||
/turf/open/floor/plasteel/dark/neutral/side
|
||||
icon_state = "dark_neutral"
|
||||
/turf/open/floor/plasteel/dark/neutral/corner
|
||||
icon_state = "dark_neutral_corner"
|
||||
|
||||
// Dark Security
|
||||
/turf/open/floor/plasteel/dark/security
|
||||
icon_state = "dark_red_full"
|
||||
/turf/open/floor/plasteel/dark/security/checker
|
||||
icon_state = "dark_red_checker"
|
||||
/turf/open/floor/plasteel/dark/security/side
|
||||
icon_state = "dark_red"
|
||||
/turf/open/floor/plasteel/dark/security/corner
|
||||
icon_state = "dark_red_corner"
|
||||
|
||||
// Engineering
|
||||
/turf/open/floor/plasteel/engineering
|
||||
icon_state = "engineering_full"
|
||||
/turf/open/floor/plasteel/engineering/side
|
||||
icon_state = "engineering"
|
||||
/turf/open/floor/plasteel/engineering/corner
|
||||
icon_state = "engineering_corner"
|
||||
|
||||
// Atmospherics
|
||||
/turf/open/floor/plasteel/atmospherics
|
||||
icon_state = "atmospherics_full"
|
||||
/turf/open/floor/plasteel/atmospherics/side
|
||||
icon_state = "atmospherics"
|
||||
/turf/open/floor/plasteel/atmospherics/corner
|
||||
icon_state = "atmospherics_corner"
|
||||
|
||||
// Command
|
||||
/turf/open/floor/plasteel/command
|
||||
icon_state = "command_full"
|
||||
/turf/open/floor/plasteel/command/side
|
||||
icon_state = "command"
|
||||
/turf/open/floor/plasteel/command/corner
|
||||
icon_state = "command_corner"
|
||||
|
||||
// Medical
|
||||
/turf/open/floor/plasteel/medical
|
||||
icon_state = "medical_full"
|
||||
/turf/open/floor/plasteel/medical/alt
|
||||
icon_state = "medical_alt"
|
||||
/turf/open/floor/plasteel/medical/side
|
||||
icon_state = "medical"
|
||||
/turf/open/floor/plasteel/medical/corner
|
||||
icon_state = "medical_corner"
|
||||
|
||||
// Security
|
||||
/turf/open/floor/plasteel/security
|
||||
icon_state = "security_full"
|
||||
/turf/open/floor/plasteel/security/side
|
||||
icon_state = "security"
|
||||
/turf/open/floor/plasteel/security/corner
|
||||
icon_state = "security_corner"
|
||||
|
||||
// Cargo
|
||||
/turf/open/floor/plasteel/cargo
|
||||
icon_state = "cargo_full"
|
||||
/turf/open/floor/plasteel/cargo/side
|
||||
icon_state = "cargo"
|
||||
/turf/open/floor/plasteel/cargo/corner
|
||||
icon_state = "cargo_corner"
|
||||
|
||||
// Misc
|
||||
/turf/open/floor/plasteel/showroomfloor/shower
|
||||
icon_state = "shower"
|
||||
/turf/open/floor/plasteel/goonplaque/alien
|
||||
icon_state = "plaque1"
|
||||
desc = "\"This is a plaque is a collaboration of iconography celebrating the peaceful collaboration between the people of Earth and distant alien species."
|
||||
/turf/open/floor/plasteel/goonplaque/charter
|
||||
icon_state = "plaque2"
|
||||
desc = "\"A golden plaque. Etched into it is the introductory article for a cross-species interplanetary constitution, guaranteeing equal rights between species that Nanotrasen relunctantly agreed to."
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#define VV_HTML_ENCODE(thing) ( sanitize ? html_encode(thing) : thing )
|
||||
/// Get displayed variable in VV variable list
|
||||
/proc/debug_variable(name, value, level, datum/D, sanitize = TRUE) //if D is a list, name will be index, and value will be assoc value.
|
||||
var/header
|
||||
if(D)
|
||||
@@ -35,6 +36,19 @@
|
||||
else if (isfile(value))
|
||||
item = "[VV_HTML_ENCODE(name)] = <span class='value'>'[value]'</span>"
|
||||
|
||||
else if(istype(value, /matrix)) // Needs to be before datum
|
||||
var/matrix/M = value
|
||||
item = {"[VV_HTML_ENCODE(name)] = <span class='value'>
|
||||
<table class='matrixbrak'><tbody><tr>
|
||||
<td class='lbrak'> </td>
|
||||
<td><table class='matrix'><tbody>
|
||||
<tr><td>[M.a]</td><td>[M.d]</td><td>0</td></tr>
|
||||
<tr><td>[M.b]</td><td>[M.e]</td><td>0</td></tr>
|
||||
<tr><td>[M.c]</td><td>[M.f]</td><td>1</td></tr>
|
||||
</tbody></table></td>
|
||||
<td class='rbrak'> </td>
|
||||
</tr></tbody></table></span>"} //TODO link to modify_transform wrapper for all matrices
|
||||
|
||||
else if (istype(value, /datum))
|
||||
var/datum/DV = value
|
||||
if ("[DV]" != "[DV.type]") //if the thing as a name var, lets use it.
|
||||
|
||||
@@ -96,16 +96,7 @@
|
||||
<head>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
|
||||
<title>[title]</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Verdana, sans-serif;
|
||||
font-size: 9pt;
|
||||
}
|
||||
.value {
|
||||
font-family: "Courier New", monospace;
|
||||
font-size: 8pt;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" type="text/css" href="view_variables.css">
|
||||
</head>
|
||||
<body onload='selectTextField()' onkeydown='return handle_keydown()' onkeyup='handle_keyup()'>
|
||||
<script type="text/javascript">
|
||||
|
||||
@@ -135,6 +135,29 @@
|
||||
|
||||
return TRUE
|
||||
|
||||
//For the Volt Void scripture, fires a ray of energy at a target location
|
||||
/obj/effect/proc_holder/slab/volt
|
||||
ranged_mousepointer = 'icons/effects/volt_target.dmi'
|
||||
|
||||
/obj/effect/proc_holder/slab/volt/InterceptClickOn(mob/living/caller, params, atom/target)
|
||||
if(target == slab || ..()) //we can't cancel
|
||||
return TRUE
|
||||
|
||||
var/turf/T = ranged_ability_user.loc
|
||||
if(!isturf(T))
|
||||
return TRUE
|
||||
|
||||
if(target in view(7, get_turf(ranged_ability_user)))
|
||||
successful = TRUE
|
||||
ranged_ability_user.visible_message("<span class='warning'>[ranged_ability_user] fires a ray of energy at [target]!</span>", "<span class='nzcrentr'>You fire a volt ray at [target].</span>")
|
||||
playsound(ranged_ability_user, 'sound/effects/light_flicker.ogg', 50, 1)
|
||||
T = get_turf(target)
|
||||
new/obj/effect/temp_visual/ratvar/volt_hit(T, ranged_ability_user)
|
||||
log_combat(ranged_ability_user, T, "fired a volt ray")
|
||||
remove_ranged_ability()
|
||||
|
||||
return TRUE
|
||||
|
||||
//For the Kindle scripture; stuns and mutes a target non-servant.
|
||||
/obj/effect/proc_holder/slab/kindle
|
||||
ranged_mousepointer = 'icons/effects/volt_target.dmi'
|
||||
|
||||
@@ -263,3 +263,160 @@
|
||||
duration = max(duration, 100)
|
||||
return slab.procure_gateway(invoker, duration, portal_uses)
|
||||
|
||||
|
||||
//Mending Mantra: Channeled for up to ten times over twenty seconds to repair structures and heal allies
|
||||
/datum/clockwork_scripture/channeled/mending_mantra
|
||||
descname = "Channeled, Area Healing and Repair"
|
||||
name = "Mending Mantra"
|
||||
desc = "Repairs nearby structures and constructs. Servants wearing clockwork armor will also be healed. Channeled every two seconds for a maximum of twenty seconds."
|
||||
chant_invocations = list("Mend our dents!", "Heal our scratches!", "Repair our gears!")
|
||||
chant_amount = 10
|
||||
chant_interval = 20
|
||||
power_cost = 400
|
||||
usage_tip = "This is a very effective way to rapidly reinforce a base after an attack."
|
||||
tier = SCRIPTURE_SCRIPT
|
||||
primary_component = VANGUARD_COGWHEEL
|
||||
sort_priority = 7
|
||||
quickbind = TRUE
|
||||
quickbind_desc = "Repairs nearby structures and constructs. Servants wearing clockwork armor will also be healed.<br><b>Maximum 10 chants.</b>"
|
||||
var/heal_attempts = 4
|
||||
var/heal_amount = 2.5
|
||||
var/static/list/damage_heal_order = list(BRUTE, BURN, OXY)
|
||||
var/static/list/heal_finish_messages = list("There, all mended!", "Try not to get too damaged.", "No more dents and scratches for you!", "Champions never die.", "All patched up.", \
|
||||
"Ah, child, it's okay now.", "Pain is temporary.", "What you do for the Justiciar is eternal.", "Bear this for me.", "Be strong, child.", "Please, be careful!", \
|
||||
"If you die, you will be remembered.")
|
||||
var/static/list/heal_target_typecache = typecacheof(list(
|
||||
/obj/structure/destructible/clockwork,
|
||||
/obj/machinery/door/airlock/clockwork,
|
||||
/obj/machinery/door/window/clockwork,
|
||||
/obj/structure/window/reinforced/clockwork,
|
||||
/obj/structure/table/reinforced/brass))
|
||||
var/static/list/ratvarian_armor_typecache = typecacheof(list(
|
||||
/obj/item/clothing/suit/armor/clockwork,
|
||||
/obj/item/clothing/head/helmet/clockwork,
|
||||
/obj/item/clothing/gloves/clockwork,
|
||||
/obj/item/clothing/shoes/clockwork))
|
||||
|
||||
/datum/clockwork_scripture/channeled/mending_mantra/chant_effects(chant_number)
|
||||
var/turf/T
|
||||
for(var/atom/movable/M in range(7, invoker))
|
||||
if(isliving(M))
|
||||
if(isclockmob(M) || istype(M, /mob/living/simple_animal/drone/cogscarab))
|
||||
var/mob/living/simple_animal/S = M
|
||||
if(S.health == S.maxHealth || S.stat == DEAD)
|
||||
continue
|
||||
T = get_turf(M)
|
||||
for(var/i in 1 to heal_attempts)
|
||||
if(S.health < S.maxHealth)
|
||||
S.adjustHealth(-heal_amount)
|
||||
new /obj/effect/temp_visual/heal(T, "#1E8CE1")
|
||||
if(i == heal_attempts && S.health >= S.maxHealth) //we finished healing on the last tick, give them the message
|
||||
to_chat(S, "<span class='inathneq'>\"[text2ratvar(pick(heal_finish_messages))]\"</span>")
|
||||
break
|
||||
else
|
||||
to_chat(S, "<span class='inathneq'>\"[text2ratvar(pick(heal_finish_messages))]\"</span>")
|
||||
break
|
||||
else if(issilicon(M))
|
||||
var/mob/living/silicon/S = M
|
||||
if(S.health == S.maxHealth || S.stat == DEAD || !is_servant_of_ratvar(S))
|
||||
continue
|
||||
T = get_turf(M)
|
||||
for(var/i in 1 to heal_attempts)
|
||||
if(S.health < S.maxHealth)
|
||||
S.heal_ordered_damage(heal_amount, damage_heal_order)
|
||||
new /obj/effect/temp_visual/heal(T, "#1E8CE1")
|
||||
if(i == heal_attempts && S.health >= S.maxHealth)
|
||||
to_chat(S, "<span class='inathneq'>\"[text2ratvar(pick(heal_finish_messages))]\"</span>")
|
||||
break
|
||||
else
|
||||
to_chat(S, "<span class='inathneq'>\"[text2ratvar(pick(heal_finish_messages))]\"</span>")
|
||||
break
|
||||
else if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.health == H.maxHealth || H.stat == DEAD || !is_servant_of_ratvar(H))
|
||||
continue
|
||||
T = get_turf(M)
|
||||
var/heal_ticks = 0 //one heal tick for each piece of ratvarian armor worn
|
||||
var/obj/item/I = H.get_item_by_slot(SLOT_WEAR_SUIT)
|
||||
if(is_type_in_typecache(I, ratvarian_armor_typecache))
|
||||
heal_ticks++
|
||||
I = H.get_item_by_slot(SLOT_HEAD)
|
||||
if(is_type_in_typecache(I, ratvarian_armor_typecache))
|
||||
heal_ticks++
|
||||
I = H.get_item_by_slot(SLOT_GLOVES)
|
||||
if(is_type_in_typecache(I, ratvarian_armor_typecache))
|
||||
heal_ticks++
|
||||
I = H.get_item_by_slot(SLOT_SHOES)
|
||||
if(is_type_in_typecache(I, ratvarian_armor_typecache))
|
||||
heal_ticks++
|
||||
if(heal_ticks)
|
||||
for(var/i in 1 to heal_ticks)
|
||||
if(H.health < H.maxHealth)
|
||||
H.heal_ordered_damage(heal_amount, damage_heal_order)
|
||||
new /obj/effect/temp_visual/heal(T, "#1E8CE1")
|
||||
if(i == heal_ticks && H.health >= H.maxHealth)
|
||||
to_chat(H, "<span class='inathneq'>\"[text2ratvar(pick(heal_finish_messages))]\"</span>")
|
||||
break
|
||||
else
|
||||
to_chat(H, "<span class='inathneq'>\"[text2ratvar(pick(heal_finish_messages))]\"</span>")
|
||||
break
|
||||
else if(is_type_in_typecache(M, heal_target_typecache))
|
||||
var/obj/structure/destructible/clockwork/C = M
|
||||
if(C.obj_integrity == C.max_integrity || (istype(C) && !C.can_be_repaired))
|
||||
continue
|
||||
T = get_turf(M)
|
||||
for(var/i in 1 to heal_attempts)
|
||||
if(C.obj_integrity < C.max_integrity)
|
||||
C.obj_integrity = min(C.obj_integrity + 5, C.max_integrity)
|
||||
C.update_icon()
|
||||
new /obj/effect/temp_visual/heal(T, "#1E8CE1")
|
||||
else
|
||||
break
|
||||
new /obj/effect/temp_visual/ratvar/mending_mantra(get_turf(invoker))
|
||||
return TRUE
|
||||
|
||||
//Volt Blaster: Channeled for up to five times over ten seconds to fire up to five rays of energy at target locations.
|
||||
/datum/clockwork_scripture/channeled/volt_blaster
|
||||
descname = "Channeled, Targeted Energy Blasts"
|
||||
name = "Volt Blaster"
|
||||
desc = "Allows you to fire five energy rays at target locations. Channeled every fourth of a second for a maximum of ten seconds."
|
||||
channel_time = 30
|
||||
invocations = list("Amperage...", "...grant me your power!")
|
||||
chant_invocations = list("Use charge to kill!", "Slay with power!", "Hunt with energy!")
|
||||
chant_amount = 5
|
||||
chant_interval = 4
|
||||
power_cost = 500
|
||||
usage_tip = "Though it requires you to stand still, this scripture can do massive damage."
|
||||
tier = SCRIPTURE_SCRIPT
|
||||
primary_component = HIEROPHANT_ANSIBLE
|
||||
sort_priority = 10
|
||||
quickbind = TRUE
|
||||
quickbind_desc = "Allows you to fire energy rays at target locations.<br><b>Maximum 5 chants.</b>"
|
||||
var/static/list/nzcrentr_insults = list("You're not very good at aiming.", "You hunt badly.", "What a waste of energy.", "Almost funny to watch.",
|
||||
"Boss says </span><span class='heavy_brass'>\"Click something, you idiot!\"</span><span class='nzcrentr'>.", "Stop wasting power if you can't aim.")
|
||||
|
||||
/datum/clockwork_scripture/channeled/volt_blaster/chant_effects(chant_number)
|
||||
slab.busy = null
|
||||
var/datum/clockwork_scripture/ranged_ability/volt_ray/ray = new
|
||||
ray.slab = slab
|
||||
ray.invoker = invoker
|
||||
var/turf/T = get_turf(invoker)
|
||||
if(!ray.run_scripture() && slab && invoker)
|
||||
if(can_recite() && T == get_turf(invoker))
|
||||
to_chat(invoker, "<span class='nzcrentr'>\"[text2ratvar(pick(nzcrentr_insults))]\"</span>")
|
||||
else
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/effect/ebeam/volt_ray
|
||||
name = "volt_ray"
|
||||
layer = LYING_MOB_LAYER
|
||||
|
||||
/datum/clockwork_scripture/ranged_ability/volt_ray
|
||||
name = "Volt Ray"
|
||||
slab_overlay = "volt"
|
||||
allow_mobility = FALSE
|
||||
ranged_type = /obj/effect/proc_holder/slab/volt
|
||||
ranged_message = "<span class='nzcrentr_small'><i>You charge the clockwork slab with shocking might.</i>\n\
|
||||
<b>Left-click a target to fire, quickly!</b></span>"
|
||||
timeout_time = 20
|
||||
|
||||
@@ -343,7 +343,7 @@
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
icon_state = "disintegrate"
|
||||
item_state = null
|
||||
item_flags = NEEDS_PERMIT | ABSTRACT | DROPDEL | NO_ATTACK_CHAIN_SOFT_STAMCRIT
|
||||
item_flags = NEEDS_PERMIT | ABSTRACT | DROPDEL
|
||||
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
throwforce = 0
|
||||
|
||||
@@ -116,24 +116,11 @@
|
||||
/mob/living/carbon/true_devil/get_ear_protection()
|
||||
return 2
|
||||
|
||||
|
||||
/mob/living/carbon/true_devil/attacked_by(obj/item/I, mob/living/user, def_zone, attackchain_flags = NONE, damage_multiplier = 1)
|
||||
var/weakness = check_weakness(I, user)
|
||||
apply_damage(I.force * weakness * damage_multiplier, I.damtype, def_zone)
|
||||
var/message_verb = ""
|
||||
if(I.attack_verb && I.attack_verb.len)
|
||||
message_verb = "[pick(I.attack_verb)]"
|
||||
else if(I.force)
|
||||
message_verb = "attacked"
|
||||
|
||||
var/attack_message = "[src] has been [message_verb] with [I]."
|
||||
if(user)
|
||||
user.do_attack_animation(src)
|
||||
if(user in viewers(src, null))
|
||||
attack_message = "[user] has [message_verb] [src] with [I]!"
|
||||
if(message_verb)
|
||||
visible_message("<span class='danger'>[attack_message]</span>",
|
||||
"<span class='userdanger'>[attack_message]</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
var/totitemdamage = pre_attacked_by(I, user)
|
||||
totitemdamage *= check_weakness(I, user)
|
||||
apply_damage(totitemdamage, I.damtype, def_zone)
|
||||
send_item_attack_message(I, user, null, totitemdamage)
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/true_devil/singularity_act()
|
||||
|
||||
@@ -66,6 +66,16 @@
|
||||
crate_name = "shaft miner starter kit"
|
||||
crate_type = /obj/structure/closet/crate/secure
|
||||
|
||||
/datum/supply_pack/service/snowmobile
|
||||
name = "Snowmobile kit"
|
||||
desc = "trapped on a frigid wasteland? need to get around fast? purchase a refurbished snowmobile, with a FREE 10 microsecond warranty!"
|
||||
cost = 1500 // 1000 points cheaper than ATV
|
||||
contains = list(/obj/vehicle/ridden/atv/snowmobile = 1,
|
||||
/obj/item/key = 1,
|
||||
/obj/item/clothing/mask/gas/explorer = 1)
|
||||
crate_name = "Snowmobile kit"
|
||||
crate_type = /obj/structure/closet/crate/large
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////// Chef, Botanist, Bartender ////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -743,4 +743,9 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
"dna_discovered.gif" = 'html/dna_discovered.gif',
|
||||
"dna_undiscovered.gif" = 'html/dna_undiscovered.gif',
|
||||
"dna_extra.gif" = 'html/dna_extra.gif'
|
||||
)
|
||||
)
|
||||
|
||||
/datum/asset/simple/vv
|
||||
assets = list(
|
||||
"view_variables.css" = 'html/admin/view_variables.css'
|
||||
)
|
||||
|
||||
@@ -2572,8 +2572,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
current_tab = text2num(href_list["tab"])
|
||||
if(href_list["preference"] == "gear")
|
||||
if(href_list["clear_loadout"])
|
||||
LAZYCLEARLIST(chosen_gear)
|
||||
gear_points = initial(gear_points)
|
||||
chosen_gear = list()
|
||||
gear_points = CONFIG_GET(number/initial_gear_points)
|
||||
save_preferences()
|
||||
if(href_list["select_category"])
|
||||
for(var/i in GLOB.loadout_items)
|
||||
@@ -2585,7 +2585,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
return
|
||||
var/toggle = text2num(href_list["toggle_gear"])
|
||||
if(!toggle && (G.type in chosen_gear))//toggling off and the item effectively is in chosen gear)
|
||||
LAZYREMOVE(chosen_gear, G.type)
|
||||
chosen_gear -= G.type
|
||||
gear_points += initial(G.cost)
|
||||
else if(toggle && (!(is_type_in_ref_list(G, chosen_gear))))
|
||||
if(!is_loadout_slot_available(G.category))
|
||||
@@ -2595,7 +2595,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
to_chat(user, "<span class='danger'>This is an item intended for donator use only. You are not authorized to use this item.</span>")
|
||||
return
|
||||
if(gear_points >= initial(G.cost))
|
||||
LAZYADD(chosen_gear, G.type)
|
||||
chosen_gear += G.type
|
||||
gear_points -= initial(G.cost)
|
||||
|
||||
ShowChoices(user)
|
||||
|
||||
@@ -434,3 +434,4 @@
|
||||
desc = "A symbol of discipline, honor, and lots and lots of removal of some type of skewered food."
|
||||
icon_state = "russobluecamohat"
|
||||
item_state = "russobluecamohat"
|
||||
dynamic_hair_suffix = ""
|
||||
|
||||
@@ -40,9 +40,6 @@
|
||||
return ..()
|
||||
return ..()
|
||||
|
||||
/obj/item/holo/esword/attack(target as mob, mob/user as mob)
|
||||
..()
|
||||
|
||||
/obj/item/holo/esword/Initialize()
|
||||
. = ..()
|
||||
saber_color = pick("red","blue","green","purple")
|
||||
|
||||
@@ -205,6 +205,11 @@
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/biogenerator/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
if(istype(user) && user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
detach(user)
|
||||
|
||||
/obj/machinery/biogenerator/proc/activate()
|
||||
if (usr.stat != CONSCIOUS)
|
||||
return
|
||||
@@ -293,9 +298,9 @@
|
||||
update_icon()
|
||||
return .
|
||||
|
||||
/obj/machinery/biogenerator/proc/detach()
|
||||
/obj/machinery/biogenerator/proc/detach(mob/living/user)
|
||||
if(beaker)
|
||||
beaker.forceMove(drop_location())
|
||||
user.put_in_hands(beaker)
|
||||
beaker = null
|
||||
update_icon()
|
||||
|
||||
@@ -310,7 +315,7 @@
|
||||
updateUsrDialog()
|
||||
|
||||
else if(href_list["detach"])
|
||||
detach()
|
||||
detach(usr)
|
||||
updateUsrDialog()
|
||||
|
||||
else if(href_list["create"])
|
||||
|
||||
@@ -189,6 +189,26 @@
|
||||
name = "Coffee House"
|
||||
icon_state = "hair_coffeehouse"
|
||||
|
||||
/datum/sprite_accessory/hair/cornrows1
|
||||
name = "Cornrows"
|
||||
icon_state = "hair_cornrows"
|
||||
|
||||
/datum/sprite_accessory/hair/cornrows2
|
||||
name = "Cornrows 2"
|
||||
icon_state = "hair_cornrows2"
|
||||
|
||||
/datum/sprite_accessory/hair/cornrowbun
|
||||
name = "Cornrow Bun"
|
||||
icon_state = "hair_cornrowbun"
|
||||
|
||||
/datum/sprite_accessory/hair/cornrowbraid
|
||||
name = "Cornrow Braid"
|
||||
icon_state = "hair_cornrowbraid"
|
||||
|
||||
/datum/sprite_accessory/hair/cornrowdualtail
|
||||
name = "Cornrow Tail"
|
||||
icon_state = "hair_cornrowtail"
|
||||
|
||||
/datum/sprite_accessory/hair/country
|
||||
name = "Country"
|
||||
icon_state = "hair_country"
|
||||
|
||||
@@ -280,25 +280,15 @@
|
||||
. = ..()
|
||||
C.faction |= "plants"
|
||||
C.faction |= "vines"
|
||||
C.AddElement(/datum/element/photosynthesis)
|
||||
|
||||
/datum/species/golem/wood/on_species_loss(mob/living/carbon/C)
|
||||
. = ..()
|
||||
C.faction -= "plants"
|
||||
C.faction -= "vines"
|
||||
C.RemoveElement(/datum/element/photosynthesis)
|
||||
|
||||
/datum/species/golem/wood/spec_life(mob/living/carbon/human/H)
|
||||
if(H.stat == DEAD)
|
||||
return
|
||||
var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing
|
||||
if(isturf(H.loc)) //else, there's considered to be no light
|
||||
var/turf/T = H.loc
|
||||
light_amount = min(1,T.get_lumcount()) - 0.5
|
||||
H.adjust_nutrition(light_amount * 4, NUTRITION_LEVEL_FULL)
|
||||
if(light_amount > 0.2) //if there's enough light, heal
|
||||
H.heal_overall_damage(1,1)
|
||||
H.adjustToxLoss(-1)
|
||||
H.adjustOxyLoss(-1)
|
||||
|
||||
if(H.nutrition < NUTRITION_LEVEL_STARVING + 50)
|
||||
H.take_overall_damage(2,0)
|
||||
|
||||
|
||||
@@ -14,34 +14,24 @@
|
||||
liked_food = VEGETABLES | FRUIT | GRAIN
|
||||
species_language_holder = /datum/language_holder/sylvan
|
||||
var/light_nutrition_gain_factor = 4
|
||||
var/light_toxheal = 1
|
||||
var/light_oxyheal = 1
|
||||
var/light_burnheal = 1
|
||||
var/light_bruteheal = 1
|
||||
var/light_toxheal = -1
|
||||
var/light_oxyheal = -1
|
||||
var/light_burnheal = -1
|
||||
var/light_bruteheal = -1
|
||||
|
||||
/datum/species/pod/on_species_gain(mob/living/carbon/C, datum/species/old_species)
|
||||
. = ..()
|
||||
C.faction |= "plants"
|
||||
C.faction |= "vines"
|
||||
C.AddElement(/datum/element/photosynthesis, light_bruteheal, light_burnheal, light_toxheal, light_oxyheal, light_nutrition_gain_factor)
|
||||
|
||||
/datum/species/pod/on_species_loss(mob/living/carbon/C)
|
||||
. = ..()
|
||||
C.faction -= "plants"
|
||||
C.faction -= "vines"
|
||||
C.RemoveElement(/datum/element/photosynthesis, light_bruteheal, light_burnheal, light_toxheal, light_oxyheal, light_nutrition_gain_factor)
|
||||
|
||||
/datum/species/pod/spec_life(mob/living/carbon/human/H)
|
||||
if(H.stat == DEAD)
|
||||
return
|
||||
var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing
|
||||
if(isturf(H.loc)) //else, there's considered to be no light
|
||||
var/turf/T = H.loc
|
||||
light_amount = min(1,T.get_lumcount()) - 0.5
|
||||
H.adjust_nutrition(light_amount * light_nutrition_gain_factor, NUTRITION_LEVEL_FULL)
|
||||
if(light_amount > 0.2) //if there's enough light, heal
|
||||
H.heal_overall_damage(light_bruteheal, light_burnheal)
|
||||
H.adjustToxLoss(-light_toxheal)
|
||||
H.adjustOxyLoss(-light_oxyheal)
|
||||
|
||||
if(H.nutrition < NUTRITION_LEVEL_STARVING + 50)
|
||||
H.take_overall_damage(2,0)
|
||||
|
||||
@@ -77,9 +67,9 @@
|
||||
mutant_bodyparts = list("mcolor" = "FFF","mcolor2" = "FFF","mcolor3" = "FFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "mam_body_markings" = "Husky", "taur" = "None", "legs" = "Normal Legs")
|
||||
limbs_id = "pod"
|
||||
light_nutrition_gain_factor = 3
|
||||
light_bruteheal = 0.2
|
||||
light_burnheal = 0.2
|
||||
light_toxheal = 0.7
|
||||
light_bruteheal = -0.2
|
||||
light_burnheal = -0.2
|
||||
light_toxheal = -0.7
|
||||
|
||||
/datum/species/pod/pseudo_weak/spec_death(gibbed, mob/living/carbon/human/H)
|
||||
if(H)
|
||||
|
||||
@@ -15,16 +15,13 @@
|
||||
dangerous_existence = 1
|
||||
mutanteyes = /obj/item/organ/eyes/night_vision
|
||||
|
||||
/datum/species/shadow/on_species_gain(mob/living/carbon/C, datum/species/old_species)
|
||||
. = ..()
|
||||
C.AddElement(/datum/element/photosynthesis, 1, 1, 0, 0, 0, 0, SHADOW_SPECIES_LIGHT_THRESHOLD, SHADOW_SPECIES_LIGHT_THRESHOLD)
|
||||
|
||||
/datum/species/shadow/spec_life(mob/living/carbon/human/H)
|
||||
var/turf/T = H.loc
|
||||
if(istype(T))
|
||||
var/light_amount = T.get_lumcount()
|
||||
|
||||
if(light_amount > SHADOW_SPECIES_LIGHT_THRESHOLD) //if there's enough light, start dying
|
||||
H.take_overall_damage(1,1)
|
||||
else if (light_amount < SHADOW_SPECIES_LIGHT_THRESHOLD) //heal in the dark
|
||||
H.heal_overall_damage(1,1)
|
||||
/datum/species/shadow/on_species_loss(mob/living/carbon/C)
|
||||
. = ..()
|
||||
C.RemoveElement(/datum/element/photosynthesis, 1, 1, 0, 0, 0, 0, SHADOW_SPECIES_LIGHT_THRESHOLD, SHADOW_SPECIES_LIGHT_THRESHOLD)
|
||||
|
||||
/datum/species/shadow/check_roundstart_eligible()
|
||||
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
typing_indicator_enabled = TRUE
|
||||
|
||||
var/last_click_move = 0 // Stores the previous next_move value.
|
||||
|
||||
var/resize = 1 //Badminnery resize
|
||||
var/lastattacker = null
|
||||
var/lastattackerckey = null
|
||||
|
||||
@@ -2,15 +2,16 @@
|
||||
name = "A Perfectly Generic Boss Placeholder"
|
||||
desc = ""
|
||||
threat = 10
|
||||
robust_searching = 1
|
||||
robust_searching = TRUE
|
||||
stat_attack = UNCONSCIOUS
|
||||
status_flags = 0
|
||||
status_flags = NONE
|
||||
a_intent = INTENT_HARM
|
||||
gender = NEUTER
|
||||
has_field_of_vision = FALSE //You are a frikkin boss
|
||||
var/list/boss_abilities = list() //list of /datum/action/boss
|
||||
var/datum/boss_active_timed_battle/atb
|
||||
var/point_regen_delay = 1
|
||||
var/point_regen_delay = 20
|
||||
var/point_regen_amount = 1
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/boss/Initialize()
|
||||
@@ -18,6 +19,7 @@
|
||||
|
||||
atb = new()
|
||||
atb.point_regen_delay = point_regen_delay
|
||||
atb.point_regen_amount = point_regen_amount
|
||||
atb.boss = src
|
||||
|
||||
for(var/ab in boss_abilities)
|
||||
@@ -40,6 +42,7 @@
|
||||
required_mobility_flags = NONE
|
||||
var/boss_cost = 100 //Cost of usage for the boss' AI 1-100
|
||||
var/usage_probability = 100
|
||||
var/list/req_statuses //If set, will only trigger if the mob AI status is present in this list.
|
||||
var/mob/living/simple_animal/hostile/boss/boss
|
||||
var/boss_type = /mob/living/simple_animal/hostile/boss
|
||||
var/needs_target = TRUE //Does the boss need to have a target? (Only matters for the AI)
|
||||
@@ -57,7 +60,7 @@
|
||||
. = ..()
|
||||
boss = null
|
||||
|
||||
/datum/action/boss/Trigger()
|
||||
/datum/action/boss/IsAvailable(silent = FALSE)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
@@ -69,6 +72,11 @@
|
||||
return FALSE
|
||||
if(!boss.client && needs_target && !boss.target)
|
||||
return FALSE
|
||||
|
||||
/datum/action/boss/Trigger()
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(!boss.atb.spend(boss_cost))
|
||||
return FALSE
|
||||
if(say_when_triggered)
|
||||
@@ -85,7 +93,8 @@
|
||||
//Designed for boss mobs only
|
||||
/datum/boss_active_timed_battle
|
||||
var/list/abilities //a list of /datum/action/boss owned by a boss mob
|
||||
var/point_regen_delay = 5
|
||||
var/point_regen_delay = 20
|
||||
var/point_regen_amount = 1
|
||||
var/max_points = 100
|
||||
var/points = 50 //start with 50 so we can use some abilities but not insta-buttfug somebody
|
||||
var/next_point_time = 0
|
||||
@@ -93,48 +102,45 @@
|
||||
var/highest_cost = 0
|
||||
var/mob/living/simple_animal/hostile/boss/boss
|
||||
|
||||
|
||||
/datum/boss_active_timed_battle/New()
|
||||
..()
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
|
||||
/datum/boss_active_timed_battle/proc/assign_abilities(list/L)
|
||||
if(!L)
|
||||
return 0
|
||||
return FALSE
|
||||
abilities = L
|
||||
for(var/ab in abilities)
|
||||
var/datum/action/boss/AB = ab
|
||||
if(AB.boss_cost > highest_cost)
|
||||
highest_cost = AB.boss_cost
|
||||
|
||||
|
||||
/datum/boss_active_timed_battle/proc/spend(cost)
|
||||
if(cost <= points)
|
||||
points = max(0,points-cost)
|
||||
points -= cost
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
/datum/boss_active_timed_battle/proc/refund(cost)
|
||||
points = min(points+cost, max_points)
|
||||
|
||||
|
||||
/datum/boss_active_timed_battle/process()
|
||||
if(world.time >= next_point_time && points < max_points)
|
||||
next_point_time = world.time + point_regen_delay
|
||||
points = min(max_points, ++points) //has to be out of 100
|
||||
points = min(max_points, points + point_regen_amount)
|
||||
|
||||
if(abilities)
|
||||
chance_to_hold_onto_points = highest_cost*0.5
|
||||
if(points != max_points && prob(chance_to_hold_onto_points))
|
||||
return //Let's save our points for a better ability (unless we're at max points, in which case we can't save anymore!)
|
||||
if(!boss.client)
|
||||
abilities = shuffle(abilities)
|
||||
for(var/ab in abilities)
|
||||
var/datum/action/boss/AB = ab
|
||||
if(prob(AB.usage_probability) && AB.Trigger())
|
||||
break
|
||||
if(!abilities)
|
||||
return
|
||||
chance_to_hold_onto_points = highest_cost*0.5
|
||||
if(points != max_points && prob(chance_to_hold_onto_points))
|
||||
return //Let's save our points for a better ability (unless we're at max points, in which case we can't save anymore!)
|
||||
if(!boss.client)
|
||||
abilities = shuffle(abilities)
|
||||
for(var/ab in abilities)
|
||||
var/datum/action/boss/AB = ab
|
||||
if(!boss.client && (!AB.req_statuses || (boss.AIStatus in AB.req_statuses)) && prob(AB.usage_probability) && AB.Trigger())
|
||||
break
|
||||
AB.UpdateButtonIcon(TRUE)
|
||||
|
||||
|
||||
/datum/boss_active_timed_battle/Destroy()
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
boss_cost = 30
|
||||
boss_type = /mob/living/simple_animal/hostile/boss/paper_wizard
|
||||
needs_target = FALSE
|
||||
req_statuses = list(AI_ON)
|
||||
say_when_triggered = "Rise, my creations! Jump off your pages and into this realm!"
|
||||
var/list/summoned_minions = list()
|
||||
var/maximum_stickmen = 6
|
||||
@@ -85,6 +86,7 @@
|
||||
usage_probability = 30
|
||||
boss_cost = 40
|
||||
boss_type = /mob/living/simple_animal/hostile/boss/paper_wizard
|
||||
req_statuses = list(AI_ON)
|
||||
say_when_triggered = ""
|
||||
|
||||
/datum/action/boss/wizard_mimic/Trigger()
|
||||
|
||||
@@ -105,6 +105,7 @@ IGNORE_PROC_IF_NOT_TARGET(attack_slime)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/curseblob/attacked_by(obj/item/I, mob/living/L, attackchain_flags = NONE, damage_multiplier = 1)
|
||||
if(L != set_target)
|
||||
L.changeNext_move(I.click_delay) //pre_attacked_by not called
|
||||
return
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
throw_speed = 3
|
||||
throw_range = 5
|
||||
force = 5
|
||||
item_flags = NEEDS_PERMIT | NO_ATTACK_CHAIN_SOFT_STAMCRIT
|
||||
item_flags = NEEDS_PERMIT
|
||||
attack_verb = list("struck", "hit", "bashed")
|
||||
|
||||
var/fire_sound = "gunshot"
|
||||
@@ -140,12 +140,13 @@
|
||||
to_chat(user, "<span class='danger'>*click*</span>")
|
||||
playsound(src, "gun_dry_fire", 30, 1)
|
||||
|
||||
/obj/item/gun/proc/shoot_live_shot(mob/living/user as mob|obj, pointblank = 0, mob/pbtarget = null, message = 1)
|
||||
/obj/item/gun/proc/shoot_live_shot(mob/living/user, pointblank = FALSE, mob/pbtarget, message = 1, stam_cost = 0)
|
||||
if(recoil)
|
||||
shake_camera(user, recoil + 1, recoil)
|
||||
|
||||
if(isliving(user)) //CIT CHANGE - makes gun recoil cause staminaloss
|
||||
user.adjustStaminaLossBuffered(getstamcost(user)*(firing && burst_size >= 2 ? 1/burst_size : 1)) //CIT CHANGE - ditto
|
||||
if(stam_cost) //CIT CHANGE - makes gun recoil cause staminaloss
|
||||
var/safe_cost = clamp(stam_cost, 0, STAMINA_NEAR_CRIT - user.getStaminaLoss())*(firing && burst_size >= 2 ? 1/burst_size : 1)
|
||||
user.adjustStaminaLossBuffered(safe_cost) //CIT CHANGE - ditto
|
||||
|
||||
if(suppressed)
|
||||
playsound(user, fire_sound, 10, 1)
|
||||
@@ -172,9 +173,10 @@
|
||||
return
|
||||
if(firing)
|
||||
return
|
||||
if(IS_STAMCRIT(user)) //respect stamina softcrit
|
||||
to_chat(user, "<span class='warning'>You are too exhausted to fire [src]!</span>")
|
||||
return
|
||||
var/stamloss = user.getStaminaLoss()
|
||||
if(stamloss >= STAMINA_NEAR_SOFTCRIT) //The more tired you are, the less damage you do.
|
||||
var/penalty = (stamloss - STAMINA_NEAR_SOFTCRIT)/(STAMINA_NEAR_CRIT - STAMINA_NEAR_SOFTCRIT)*STAM_CRIT_GUN_DELAY
|
||||
user.changeNext_move(CLICK_CD_RANGE+(CLICK_CD_RANGE*penalty))
|
||||
if(flag) //It's adjacent, is the user, or is on the user's person
|
||||
if(target in user.contents) //can't shoot stuff inside us.
|
||||
return
|
||||
@@ -216,7 +218,7 @@
|
||||
var/loop_counter = 0
|
||||
|
||||
if(user)
|
||||
bonus_spread += getinaccuracy(user) //CIT CHANGE - adds bonus spread while not aiming
|
||||
bonus_spread = getinaccuracy(user, bonus_spread, stamloss) //CIT CHANGE - adds bonus spread while not aiming
|
||||
if(ishuman(user) && user.a_intent == INTENT_HARM && weapon_weight <= WEAPON_LIGHT)
|
||||
var/mob/living/carbon/human/H = user
|
||||
for(var/obj/item/gun/G in H.held_items)
|
||||
@@ -225,9 +227,11 @@
|
||||
else if(G.can_trigger_gun(user))
|
||||
bonus_spread += 24 * G.weapon_weight * G.dualwield_spread_mult
|
||||
loop_counter++
|
||||
addtimer(CALLBACK(G, /obj/item/gun.proc/process_fire, target, user, TRUE, params, null, bonus_spread), loop_counter)
|
||||
var/stam_cost = G.getstamcost(user)
|
||||
addtimer(CALLBACK(G, /obj/item/gun.proc/process_fire, target, user, TRUE, params, null, bonus_spread, stam_cost), loop_counter)
|
||||
|
||||
process_fire(target, user, TRUE, params, null, bonus_spread)
|
||||
var/stam_cost = getstamcost(user)
|
||||
process_fire(target, user, TRUE, params, null, bonus_spread, stam_cost)
|
||||
|
||||
/obj/item/gun/can_trigger_gun(mob/living/user)
|
||||
. = ..()
|
||||
@@ -258,21 +262,21 @@
|
||||
/obj/item/gun/proc/on_cooldown()
|
||||
return busy_action || firing || ((last_fire + fire_delay) > world.time)
|
||||
|
||||
/obj/item/gun/proc/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
|
||||
/obj/item/gun/proc/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
|
||||
add_fingerprint(user)
|
||||
|
||||
if(on_cooldown())
|
||||
return
|
||||
firing = TRUE
|
||||
. = do_fire(target, user, message, params, zone_override, bonus_spread)
|
||||
. = do_fire(target, user, message, params, zone_override, bonus_spread, stam_cost)
|
||||
firing = FALSE
|
||||
last_fire = world.time
|
||||
|
||||
if(user)
|
||||
user.update_inv_hands()
|
||||
SEND_SIGNAL(user, COMSIG_LIVING_GUN_PROCESS_FIRE, target, params, zone_override)
|
||||
SEND_SIGNAL(user, COMSIG_LIVING_GUN_PROCESS_FIRE, target, params, zone_override, bonus_spread, stam_cost)
|
||||
|
||||
/obj/item/gun/proc/do_fire(atom/target, mob/living/user, message = TRUE, params, zone_override = "", bonus_spread = 0)
|
||||
/obj/item/gun/proc/do_fire(atom/target, mob/living/user, message = TRUE, params, zone_override = "", bonus_spread = 0, stam_cost = 0)
|
||||
var/sprd = 0
|
||||
var/randomized_gun_spread = 0
|
||||
var/rand_spr = rand()
|
||||
@@ -290,7 +294,7 @@
|
||||
sleep(burst_shot_delay)
|
||||
if(QDELETED(src))
|
||||
break
|
||||
do_burst_shot(user, target, message, params, zone_override, sprd, randomized_gun_spread, randomized_bonus_spread, rand_spr, i)
|
||||
do_burst_shot(user, target, message, params, zone_override, sprd, randomized_gun_spread, randomized_bonus_spread, rand_spr, i, stam_cost)
|
||||
else
|
||||
if(chambered)
|
||||
sprd = round((rand() - 0.5) * DUALWIELD_PENALTY_EXTRA_MULTIPLIER * (randomized_gun_spread + randomized_bonus_spread))
|
||||
@@ -300,9 +304,9 @@
|
||||
return
|
||||
else
|
||||
if(get_dist(user, target) <= 1) //Making sure whether the target is in vicinity for the pointblank shot
|
||||
shoot_live_shot(user, 1, target, message)
|
||||
shoot_live_shot(user, 1, target, message, stam_cost)
|
||||
else
|
||||
shoot_live_shot(user, 0, target, message)
|
||||
shoot_live_shot(user, 0, target, message, stam_cost)
|
||||
else
|
||||
shoot_with_empty_chamber(user)
|
||||
return
|
||||
@@ -312,7 +316,7 @@
|
||||
SSblackbox.record_feedback("tally", "gun_fired", 1, type)
|
||||
return TRUE
|
||||
|
||||
/obj/item/gun/proc/do_burst_shot(mob/living/user, atom/target, message = TRUE, params=null, zone_override = "", sprd = 0, randomized_gun_spread = 0, randomized_bonus_spread = 0, rand_spr = 0, iteration = 0)
|
||||
/obj/item/gun/proc/do_burst_shot(mob/living/user, atom/target, message = TRUE, params=null, zone_override = "", sprd = 0, randomized_gun_spread = 0, randomized_bonus_spread = 0, rand_spr = 0, iteration = 0, stam_cost = 0)
|
||||
if(!user || !firing)
|
||||
firing = FALSE
|
||||
return FALSE
|
||||
@@ -336,9 +340,9 @@
|
||||
return FALSE
|
||||
else
|
||||
if(get_dist(user, target) <= 1) //Making sure whether the target is in vicinity for the pointblank shot
|
||||
shoot_live_shot(user, 1, target, message)
|
||||
shoot_live_shot(user, 1, target, message, stam_cost)
|
||||
else
|
||||
shoot_live_shot(user, 0, target, message)
|
||||
shoot_live_shot(user, 0, target, message, stam_cost)
|
||||
if (iteration >= burst_size)
|
||||
firing = FALSE
|
||||
else
|
||||
@@ -349,20 +353,21 @@
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
/obj/item/gun/attack(mob/M as mob, mob/user)
|
||||
/obj/item/gun/attack(mob/living/M, mob/user)
|
||||
if(user.a_intent == INTENT_HARM) //Flogging
|
||||
if(bayonet)
|
||||
M.attackby(bayonet, user)
|
||||
attack_delay_done = TRUE
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
return
|
||||
attack_delay_done = TRUE //we are firing the gun, not bashing people with its butt.
|
||||
|
||||
/obj/item/gun/attack_obj(obj/O, mob/user)
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
if(bayonet)
|
||||
O.attackby(bayonet, user)
|
||||
return
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/item/gun/attackby(obj/item/I, mob/user, params)
|
||||
@@ -498,7 +503,7 @@
|
||||
if(chambered && chambered.BB)
|
||||
chambered.BB.damage *= 5
|
||||
|
||||
process_fire(target, user, TRUE, params)
|
||||
process_fire(target, user, TRUE, params, stam_cost = getstamcost(user))
|
||||
|
||||
/obj/item/gun/proc/unlock() //used in summon guns and as a convience for admins
|
||||
if(pin)
|
||||
@@ -566,7 +571,25 @@
|
||||
chambered = null
|
||||
update_icon()
|
||||
|
||||
/obj/item/gun/proc/getinaccuracy(mob/user)
|
||||
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
|
||||
return ((weapon_weight * 25) * inaccuracy_modifier)
|
||||
return 0
|
||||
/obj/item/gun/proc/getinaccuracy(mob/living/user, bonus_spread, stamloss)
|
||||
if(inaccuracy_modifier == 0)
|
||||
return bonus_spread
|
||||
var/base_inaccuracy = weapon_weight * 25 * inaccuracy_modifier
|
||||
var/aiming_delay = 0 //Otherwise aiming would be meaningless for slower guns such as sniper rifles and launchers.
|
||||
if(fire_delay)
|
||||
var/penalty = (last_fire + GUN_AIMING_TIME + fire_delay) - world.time
|
||||
if(penalty > 0) //Yet we only penalize users firing it multiple times in a haste. fire_delay isn't necessarily cumbersomeness.
|
||||
aiming_delay = penalty
|
||||
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)) //To be removed in favor of something less tactless later.
|
||||
base_inaccuracy /= 1.5
|
||||
if(stamloss > STAMINA_NEAR_SOFTCRIT) //This can null out the above bonus.
|
||||
base_inaccuracy *= 1 + (stamloss - STAMINA_NEAR_SOFTCRIT)/(STAMINA_NEAR_CRIT - STAMINA_NEAR_SOFTCRIT)*0.5
|
||||
var/mult = max((GUN_AIMING_TIME + aiming_delay + user.last_click_move - world.time)/GUN_AIMING_TIME, -0.5) //Yes, there is a bonus for taking time aiming.
|
||||
if(mult < 0) //accurate weapons should provide a proper bonus with negative inaccuracy. the opposite is true too.
|
||||
mult *= 1/inaccuracy_modifier
|
||||
return max(bonus_spread + (base_inaccuracy * mult), 0) //no negative spread.
|
||||
|
||||
/obj/item/gun/proc/getstamcost(mob/living/carbon/user)
|
||||
. = recoil
|
||||
if(user && !user.has_gravity())
|
||||
. = recoil*5
|
||||
|
||||
@@ -365,7 +365,7 @@
|
||||
can_unsuppress = TRUE
|
||||
can_suppress = TRUE
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
inaccuracy_modifier = 0
|
||||
inaccuracy_modifier = 0.5
|
||||
zoomable = TRUE
|
||||
zoom_amt = 10 //Long range, enough to see in front of you, but no tiles behind you.
|
||||
zoom_out_amt = 13
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
else
|
||||
qdel(src)
|
||||
|
||||
/obj/item/gun/ballistic/minigun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
|
||||
/obj/item/gun/ballistic/minigun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
|
||||
if(ammo_pack)
|
||||
if(ammo_pack.overheat < ammo_pack.overheat_max)
|
||||
ammo_pack.overheat += burst_size
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
name = "grenade launcher"
|
||||
icon_state = "dshotgun-sawn"
|
||||
item_state = "gun"
|
||||
inaccuracy_modifier = 0
|
||||
inaccuracy_modifier = 0.5
|
||||
mag_type = /obj/item/ammo_box/magazine/internal/grenadelauncher
|
||||
fire_sound = 'sound/weapons/grenadelaunch.ogg'
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
@@ -87,7 +87,7 @@
|
||||
pin = /obj/item/firing_pin/implant/pindicate
|
||||
burst_size = 1
|
||||
fire_delay = 0
|
||||
inaccuracy_modifier = 0
|
||||
inaccuracy_modifier = 0.25
|
||||
casing_ejector = FALSE
|
||||
weapon_weight = WEAPON_HEAVY
|
||||
magazine_wording = "rocket"
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
spread = 0
|
||||
recoil = 0.1
|
||||
casing_ejector = FALSE
|
||||
inaccuracy_modifier = 0
|
||||
inaccuracy_modifier = 0.15
|
||||
dualwield_spread_mult = 1.4
|
||||
weapon_weight = WEAPON_MEDIUM
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
@@ -46,7 +46,7 @@
|
||||
return 0
|
||||
. = ..()
|
||||
|
||||
/obj/item/gun/ballistic/automatic/magrifle/shoot_live_shot()
|
||||
/obj/item/gun/ballistic/automatic/magrifle/shoot_live_shot(mob/living/user, pointblank = FALSE, mob/pbtarget, message = 1, stam_cost = 0)
|
||||
var/obj/item/ammo_casing/caseless/magnetic/shot = chambered
|
||||
cell.use(shot.energy_cost)
|
||||
. = ..()
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
. = ..()
|
||||
safe_calibers = magazine.caliber
|
||||
|
||||
/obj/item/gun/ballistic/revolver/detective/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
|
||||
/obj/item/gun/ballistic/revolver/detective/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
|
||||
if(chambered && !(chambered.caliber in safe_calibers))
|
||||
if(prob(70 - (magazine.ammo_count() * 10))) //minimum probability of 10, maximum of 60
|
||||
playsound(user, fire_sound, 50, 1)
|
||||
@@ -242,7 +242,7 @@
|
||||
user.visible_message("<span class='danger'>*click*</span>")
|
||||
playsound(src, "gun_dry_fire", 30, 1)
|
||||
|
||||
/obj/item/gun/ballistic/revolver/russian/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
|
||||
/obj/item/gun/ballistic/revolver/russian/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
|
||||
add_fingerprint(user)
|
||||
playsound(src, "gun_dry_fire", 30, TRUE)
|
||||
user.visible_message("<span class='danger'>[user.name] tries to fire \the [src] at the same time, but only succeeds at looking like an idiot.</span>", "<span class='danger'>\The [src]'s anti-combat mechanism prevents you from firing it at the same time!</span>")
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
icon_state = "moistnugget"
|
||||
item_state = "moistnugget"
|
||||
slot_flags = 0 //no ITEM_SLOT_BACK sprite, alas
|
||||
inaccuracy_modifier = 0
|
||||
inaccuracy_modifier = 0.5
|
||||
mag_type = /obj/item/ammo_box/magazine/internal/boltaction
|
||||
var/bolt_open = FALSE
|
||||
can_bayonet = TRUE
|
||||
@@ -191,7 +191,7 @@
|
||||
/obj/item/gun/ballistic/shotgun/boltaction/enchanted/attack_self()
|
||||
return
|
||||
|
||||
/obj/item/gun/ballistic/shotgun/boltaction/enchanted/shoot_live_shot(mob/living/user as mob|obj, pointblank = 0, mob/pbtarget = null, message = 1)
|
||||
/obj/item/gun/ballistic/shotgun/boltaction/enchanted/shoot_live_shot(mob/living/user, pointblank = FALSE, mob/pbtarget, message = 1, stam_cost = 0)
|
||||
..()
|
||||
if(guns_left)
|
||||
var/obj/item/gun/ballistic/shotgun/boltaction/enchanted/GUN = new gun_type
|
||||
@@ -205,7 +205,7 @@
|
||||
|
||||
// Automatic Shotguns//
|
||||
|
||||
/obj/item/gun/ballistic/shotgun/automatic/shoot_live_shot(mob/living/user as mob|obj)
|
||||
/obj/item/gun/ballistic/shotgun/automatic/shoot_live_shot(mob/living/user, pointblank = FALSE, mob/pbtarget, message = 1, stam_cost = 0)
|
||||
..()
|
||||
src.pump(user)
|
||||
|
||||
|
||||
@@ -127,12 +127,12 @@
|
||||
chambered = null //either way, released the prepared shot
|
||||
recharge_newshot() //try to charge a new shot
|
||||
|
||||
/obj/item/gun/energy/do_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
|
||||
/obj/item/gun/energy/do_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
|
||||
if(!chambered && can_shoot())
|
||||
process_chamber() // If the gun was drained and then recharged, load a new shot.
|
||||
return ..()
|
||||
|
||||
/obj/item/gun/energy/do_burst_shot(mob/living/user, atom/target, message = TRUE, params = null, zone_override="", sprd = 0, randomized_gun_spread = 0, randomized_bonus_spread = 0, rand_spr = 0, iteration = 0)
|
||||
/obj/item/gun/energy/do_burst_shot(mob/living/user, atom/target, message = TRUE, params = null, zone_override="", sprd = 0, randomized_gun_spread = 0, randomized_bonus_spread = 0, rand_spr = 0, iteration = 0, stam_cost = 0)
|
||||
if(!chambered && can_shoot())
|
||||
process_chamber() // Ditto.
|
||||
return ..()
|
||||
|
||||
@@ -237,7 +237,7 @@
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/gun/energy/dueling/process_fire(atom/target, mob/living/user, message, params, zone_override, bonus_spread)
|
||||
/obj/item/gun/energy/dueling/process_fire(atom/target, mob/living/user, message, params, zone_override, bonus_spread = 0, stam_cost = 0)
|
||||
if(duel.state == DUEL_READY)
|
||||
duel.confirmations[src] = TRUE
|
||||
to_chat(user,"<span class='notice'>You confirm your readiness.</span>")
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
fail_tick--
|
||||
..()
|
||||
|
||||
/obj/item/gun/energy/e_gun/nuclear/shoot_live_shot()
|
||||
/obj/item/gun/energy/e_gun/nuclear/shoot_live_shot(mob/living/user, pointblank = FALSE, mob/pbtarget, message = 1, stam_cost = 0)
|
||||
failcheck()
|
||||
update_icon()
|
||||
..()
|
||||
|
||||
@@ -60,6 +60,12 @@
|
||||
else
|
||||
cut_overlays()
|
||||
|
||||
/obj/item/gun/energy/kinetic_accelerator/getinaccuracy(mob/living/user, bonus_spread, stamloss)
|
||||
var/old_fire_delay = fire_delay //It's pretty irrelevant tbh but whatever.
|
||||
fire_delay = overheat_time
|
||||
. = ..()
|
||||
fire_delay = old_fire_delay
|
||||
|
||||
/obj/item/gun/energy/kinetic_accelerator/examine(mob/user)
|
||||
. = ..()
|
||||
if(max_mod_capacity)
|
||||
@@ -128,7 +134,7 @@
|
||||
if(!holds_charge)
|
||||
empty()
|
||||
|
||||
/obj/item/gun/energy/kinetic_accelerator/shoot_live_shot()
|
||||
/obj/item/gun/energy/kinetic_accelerator/shoot_live_shot(mob/living/user, pointblank = FALSE, mob/pbtarget, message = 1, stam_cost = 0)
|
||||
. = ..()
|
||||
attempt_reload()
|
||||
|
||||
@@ -207,6 +213,12 @@
|
||||
var/obj/item/gun/energy/kinetic_accelerator/KA = loc
|
||||
KA.modify_projectile(BB)
|
||||
|
||||
/obj/item/gun/energy/kinetic_accelerator/getstamcost(mob/living/carbon/user)
|
||||
if(user && !lavaland_equipment_pressure_check(get_turf(user)))
|
||||
return 0
|
||||
else
|
||||
return ..()
|
||||
|
||||
//Projectiles
|
||||
/obj/item/projectile/kinetic
|
||||
name = "kinetic force"
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
slot_flags = ITEM_SLOT_BACK
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
weapon_weight = WEAPON_MEDIUM
|
||||
inaccuracy_modifier = 0.5
|
||||
inaccuracy_modifier = 0.7
|
||||
force = 10
|
||||
throwforce = 10
|
||||
cell_type = /obj/item/stock_parts/cell/lascarbine
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
suppressed = TRUE
|
||||
ammo_type = list(/obj/item/ammo_casing/energy/bolt)
|
||||
weapon_weight = WEAPON_LIGHT
|
||||
inaccuracy_modifier = 0
|
||||
inaccuracy_modifier = 0.25
|
||||
obj_flags = 0
|
||||
overheat_time = 20
|
||||
holds_charge = TRUE
|
||||
@@ -126,7 +126,7 @@
|
||||
attack_verb = list("attacked", "slashed", "cut", "sliced")
|
||||
force = 12
|
||||
sharpness = IS_SHARP
|
||||
inaccuracy_modifier = 0
|
||||
inaccuracy_modifier = 0.25
|
||||
can_charge = 0
|
||||
|
||||
heat = 3800
|
||||
@@ -182,7 +182,7 @@
|
||||
item_state = null
|
||||
icon_state = "wormhole_projector"
|
||||
pin = null
|
||||
inaccuracy_modifier = 0
|
||||
inaccuracy_modifier = 0.25
|
||||
var/obj/effect/portal/p_blue
|
||||
var/obj/effect/portal/p_orange
|
||||
var/atmos_link = FALSE
|
||||
@@ -318,7 +318,7 @@
|
||||
icon_state = "emitter_carbine"
|
||||
force = 12
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
inaccuracy_modifier = 0
|
||||
inaccuracy_modifier = 0.25
|
||||
cell_type = /obj/item/stock_parts/cell/super
|
||||
ammo_type = list(/obj/item/ammo_casing/energy/emitter)
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
/obj/item/projectile/magic/death, /obj/item/projectile/magic/teleport, /obj/item/projectile/magic/door, /obj/item/projectile/magic/aoe/fireball,
|
||||
/obj/item/projectile/magic/spellblade, /obj/item/projectile/magic/arcane_barrage, /obj/item/projectile/magic/locker)
|
||||
|
||||
/obj/item/gun/magic/staff/chaos/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
|
||||
/obj/item/gun/magic/staff/chaos/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
|
||||
chambered.projectile_type = pick(allowed_projectile_types)
|
||||
. = ..()
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
throw_speed = 3
|
||||
throw_range = 7
|
||||
force = 4
|
||||
inaccuracy_modifier = 0
|
||||
inaccuracy_modifier = 0.25
|
||||
custom_materials = list(/datum/material/iron=2000)
|
||||
clumsy_check = FALSE
|
||||
fire_sound = 'sound/items/syringeproj.ogg'
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
/obj/item/gun/grenadelauncher/can_shoot()
|
||||
return grenades.len
|
||||
|
||||
/obj/item/gun/grenadelauncher/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
|
||||
/obj/item/gun/grenadelauncher/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
|
||||
user.visible_message("<span class='danger'>[user] fired a grenade!</span>", \
|
||||
"<span class='danger'>You fire the grenade launcher!</span>")
|
||||
var/obj/item/grenade/F = grenades[1] //Now with less copypasta!
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
on_beam_release(current_target)
|
||||
current_target = null
|
||||
|
||||
/obj/item/gun/medbeam/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
|
||||
/obj/item/gun/medbeam/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
|
||||
if(isliving(user))
|
||||
add_fingerprint(user)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
throw_speed = 3
|
||||
throw_range = 7
|
||||
force = 4
|
||||
inaccuracy_modifier = 0
|
||||
inaccuracy_modifier = 0.25
|
||||
custom_materials = list(/datum/material/iron=2000)
|
||||
clumsy_check = 0
|
||||
fire_sound = 'sound/items/syringeproj.ogg'
|
||||
@@ -160,7 +160,7 @@
|
||||
item_state = "blowgun"
|
||||
fire_sound = 'sound/items/syringeproj.ogg'
|
||||
|
||||
/obj/item/gun/syringe/blowgun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
|
||||
/obj/item/gun/syringe/blowgun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
|
||||
visible_message("<span class='danger'>[user] starts aiming with a blowgun!</span>")
|
||||
if(do_after(user, 25, target = src))
|
||||
user.adjustStaminaLoss(20)
|
||||
|
||||
@@ -272,7 +272,7 @@
|
||||
return TRUE
|
||||
|
||||
var/distance = get_dist(T, starting) // Get the distance between the turf shot from and the mob we hit and use that for the calculations.
|
||||
if(check_zone(def_zone) != BODY_ZONE_CHEST)
|
||||
if(def_zone && check_zone(def_zone) != BODY_ZONE_CHEST)
|
||||
def_zone = ran_zone(def_zone, max(100-(7*distance), 5) * zone_accuracy_factor) //Lower accurancy/longer range tradeoff. 7 is a balanced number to use.
|
||||
|
||||
if(isturf(A) && hitsound_wall)
|
||||
@@ -548,7 +548,7 @@
|
||||
var/safety = CEILING(pixel_increment_amount / world.icon_size, 1) * 2 + 1
|
||||
while(T != loc)
|
||||
if(!--safety)
|
||||
CRASH("Projectile took more than pixel incrememnt speed times 2 to get to its location, this is probably something seriously scuffed going on.")
|
||||
CRASH("[type] took too long (allowed: [CEILING(pixel_increment_amount/world.icon_size,1)*2] moves) to get to its location.")
|
||||
step_towards(src, T)
|
||||
if(QDELETED(src))
|
||||
return
|
||||
|
||||
@@ -213,6 +213,11 @@
|
||||
for(var/datum/reagent/R in beaker.reagents.reagent_list)
|
||||
. += "<span class='notice'>- [R.volume] units of [R.name].</span>"
|
||||
|
||||
/obj/machinery/reagentgrinder/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(istype(user) && user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
replace_beaker(user)
|
||||
|
||||
/obj/machinery/reagentgrinder/proc/eject(mob/user)
|
||||
for(var/i in holdingitems)
|
||||
var/obj/item/O = i
|
||||
|
||||
@@ -25,14 +25,8 @@
|
||||
/obj/item/reagent_containers/pill/attack_self(mob/user)
|
||||
return
|
||||
|
||||
/obj/item/reagent_containers/pill/get_w_volume()
|
||||
switch(reagents.total_volume)
|
||||
if(0 to 9.5)
|
||||
return 1
|
||||
if(9.5 to 25)
|
||||
return DEFAULT_VOLUME_TINY
|
||||
else
|
||||
return DEFAULT_VOLUME_SMALL
|
||||
/obj/item/reagent_containers/pill/get_w_volume() // DEFAULT_VOLUME_TINY at 25u, DEFAULT_VOLUME_SMALL at 50u
|
||||
return DEFAULT_VOLUME_TINY/2 + reagents.total_volume / reagents.maximum_volume * DEFAULT_VOLUME_TINY
|
||||
|
||||
/obj/item/reagent_containers/pill/attack(mob/M, mob/user, def_zone)
|
||||
if(!canconsume(M, user))
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
/obj/machinery/computer/shuttle/snow_taxi
|
||||
name = "snow taxi console"
|
||||
desc = "Used to direct the snow taxi."
|
||||
circuit = /obj/item/circuitboard/computer/snow_taxi
|
||||
shuttleId = "snow_taxi"
|
||||
possible_destinations = "snaxi_nw;snaxi_ne;snaxi_s"
|
||||
no_destination_swap = TRUE
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user