This commit is contained in:
Fordoxia
2024-04-23 03:22:48 +01:00
150 changed files with 1354 additions and 611 deletions

View File

@@ -259,7 +259,6 @@
/area/ruin/space/onehalf/hallway)
"aM" = (
/obj/structure/disposalpipe/segment,
/obj/structure/disposalpipe/segment,
/obj/machinery/door/poddoor{
id_tag = "bayint1";
name = "mining drone bay blast door"
@@ -636,9 +635,6 @@
/area/ruin/space/onehalf/hallway)
"bA" = (
/obj/structure/disposalpipe/segment,
/obj/structure/disposalpipe/segment{
dir = 4
},
/obj/structure/disposalpipe/segment{
dir = 4
},
@@ -653,15 +649,6 @@
},
/turf/simulated/floor/plasteel,
/area/ruin/space/onehalf/drone_bay)
"bC" = (
/obj/structure/disposalpipe/segment{
dir = 4
},
/obj/structure/disposalpipe/segment{
dir = 4
},
/turf/simulated/floor/plasteel,
/area/ruin/space/onehalf/drone_bay)
"bD" = (
/obj/structure/disposalpipe/junction{
dir = 8
@@ -1643,7 +1630,7 @@ aD
aq
aX
bm
bC
bn
bT
aa
cn

View File

@@ -52972,7 +52972,6 @@
icon_state = "1-2"
},
/obj/structure/disposalpipe/segment,
/obj/structure/disposalpipe/segment,
/obj/structure/sign/securearea{
pixel_x = -32
},
@@ -74887,7 +74886,6 @@
/area/station/maintenance/apmaint)
"owP" = (
/obj/structure/disposalpipe/segment,
/obj/structure/disposalpipe/segment,
/turf/simulated/floor/plating/airless,
/area/station/maintenance/asmaint)
"oxe" = (

View File

@@ -1839,6 +1839,11 @@
icon_state = "asteroidplating"
},
/area/station/security/permabrig)
"alq" = (
/obj/structure/closet,
/obj/effect/spawner/lootdrop/maintenance/two,
/turf/simulated/floor/plating/asteroid/ancient,
/area/station/maintenance/starboard)
"alt" = (
/obj/machinery/camera{
c_tag = "Prison Central";
@@ -6609,6 +6614,7 @@
/area/station/security/permabrig)
"aQR" = (
/obj/structure/closet/crate,
/obj/effect/spawner/lootdrop/maintenance/two,
/turf/simulated/floor/plating,
/area/station/maintenance/maintcentral)
"aQS" = (
@@ -14849,6 +14855,7 @@
dir = 8
},
/obj/structure/closet,
/obj/effect/spawner/lootdrop/maintenance/two,
/turf/simulated/floor/plating,
/area/station/maintenance/fsmaint2)
"bEP" = (
@@ -16885,6 +16892,7 @@
/area/station/command/bridge)
"bMX" = (
/obj/structure/closet/wardrobe/mixed,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating,
/area/station/maintenance/port)
"bMY" = (
@@ -17189,6 +17197,7 @@
dir = 4
},
/obj/structure/closet/emcloset,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating{
icon_state = "asteroidplating"
},
@@ -19083,7 +19092,6 @@
pixel_x = 24;
name = "east bump"
},
/obj/structure/disposalpipe/segment,
/obj/effect/spawner/random_spawners/dirt_often,
/turf/simulated/floor/plasteel{
icon_state = "cafeteria"
@@ -19255,6 +19263,7 @@
},
/obj/effect/decal/cleanable/cobweb,
/obj/structure/closet,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating,
/area/station/maintenance/fore2)
"bWl" = (
@@ -19526,6 +19535,7 @@
"bXu" = (
/obj/structure/rack,
/obj/item/pickaxe/emergency,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating,
/area/station/maintenance/fore2)
"bXv" = (
@@ -20176,6 +20186,11 @@
},
/turf/simulated/floor/plating,
/area/station/maintenance/fore2)
"ccV" = (
/obj/structure/rack,
/obj/effect/spawner/lootdrop/maintenance/two,
/turf/simulated/floor/plating/asteroid/ancient,
/area/station/maintenance/fore2)
"ccW" = (
/turf/simulated/mineral/ancient,
/area/mine/unexplored/cere/research)
@@ -21976,10 +21991,10 @@
d2 = 8;
icon_state = "4-8"
},
/obj/structure/disposalpipe/sortjunction{
dir = 2;
name = "disposal pipe - Chemistry";
sort_type_txt = "11"
/obj/structure/disposalpipe/sortjunction/reversed{
name = "disposal pipe - Medbay";
sort_type_txt = "9";
dir = 8
},
/turf/simulated/floor/plasteel{
icon_state = "cafeteria"
@@ -22079,6 +22094,7 @@
/obj/structure/closet/emcloset,
/obj/machinery/light/small,
/obj/effect/decal/cleanable/dirt,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating,
/area/station/maintenance/port)
"coO" = (
@@ -23749,6 +23765,7 @@
"czP" = (
/obj/structure/closet/crate,
/obj/item/pickaxe,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating/asteroid/ancient,
/area/station/maintenance/apmaint)
"czQ" = (
@@ -31090,6 +31107,7 @@
/area/station/maintenance/disposal/west)
"doo" = (
/obj/structure/closet/emcloset,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating/asteroid/ancient,
/area/station/maintenance/fpmaint)
"dos" = (
@@ -33825,6 +33843,7 @@
/area/station/maintenance/starboard)
"dCU" = (
/obj/structure/closet/emcloset,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating/asteroid/ancient,
/area/station/maintenance/starboard)
"dCV" = (
@@ -35470,6 +35489,7 @@
"eeZ" = (
/obj/structure/closet/crate,
/obj/effect/decal/cleanable/dirt,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating,
/area/station/maintenance/fore2)
"efa" = (
@@ -35983,6 +36003,7 @@
/area/station/hallway/primary/central/west)
"eot" = (
/obj/structure/closet,
/obj/effect/spawner/lootdrop/maintenance/two,
/turf/simulated/floor/plating,
/area/station/maintenance/maintcentral)
"eoz" = (
@@ -36240,6 +36261,7 @@
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 5
},
/obj/effect/spawner/lootdrop/maintenance/two,
/turf/simulated/floor/plating,
/area/station/maintenance/storage)
"etG" = (
@@ -36307,6 +36329,7 @@
/area/station/service/clown)
"eux" = (
/obj/structure/closet/emcloset,
/obj/effect/spawner/lootdrop/maintenance/two,
/turf/simulated/floor/plating/asteroid/ancient,
/area/station/maintenance/maintcentral)
"euL" = (
@@ -36637,6 +36660,7 @@
/obj/structure/closet/crate{
name = "top secret mime supplies"
},
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating{
icon_state = "asteroidplating"
},
@@ -37705,6 +37729,11 @@
},
/turf/simulated/floor/grass,
/area/station/hallway/spacebridge/scidock)
"eTI" = (
/obj/structure/table,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating/asteroid/ancient,
/area/station/maintenance/port)
"eTJ" = (
/obj/item/kirbyplants,
/obj/structure/disposalpipe/segment{
@@ -38204,6 +38233,7 @@
/obj/structure/disposalpipe/segment/corner{
dir = 8
},
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating{
icon_state = "asteroidplating"
},
@@ -39912,11 +39942,6 @@
},
/area/station/hallway/primary/aft/west)
"fLp" = (
/obj/structure/disposalpipe/sortjunction{
dir = 2;
name = "disposal pipe - CMO Office";
sort_type_txt = "10"
},
/obj/effect/spawner/random_spawners/dirt_often,
/obj/machinery/atmospherics/unary/vent_pump/on{
dir = 8
@@ -40732,10 +40757,6 @@
icon_state = "whitegreen"
},
/area/station/public/sleep)
"fYD" = (
/obj/structure/rack,
/turf/simulated/floor/plating/asteroid/ancient,
/area/station/maintenance/apmaint)
"fYG" = (
/obj/machinery/door/airlock/public/glass{
name = "Walkway"
@@ -41262,6 +41283,8 @@
/obj/structure/disposalpipe/segment/corner{
dir = 1
},
/obj/structure/closet,
/obj/effect/spawner/lootdrop/maintenance/two,
/turf/simulated/floor/plating{
icon_state = "asteroidplating"
},
@@ -41465,9 +41488,6 @@
name = "Port Asteroid Maintenance"
},
/obj/effect/mapping_helpers/airlock/access/all/engineering/maintenance,
/obj/structure/disposalpipe/segment{
dir = 4
},
/obj/structure/disposalpipe/segment{
dir = 4
},
@@ -41549,14 +41569,6 @@
icon_state = "wood-broken7"
},
/area/station/maintenance/asmaint)
"gqG" = (
/obj/structure/disposalpipe/segment/corner{
dir = 4
},
/turf/simulated/floor/plasteel{
icon_state = "cafeteria"
},
/area/station/medical/break_room)
"gqH" = (
/obj/structure/cable/orange{
d1 = 1;
@@ -43786,6 +43798,7 @@
"hcK" = (
/obj/effect/decal/cleanable/cobweb,
/obj/structure/closet/wardrobe/black,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating,
/area/station/maintenance/port)
"hcT" = (
@@ -44813,6 +44826,7 @@
/area/mine/unexplored/cere/cargo)
"huF" = (
/obj/structure/table,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating,
/area/station/maintenance/disposal/west)
"huM" = (
@@ -44923,6 +44937,7 @@
/area/station/maintenance/disposal/west)
"hxc" = (
/obj/structure/closet/crate,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating{
icon_state = "asteroidplating"
},
@@ -46588,7 +46603,6 @@
/obj/structure/chair/sofa/corp/right{
dir = 8
},
/obj/structure/disposalpipe/segment,
/turf/simulated/floor/plasteel{
icon_state = "cafeteria"
},
@@ -46778,6 +46792,7 @@
/area/station/command/office/ntrep)
"ibf" = (
/obj/structure/closet/emcloset,
/obj/effect/spawner/lootdrop/maintenance/two,
/turf/simulated/floor/plating,
/area/station/maintenance/maintcentral)
"ibH" = (
@@ -48016,10 +48031,10 @@
d2 = 8;
icon_state = "4-8"
},
/obj/structure/disposalpipe/segment/corner{
dir = 1
},
/obj/effect/spawner/random_spawners/dirt_frequent,
/obj/structure/disposalpipe/segment{
dir = 4
},
/turf/simulated/floor/plasteel{
icon_state = "cafeteria"
},
@@ -49289,6 +49304,7 @@
/area/station/maintenance/fore)
"iOU" = (
/obj/structure/table/wood,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/wood,
/area/station/maintenance/starboard)
"iPa" = (
@@ -49913,6 +49929,7 @@
/area/station/science/xenobiology)
"iXm" = (
/obj/structure/closet,
/obj/effect/spawner/lootdrop/maintenance/two,
/turf/simulated/floor/plating/asteroid/ancient,
/area/station/maintenance/fsmaint)
"iXt" = (
@@ -50016,6 +50033,7 @@
/area/mine/unexplored/cere/orbiting)
"iZd" = (
/obj/structure/closet/emcloset,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating,
/area/station/hallway/primary/fore/west)
"iZr" = (
@@ -50488,7 +50506,6 @@
dir = 4;
pixel_x = 11
},
/obj/structure/disposalpipe/segment/corner,
/turf/simulated/floor/plasteel{
icon_state = "cafeteria"
},
@@ -50927,6 +50944,7 @@
/obj/structure/disposalpipe/segment/corner{
dir = 4
},
/obj/effect/spawner/lootdrop/maintenance/two,
/turf/simulated/floor/plating,
/area/station/maintenance/disposal/east)
"jpP" = (
@@ -52644,16 +52662,6 @@
},
/turf/simulated/floor/plating,
/area/station/maintenance/apmaint)
"jOU" = (
/obj/structure/disposalpipe/sortjunction{
dir = 2;
name = "disposal pipe - Genetics";
sort_type_txt = "23"
},
/turf/simulated/floor/plasteel{
icon_state = "cafeteria"
},
/area/station/medical/break_room)
"jPa" = (
/obj/structure/grille,
/turf/simulated/floor/plating{
@@ -55307,6 +55315,7 @@
"kIn" = (
/obj/structure/table,
/obj/item/storage/fancy/cigarettes,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating,
/area/station/maintenance/disposal/south)
"kIo" = (
@@ -56432,10 +56441,6 @@
icon_state = "redcorner"
},
/area/station/hallway/secondary/entry/north)
"kYJ" = (
/obj/structure/closet/crate,
/turf/simulated/floor/plating,
/area/station/maintenance/storage)
"kYN" = (
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
@@ -60579,6 +60584,7 @@
dir = 4
},
/obj/structure/closet/crate,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating,
/area/station/maintenance/disposal/east)
"mlM" = (
@@ -62181,6 +62187,7 @@
/area/station/maintenance/electrical_shop)
"mPu" = (
/obj/structure/table/wood/poker,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/wood{
icon_state = "wood-broken"
},
@@ -63160,10 +63167,6 @@
},
/turf/simulated/floor/plating,
/area/station/hallway/secondary/entry/north)
"neV" = (
/obj/structure/closet/crate,
/turf/simulated/floor/plating/asteroid/ancient,
/area/station/maintenance/port)
"nfb" = (
/obj/structure/table/glass,
/obj/item/storage/box/syringes,
@@ -63932,6 +63935,7 @@
d2 = 8;
icon_state = "4-8"
},
/obj/effect/mapping_helpers/airlock/access/all/command/general,
/turf/simulated/floor/plating,
/area/station/engineering/tech_storage)
"nta" = (
@@ -63956,6 +63960,11 @@
icon_state = "dark"
},
/area/station/turret_protected/ai_upload)
"ntf" = (
/obj/structure/closet/emcloset,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating/asteroid/ancient,
/area/station/maintenance/port)
"nto" = (
/obj/effect/spawner/window/reinforced/grilled,
/obj/structure/cable/orange,
@@ -65217,7 +65226,6 @@
/turf/simulated/wall,
/area/station/hallway/primary/aft/west)
"nOU" = (
/obj/structure/disposalpipe/segment,
/obj/machinery/door/airlock/maintenance/external{
name = "External Airlock Access"
},
@@ -67790,6 +67798,13 @@
},
/turf/simulated/floor/plating,
/area/station/turret_protected/aisat/interior/secondary)
"oHm" = (
/obj/structure/disposalpipe/segment,
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/turf/simulated/floor/plasteel{
icon_state = "cafeteria"
},
/area/station/medical/break_room)
"oIc" = (
/obj/structure/cable{
d2 = 4;
@@ -70426,6 +70441,7 @@
},
/obj/structure/rack,
/obj/item/stack/rods,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating/asteroid/ancient,
/area/station/maintenance/starboard)
"pxV" = (
@@ -71427,6 +71443,7 @@
/area/station/command/office/hos)
"pOf" = (
/obj/structure/closet/firecloset/full,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating/asteroid/ancient,
/area/station/maintenance/fsmaint2)
"pOk" = (
@@ -76558,6 +76575,7 @@
/area/station/public/quantum/cargo)
"rxg" = (
/obj/structure/closet,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating/asteroid/ancient,
/area/station/maintenance/apmaint)
"rxi" = (
@@ -85427,9 +85445,6 @@
name = "Engine Room"
},
/obj/effect/mapping_helpers/airlock/access/all/engineering/general,
/obj/structure/disposalpipe/segment{
dir = 4
},
/obj/structure/cable{
d1 = 4;
d2 = 8;
@@ -85474,6 +85489,16 @@
icon_state = "neutralfull"
},
/area/station/hallway/primary/port/east)
"urD" = (
/obj/structure/disposalpipe/segment,
/obj/structure/chair/stool,
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 5
},
/turf/simulated/floor/plasteel{
icon_state = "cafeteria"
},
/area/station/medical/break_room)
"urK" = (
/obj/machinery/mineral/stacking_machine{
output_dir = 2;
@@ -85504,15 +85529,6 @@
icon_state = "asteroidplating"
},
/area/station/maintenance/port)
"uso" = (
/obj/structure/disposalpipe/junction{
dir = 1
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/turf/simulated/floor/plasteel{
icon_state = "cafeteria"
},
/area/station/medical/break_room)
"usr" = (
/obj/machinery/atmospherics/pipe/simple/hidden/supply,
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
@@ -87202,18 +87218,6 @@
},
/turf/simulated/floor/plating,
/area/station/command/bridge)
"uSc" = (
/obj/structure/chair/stool,
/obj/structure/disposalpipe/junction{
dir = 1
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 5
},
/turf/simulated/floor/plasteel{
icon_state = "cafeteria"
},
/area/station/medical/break_room)
"uSr" = (
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{
dir = 5
@@ -87878,10 +87882,6 @@
/obj/structure/disposalpipe/junction/reversed,
/turf/simulated/floor/plating,
/area/station/maintenance/starboard)
"vbu" = (
/obj/structure/closet,
/turf/simulated/floor/plating/asteroid/ancient,
/area/station/maintenance/fpmaint)
"vbD" = (
/obj/machinery/atmospherics/pipe/manifold/hidden,
/turf/simulated/floor/plasteel{
@@ -95118,6 +95118,7 @@
"xiV" = (
/obj/structure/closet/emcloset,
/obj/effect/decal/cleanable/cobweb,
/obj/effect/spawner/lootdrop/maintenance,
/turf/simulated/floor/plating/asteroid/ancient,
/area/station/maintenance/port)
"xja" = (
@@ -108722,7 +108723,7 @@ xJa
xJa
rUo
nxA
vbu
bzh
xJa
cRv
rNK
@@ -108820,7 +108821,7 @@ vtY
uCK
vtY
uCK
uCK
eTI
vtY
ccW
ccW
@@ -110879,7 +110880,7 @@ uCK
uCK
uCK
uCK
uCK
bWG
vtY
vtY
ccW
@@ -111574,7 +111575,7 @@ rNK
rNK
pXy
pXy
ccx
ntf
eCI
aue
uaW
@@ -111654,7 +111655,7 @@ vtY
vtY
uCK
uCK
neV
taQ
vtY
ccW
rWw
@@ -121944,7 +121945,7 @@ chX
ciG
gPL
pQN
sKh
wQl
nta
cGd
dzs
@@ -124257,7 +124258,7 @@ njR
ciG
gPL
pQN
fYD
tnj
clq
cGd
xPU
@@ -125148,7 +125149,7 @@ uEU
abW
abW
wDs
bbc
ccV
rVx
qLN
aJp
@@ -130134,7 +130135,7 @@ bWU
bXA
bYe
bDR
kYJ
kyo
oqB
cRo
kzf
@@ -146851,7 +146852,7 @@ iJa
imG
imG
imG
imG
gge
aXn
imG
vRX
@@ -148620,8 +148621,8 @@ bHr
uhF
mqe
dYc
uso
uSc
oHm
urD
xQF
uhF
nDq
@@ -148876,8 +148877,8 @@ xeq
cdI
uhF
owY
gqG
jOU
tKE
tKE
fLp
cnW
gxB
@@ -151461,7 +151462,7 @@ itf
dCS
xAV
ozK
gFg
aUU
wyL
jeB
hpB
@@ -152737,7 +152738,7 @@ mOC
frg
lWu
gSQ
gSQ
alq
itf
itf
gSQ

View File

@@ -10845,7 +10845,6 @@
/area/station/maintenance/incinerator)
"aLk" = (
/obj/structure/disposalpipe/segment,
/obj/structure/disposalpipe/segment,
/obj/effect/turf_decal/stripes/line{
dir = 8
},
@@ -11828,7 +11827,6 @@
},
/area/station/service/bar)
"aOd" = (
/obj/structure/disposalpipe/segment,
/obj/machinery/atmospherics/pipe/simple/visible{
dir = 10
},
@@ -70042,9 +70040,6 @@
/area/station/command/office/hop)
"gFa" = (
/obj/machinery/door/firedoor,
/obj/structure/disposalpipe/segment{
dir = 4
},
/obj/effect/turf_decal/delivery,
/obj/structure/disposalpipe/segment{
dir = 4
@@ -82625,15 +82620,6 @@
},
/area/station/security/prison/cell_block)
"ont" = (
/obj/structure/disposalpipe/segment{
dir = 4
},
/obj/effect/turf_decal/stripes/line{
dir = 1
},
/obj/machinery/light{
dir = 1
},
/obj/structure/disposalpipe/segment{
dir = 4
},

View File

@@ -71465,20 +71465,6 @@
/obj/effect/landmark/damageturf,
/turf/simulated/floor/plating,
/area/station/maintenance/apmaint)
"oDZ" = (
/obj/structure/cable{
d1 = 4;
d2 = 8;
icon_state = "4-8"
},
/obj/structure/disposalpipe/segment{
dir = 4
},
/obj/structure/disposalpipe/segment{
dir = 4
},
/turf/simulated/floor/plating,
/area/station/maintenance/port)
"oEe" = (
/obj/machinery/atmospherics/trinary/filter{
dir = 4;
@@ -115249,7 +115235,7 @@ nBj
cgt
cdT
wfa
oDZ
bqQ
cCj
cdT
kNJ

View File

@@ -157,3 +157,10 @@
#define STATUS_EFFECT_CONSTANT * 20
#define IS_HORIZONTAL(x) x.body_position
/// Compatible firemode is in the gun. Wait until it's held in the user hands.
#define AUTOFIRE_STAT_IDLE (1<<0)
/// Gun is active and in the user hands. Wait until user does a valid click.
#define AUTOFIRE_STAT_ALERT (1<<1)
/// Gun is shooting.
#define AUTOFIRE_STAT_FIRING (1<<2)

View File

@@ -219,8 +219,17 @@
/////////////////
///from base of client/Click(): (atom/target, atom/location, control, params, mob/user)
// /client signals
/// from base of client/Click(): (atom/target, atom/location, control, params, mob/user)
#define COMSIG_CLIENT_CLICK "atom_client_click"
/// from base of client/MouseDown(): (/client, object, location, control, params)
#define COMSIG_CLIENT_MOUSEDOWN "client_mousedown"
/// from base of client/MouseUp(): (/client, object, location, control, params)
#define COMSIG_CLIENT_MOUSEUP "client_mouseup"
#define COMPONENT_CLIENT_MOUSEUP_INTERCEPT (1<<0)
/// from base of client/MouseUp(): (/client, object, location, control, params)
#define COMSIG_CLIENT_MOUSEDRAG "client_mousedrag"
///from base of area/Entered(): (/area)
#define COMSIG_ENTER_AREA "enter_area"
@@ -708,11 +717,16 @@
// /obj/item/gun signals
///called in /obj/item/gun/process_fire (user, target, params, zone_override)
/// called in /obj/item/gun/process_fire (user, target, params, zone_override)
#define COMSIG_MOB_FIRED_GUN "mob_fired_gun"
///called in /obj/item/gun/process_fire (user, target)
/// called in /obj/item/gun/process_fire (user, target)
#define COMSIG_GUN_FIRED "gun_fired"
/// called in /datum/component/automatic_fire/proc/on_mouse_down: (client/clicker, atom/target, turf/location, control, params)
#define COMSIG_AUTOFIRE_ONMOUSEDOWN "autofire_onmousedown"
#define COMPONENT_AUTOFIRE_ONMOUSEDOWN_BYPASS (1<<0)
/// called in /datum/component/automatic_fire/proc/process_shot(): (atom/target, mob/living/shooter, allow_akimbo, params)
#define COMSIG_AUTOFIRE_SHOT "autofire_shot"
#define COMPONENT_AUTOFIRE_SHOT_SUCCESS (1<<0)
// /obj/item/grenade signals
@@ -1044,3 +1058,6 @@
// Sent when a mob spawner is attacked directly or via projectile.
#define COMSIG_SPAWNER_SET_TARGET "spawner_set_target"
/// Used by admin-tooling to remove radiation
#define COMSIG_ADMIN_DECONTAMINATE "admin_decontaminate"

View File

@@ -58,6 +58,10 @@
#define isclothing(A) (istype(A, /obj/item/clothing))
#define isprojectile(A) (istype(A, /obj/item/projectile))
#define isgun(A) (istype(A, /obj/item/gun))
#define is_pen(W) (istype(W, /obj/item/pen) || istype(W, /obj/item/flashlight/pen))
#define is_pda(W) (istype(W, /obj/item/pda))

View File

@@ -14,4 +14,4 @@
#define MARTIAL_COMBO_STEP_HELP "Help"
// A check used for all act types. Such as disarm_act
#define MARTIAL_ARTS_ACT_CHECK if((. = ..()) != FALSE) return .
#define MARTIAL_ARTS_ACT_CHECK if((. = ..()) != FALSE) return

View File

@@ -263,8 +263,6 @@
#define ispathsilicon(A) (ispath(A, /mob/living/silicon))
#define ispathanimal(A) (ispath(A, /mob/living/simple_animal))
#define isAutoAnnouncer(A) (istype((A), /mob/living/automatedannouncer))
#define iscameramob(A) (istype((A), /mob/camera))
#define isAIEye(A) (istype((A), /mob/camera/aiEye))
#define isovermind(A) (istype((A), /mob/camera/blob))

View File

@@ -242,7 +242,6 @@
continue
if(is_same_root_atom(M, speaker_coverage[ear]))
. |= M
return .
/proc/inLineOfSight(X1,Y1,X2,Y2,Z=1,PX1=16.5,PY1=16.5,PX2=16.5,PY2=16.5)
var/turf/T

View File

@@ -189,7 +189,6 @@
return min(max(. + rand(-25, 25), -185), 34)
else if(species == "Vox")
. = rand(1, 6)
return .
/proc/skintone2racedescription(tone, species = "Human")
if(species == "Human")
@@ -609,7 +608,7 @@ GLOBAL_LIST_EMPTY(do_after_once_tracker)
var/viewX
var/viewY
if(isnum(view))
var/totalviewrange = 1 + 2 * view
var/totalviewrange = (view < 0 ? -1 : 1) + 2 * view
viewX = totalviewrange
viewY = totalviewrange
else if(istext(view))
@@ -625,6 +624,12 @@ GLOBAL_LIST_EMPTY(do_after_once_tracker)
return list(viewX, viewY)
/proc/in_view_range(mob/user, atom/A)
var/list/view_range = getviewsize(user.client.view)
var/turf/source = get_turf(user)
var/turf/target = get_turf(A)
return ISINRANGE(target.x, source.x - view_range[1], source.x + view_range[1]) && ISINRANGE(target.y, source.y - view_range[2], source.y + view_range[2])
//Used in chemical_mob_spawn. Generates a random mob based on a given gold_core_spawnable value.
/proc/create_random_mob(spawn_location, mob_class = HOSTILE_SPAWN)
var/static/list/mob_spawn_meancritters = list() // list of possible hostile mobs

View File

@@ -12,9 +12,12 @@
return default
/proc/sanitize_inlist(value, list/List, default)
if(value in List) return value
if(default) return default
if(length(List)) return pick(List)
if(value in List)
return value
if(default)
return default
if(length(List))
return pick(List)
/proc/sanitize_json(json_input)
if(length(json_input) && istext(json_input))
@@ -35,19 +38,25 @@
return default
/proc/sanitize_hexcolor(color, default="#000000")
if(!istext(color)) return default
if(!istext(color))
return default
var/len = length(color)
if(len != 7 && len !=4) return default
if(text2ascii(color,1) != 35) return default //35 is the ascii code for "#"
if(len != 7 && len !=4)
return default
if(text2ascii(color, 1) != 35)
return default //35 is the ascii code for "#"
. = "#"
for(var/i=2,i<=len,i++)
var/ascii = text2ascii(color,i)
switch(ascii)
if(48 to 57) . += ascii2text(ascii) //numbers 0 to 9
if(97 to 102) . += ascii2text(ascii) //letters a to f
if(65 to 70) . += ascii2text(ascii+32) //letters A to F - translates to lowercase
else return default
return .
if(48 to 57)
. += ascii2text(ascii) //numbers 0 to 9
if(97 to 102)
. += ascii2text(ascii) //letters a to f
if(65 to 70)
. += ascii2text(ascii + 32) //letters A to F - translates to lowercase
else
return default
/proc/sanitize_ooccolor(color)
var/list/HSL = rgb2hsl(hex2num(copytext(color,2,4)),hex2num(copytext(color,4,6)),hex2num(copytext(color,6,8)))

View File

@@ -193,7 +193,6 @@
if(rights & R_MENTOR) . += "[seperator]+MENTOR"
if(rights & R_VIEWRUNTIMES) . += "[seperator]+VIEWRUNTIMES"
if(rights & R_MAINTAINER) . += "[seperator]+MAINTAINER"
return .
/proc/ui_style2icon(ui_style)
switch(ui_style)

View File

@@ -323,7 +323,6 @@
if(A.control_disabled)
continue
. += A
return .
//Find an active ai with the least borgs. VERBOSE PROCNAME HUH!
/proc/select_active_ai_with_fewest_borgs()
@@ -1951,6 +1950,27 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
pixel_x = initialpixelx
pixel_y = initialpixely
/// Returns a turf based on text inputs, original turf and viewing client
/proc/parse_caught_click_modifiers(list/modifiers, turf/origin, client/viewing_client)
if(!modifiers)
return
var/screen_loc = splittext(modifiers["screen-loc"], ",")
var/list/actual_view = getviewsize(viewing_client ? viewing_client.view : world.view)
var/click_turf_x = splittext(screen_loc[1], ":")
var/click_turf_y = splittext(screen_loc[2], ":")
var/click_turf_z = origin.z
var/click_turf_px = text2num(click_turf_x[2])
var/click_turf_py = text2num(click_turf_y[2])
click_turf_x = origin.x + text2num(click_turf_x[1]) - round(actual_view[1] / 2) - 1
click_turf_y = origin.y + text2num(click_turf_y[1]) - round(actual_view[2] / 2) - 1
var/turf/click_turf = locate(clamp(click_turf_x, 1, world.maxx), clamp(click_turf_y, 1, world.maxy), click_turf_z)
LAZYSET(modifiers, "icon-x", "[(click_turf_px - click_turf.pixel_x) + ((click_turf_x - click_turf.x) * world.icon_size)]")
LAZYSET(modifiers, "icon-y", "[(click_turf_py - click_turf.pixel_y) + ((click_turf_y - click_turf.y) * world.icon_size)]")
return click_turf
/proc/params2turf(scr_loc, turf/origin, client/C)
if(!scr_loc)
return null

View File

@@ -47,4 +47,71 @@ actually if you do something in that proc like changing user location or whateve
to inform the game this action was expected and its fine
*/
/atom/proc/MouseDrop_T(atom/dropping, mob/user, params) // return TRUE if you want to prevent us click the object after it
return
return FALSE
/client/MouseDown(datum/object, location, control, params)
if(QDELETED(object)) // Yep, you can click on qdeleted things before they have time to nullspace. Fun.
return
SEND_SIGNAL(src, COMSIG_CLIENT_MOUSEDOWN, object, location, control, params)
if(mouse_down_icon)
mouse_pointer_icon = mouse_down_icon
var/delay = mob.CanMobAutoclick(object, location, params)
if(delay)
selected_target[1] = object
selected_target[2] = params
while(selected_target[1])
Click(selected_target[1], location, control, selected_target[2])
sleep(delay)
/client/MouseUp(object, location, control, params)
if(SEND_SIGNAL(src, COMSIG_CLIENT_MOUSEUP, object, location, control, params) & COMPONENT_CLIENT_MOUSEUP_INTERCEPT)
click_intercept_time = world.time
if(mouse_up_icon)
mouse_pointer_icon = mouse_up_icon
selected_target[1] = null
/mob/proc/CanMobAutoclick(object, location, params)
return FALSE
/mob/living/carbon/CanMobAutoclick(atom/object, location, params)
if(!object.IsAutoclickable())
return FALSE
var/obj/item/active_item = get_active_hand()
return active_item?.CanItemAutoclick(object, location, params)
/obj/item/proc/CanItemAutoclick(object, location, params)
return FALSE
/atom/proc/IsAutoclickable()
return TRUE
/obj/screen/IsAutoclickable()
return FALSE
/obj/screen/click_catcher/IsAutoclickable()
return TRUE
// The actual arguments of this:
// MouseDrag(src_object as null|atom in usr.client,
// over_object as null|atom in usr.client,
// src_location as null|turf|text in usr.client,
// over_location as null|turf|text in usr.client,
// src_control as text, over_control as text, params as text)
/client/MouseDrag(src_object, atom/over_object, src_location, turf/over_location, src_control, over_control, params)
var/list/modifiers = params2list(params)
if(!drag_start) // If we're just starting to drag
drag_start = world.time
drag_details = modifiers.Copy()
mouseParams = params
mouse_location_UID = isturf(over_location) ? over_location.UID() : over_location
mouse_object_UID = over_object?.UID()
if(selected_target[1] && over_object?.IsAutoclickable())
selected_target[1] = over_object
selected_target[2] = params
SEND_SIGNAL(src, COMSIG_CLIENT_MOUSEDRAG, src_object, over_object, src_location, over_location, src_control, over_control, params)
return ..()
/client/MouseDrop(atom/src_object, atom/over_object, atom/src_location, atom/over_location, src_control, over_control, params)
..()
drag_start = 0
drag_details = null

View File

@@ -13,6 +13,8 @@ PROCESSING_SUBSYSTEM_DEF(radiation)
var/rad_cache_update_interval = 5 SECONDS
var/list/turf_rad_cache = list()
var/list/prev_rad_cache = list()
/// Lazy list of all radioactive components
var/list/all_radiations
/datum/controller/subsystem/processing/radiation/proc/warn(datum/component/radioactive/contamination)

View File

@@ -81,9 +81,9 @@ SUBSYSTEM_DEF(ticker)
switch(current_state)
if(GAME_STATE_STARTUP)
// This is ran as soon as the MC starts firing, and should only run ONCE, unless startup fails
round_start_time = world.time + (GLOB.configuration.general.lobby_time SECONDS)
pregame_timeleft = GLOB.configuration.general.lobby_time SECONDS
to_chat(world, "<b><span class='darkmblue'>Welcome to the pre-game lobby!</span></b>")
round_start_time = world.time + pregame_timeleft
to_chat(world, "<B><span class='darkmblue'>Welcome to the pre-game lobby!</span></B>")
to_chat(world, "Please, setup your character and select ready. Game will start in [GLOB.configuration.general.lobby_time] seconds")
current_state = GAME_STATE_PREGAME
fire() // TG says this is a good idea
@@ -95,12 +95,9 @@ SUBSYSTEM_DEF(ticker)
return
// This is so we dont have sleeps in controllers, because that is a bad, bad thing
if(!delay_end)
pregame_timeleft = max(0, round_start_time - world.time) // Normal lobby countdown when roundstart was not delayed
else
pregame_timeleft = max(0, pregame_timeleft - wait) // If roundstart was delayed, we should resume the countdown where it left off
pregame_timeleft = max(0, round_start_time - world.time)
if(pregame_timeleft <= 600 && !tipped) // 60 seconds
if(pregame_timeleft <= 1 MINUTES && !tipped)
send_tip_of_the_round()
tipped = TRUE

View File

@@ -120,7 +120,8 @@
return
if(!status_only)
button.name = name
button.desc = desc
if(desc)
button.desc = "[desc] [initial(button.desc)]"
if(owner?.hud_used && background_icon_state == ACTION_BUTTON_DEFAULT_BACKGROUND)
var/list/settings = owner.hud_used.get_action_buttons_icons()
if(button.icon != settings["bg_icon"])
@@ -679,7 +680,7 @@
var/datum/spell/spell = target
if(owner)
return spell.can_cast(owner)
return spell.can_cast(owner, show_message = TRUE)
return FALSE
/datum/action/spell_action/apply_unavailable_effect(atom/movable/screen/movable/action_button/button)

View File

@@ -0,0 +1,325 @@
#define AUTOFIRE_MOUSEUP 0
#define AUTOFIRE_MOUSEDOWN 1
/datum/component/automatic_fire
var/client/clicker
var/mob/living/shooter
var/atom/target
var/turf/target_loc // For dealing with locking on targets due to BYOND engine limitations (the mouse input only happening when mouse moves).
var/autofire_stat = AUTOFIRE_STAT_IDLE
var/mouse_parameters
/// Time between individual shots.
var/autofire_shot_delay = 0.3 SECONDS
/// This seems hacky but there can be two MouseDown() without a MouseUp() in between if the user holds click and uses alt+tab, printscreen or similar.
var/mouse_status = AUTOFIRE_MOUSEUP
/// Should dual wielding be allowed?
var/allow_akimbo
/// windup autofire vars
/// Whether the delay between shots increases over time, simulating a spooling weapon
var/windup_autofire = FALSE
/// the reduction to shot delay for windup
var/current_windup_reduction = 0
/// the percentage of autfire_shot_delay that is added to current_windup_reduction
var/windup_autofire_reduction_multiplier = 0.3
/// How high of a reduction that current_windup_reduction can reach
var/windup_autofire_cap = 0.3
/// How long it takes for weapons that have spooled-up to reset back to the original firing speed
var/windup_spindown = 3 SECONDS
/// Timer for tracking the spindown reset timings
var/timerid
COOLDOWN_DECLARE(next_shot_cd)
/datum/component/automatic_fire/Initialize(autofire_shot_delay, windup_autofire, windup_autofire_reduction_multiplier, windup_autofire_cap, windup_spindown, allow_akimbo = TRUE)
. = ..()
if(!isgun(parent))
return COMPONENT_INCOMPATIBLE
var/obj/item/gun = parent
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(wake_up))
if(autofire_shot_delay)
src.autofire_shot_delay = autofire_shot_delay
src.allow_akimbo = allow_akimbo
if(windup_autofire)
src.windup_autofire = windup_autofire
src.windup_autofire_reduction_multiplier = windup_autofire_reduction_multiplier
src.windup_autofire_cap = windup_autofire_cap
src.windup_spindown = windup_spindown
if(autofire_stat == AUTOFIRE_STAT_IDLE && ismob(gun.loc))
var/mob/user = gun.loc
wake_up(src, user)
/datum/component/automatic_fire/Destroy()
autofire_off()
return ..()
/datum/component/automatic_fire/process(seconds_per_tick)
if(autofire_stat != AUTOFIRE_STAT_FIRING)
STOP_PROCESSING(SSprojectiles, src)
return
process_shot()
/datum/component/automatic_fire/proc/wake_up(datum/source, mob/user, slot)
SIGNAL_HANDLER // COMSIG_ITEM_EQUIPPED
if(autofire_stat == AUTOFIRE_STAT_ALERT)
return // We've updated the firemode. No need for more.
if(autofire_stat == AUTOFIRE_STAT_FIRING)
stop_autofiring() // Let's stop shooting to avoid issues.
return
if(user.is_holding(parent))
autofire_on(user.client)
// There is a gun and there is a user wielding it. The component now waits for the mouse click.
/datum/component/automatic_fire/proc/autofire_on(client/user_client)
if(autofire_stat != AUTOFIRE_STAT_IDLE)
return
autofire_stat = AUTOFIRE_STAT_ALERT
if(!QDELETED(user_client))
clicker = user_client
shooter = user_client.mob
RegisterSignal(user_client, COMSIG_CLIENT_MOUSEDOWN, PROC_REF(on_mouse_down))
if(!QDELETED(shooter))
RegisterSignal(shooter, COMSIG_MOB_LOGOUT, PROC_REF(autofire_off))
UnregisterSignal(shooter, COMSIG_MOB_LOGIN)
RegisterSignal(parent, list(COMSIG_PARENT_QDELETING, COMSIG_ITEM_DROPPED), PROC_REF(autofire_off))
parent.RegisterSignal(src, COMSIG_AUTOFIRE_ONMOUSEDOWN, TYPE_PROC_REF(/obj/item/gun, autofire_bypass_check))
parent.RegisterSignal(parent, COMSIG_AUTOFIRE_SHOT, TYPE_PROC_REF(/obj/item/gun, do_autofire))
/datum/component/automatic_fire/proc/autofire_off(datum/source)
SIGNAL_HANDLER // COMSIG_MOB_LOGOUT
if(autofire_stat == AUTOFIRE_STAT_IDLE)
return
if(autofire_stat == AUTOFIRE_STAT_FIRING)
stop_autofiring()
autofire_stat = AUTOFIRE_STAT_IDLE
if(!QDELETED(clicker))
UnregisterSignal(clicker, list(COMSIG_CLIENT_MOUSEDOWN, COMSIG_CLIENT_MOUSEUP, COMSIG_CLIENT_MOUSEDRAG))
mouse_status = AUTOFIRE_MOUSEUP // In regards to the component there's no click anymore to care about.
clicker = null
if(!QDELETED(shooter))
RegisterSignal(shooter, COMSIG_MOB_LOGIN, PROC_REF(on_client_login))
UnregisterSignal(shooter, COMSIG_MOB_LOGOUT)
UnregisterSignal(parent, list(COMSIG_PARENT_QDELETING, COMSIG_ITEM_DROPPED))
shooter = null
parent.UnregisterSignal(parent, COMSIG_AUTOFIRE_SHOT)
parent.UnregisterSignal(src, COMSIG_AUTOFIRE_ONMOUSEDOWN)
/datum/component/automatic_fire/proc/on_client_login(mob/source)
SIGNAL_HANDLER // COMSIG_MOB_LOGIN
if(!source.client)
return
if(source.is_holding(parent))
autofire_on(source.client)
/datum/component/automatic_fire/proc/on_mouse_down(client/source, atom/_target, turf/location, control, params)
SIGNAL_HANDLER // COMSIG_CLIENT_MOUSEDOWN
var/list/modifiers = params2list(params) // If they're shift+clicking, for example, let's not have them accidentally shoot.
if(modifiers["shift"])
return
if(modifiers["ctrl"])
return
if(modifiers["middle"])
return
if(modifiers["right"])
return
if(modifiers["alt"])
return
if(source.mob.in_throw_mode)
return
if(!isturf(source.mob.loc)) // No firing inside lockers and stuff.
return
if(get_dist(source.mob, _target) < 2) // Adjacent clicking.
return
if(isnull(location) || istype(_target, /obj/screen)) // Clicking on a screen object.
if(_target.plane != CLICKCATCHER_PLANE) // The clickcatcher is a special case. We want the click to trigger then, under it.
return // If we click and drag on our worn backpack, for example, we want it to open instead.
_target = parse_caught_click_modifiers(modifiers, get_turf(source.eye), source)
params = list2params(modifiers)
if(!_target)
CRASH("Failed to get the turf under clickcatcher")
if(SEND_SIGNAL(src, COMSIG_AUTOFIRE_ONMOUSEDOWN, source, _target, location, control, params) & COMPONENT_AUTOFIRE_ONMOUSEDOWN_BYPASS)
return
source.click_intercept_time = world.time // From this point onwards Click() will no longer be triggered.
if(autofire_stat == AUTOFIRE_STAT_IDLE)
CRASH("on_mouse_down() called with [autofire_stat] autofire_stat")
if(autofire_stat == AUTOFIRE_STAT_FIRING)
stop_autofiring() // This can happen if we click and hold and then alt+tab, printscreen or other such action. MouseUp won't be called then and it will keep autofiring.
target = _target
target_loc = get_turf(target)
mouse_parameters = params
INVOKE_ASYNC(src, PROC_REF(start_autofiring))
/datum/component/automatic_fire/proc/start_autofiring()
if(autofire_stat == AUTOFIRE_STAT_FIRING)
return
autofire_stat = AUTOFIRE_STAT_FIRING
clicker.mouse_override_icon = 'icons/effects/mouse_pointers/weapon_pointer.dmi'
clicker.mouse_pointer_icon = clicker.mouse_override_icon
if(mouse_status == AUTOFIRE_MOUSEUP) // See mouse_status definition for the reason for this.
RegisterSignal(clicker, COMSIG_CLIENT_MOUSEUP, PROC_REF(on_mouse_up))
mouse_status = AUTOFIRE_MOUSEDOWN
RegisterSignal(shooter, COMSIG_MOB_SWAPPED_HANDS, PROC_REF(stop_autofiring))
if(isgun(parent))
var/obj/item/gun/shoota = parent
if(!shoota.on_autofire_start(shooter)) // This is needed because the minigun has a do_after before firing and signals are async.
stop_autofiring()
return
if(autofire_stat != AUTOFIRE_STAT_FIRING)
return // Things may have changed while on_autofire_start() was being processed, due to do_after's sleep.
if(!process_shot()) // First shot is processed instantly.
return // If it fails, such as when the gun is empty, then there's no need to schedule a second shot.
START_PROCESSING(SSprojectiles, src)
RegisterSignal(clicker, COMSIG_CLIENT_MOUSEDRAG, PROC_REF(on_mouse_drag))
/datum/component/automatic_fire/proc/on_mouse_up(datum/source, atom/object, turf/location, control, params)
SIGNAL_HANDLER // COMSIG_CLIENT_MOUSEUP
UnregisterSignal(clicker, COMSIG_CLIENT_MOUSEUP)
mouse_status = AUTOFIRE_MOUSEUP
if(autofire_stat == AUTOFIRE_STAT_FIRING)
stop_autofiring()
return COMPONENT_CLIENT_MOUSEUP_INTERCEPT
/datum/component/automatic_fire/proc/stop_autofiring(datum/source, atom/object, turf/location, control, params)
SIGNAL_HANDLER // COMSIG_MOB_SWAPPED_HANDS
if(autofire_stat != AUTOFIRE_STAT_FIRING)
return
STOP_PROCESSING(SSprojectiles, src)
autofire_stat = AUTOFIRE_STAT_ALERT
if(clicker)
clicker.mouse_override_icon = null
clicker.mouse_pointer_icon = clicker.mouse_override_icon
UnregisterSignal(clicker, COMSIG_CLIENT_MOUSEDRAG)
if(!QDELETED(shooter))
UnregisterSignal(shooter, COMSIG_MOB_SWAPPED_HANDS)
target = null
target_loc = null
mouse_parameters = null
/datum/component/automatic_fire/proc/on_mouse_drag(client/source, atom/src_object, atom/over_object, turf/src_location, turf/over_location, src_control, over_control, params)
SIGNAL_HANDLER // COMSIG_CLIENT_MOUSEDRAG
if(isnull(over_location)) // This happens when the mouse is over an inventory or screen object, or on entering deep darkness, for example.
var/list/modifiers = params2list(params)
var/new_target = parse_caught_click_modifiers(modifiers, get_turf(source.eye), source)
params = list2params(modifiers)
mouse_parameters = params
if(!new_target)
if(QDELETED(target)) // No new target acquired, and old one was deleted, get us out of here.
stop_autofiring()
CRASH("on_mouse_drag failed to get the turf under screen object [over_object.type]. Old target was incidentally QDELETED.")
target = get_turf(target) // If previous target wasn't a turf, let's turn it into one to avoid locking onto a potentially moving target.
target_loc = target
CRASH("on_mouse_drag failed to get the turf under screen object [over_object.type]")
target = new_target
target_loc = new_target
return
target = over_object
target_loc = get_turf(over_object)
mouse_parameters = params
/datum/component/automatic_fire/proc/process_shot()
if(autofire_stat != AUTOFIRE_STAT_FIRING)
return FALSE
if(!COOLDOWN_FINISHED(src, next_shot_cd))
return TRUE
if(QDELETED(target) || get_turf(target) != target_loc) // Target moved or got destroyed since we last aimed.
target = target_loc // So we keep firing on the emptied tile until we move our mouse and find a new target.
if(get_dist(shooter, target) <= 0)
target = get_step(shooter, shooter.dir) // Shoot in the direction faced if the mouse is on the same tile as we are.
target_loc = target
else if(!in_view_range(shooter, target))
stop_autofiring() // Elvis has left the building.
return FALSE
shooter.face_atom(target)
var/next_delay = autofire_shot_delay
if(windup_autofire)
next_delay = clamp(next_delay - current_windup_reduction, round(autofire_shot_delay * windup_autofire_cap), autofire_shot_delay)
current_windup_reduction = (current_windup_reduction + round(autofire_shot_delay * windup_autofire_reduction_multiplier))
timerid = addtimer(CALLBACK(src, PROC_REF(windup_reset), FALSE), windup_spindown, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_STOPPABLE)
COOLDOWN_START(src, next_shot_cd, next_delay)
if(SEND_SIGNAL(parent, COMSIG_AUTOFIRE_SHOT, target, shooter, allow_akimbo, mouse_parameters) & COMPONENT_AUTOFIRE_SHOT_SUCCESS)
return TRUE
stop_autofiring()
return FALSE
/// Reset for our windup, resetting everything back to initial values after a variable set amount of time (determined by var/windup_spindown).
/datum/component/automatic_fire/proc/windup_reset(deltimer)
current_windup_reduction = initial(current_windup_reduction)
if(deltimer && timerid)
deltimer(timerid)
// Gun procs.
/obj/item/gun/proc/on_autofire_start(mob/living/shooter)
if(semicd || shooter.incapacitated() || !can_trigger_gun(shooter))
return FALSE
if(!can_shoot())
shoot_with_empty_chamber(shooter)
return FALSE
var/other_hand = shooter.get_organ(shooter.hand ? BODY_ZONE_PRECISE_R_HAND : BODY_ZONE_PRECISE_L_HAND)
if(weapon_weight == WEAPON_HEAVY && (shooter.get_inactive_hand() || !other_hand))
to_chat(shooter, "<span class='warning'>You need to use both hands!</span>")
return FALSE
return TRUE
/obj/item/gun/proc/autofire_bypass_check(datum/source, client/clicker, atom/target, turf/location, control, params)
SIGNAL_HANDLER // COMSIG_AUTOFIRE_ONMOUSEDOWN
if(clicker.mob.get_active_hand() != src)
return COMPONENT_AUTOFIRE_ONMOUSEDOWN_BYPASS
/obj/item/gun/proc/do_autofire(datum/source, atom/target, mob/living/shooter, allow_akimbo, params)
SIGNAL_HANDLER // COMSIG_AUTOFIRE_SHOT
if(semicd || shooter.incapacitated())
return NONE
if(!can_shoot())
shoot_with_empty_chamber(shooter)
return NONE
INVOKE_ASYNC(src, PROC_REF(do_autofire_shot), source, target, shooter, allow_akimbo, params)
return COMPONENT_AUTOFIRE_SHOT_SUCCESS // All is well, we can continue shooting.
/obj/item/gun/proc/do_autofire_shot(datum/source, atom/target, mob/living/shooter, allow_akimbo, params)
var/obj/item/gun/akimbo_gun = shooter.get_inactive_hand()
var/bonus_spread = 0
if(isgun(akimbo_gun) && weapon_weight < WEAPON_MEDIUM && allow_akimbo)
if(akimbo_gun.weapon_weight < WEAPON_MEDIUM && akimbo_gun.can_trigger_gun(shooter))
bonus_spread = dual_wield_spread
addtimer(CALLBACK(akimbo_gun, TYPE_PROC_REF(/obj/item/gun, process_fire), target, shooter, TRUE, params, null, bonus_spread), 1)
process_fire(target, shooter, TRUE, params, null, bonus_spread)
#undef AUTOFIRE_MOUSEUP
#undef AUTOFIRE_MOUSEDOWN

View File

@@ -13,17 +13,17 @@
var/can_contaminate
/datum/component/radioactive/Initialize(_strength = 0, _source, _half_life = RAD_HALF_LIFE, _can_contaminate = TRUE)
if(!istype(parent, /atom))
return COMPONENT_INCOMPATIBLE
strength = _strength
source = _source
hl3_release_date = _half_life
can_contaminate = _can_contaminate
if(istype(parent, /atom))
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, PROC_REF(rad_examine))
if(isitem(parent))
RegisterSignal(parent, COMSIG_ITEM_ATTACK, PROC_REF(rad_attack))
RegisterSignal(parent, COMSIG_ITEM_ATTACK_OBJ, PROC_REF(rad_attack))
else
return COMPONENT_INCOMPATIBLE
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, PROC_REF(rad_examine))
RegisterSignal(parent, COMSIG_ADMIN_DECONTAMINATE, PROC_REF(admin_decontaminate))
if(isitem(parent))
RegisterSignal(parent, COMSIG_ITEM_ATTACK, PROC_REF(rad_attack))
RegisterSignal(parent, COMSIG_ITEM_ATTACK_OBJ, PROC_REF(rad_attack))
if(strength > RAD_MINIMUM_CONTAMINATION)
SSradiation.warn(src)
//Let's make er glow
@@ -31,10 +31,12 @@
var/atom/movable/master = parent
master.add_filter("rad_glow", 2, list("type" = "outline", "color" = "#39ff1430", "size" = 2))
addtimer(CALLBACK(src, PROC_REF(glow_loop), master), rand(1, 19)) //Things should look uneven
LAZYADD(SSradiation.all_radiations, src)
START_PROCESSING(SSradiation, src)
/datum/component/radioactive/Destroy()
STOP_PROCESSING(SSradiation, src)
LAZYREMOVE(SSradiation.all_radiations, src)
var/atom/movable/master = parent
master.remove_filter("rad_glow")
return ..()
@@ -99,6 +101,17 @@
return
strength -= strength / hl3_release_date
/datum/component/radioactive/proc/admin_decontaminate()
SIGNAL_HANDLER
. = TRUE
if(ismob(parent))
var/mob/M = parent
M.radiation = 0
if(ismob(source))
var/mob/M = source
M.radiation = 0
qdel(src)
#undef RAD_AMOUNT_LOW
#undef RAD_AMOUNT_MEDIUM
#undef RAD_AMOUNT_HIGH

View File

@@ -158,7 +158,7 @@
var/charge_loss = 1 // how many charges do we lose
if(istype(hitby, /obj/item/projectile))
if(isprojectile(hitby))
var/obj/item/projectile/P = hitby
if(P.shield_buster)
charge_loss = 3

View File

@@ -76,7 +76,7 @@
var/obj/item/I = AM
if(I.flags & ABSTRACT)
return
else if(istype(AM, /obj/item/projectile))
else if(isprojectile(AM))
var/obj/item/projectile/P = AM
if(P.original != parent)
return

View File

@@ -23,9 +23,7 @@
effect_in = effect
if(isnull(effect_out))
effect_out = effect
if(D.start(atom_to_teleport, destination, variance_range, force_teleport, effect_in, effect_out, sound_in, sound_out, bypass_area_flag, safe_turf_pick, do_effect))
return TRUE
return FALSE
return D.start(atom_to_teleport, destination, variance_range, force_teleport, effect_in, effect_out, sound_in, sound_out, bypass_area_flag, safe_turf_pick, do_effect)
/datum/teleport
var/atom/movable/teleatom //atom to teleport
@@ -166,6 +164,16 @@
playSpecials(curturf,effectin,soundin)
if(isliving(teleatom))
var/mob/living/target_mob = teleatom
if(target_mob.buckled)
target_mob.buckled.unbuckle_mob(target_mob, force = TRUE)
if(target_mob.has_buckled_mobs())
target_mob.unbuckle_all_mobs(force = TRUE)
if(ismachinery(target_mob.loc) || istype(target_mob.loc, /obj/item/mecha_parts/mecha_equipment/medical/sleeper))
var/obj/location = target_mob.loc
location.force_eject_occupant(target_mob)
if(force_teleport)
teleatom.forceMove(destturf)
playSpecials(destturf,effectout,soundout)
@@ -173,13 +181,6 @@
if(teleatom.Move(destturf))
playSpecials(destturf,effectout,soundout)
if(isliving(teleatom))
var/mob/living/L = teleatom
if(L.buckled)
L.buckled.unbuckle_mob(L, force = TRUE)
if(L.has_buckled_mobs())
L.unbuckle_all_mobs(force = TRUE)
destarea.Entered(teleatom)
return TRUE

View File

@@ -53,7 +53,6 @@
return 0
if((reagents?(length(reagents)):(0)) < length(avail_reagents.reagent_list))
return -1
return .
/datum/recipe/proc/check_items(obj/container, list/ignored_items = null) //1=precisely, 0=insufficiently, -1=superfluous
. = 1
@@ -73,7 +72,6 @@
. = -1
if(length(checklist))
return 0
return .
//general version
/datum/recipe/proc/make(obj/container)
@@ -118,7 +116,6 @@
r_count = N_r
i_count = N_i
. = recipe
return .
/datum/recipe/proc/get_byproduct()
if(byproduct)

View File

@@ -32,6 +32,9 @@ Updates the spell's actions on use as well, so they know when they can or can't
..()
if(plasma_cost)
name = "[name] ([plasma_cost])"
action.name = name
action.desc = desc
action.UpdateButtons()
/datum/spell/alien_spell/write_custom_logs(list/targets, mob/user)
user.create_log(ATTACK_LOG, "Cast the spell [name]")

View File

@@ -68,8 +68,6 @@
. += "/([name])"
return .
/proc/key_name_admin(whom)
if(whom)
var/datum/whom_datum = whom //As long as it's not null, will be close enough/has the proc UID() that is all that's needed
@@ -92,3 +90,7 @@
/proc/log_and_message_admins(message)
log_admin("[key_name(usr)] " + message)
message_admins("[key_name_admin(usr)] " + message)
/proc/log_and_message_admins_no_usr(message)
log_admin(message)
message_admins(message)

View File

@@ -546,7 +546,7 @@
var/input_rune_key = tgui_input_list(user, "Choose a rune to teleport to", "Rune to Teleport to", potential_runes) //we know what key they picked
var/obj/effect/rune/teleport/actual_selected_rune = potential_runes[input_rune_key] //what rune does that key correspond to?
if(QDELETED(src) || !user || user.l_hand != src && user.r_hand != src || user.incapacitated() || !actual_selected_rune)
if(QDELETED(src) || !user || !user.is_holding(src) || user.incapacitated() || !actual_selected_rune)
return
if(HAS_TRAIT(user, TRAIT_FLOORED))

View File

@@ -466,7 +466,7 @@
if(IS_CULTIST(owner) && !owner.holy_check()) // Cultist holding the shield
// Hit by a projectile
if(istype(hitby, /obj/item/projectile))
if(isprojectile(hitby))
var/obj/item/projectile/P = hitby
var/shatter_chance = 0 // Percent chance of the shield shattering on a projectile hit
var/threshold // Depends on the damage Type (Brute or Burn)

View File

@@ -851,12 +851,6 @@
selection_deactivated_message = "<span class='notice'>APC logic thread restarting...</span>"
var/is_active = FALSE
/datum/spell/ai_spell/ranged/repair_cyborg/create_new_targeting()
var/datum/spell_targeting/click/T = new
T.allowed_type = /mob/living/silicon/robot
T.try_auto_target = FALSE
return T
/datum/spell/ai_spell/ranged/repair_cyborg/cast(list/targets, mob/user)
var/mob/living/silicon/robot/robot_target = targets[1]
if(!istype(robot_target))

View File

@@ -216,6 +216,9 @@
occupant = null
update_icon(UPDATE_ICON_STATE)
/obj/machinery/abductor/experiment/force_eject_occupant(mob/target)
eject_abductee()
/obj/machinery/abductor/experiment/broken
stat = BROKEN

View File

@@ -8,6 +8,9 @@
..()
if(hunger_cost)
name = "[name] ([hunger_cost])"
action.name = name
action.desc = desc
action.UpdateButtons()
/datum/spell/morph_spell/create_new_handler()
var/datum/spell_handler/morph/H = new

View File

@@ -28,10 +28,10 @@
/datum/spell/pulse_demon/proc/update_info()
if(locked)
name = "[initial(name)] (Locked) ([format_si_suffix(unlock_cost)]W)"
desc = "[initial(desc)] It costs [format_si_suffix(unlock_cost)]W to unlock."
desc = "[initial(desc)] It costs [format_si_suffix(unlock_cost)]W to unlock. <b>Alt-Click</b> this spell to unlock it."
else
name = "[initial(name)][cast_cost == 0 ? "" : " ([format_si_suffix(cast_cost)]W)"]"
desc = "[initial(desc)][spell_level == level_max ? "" : " It costs [format_si_suffix(upgrade_cost)]W to upgrade."]"
desc = "[initial(desc)][spell_level == level_max ? "" : " It costs [format_si_suffix(upgrade_cost)]W to upgrade. <b>Alt-Click</b> this spell to upgrade it."]"
action.name = name
action.desc = desc
action.UpdateButtons()

View File

@@ -163,6 +163,9 @@
name = "[initial(name)] ([unlock_amount]E)"
else
name = "[initial(name)] ([cast_amount]E)"
action.name = name
action.desc = desc
action.UpdateButtons()
/datum/spell/aoe/revenant/revert_cast(mob/user)
. = ..()

View File

@@ -1,9 +1,9 @@
#define CHALLENGE_TELECRYSTALS 1400
#define CHALLENGE_TIME_LIMIT 6000
#define CHALLENGE_TIME_LIMIT 10 MINUTES
#define CHALLENGE_SCALE_PLAYER 1 // How many player per scaling bonus
#define CHALLENGE_SCALE_BONUS 10 // How many TC per scaling bonus
#define CHALLENGE_MIN_PLAYERS 50
#define CHALLENGE_SHUTTLE_DELAY 18000 //30 minutes, so the ops have at least 10 minutes before the shuttle is callable. Gives the nuke ops at least 15 minutes before shuttle arrive.
#define CHALLENGE_SHUTTLE_DELAY 30 MINUTES // So the ops have at least 10 minutes before the shuttle is callable. Gives the nuke ops at least 15 minutes before shuttle arrive.
/obj/item/nuclear_challenge
name = "Declaration of War (Challenge Mode)"

View File

@@ -504,7 +504,7 @@ GLOBAL_VAR(bomb_set)
update_icon(UPDATE_OVERLAYS)
if(!safety)
message_admins("[key_name_admin(usr)] engaged a nuclear bomb [ADMIN_JMP(src)]")
if(!is_syndicate)
if(!is_syndicate && SSsecurity_level.get_current_level_as_number() != SEC_LEVEL_EPSILON)
SSsecurity_level.set_level(SEC_LEVEL_DELTA)
GLOB.bomb_set = TRUE // There can still be issues with this resetting when there are multiple bombs. Not a big deal though for Nuke
else

View File

@@ -439,7 +439,6 @@
. = ..()
if(.)
user.mind.AddSpell(new /datum/spell/aoe/conjure/construct(null))
return .
/datum/spellbook_entry/item/wands
name = "Wand Assortment"

View File

@@ -60,7 +60,7 @@
if(console)
console.scanner = null
if(occupant)
remove_mob(occupant)
remove_mob()
return ..()
/obj/machinery/clonescanner/MouseDrop_T(atom/movable/O, mob/user)
@@ -84,16 +84,16 @@
if(!occupant)
return
if(issilicon(user))
remove_mob(occupant)
remove_mob()
return
if(!Adjacent(user) || !ishuman(user) || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED))
return
remove_mob(occupant)
remove_mob()
/obj/machinery/clonescanner/relaymove(mob/user)
if(user.stat)
return
remove_mob(user)
remove_mob()
/obj/machinery/clonescanner/proc/try_scan(mob/living/carbon/human/scanned)
if(!scanned)
@@ -158,10 +158,10 @@
occupant = inserted
update_icon(UPDATE_ICON_STATE)
/obj/machinery/clonescanner/proc/remove_mob(mob/living/carbon/human/removed)
if(!istype(removed))
/obj/machinery/clonescanner/proc/remove_mob()
if(!occupant)
return
removed.forceMove(get_turf(loc))
occupant.forceMove(get_turf(loc))
occupant = null
update_scan_status()
update_icon(UPDATE_ICON_STATE)
@@ -192,3 +192,6 @@
return
var/obj/item/multitool/M = I
M.set_multitool_buffer(user, src)
/obj/machinery/clonescanner/force_eject_occupant(mob/target)
remove_mob()

View File

@@ -61,7 +61,7 @@
var/obj/machinery/door_timer/T = locate(ref)
if(T)
T.timer_end()
T.Radio.autosay("Timer stopped manually from a cell management console.", T.name, "Security", list(z))
T.Radio.autosay("Timer stopped manually from a cell management console.", T.name, "Security")
return TRUE
return FALSE

View File

@@ -645,7 +645,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
if(R.fields["id"] == E.fields["id"])
if(status_valid_for_demotion(R.fields["criminal"]))
set_criminal_status(usr, R, SEC_RECORD_STATUS_DEMOTE, reason, scan.assignment)
Radio.autosay("[scan.registered_name] ([scan.assignment]) has set [tempname] ([temprank]) to demote for: [reason]", name, "Command", list(z))
Radio.autosay("[scan.registered_name] ([scan.assignment]) has set [tempname] ([temprank]) to demote for: [reason]", name, "Command")
message_admins("[key_name_admin(usr)] ([scan.assignment]) has set [tempname] ([temprank]) to demote for: \"[reason]\"")
log_game("[key_name(usr)] ([scan.assignment]) has set \"[tempname]\" ([temprank]) to demote for: \"[reason]\".")
SSjobs.notify_by_name(tempname, "[scan.registered_name] ([scan.assignment]) has ordered your demotion. Report to their office, or the HOP. Reason given: \"[reason]\"")

View File

@@ -433,7 +433,7 @@
announce.autosay("[occupant.real_name] ([announce_rank]) [on_store_message]", "[on_store_name]")
else
if(announce_rank)
announce.autosay("[occupant.real_name] ([announce_rank]) [on_store_message]", "[on_store_name]")
announce.autosay("[occupant.real_name] ([announce_rank]) [on_store_message]", "[on_store_name]")
else
announce.autosay("[occupant.real_name] [on_store_message]", "[on_store_name]")
visible_message("<span class='notice'>[src] hums and hisses as it moves [occupant.real_name] into storage.</span>")
@@ -613,6 +613,9 @@
/obj/machinery/cryopod/blob_act()
return //Sorta gamey, but we don't really want these to be destroyed.
/obj/machinery/cryopod/force_eject_occupant(mob/target)
go_out()
/obj/machinery/cryopod/offstation
// Won't announce when used for cryoing.
silent = TRUE
@@ -667,7 +670,7 @@
/proc/cryo_ssd(mob/living/person_to_cryo)
if(istype(person_to_cryo.loc, /obj/machinery/cryopod))
return 0
return FALSE
if(isobj(person_to_cryo.loc))
var/obj/O = person_to_cryo.loc
O.force_eject_occupant(person_to_cryo)
@@ -685,8 +688,8 @@
var/obj/effect/portal/SP = new /obj/effect/portal(T, null, null, 40, create_sparks = FALSE)
SP.name = "NT SSD Teleportation Portal"
target_cryopod.take_occupant(person_to_cryo, 1)
return 1
return 0
return TRUE
return FALSE
/proc/force_cryo_human(mob/living/carbon/person_to_cryo)
if(!istype(person_to_cryo))

View File

@@ -56,7 +56,7 @@
/obj/structure/barricade/CanPass(atom/movable/mover, turf/target)//So bullets will fly over and stuff.
if(locate(/obj/structure/barricade) in get_turf(mover))
return TRUE
else if(istype(mover, /obj/item/projectile))
else if(isprojectile(mover))
if(!anchored)
return TRUE
var/obj/item/projectile/proj = mover
@@ -449,7 +449,7 @@
/obj/structure/barricade/dropwall/firewall/Crossed(atom/movable/AM, oldloc)
. = ..()
if(!istype(AM, /obj/item/projectile))
if(!isprojectile(AM))
return
var/obj/item/projectile/P = AM
P.immolate ++

View File

@@ -166,7 +166,7 @@
return
if(timing)
if(timeleft() <= 0)
Radio.autosay("Timer has expired. Releasing prisoner.", name, "Security", list(z))
Radio.autosay("Timer has expired. Releasing prisoner.", name, "Security")
occupant = CELL_NONE
timer_end() // open doors, reset timer, clear status screen
timing = FALSE
@@ -385,7 +385,7 @@
return FALSE
releasetime = world.timeofday + timetoset
var/resettext = isobserver(usr) ? "for: [reset_reason]." : "by [usr.name] for: [reset_reason]."
Radio.autosay("Prisoner [occupant] had their timer reset [resettext]", name, "Security", list(z))
Radio.autosay("Prisoner [occupant] had their timer reset [resettext]", name, "Security")
notify_prisoner("Your brig timer has been reset for: '[reset_reason]'.")
var/datum/data/record/R = find_security_record("name", occupant)
if(istype(R))
@@ -396,7 +396,7 @@
if(timing)
timer_end()
var/stoptext = isobserver(usr) ? "from cell control." : "by [usr.name]."
Radio.autosay("Timer stopped manually [stoptext]", name, "Security", list(z))
Radio.autosay("Timer stopped manually [stoptext]", name, "Security")
else
. = FALSE
if("flash")

View File

@@ -93,7 +93,7 @@
/obj/machinery/iv_drip/Move(NewLoc, direct)
. = ..()
if(!.) // ..() will return 0 if we didn't actually move anywhere.
return .
return
playsound(loc, pick('sound/items/cartwheel1.ogg', 'sound/items/cartwheel2.ogg'), 100, 1, ignore_walls = FALSE)
#undef IV_TAKING

View File

@@ -547,7 +547,7 @@
if(istype(mover) && mover.checkpass(PASSGLASS))
return prob(20)
else
if(istype(mover, /obj/item/projectile))
if(isprojectile(mover))
return prob(10)
else
return !density
@@ -563,7 +563,7 @@
var/mob/living/M = mover
if("syndicate" in M.faction)
return TRUE
if(istype(mover, /obj/item/projectile))
if(isprojectile(mover))
return FALSE
return ..(mover, target, height)

View File

@@ -191,7 +191,7 @@ GLOBAL_LIST_EMPTY(tcomms_machines)
/// Origin of the signal
var/datum/radio_frequency/connection
/// Who sent it
var/mob/sender
var/atom/movable/sender
/// The radio it was sent from
var/obj/item/radio/radio
/// The signal data (See defines/radio.dm)

View File

@@ -223,7 +223,7 @@
sleep(30)
/obj/machinery/transformer/xray/proc/scan_rec(obj/item/I)
if(istype(I, /obj/item/gun))
if(isgun(I))
return TRUE
if(istype(I, /obj/item/transfer_valve))
return TRUE

View File

@@ -233,6 +233,8 @@
chassis.use_power(energy_drain)
update_equip_info()
/obj/item/mecha_parts/mecha_equipment/medical/sleeper/force_eject_occupant(mob/target)
go_out()
/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun
name = "exosuit syringe gun"

View File

@@ -47,7 +47,7 @@
if(prob(50))
to_chat(mover, "<span class='danger'>You get stuck in [src] for a moment.</span>")
return FALSE
else if(istype(mover, /obj/item/projectile))
else if(isprojectile(mover))
return prob(30)
return TRUE

View File

@@ -256,7 +256,7 @@ GLOBAL_LIST_EMPTY(deadsay_radio_systems)
/obj/item/radio/proc/ToggleReception()
listening = !listening && !(wires.is_cut(WIRE_RADIO_RECEIVER) || wires.is_cut(WIRE_RADIO_SIGNAL))
/obj/item/radio/proc/autosay(message, from, channel, role = "Unknown", follow_target_override) //BS12 EDIT
/obj/item/radio/proc/autosay(message, from, channel, follow_target_override) //BS12 EDIT
var/datum/radio_frequency/connection = null
if(channel && channels && length(channels) > 0)
if(channel == "department")
@@ -274,10 +274,6 @@ GLOBAL_LIST_EMPTY(deadsay_radio_systems)
return
if(!connection)
return
var/mob/living/automatedannouncer/A = new /mob/living/automatedannouncer(src)
A.name = from
A.role = role
A.message = message
var/jammed = FALSE
for(var/obj/item/jammer/jammer in GLOB.active_jammers)
if(get_dist(get_turf(src), get_turf(jammer)) < jammer.range)
@@ -290,7 +286,7 @@ GLOBAL_LIST_EMPTY(deadsay_radio_systems)
// Make us a message datum!
var/datum/tcomms_message/tcm = new
tcm.connection = connection
tcm.sender = A
tcm.sender = src
tcm.radio = src
tcm.sender_name = from
tcm.message_pieces = message_pieces
@@ -312,29 +308,6 @@ GLOBAL_LIST_EMPTY(deadsay_radio_systems)
for(var/obj/machinery/tcomms/core/C in GLOB.tcomms_machines)
C.handle_message(tcm)
qdel(tcm) // Delete the message datum
qdel(A)
// Just a dummy mob used for making announcements, so we don't create AIs to do this
// I'm not sure who thought that was a good idea. -- Crazylemon
/mob/living/automatedannouncer
var/role = ""
var/lifetime_timer
var/message = ""
universal_speak = TRUE
/mob/living/automatedannouncer/New()
lifetime_timer = addtimer(CALLBACK(src, PROC_REF(autocleanup)), 10 SECONDS, TIMER_STOPPABLE)
..()
/mob/living/automatedannouncer/Destroy()
if(lifetime_timer)
deltimer(lifetime_timer)
lifetime_timer = null
return ..()
/mob/living/automatedannouncer/proc/autocleanup()
stack_trace("An announcer somehow managed to outlive the radio! Deleting! (Message: [message])")
qdel(src)
// Interprets the message mode when talking into a radio, possibly returning a connection datum
/obj/item/radio/proc/handle_message_mode(mob/living/M as mob, list/message_pieces, message_mode)

View File

@@ -75,7 +75,7 @@
/obj/item/taperecorder/attack_hand(mob/user)
if(loc == user)
if(mytape)
if(user.l_hand != src && user.r_hand != src)
if(!user.is_holding(src))
..()
return
eject(user)

View File

@@ -110,7 +110,7 @@
go_rabid()
return
if(!(src in list(master.l_hand, master.r_hand)))
if(!master.is_holding(src))
go_rabid()
return

View File

@@ -46,7 +46,7 @@
. = ..()
var/mob/living/carbon/human/M = hit_atom
if(ishuman(hit_atom) && (M.wear_suit?.type in suit_types))
if(M.r_hand == src || M.l_hand == src)
if(M.is_holding(src))
return
playsound(src, 'sound/items/dodgeball.ogg', 50, 1)
M.KnockDown(6 SECONDS)
@@ -86,7 +86,7 @@
return
/obj/structure/holohoop/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
if(isitem(AM) && !istype(AM, /obj/item/projectile))
if(isitem(AM) && !isprojectile(AM))
if(prob(50) || HAS_TRAIT(throwingdatum.thrower, TRAIT_BADASS))
AM.forceMove(get_turf(src))
visible_message("<span class='notice'>Swish! [AM] lands in [src].</span>")

View File

@@ -336,6 +336,7 @@ GLOBAL_LIST_INIT(cloth_recipes, list (
new /datum/stack_recipe("fish bag", /obj/item/storage/bag/fish, 4),
new /datum/stack_recipe("mail bag", /obj/item/storage/bag/mail, 4),
new /datum/stack_recipe("construction bag", /obj/item/storage/bag/construction, 4),
new /datum/stack_recipe("money bag", /obj/item/storage/bag/money, 3),
)),
null,
new /datum/stack_recipe("improvised gauze", /obj/item/stack/medical/bruise_pack/improvised, 1, 2, 6),

View File

@@ -45,6 +45,7 @@
C.forceMove(src)
case = C
update_icon(UPDATE_ICON_STATE)
SStgui.update_uis(src)
/obj/item/bio_chip_pad/proc/eject_case(mob/user)
if(!case)
@@ -53,13 +54,9 @@
if(user.put_in_hands(case))
add_fingerprint(user)
case.add_fingerprint(user)
case = null
update_icon(UPDATE_ICON_STATE)
return
case.forceMove(get_turf(src))
case = null
update_icon(UPDATE_ICON_STATE)
SStgui.update_uis(src)
/obj/item/bio_chip_pad/AltClick(mob/user)
if(user.stat || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED) || !Adjacent(user))
@@ -74,6 +71,7 @@
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "BioChipPad", name)
ui.set_autoupdate(FALSE)
ui.open()
/obj/item/bio_chip_pad/ui_data(mob/user)
@@ -97,7 +95,7 @@
/obj/item/bio_chip_pad/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
if(..())
return
. = TRUE
switch(action)
if("eject_case")
eject_case(ui.user)

View File

@@ -42,7 +42,7 @@
var/turf/location = loc
if(ismob(location))
var/mob/M = location
if(M.l_hand == src || M.r_hand == src)
if(M.is_holding(src))
location = M.loc
if(isturf(location)) //start a fire if possible
igniter.flamethrower_process(location)

View File

@@ -360,7 +360,7 @@
if(ishuman(loc))
var/mob/living/carbon/human/our_location = loc
if(istype(our_location))
if(src != our_location.l_hand && src != our_location.r_hand)
if(!our_location.is_holding(src))
return
if(our_location.Adjacent(attacking_atom)) // with a buddy we deal 12 damage :D
our_location.do_attack_animation(attacking_atom, used_item = src)

View File

@@ -240,7 +240,7 @@
. = ..()
if(!.) // they did not block the attack
return
if(istype(hitby, /obj/item/projectile))
if(isprojectile(hitby))
var/obj/item/projectile/P = hitby
if(P.reflectability == REFLECTABILITY_NEVER) //only 1 magic spell does this, but hey, needed
owner.visible_message("<span class='danger'>[owner] blocks [attack_text] with [src]!</span>")

View File

@@ -86,7 +86,7 @@
return
/obj/item/shield/energy/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
if(istype(hitby, /obj/item/projectile))
if(isprojectile(hitby))
var/obj/item/projectile/P = hitby
if(P.shield_buster && active)
toggle(owner, TRUE)

View File

@@ -43,7 +43,7 @@
/obj/item/storage/briefcase/false_bottomed/afterattack(atom/A, mob/user, flag, params)
..()
if(stored_item && istype(stored_item, /obj/item/gun) && !Adjacent(A))
if(stored_item && isgun(stored_item) && !Adjacent(A))
var/obj/item/gun/stored_gun = stored_item
stored_gun.afterattack(A, user, flag, params)

View File

@@ -61,7 +61,7 @@
/obj/structure/fence/CanPass(atom/movable/mover, turf/target)
if(istype(mover) && mover.checkpass(PASSFENCE))
return TRUE
if(istype(mover, /obj/item/projectile))
if(isprojectile(mover))
return TRUE
if(!density)
return TRUE

View File

@@ -410,7 +410,7 @@
if(istype(mover) && mover.checkpass(PASSGRILLE))
return prob(girderpasschance)
else
if(istype(mover, /obj/item/projectile))
if(isprojectile(mover))
return prob(girderpasschance)
else
return 0

View File

@@ -123,7 +123,7 @@
return TRUE
if(istype(mover) && mover.checkpass(PASSGRILLE))
return TRUE
if(istype(mover, /obj/item/projectile))
if(isprojectile(mover))
return (prob(30) || !density)
/obj/structure/grille/CanPathfindPass(obj/item/card/id/ID, dir, caller, no_id = FALSE)

View File

@@ -102,7 +102,7 @@
/obj/structure/railing/CanPass(atom/movable/mover, turf/target)
if(istype(mover) && mover.checkpass(PASSFENCE))
return TRUE
if(istype(mover, /obj/item/projectile))
if(isprojectile(mover))
return TRUE
if(ismob(mover))
var/mob/living/M = mover
@@ -130,7 +130,7 @@
var/mob/living/M = O
if(istype(O) && O.checkpass(PASSFENCE))
return TRUE
if(istype(O, /obj/item/projectile))
if(isprojectile(O))
return TRUE
if(istype(M))
if(M.flying || M.floating || (IS_HORIZONTAL(M) && HAS_TRAIT(M, TRAIT_CONTORTED_BODY)))

View File

@@ -799,10 +799,10 @@
. = ..()
if(!.) // ..() will return 0 if we didn't actually move anywhere.
return .
return
if(direct & (direct - 1)) // This represents a diagonal movement, which is split into multiple cardinal movements. We'll handle moving the items on the cardinals only.
return .
return
playsound(loc, pick('sound/items/cartwheel1.ogg', 'sound/items/cartwheel2.ogg'), 100, 1, ignore_walls = FALSE)

View File

@@ -207,7 +207,7 @@
if(log_info)
INVOKE_ASYNC(GLOBAL_PROC, GLOBAL_PROC_REF(log_connection), ckey(key), address, computer_id, CONNECTION_TYPE_DROPPED_BANNED)
qdel(query)
return .
return
qdel(query)
. = ..() //default pager ban stuff
@@ -224,4 +224,3 @@
log_adminwarn("Failed Login: [key] [computer_id] [address] - Banned [.["message"]]")
if(log_info)
INVOKE_ASYNC(GLOBAL_PROC, GLOBAL_PROC_REF(log_connection), ckey(key), address, computer_id, CONNECTION_TYPE_DROPPED_BANNED)
return .

View File

@@ -613,6 +613,7 @@ GLOBAL_VAR_INIT(nologevent, 0)
log_admin("[key_name(usr)] delayed the game.")
else
SSticker.ticker_going = TRUE
SSticker.round_start_time = world.time + SSticker.pregame_timeleft
to_chat(world, "<b>The game will start soon.</b>")
log_admin("[key_name(usr)] removed the delay.")

View File

@@ -187,17 +187,18 @@
else
receive_message = chat_box_ahelp(receive_message)
to_chat(C, receive_message)
var/send_window_link = "(<a href='byond://?src=[pm_tracker.UID()];newtitle=[C.key]'>WINDOW</a>)"
if(message_type == MESSAGE_TYPE_MENTORPM && check_rights(R_ADMIN|R_MENTOR, 0, mob))
send_window_link = ticket_link
else if(message_type == MESSAGE_TYPE_ADMINPM && check_rights(R_ADMIN, 0, mob))
send_window_link = ticket_link
var/send_message = "<span class='[send_span]'>[send_pm_type][type] to-<b>[holder ? key_name(C, TRUE, type, ticket_id = ticket_id) : key_name_hidden(C, TRUE, type, ticket_id = ticket_id)]</b>:<br><br>[emoji_msg]</span><br>[ping_link] [send_window_link] [alert_link]"
if(message_type == MESSAGE_TYPE_MENTORPM)
send_message = chat_box_mhelp(send_message)
else
send_message = chat_box_ahelp(send_message)
to_chat(src, send_message)
if(C != src)
var/send_window_link = "(<a href='byond://?src=[pm_tracker.UID()];newtitle=[C.key]'>WINDOW</a>)"
if(message_type == MESSAGE_TYPE_MENTORPM && check_rights(R_ADMIN|R_MENTOR, 0, mob))
send_window_link = ticket_link
else if(message_type == MESSAGE_TYPE_ADMINPM && check_rights(R_ADMIN, 0, mob))
send_window_link = ticket_link
var/send_message = "<span class='[send_span]'>[send_pm_type][type] to-<b>[holder ? key_name(C, TRUE, type, ticket_id = ticket_id) : key_name_hidden(C, TRUE, type, ticket_id = ticket_id)]</b>:<br><br>[emoji_msg]</span><br>[ping_link] [send_window_link] [alert_link]"
if(message_type == MESSAGE_TYPE_MENTORPM)
send_message = chat_box_mhelp(send_message)
else
send_message = chat_box_ahelp(send_message)
to_chat(src, send_message)
var/third_party_message
if(message_type == MESSAGE_TYPE_MENTORPM)

View File

@@ -989,3 +989,24 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
vis.set_content(ui_dat.Join(""))
vis.open(FALSE)
/client/proc/cmd_clean_radiation()
set name = "Remove All Radiation"
set desc = "Remove all radiation in the world."
set category = "Debug"
if(!check_rights(R_DEBUG))
return
if(alert(src, "Are you sure you want to remove all radiation in the world? This may lag the server. Alternatively, use the radiation cleaning buildmode.", "Lag warning", "Yes, I'm sure", "No, I want to live") != "Yes, I'm sure")
return
log_and_message_admins("is decontaminating the world of all radiation. (This may be laggy!)")
var/counter = 0
for(var/datum/component/radioactive/rad as anything in SSradiation.all_radiations)
rad.admin_decontaminate()
counter++
CHECK_TICK
log_and_message_admins_no_usr("The world has been decontaminated of [counter] radiation components.")

View File

@@ -93,12 +93,12 @@ GLOBAL_LIST_EMPTY(frozen_atom_list) // A list of admin-frozen atoms.
/obj/machinery/atmospherics/supermatter_crystal/admin_Freeze(client/admin)
var/obj/effect/overlay/adminoverlay/freeze_overlay = new
if(processes)
radio.autosay("Alert: Unknown intervention has frozen causality around the crystal. It is not progressing in local timespace.", name, "Engineering", list(z))
radio.autosay("Alert: Unknown intervention has frozen causality around the crystal. It is not progressing in local timespace.", name, "Engineering")
GLOB.frozen_atom_list += src
processes = FALSE
add_overlay(freeze_overlay)
else
radio.autosay("Alert: Unknown intervention has ceased around the crystal. It has returned to the regular flow of time.", name, "Engineering", list(z))
radio.autosay("Alert: Unknown intervention has ceased around the crystal. It has returned to the regular flow of time.", name, "Engineering")
GLOB.frozen_atom_list -= src
processes = TRUE
cut_overlay(freeze_overlay)

View File

@@ -16,6 +16,7 @@ GLOBAL_LIST_INIT(admin_verbs_show_debug_verbs, list(
/client/proc/forceEvent,
/client/proc/admin_redo_space_transitions,
/client/proc/make_turf_space_map,
/client/proc/cmd_clean_radiation,
))
// Would be nice to make this a permanent admin pref so we don't need to click it each time

View File

@@ -0,0 +1,55 @@
/datum/buildmode_mode/clean_radiation
key = "rad"
/datum/buildmode_mode/clean_radiation/show_help(mob/user)
var/list/messages = list(
"***********************************************************",
"Left Mouse Button on obj/turf/mob = Remove radiation of selected target.",
"Ctrl-Left Mouse Button on screen = Remove all radiation in your sight.",
"Right Mouse Button on obj/turf/mob = Deep clean: Remove radiation of all recursive contents of turf.",
"Ctrl-Right Mouse Button on screen = Deep clean: Remove radiation of all recursive contents in your sight.",
"***********************************************************"
)
to_chat(user, messages.Join("<br>"))
/datum/buildmode_mode/clean_radiation/handle_click(mob/user, params, atom/target)
var/list/pa = params2list(params)
var/deep_clean = pa.Find("right")
var/clean_screen = pa.Find("ctrl")
if(!clean_screen)
if(!deep_clean)
if(SEND_SIGNAL(target, COMSIG_ADMIN_DECONTAMINATE))
to_chat(user, "<span class='notice'>Decontaminated [target].</span>")
log_admin("Build Mode: [key_name(user)] decontaminated radiation at ([target.x],[target.y],[target.z])")
return
var/counter = 0
var/turf/T = get_turf(target)
counter += SEND_SIGNAL(T, COMSIG_ADMIN_DECONTAMINATE)
for(var/atom/movable/cleanable in T)
counter += SEND_SIGNAL(cleanable, COMSIG_ADMIN_DECONTAMINATE)
CHECK_TICK
if(isliving(cleanable))
var/mob/living/L = cleanable
for(var/atom/movable/cleanable2 in L.get_contents())
counter += SEND_SIGNAL(cleanable2, COMSIG_ADMIN_DECONTAMINATE)
CHECK_TICK
to_chat(user, "<span class='notice'>Decontaminated [counter] atom\s.</span>")
log_admin("Build Mode: [key_name(user)] deep-clean decontaminated radiation at ([target.x],[target.y],[target.z])")
return
var/counter = 0
for(var/turf/T in range(user.client.view, user))
counter += SEND_SIGNAL(T, COMSIG_ADMIN_DECONTAMINATE)
for(var/atom/movable/cleanable in T)
counter += SEND_SIGNAL(cleanable, COMSIG_ADMIN_DECONTAMINATE)
CHECK_TICK
if(deep_clean && isliving(cleanable))
var/mob/living/L = cleanable
for(var/atom/movable/cleanable2 in L.get_contents())
counter += SEND_SIGNAL(cleanable2, COMSIG_ADMIN_DECONTAMINATE)
CHECK_TICK
to_chat(user, "<span class='notice'>Decontaminated [counter] atom\s.</span>")
log_admin("Build Mode: [key_name(user)] [deep_clean ? "deep-clean " : ""]decontaminated their screen of radiation at ([target.x],[target.y],[target.z])")

View File

@@ -62,6 +62,9 @@
var/datum/click_intercept/click_intercept = null
/// Time when the click was intercepted
var/click_intercept_time = 0
//datum that controls the displaying and hiding of tooltips
var/datum/tooltip/tooltips
@@ -132,6 +135,27 @@
var/list/active_keybindings = list()
/// The client's movement keybindings to directions, which work regardless of modifiers.
var/list/movement_kb_dirs = list()
/// Used to make a special mouse cursor, this one for mouse up icon
var/mouse_up_icon = null
/// Used to make a special mouse cursor, this one for mouse up icon
var/mouse_down_icon = null
/// Used to override the mouse cursor so it doesnt get reset
var/mouse_override_icon = null
/// Autoclick list of two elements, first being the clicked thing, second being the parameters.
var/list/atom/selected_target[2]
/// Used in MouseDrag to preserve the original mouse click parameters
var/mouseParams = ""
/// Used in MouseDrag to preserve the last mouse-entered location.
var/mouse_location_UID
/// Used in MouseDrag to preserve the last mouse-entered object.
var/mouse_object_UID
/// When we started the currently active drag
var/drag_start = 0
/// The params we passed at the start of the drag, in list form
var/list/drag_details
/// The client's currently moused over datum, limited to movable and stored as UID
var/atom/movable/moused_over

View File

@@ -75,7 +75,7 @@
var/turf/location = loc
if(ismob(location))
var/mob/living/carbon/human/M = location
if(M.l_hand == src || M.r_hand == src || M.head == src)
if(M.is_holding(src) || M.head == src)
location = M.loc
if(isturf(location))

View File

@@ -476,7 +476,7 @@
/obj/item/clothing/suit/armor/reactive/proc/reaction_check(hitby)
if(prob(hit_reaction_chance))
if(istype(hitby, /obj/item/projectile))
if(isprojectile(hitby))
var/obj/item/projectile/P = hitby
if(istype(P, /obj/item/projectile/ion))
return FALSE

View File

@@ -231,7 +231,7 @@
return
if(!is_station_level(user.z))
return
GLOB.global_announcer.autosay("[H] has been rewarded [src] by [user]!", "Medal Announcer", channel = channel, follow_target_override = src)
GLOB.global_announcer.autosay("[H] has been rewarded [src] by [user]!", "Medal Announcer", channel, src)
channel = null
// GOLD (awarded by centcom)

View File

@@ -36,7 +36,7 @@
to_chat(user, "<span class='warning'>There is already a [holstered] holstered here!</span>")
return
if(!istype(I, /obj/item/gun))
if(!isgun(I))
to_chat(user, "<span class='warning'>Only guns can be holstered!</span>")
return

View File

@@ -70,6 +70,11 @@ GLOBAL_LIST_EMPTY(blob_minions)
/obj/structure/blob/blob_act(obj/structure/blob/B)
return
/obj/structure/blob/bullet_act(obj/item/projectile/P)
if(istype(P, /obj/item/projectile/kinetic))
P.damage /= 2
return ..()
/obj/structure/blob/proc/Life()
return

View File

@@ -49,7 +49,7 @@
if(can_opened)
to_chat(H, "<span class='warning'>You can't shake up an already opened drink!")
return
if(src == H.l_hand || src == H.r_hand)
if(H.is_holding(src))
can_shake = FALSE
addtimer(CALLBACK(src, PROC_REF(reset_shakable)), 1 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE)
to_chat(H, "<span class='notice'>You start shaking up [src].</span>")

View File

@@ -321,7 +321,8 @@
operating = FALSE
update_icon(UPDATE_OVERLAYS | UPDATE_ICON_STATE)
/obj/machinery/gibber/force_eject_occupant(mob/target)
go_out()
/* AUTOGIBBER */

View File

@@ -171,6 +171,7 @@
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "GeneModder", name)
ui.set_autoupdate(FALSE)
ui.open()
/obj/machinery/plantgenes/ui_data(mob/user)

View File

@@ -96,6 +96,7 @@
if(loaded)
to_chat(user, "<span class='notice'>You transfer [loaded] seeds from [O] into [src].</span>")
SStgui.update_uis(src)
else
var/seedable = 0
for(var/obj/item/food/snacks/grown/ignored in P)
@@ -115,10 +116,10 @@
else if(istype(O, /obj/item/unsorted_seeds))
to_chat(user, "<span class='warning'>You need to sort [O] first!</span>")
return ..()
else if(istype(O,/obj/item/seeds))
if(add_seed(O, user))
to_chat(user, "<span class='notice'>You add [O] to [name].</span>")
updateUsrDialog()
else if(istype(O, /obj/item/seeds))
add_seed(O, user)
to_chat(user, "<span class='notice'>You add [O] to [name].</span>")
SStgui.update_uis(src)
return
else if(seedify(O,-1, src, user))
to_chat(user, "<span class='notice'>You extract some seeds.</span>")
@@ -143,6 +144,7 @@
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "SeedExtractor", name)
ui.set_autoupdate(FALSE)
ui.open()
/obj/machinery/seed_extractor/ui_data(mob/user)
@@ -177,18 +179,14 @@
/obj/machinery/seed_extractor/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
if(..())
return
. = FALSE
. = TRUE
switch(action)
if("vend")
vend_seed(params["seed_id"], params["seed_variant"], params["vend_amount"])
add_fingerprint(usr)
. = TRUE
if("set_vend_amount")
if(!length(params["vend_amount"]))
return
vend_amount = clamp(params["vend_amount"], 1, MAX_DISPENSE_SEEDS)
add_fingerprint(usr)
. = TRUE
/obj/machinery/seed_extractor/proc/vend_seed(seed_id, seed_variant, amount)
if(!seed_id)
@@ -241,7 +239,6 @@
pile_count++
piles += new_pile
O.forceMove(src)
return
/datum/seed_pile
var/path

View File

@@ -57,7 +57,7 @@
/obj/item/shared_storage/attack_self(mob/living/carbon/user)
if(!iscarbon(user))
return
if(src == user.l_hand || src == user.r_hand)
if(user.is_holding(src))
bag?.open(user)
else
..()

View File

@@ -223,7 +223,7 @@
/obj/item/clothing/head/hooded/berserker/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
if(berserk_active)
return
if(istype(hitby, /obj/item/projectile))
if(isprojectile(hitby))
var/obj/item/projectile/P = hitby
if(P.damage_type == STAMINA)
return //no disabler rage

View File

@@ -1,116 +1,193 @@
/**********************Mint**************************/
#define COIN_COST MINERAL_MATERIAL_AMOUNT * 0.2
/obj/machinery/mineral/mint
name = "coin press"
icon = 'icons/obj/economy.dmi'
icon_state = "coinpress0"
icon_state = "coin_press"
density = TRUE
anchored = TRUE
var/newCoins = 0 //how many coins the machine made in it's last load
var/processing = FALSE
var/chosen = MAT_METAL //which material will be used to make coins
var/coinsToProduce = 10
speed_process = TRUE
/// How many coins did the machine make in total.
var/total_coins = 0
/// Is it creating coins now?
var/active = FALSE
/// Which material will be used to make coins or for ejecting.
var/chosen_material
/// Inserted money bag.
var/obj/item/storage/bag/money/money_bag
/obj/machinery/mineral/mint/Initialize(mapload)
. = ..()
AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_PLASMA, MAT_SILVER, MAT_GOLD, MAT_URANIUM, MAT_DIAMOND, MAT_BANANIUM, MAT_TRANQUILLITE), MINERAL_MATERIAL_AMOUNT * 50, FALSE, /obj/item/stack)
var/static/list/coin_materials = list()
if(!length(coin_materials))
for(var/datum/material/coin_mat as anything in subtypesof(/datum/material))
var/obj/item/coin/coin_type = coin_mat.coin_type
if(!coin_type)
continue
coin_materials += coin_mat.id
AddComponent(/datum/component/material_container, coin_materials, MINERAL_MATERIAL_AMOUNT * 50, FALSE, /obj/item/stack, _after_insert = CALLBACK(src, PROC_REF(material_insert)))
chosen_material = pick(coin_materials[1])
/obj/machinery/mineral/mint/Destroy()
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.retrieve_all()
return ..()
/obj/machinery/mineral/mint/update_icon_state()
if(active)
icon_state = "coin_press-active"
else
icon_state = "coin_press"
/obj/machinery/mineral/mint/wrench_act(mob/user, obj/item/I)
default_unfasten_wrench(user, I, time = 4 SECONDS)
return TRUE
/obj/machinery/mineral/mint/process()
var/turf/T = get_step(src, input_dir)
if(!T)
return
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
for(var/obj/item/stack/sheet/O in T)
materials.insert_stack(O, O.amount)
/obj/machinery/mineral/mint/attack_hand(mob/user)
if(..())
return
var/dat = "<b>Coin Press</b><br>"
add_fingerprint(user)
ui_interact(user)
/obj/machinery/mineral/mint/attack_ghost(mob/user)
ui_interact(user)
/obj/machinery/mineral/mint/ui_state(mob/user)
return GLOB.default_state
/obj/machinery/mineral/mint/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "CoinMint", name)
ui.set_autoupdate(FALSE)
ui.open()
/obj/machinery/mineral/mint/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/spritesheet/materials)
)
/obj/machinery/mineral/mint/ui_data(mob/user)
var/list/data = list()
data["active"] = active
data["chosenMaterial"] = chosen_material
data["totalCoins"] = total_coins
data["moneyBag"] = !!money_bag
if(money_bag)
data["moneyBagContent"] = length(money_bag.contents)
data["moneyBagMaxContent"] = money_bag.storage_slots
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
data["totalMaterials"] = materials.total_amount
data["maxMaterials"] = materials.max_amount
var/list/material_list = list()
for(var/mat_id in materials.materials)
var/datum/material/M = materials.materials[mat_id]
if(!M.amount && chosen != mat_id)
continue
dat += "<br><b>[M.name] amount:</b> [M.amount] cm<sup>3</sup> "
if(chosen == mat_id)
dat += "<b>Chosen</b>"
else
dat += "<A href='byond://?src=[UID()];choose=[mat_id]'>Choose</A>"
var/datum/material/material = materials.materials[mat_id]
material_list += list(list(
"name" = material.name,
"amount" = material.amount / MINERAL_MATERIAL_AMOUNT,
"id" = material.id
))
data["materials"] = material_list
var/datum/material/M = materials.materials[chosen]
return data
dat += "<br><br>Will produce [coinsToProduce] [lowertext(M.name)] coins if enough materials are available.<br>"
dat += "<A href='byond://?src=[UID()];chooseAmt=-10'>-10</A> "
dat += "<A href='byond://?src=[UID()];chooseAmt=-5'>-5</A> "
dat += "<A href='byond://?src=[UID()];chooseAmt=-1'>-1</A> "
dat += "<A href='byond://?src=[UID()];chooseAmt=1'>+1</A> "
dat += "<A href='byond://?src=[UID()];chooseAmt=5'>+5</A> "
dat += "<A href='byond://?src=[UID()];chooseAmt=10'>+10</A> "
dat += "<br><br>In total this machine produced <font color='green'><b>[newCoins]</b></font> coins."
dat += "<br><A href='byond://?src=[UID()];makeCoins=[1]'>Make coins</A>"
user << browse(dat, "window=mint")
/obj/machinery/mineral/mint/Topic(href, href_list)
/obj/machinery/mineral/mint/ui_act(action, params, datum/tgui/ui)
if(..())
return
usr.set_machine(src)
add_fingerprint(usr)
if(processing)
to_chat(usr, "<span class='notice'>The machine is processing.</span>")
return
. = TRUE
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
if(href_list["choose"])
if(materials.materials[href_list["choose"]])
chosen = href_list["choose"]
if(href_list["chooseAmt"])
coinsToProduce = clamp(coinsToProduce + text2num(href_list["chooseAmt"]), 0, 1000)
if(href_list["makeCoins"])
var/temp_coins = coinsToProduce
processing = TRUE
icon_state = "coinpress1"
var/coin_mat = MINERAL_MATERIAL_AMOUNT * 0.2
var/datum/material/M = materials.materials[chosen]
if(!M || !M.coin_type)
updateUsrDialog()
switch(action)
if("selectMaterial")
if(!materials.materials[params["material"]])
return
chosen_material = params["material"]
if("activate")
if(active)
active = FALSE
else
try_make_coins()
update_icon(UPDATE_ICON_STATE)
if("ejectMat")
var/datum/material/material = materials.materials[chosen_material]
if(material.amount < MINERAL_MATERIAL_AMOUNT)
to_chat(usr, "<span class='warning'>Not enough [material.name] to eject!</span>")
return
var/num_sheets = tgui_input_number(usr, "How many sheets do you want to eject?", "Ejecting [material.name]", max_value = round(material.amount / MINERAL_MATERIAL_AMOUNT), min_value = 1)
if(isnull(num_sheets))
return
materials.retrieve_sheets(num_sheets, chosen_material)
if("ejectBag")
eject_bag(usr)
/obj/machinery/mineral/mint/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/storage/bag/money))
if(money_bag)
to_chat(user, "<span class='notice'>There is already a [money_bag.name] inside!</span>")
return
if(!user.drop_item())
return
to_chat(user, "<span class='notice'>You put a [I.name] into a [src].</span>")
I.forceMove(src)
money_bag = I
SStgui.update_uis(src)
return
while(coinsToProduce > 0 && materials.can_use_amount(coin_mat, chosen))
if(!create_coins(M.coin_type))
visible_message("<span class='notice'>[src] stops printing to prevent an overflow.</span>")
break
materials.use_amount_type(coin_mat, chosen)
coinsToProduce--
newCoins++
updateUsrDialog()
sleep(5)
return ..()
icon_state = "coinpress0"
processing = FALSE
coinsToProduce = temp_coins
updateUsrDialog()
/obj/machinery/mineral/mint/process()
if(!active)
return
if(length(money_bag.contents) >= money_bag.storage_slots)
active = FALSE
visible_message("<span class='notice'>[src] stops printing to prevent an overflow.</span>")
update_icon(UPDATE_ICON_STATE)
SStgui.update_uis(src)
return
/obj/machinery/mineral/mint/proc/create_coins(P)
var/turf/T = get_step(src,output_dir)
if(!T)
return FALSE
var/obj/item/O = new P(src)
var/obj/item/storage/bag/money/M = locate(/obj/item/storage/bag/money, T)
if(!M)
M = new /obj/item/storage/bag/money(src)
unload_mineral(M)
else if(!M.can_be_inserted(O, FALSE)) // First coin will always fit. But will the Xth?
qdel(O)
return FALSE
O.forceMove(M)
return TRUE
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/datum/material/material = materials.materials[chosen_material]
if(!materials.can_use_amount(COIN_COST, chosen_material))
active = FALSE
visible_message("<span class='notice'>[src] ceased production due to a lack of material.</span>")
update_icon(UPDATE_ICON_STATE)
SStgui.update_uis(src)
return
materials.use_amount_type(COIN_COST, chosen_material)
new material.coin_type(money_bag)
total_coins++
SStgui.update_uis(src)
/obj/machinery/mineral/mint/proc/try_make_coins(mob/user)
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
if(!money_bag)
visible_message("<span class='warning'>[src] cannot work without a money bag!</span>")
return
if(length(money_bag.contents) == money_bag.storage_slots)
visible_message("<span class='warning'>[money_bag.name] is full!</span>")
return
if(!materials.can_use_amount(COIN_COST, chosen_material))
visible_message("<span class='warning'>Lack of selected material for production!</span>")
return
active = TRUE
/obj/machinery/mineral/mint/proc/eject_bag(mob/user)
if(!money_bag || !(user && iscarbon(user) && user.Adjacent(src)))
return
if(active)
active = FALSE
if(user.put_in_hands(money_bag))
to_chat(user, "<span class='notice'>You take a [money_bag.name] out of [src].</span>")
else
var/turf/T = get_step(src, output_dir)
money_bag.forceMove(T)
money_bag = null
SStgui.update_uis(src)
/obj/machinery/mineral/mint/proc/material_insert()
SStgui.update_uis(src)
#undef COIN_COST

View File

@@ -1,5 +1,3 @@
/*****************************Money bag********************************/
/obj/item/storage/bag/money
name = "money bag"
icon_state = "moneybag"
@@ -9,8 +7,8 @@
max_integrity = 100
w_class = WEIGHT_CLASS_BULKY
max_w_class = WEIGHT_CLASS_NORMAL
storage_slots = 40
max_combined_w_class = 40
storage_slots = 50
max_combined_w_class = 50
can_hold = list(/obj/item/coin, /obj/item/stack/spacecash)
/obj/item/storage/bag/money/vault/populate_contents()

View File

@@ -9,19 +9,18 @@
return say_dead(message)
/mob/dead/observer/handle_track(message, verb = "says", mob/speaker = null, speaker_name, atom/follow_target, hard_to_hear)
/mob/dead/observer/handle_track(message, verb = "says", atom/movable/speaker = null, speaker_name, atom/follow_target, hard_to_hear)
return "[speaker_name] ([ghost_follow_link(follow_target, ghost=src)])"
/mob/dead/observer/handle_speaker_name(mob/speaker = null, vname, hard_to_hear, check_name_against)
/mob/dead/observer/handle_speaker_name(atom/movable/speaker = null, vname, hard_to_hear, check_name_against)
var/speaker_name = ..()
if(!speaker)
if(!speaker || !ismob(speaker))
return speaker_name
//Announce computer and various stuff that broadcasts doesn't use it's real name but AI's can't pretend to be other mobs.
if(isAI(speaker) || isAutoAnnouncer(speaker))
var/mob/speaker_mob = speaker
if(isAI(speaker_mob))
//AI's can't pretend to be other mobs.
return speaker_name
if(!check_name_against)
check_name_against = speaker_name
if(check_name_against == speaker.real_name)
if(!check_name_against || check_name_against == speaker_mob.real_name)
return speaker_name
speaker_name = "[speaker.real_name] ([speaker_name])"
speaker_name = "[speaker_mob.real_name] ([speaker_name])"
return speaker_name

View File

@@ -1,6 +1,6 @@
// At minimum every mob has a hear_say proc.
/mob/proc/combine_message(list/message_pieces, verb, mob/speaker, always_stars = FALSE)
/mob/proc/combine_message(list/message_pieces, verb, atom/movable/speaker, always_stars = FALSE)
var/iteration_count = 0
var/msg = "" // This is to make sure that the pieces have actually added something
for(var/datum/multilingual_say_piece/SP in message_pieces)
@@ -128,7 +128,7 @@
playsound_local(source, speech_sound, sound_vol, 1, sound_frequency)
/mob/proc/hear_radio(list/message_pieces, verb = "says", part_a, part_b, mob/speaker = null, hard_to_hear = 0, vname = "", atom/follow_target, check_name_against)
/mob/proc/hear_radio(list/message_pieces, verb = "says", part_a, part_b, atom/movable/speaker = null, hard_to_hear = 0, vname = "", atom/follow_target, check_name_against)
if(!client)
return
@@ -155,7 +155,7 @@
else
to_chat(src, "[part_a][speaker_name][part_b][message]</span></span>")
/mob/proc/handle_speaker_name(mob/speaker = null, vname, hard_to_hear)
/mob/proc/handle_speaker_name(atom/movable/speaker = null, vname, hard_to_hear)
var/speaker_name = "unknown"
if(speaker)
speaker_name = speaker.name
@@ -168,7 +168,7 @@
return speaker_name
/mob/proc/handle_track(message, verb = "says", mob/speaker = null, speaker_name, atom/follow_target, hard_to_hear)
/mob/proc/handle_track(message, verb = "says", atom/movable/speaker = null, speaker_name, atom/follow_target, hard_to_hear)
return
/mob/proc/hear_sleep(message)
@@ -192,7 +192,7 @@
to_chat(src, heard)
/mob/proc/hear_holopad_talk(list/message_pieces, verb = "says", mob/speaker = null, obj/effect/overlay/holo_pad_hologram/H)
/mob/proc/hear_holopad_talk(list/message_pieces, verb = "says", atom/movable/speaker = null, obj/effect/overlay/holo_pad_hologram/H)
if(stat == UNCONSCIOUS)
hear_sleep(multilingual_to_message(message_pieces))
return
@@ -204,8 +204,9 @@
var/message_unverbed = combine_message(message_pieces, null, speaker)
var/name = speaker.name
if(!say_understands(speaker))
name = speaker.voice_name
if(!say_understands(speaker) && ismob(speaker))
var/mob/speaker_mob = speaker
name = speaker_mob.voice_name
if((client?.prefs.toggles2 & PREFTOGGLE_2_RUNECHAT) && can_hear())
create_chat_message(H, message_unverbed)

View File

@@ -18,31 +18,14 @@
return ..()
/mob/living/brain/say_understands(other)//Goddamn is this hackish, but this say code is so odd
if(isAI(other))
if(!(container && istype(container, /obj/item/mmi)))
return 0
else
return 1
if(istype(other, /mob/living/silicon/decoy))
if(!(container && istype(container, /obj/item/mmi)))
return 0
else
return 1
if(ispAI(other))
if(!(container && istype(container, /obj/item/mmi)))
return 0
else
return 1
if(isrobot(other))
if(!(container && istype(container, /obj/item/mmi)))
return 0
else
return 1
if(!ismob(other))
return ..()
if(issilicon(other))
return istype(container, /obj/item/mmi)
if(ishuman(other))
return 1
return TRUE
if(isslime(other))
return 1
return ..()
return TRUE
/mob/living/brain/ex_act() //you cant blow up brainmobs because it makes transfer_to() freak out when borgs blow up.
return

View File

@@ -12,7 +12,7 @@
var/mob/living/carbon/human/human_user = user
if(!species_custom_messages || (human_user.mind?.miming && !species_custom_mime_messages))
return .
return
var/custom_message
if(user.mind?.miming)

View File

@@ -1448,8 +1448,7 @@ Eyes need to have significantly high darksight to shine unless the mob has the X
/mob/living/carbon/human/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_THREE)
var/list/handlist = list(l_hand, r_hand)
for(var/obj/item/hand in handlist)
for(var/obj/item/hand in get_both_hands(src))
if(prob(current_size * 5) && hand.w_class >= ((11-current_size)/2) && unEquip(hand))
step_towards(hand, src)
to_chat(src, "<span class='warning'>\The [S] pulls \the [hand] from your grip!</span>")

View File

@@ -6,23 +6,24 @@
return " (as [get_id_name("Unknown")])"
return ..()
/mob/living/carbon/human/say_understands(mob/other, datum/language/speaking = null)
/mob/living/carbon/human/say_understands(atom/movable/other, datum/language/speaking = null)
if(dna.species.can_understand(other))
return 1
return TRUE
//These only pertain to common. Languages are handled by mob/say_understands()
if(!speaking)
if(!speaking && ismob(other))
if(isnymph(other))
if(length(other.languages) >= 2) //They've sucked down some blood and can speak common now.
return 1
var/mob/nymph = other
if(length(nymph.languages) >= 2) //They've sucked down some blood and can speak common now.
return TRUE
if(issilicon(other))
return 1
return TRUE
if(isbot(other))
return 1
return TRUE
if(isbrain(other))
return 1
return TRUE
if(isslime(other))
return 1
return TRUE
return ..()

View File

@@ -317,7 +317,7 @@
ADD_SLOWDOWN(H.r_hand.slowdown)
if(ignoreslow)
return . // Only malusses after here
return // Only malusses after here
if(H.dna.species.spec_movement_delay()) //Species overrides for slowdown due to feet/legs
. += 2 * H.stance_damage //damaged/missing feet or legs is slow

View File

@@ -63,8 +63,8 @@
/datum/species/diona/can_understand(mob/other)
if(isnymph(other))
return 1
return 0
return TRUE
return FALSE
/datum/species/diona/on_species_gain(mob/living/carbon/human/H)
..()

View File

@@ -11,7 +11,6 @@
. = ..()
if(user.mind?.miming)
return FALSE // shh
return .
/datum/emote/living/blush
key = "blush"

View File

@@ -20,5 +20,3 @@
//Should update regardless of if we can ventcrawl, since we can end up in pipes in other ways.
update_pipe_vision(loc)
return .

View File

@@ -3,7 +3,7 @@
*/
/mob/living/silicon/ai/handle_track(message, verb = "says", mob/speaker = null, speaker_name, atom/follow_target, hard_to_hear)
/mob/living/silicon/ai/handle_track(message, verb = "says", atom/movable/speaker = null, speaker_name, atom/follow_target, hard_to_hear)
if(hard_to_hear)
return
@@ -34,9 +34,8 @@
jobname = "Cyborg"
else if(ispAI(speaker))
jobname = "Personal AI"
else if(isAutoAnnouncer(speaker))
var/mob/living/automatedannouncer/AA = speaker
jobname = AA.role
else if(isradio(speaker))
jobname = "Automated Announcement"
else
jobname = "Unknown"

View File

@@ -58,15 +58,15 @@
/mob/living/silicon/say_understands(other, datum/language/speaking = null)
//These only pertain to common. Languages are handled by mob/say_understands()
if(!speaking)
if(!speaking && ismob(other))
if(iscarbon(other))
return 1
return TRUE
if(issilicon(other))
return 1
return TRUE
if(isbot(other))
return 1
return TRUE
if(isbrain(other))
return 1
return TRUE
return ..()
//For holopads only. Usable by AI.

View File

@@ -8,7 +8,6 @@
var/mob/living/L = target
if(L.reagents && !poison_per_bite == 0)
L.reagents.add_reagent(poison_type, poison_per_bite)
return .
/mob/living/simple_animal/hostile/retaliate/poison/snake
name = "snake"

View File

@@ -605,7 +605,7 @@ Difficulty: Hard
return FALSE
if(mover == caster.pulledby)
return TRUE
if(istype(mover, /obj/item/projectile))
if(isprojectile(mover))
var/obj/item/projectile/P = mover
if(P.firer == caster)
return TRUE

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