@@ -66,6 +66,49 @@
|
||||
},
|
||||
/turf/closed/mineral/volcanic/lava_land_surface,
|
||||
/area/lavaland/surface/outdoors)
|
||||
"am" = (
|
||||
/obj/structure/necropolis_gate,
|
||||
/obj/structure/stone_tile/block{
|
||||
dir = 4
|
||||
},
|
||||
/obj/structure/stone_tile/block/cracked{
|
||||
dir = 8
|
||||
},
|
||||
/obj/effect/decal/cleanable/blood,
|
||||
/turf/open/indestructible/boss,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"an" = (
|
||||
/obj/structure/stone_tile/surrounding_tile/cracked,
|
||||
/obj/structure/stone_tile/center,
|
||||
/obj/structure/stone_tile/surrounding_tile{
|
||||
dir = 1
|
||||
},
|
||||
/obj/structure/stone_tile/surrounding_tile{
|
||||
dir = 8
|
||||
},
|
||||
/turf/open/lava/smooth{
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"ao" = (
|
||||
/obj/structure/stone_tile/block/cracked,
|
||||
/turf/open/lava/smooth{
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"ap" = (
|
||||
/obj/structure/stone_tile/surrounding_tile/cracked,
|
||||
/obj/structure/stone_tile/surrounding_tile/cracked{
|
||||
dir = 4
|
||||
},
|
||||
/obj/structure/stone_tile/center,
|
||||
/obj/structure/stone_tile/surrounding_tile{
|
||||
dir = 8
|
||||
},
|
||||
/turf/open/lava/smooth{
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"aq" = (
|
||||
/obj/structure/stone_tile/block/cracked{
|
||||
dir = 8
|
||||
@@ -108,7 +151,7 @@
|
||||
dir = 1
|
||||
},
|
||||
/obj/item/flashlight/lantern,
|
||||
/turf/open/indestructible/boss/air,
|
||||
/turf/open/indestructible/boss,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"av" = (
|
||||
/obj/structure/stone_tile/block,
|
||||
@@ -118,7 +161,7 @@
|
||||
/obj/structure/stone_tile{
|
||||
dir = 4
|
||||
},
|
||||
/turf/open/indestructible/boss/air,
|
||||
/turf/open/indestructible/boss,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"aw" = (
|
||||
/obj/structure/stone_tile/block,
|
||||
@@ -129,7 +172,7 @@
|
||||
dir = 4
|
||||
},
|
||||
/obj/effect/decal/cleanable/blood,
|
||||
/turf/open/indestructible/boss/air,
|
||||
/turf/open/indestructible/boss,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"ax" = (
|
||||
/obj/structure/stone_tile/block,
|
||||
@@ -139,7 +182,7 @@
|
||||
/obj/structure/stone_tile{
|
||||
dir = 4
|
||||
},
|
||||
/turf/open/indestructible/boss/air,
|
||||
/turf/open/indestructible/boss,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"ay" = (
|
||||
/obj/structure/stone_tile,
|
||||
@@ -153,7 +196,7 @@
|
||||
dir = 8
|
||||
},
|
||||
/obj/item/flashlight/lantern,
|
||||
/turf/open/indestructible/boss/air,
|
||||
/turf/open/indestructible/boss,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"az" = (
|
||||
/obj/structure/stone_tile/block{
|
||||
@@ -181,6 +224,14 @@
|
||||
/obj/item/storage/toolbox/syndicate,
|
||||
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"aD" = (
|
||||
/obj/structure/stone_tile/block/cracked{
|
||||
dir = 4
|
||||
},
|
||||
/turf/open/lava/smooth{
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"aE" = (
|
||||
/obj/structure/stone_tile{
|
||||
dir = 4
|
||||
@@ -210,33 +261,34 @@
|
||||
/obj/structure/stone_tile{
|
||||
dir = 8
|
||||
},
|
||||
/turf/open/indestructible/boss/air,
|
||||
/turf/open/indestructible/boss,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"aH" = (
|
||||
/obj/structure/stone_tile/surrounding_tile/cracked,
|
||||
/obj/structure/stone_tile/center,
|
||||
/obj/structure/stone_tile/surrounding_tile{
|
||||
dir = 1
|
||||
/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker,
|
||||
/turf/open/lava/smooth{
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/obj/structure/stone_tile/surrounding_tile{
|
||||
dir = 8
|
||||
},
|
||||
/turf/open/lava/smooth,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"aI" = (
|
||||
/obj/structure/stone_tile/block/cracked,
|
||||
/turf/open/lava/smooth,
|
||||
/obj/structure/stone_tile/block{
|
||||
dir = 8
|
||||
},
|
||||
/turf/open/lava/smooth{
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"aJ" = (
|
||||
/obj/structure/stone_tile/surrounding_tile/cracked,
|
||||
/obj/structure/stone_tile/surrounding_tile/cracked{
|
||||
dir = 4
|
||||
},
|
||||
/obj/structure/stone_tile/center,
|
||||
/obj/structure/stone_tile/center/cracked,
|
||||
/obj/structure/stone_tile/surrounding_tile,
|
||||
/obj/structure/stone_tile/surrounding_tile{
|
||||
dir = 8
|
||||
dir = 1
|
||||
},
|
||||
/turf/open/lava/smooth{
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/turf/open/lava/smooth,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"aK" = (
|
||||
/obj/structure/stone_tile/block/cracked{
|
||||
@@ -247,7 +299,15 @@
|
||||
},
|
||||
/obj/structure/stone_tile,
|
||||
/mob/living/simple_animal/hostile/asteroid/gutlunch/gubbuck,
|
||||
/turf/open/indestructible/boss/air,
|
||||
/turf/open/indestructible/boss,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"aL" = (
|
||||
/obj/structure/stone_tile/block{
|
||||
dir = 1
|
||||
},
|
||||
/turf/open/lava/smooth{
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"aM" = (
|
||||
/obj/structure/stone_tile/cracked{
|
||||
@@ -302,23 +362,22 @@
|
||||
dir = 4
|
||||
},
|
||||
/obj/effect/decal/cleanable/blood,
|
||||
/turf/open/indestructible/boss/air,
|
||||
/turf/open/indestructible/boss,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"aT" = (
|
||||
/obj/structure/stone_tile/block/cracked{
|
||||
dir = 4
|
||||
},
|
||||
/turf/open/lava/smooth,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"aU" = (
|
||||
/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker,
|
||||
/turf/open/lava/smooth,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"aV" = (
|
||||
/obj/structure/stone_tile/block{
|
||||
/obj/structure/stone_tile/surrounding_tile/cracked{
|
||||
dir = 8
|
||||
},
|
||||
/turf/open/lava/smooth,
|
||||
/obj/structure/stone_tile/center,
|
||||
/obj/structure/stone_tile/surrounding_tile{
|
||||
dir = 1
|
||||
},
|
||||
/obj/structure/stone_tile/surrounding_tile{
|
||||
dir = 4
|
||||
},
|
||||
/turf/open/lava/smooth{
|
||||
initial_gas_mix = "o2=14;n2=23;TEMP=300"
|
||||
},
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"aW" = (
|
||||
/obj/structure/stone_tile/block{
|
||||
@@ -328,7 +387,7 @@
|
||||
/obj/structure/stone_tile{
|
||||
dir = 1
|
||||
},
|
||||
/turf/open/indestructible/boss/air,
|
||||
/turf/open/indestructible/boss,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"aY" = (
|
||||
/obj/structure/stone_tile,
|
||||
@@ -376,37 +435,7 @@
|
||||
dir = 4
|
||||
},
|
||||
/mob/living/simple_animal/hostile/asteroid/gutlunch/guthen,
|
||||
/turf/open/indestructible/boss/air,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"bd" = (
|
||||
/obj/structure/stone_tile/surrounding_tile/cracked{
|
||||
dir = 4
|
||||
},
|
||||
/obj/structure/stone_tile/center/cracked,
|
||||
/obj/structure/stone_tile/surrounding_tile,
|
||||
/obj/structure/stone_tile/surrounding_tile{
|
||||
dir = 1
|
||||
},
|
||||
/turf/open/lava/smooth,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"be" = (
|
||||
/obj/structure/stone_tile/block{
|
||||
dir = 1
|
||||
},
|
||||
/turf/open/lava/smooth,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"bf" = (
|
||||
/obj/structure/stone_tile/surrounding_tile/cracked{
|
||||
dir = 8
|
||||
},
|
||||
/obj/structure/stone_tile/center,
|
||||
/obj/structure/stone_tile/surrounding_tile{
|
||||
dir = 1
|
||||
},
|
||||
/obj/structure/stone_tile/surrounding_tile{
|
||||
dir = 4
|
||||
},
|
||||
/turf/open/lava/smooth,
|
||||
/turf/open/indestructible/boss,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"bg" = (
|
||||
/obj/structure/stone_tile/block{
|
||||
@@ -416,7 +445,7 @@
|
||||
dir = 1
|
||||
},
|
||||
/obj/structure/stone_tile,
|
||||
/turf/open/indestructible/boss/air,
|
||||
/turf/open/indestructible/boss,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"bh" = (
|
||||
/obj/structure/stone_tile/block{
|
||||
@@ -514,7 +543,7 @@
|
||||
dir = 4
|
||||
},
|
||||
/obj/item/flashlight/lantern,
|
||||
/turf/open/indestructible/boss/air,
|
||||
/turf/open/indestructible/boss,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"bq" = (
|
||||
/obj/structure/stone_tile/block{
|
||||
@@ -524,11 +553,11 @@
|
||||
/obj/structure/stone_tile{
|
||||
dir = 8
|
||||
},
|
||||
/turf/open/indestructible/boss/air,
|
||||
/turf/open/indestructible/boss,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"br" = (
|
||||
/obj/structure/stone_tile/slab/cracked,
|
||||
/turf/open/indestructible/boss/air,
|
||||
/turf/open/indestructible/boss,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"bs" = (
|
||||
/obj/structure/stone_tile/block/cracked{
|
||||
@@ -539,7 +568,7 @@
|
||||
},
|
||||
/obj/structure/stone_tile,
|
||||
/obj/effect/decal/cleanable/blood,
|
||||
/turf/open/indestructible/boss/air,
|
||||
/turf/open/indestructible/boss,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"bt" = (
|
||||
/obj/structure/stone_tile,
|
||||
@@ -553,7 +582,7 @@
|
||||
dir = 4
|
||||
},
|
||||
/obj/item/flashlight/lantern,
|
||||
/turf/open/indestructible/boss/air,
|
||||
/turf/open/indestructible/boss,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"bv" = (
|
||||
/obj/structure/stone_tile/cracked{
|
||||
@@ -628,7 +657,7 @@
|
||||
/obj/structure/stone_tile/block/cracked{
|
||||
dir = 8
|
||||
},
|
||||
/turf/open/indestructible/boss/air,
|
||||
/turf/open/indestructible/boss,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"bC" = (
|
||||
/obj/structure/stone_tile/block/cracked{
|
||||
@@ -658,18 +687,6 @@
|
||||
"bG" = (
|
||||
/turf/closed/indestructible/riveted/boss/see_through,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"bH" = (
|
||||
/obj/structure/necropolis_gate,
|
||||
/obj/structure/stone_tile/block{
|
||||
dir = 4
|
||||
},
|
||||
/obj/structure/stone_tile/block/cracked{
|
||||
dir = 8
|
||||
},
|
||||
/obj/structure/fans/tiny/invisible,
|
||||
/obj/effect/decal/cleanable/blood,
|
||||
/turf/open/indestructible/boss/air,
|
||||
/area/ruin/unpowered/ash_walkers)
|
||||
"bI" = (
|
||||
/obj/structure/stone_tile/slab/cracked,
|
||||
/turf/closed/mineral/volcanic/lava_land_surface,
|
||||
@@ -1702,9 +1719,9 @@ ae
|
||||
ak
|
||||
ak
|
||||
av
|
||||
aH
|
||||
aT
|
||||
bd
|
||||
an
|
||||
aD
|
||||
aJ
|
||||
bq
|
||||
ak
|
||||
bG
|
||||
@@ -1724,12 +1741,12 @@ ac
|
||||
ak
|
||||
ak
|
||||
aw
|
||||
aI
|
||||
aU
|
||||
be
|
||||
ao
|
||||
aH
|
||||
aL
|
||||
br
|
||||
bB
|
||||
bH
|
||||
am
|
||||
bS
|
||||
ce
|
||||
dn
|
||||
@@ -1746,9 +1763,9 @@ ac
|
||||
ak
|
||||
ak
|
||||
ax
|
||||
aJ
|
||||
aV
|
||||
bf
|
||||
ap
|
||||
aI
|
||||
aT
|
||||
bs
|
||||
ak
|
||||
bG
|
||||
|
||||
@@ -350,6 +350,7 @@
|
||||
dir = 4
|
||||
},
|
||||
/obj/structure/closet/cabinet,
|
||||
/obj/item/pda/neko,
|
||||
/obj/item/gps{
|
||||
gpstag = "kitty"
|
||||
},
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#define ui_boxcraft "EAST-4:22,SOUTH+1:6"
|
||||
#define ui_boxarea "EAST-4:6,SOUTH+1:6"
|
||||
#define ui_boxlang "EAST-5:22,SOUTH+1:6"
|
||||
#define ui_boxvore "EAST-4:22,SOUTH+1:6"
|
||||
|
||||
//Filters
|
||||
#define CIT_FILTER_STAMINACRIT filter(type="drop_shadow", x=0, y=0, size=-3, border=0, color="#04080F")
|
||||
@@ -98,11 +99,11 @@
|
||||
//Citadel istypes
|
||||
#define isborer(A) (istype(A, /mob/living/simple_animal/borer))
|
||||
#define isipcperson(A) (is_species(A, /datum/species/ipc))
|
||||
#define ismammal(A) (ishumanbasic(A) && istype(A.dna.species, /datum/species/human/mammal) )
|
||||
#define isavian(A) (ishumanbasic(A) && istype(A.dna.species, /datum/species/human/avian) )
|
||||
#define isaquatic(A) (ishumanbasic(A) && istype(A.dna.species, /datum/species/human/aquatic) )
|
||||
#define isinsect(A) (ishumanbasic(A) && istype(A.dna.species, /datum/species/human/insect) )
|
||||
#define isxenoperson(A) (ishumanbasic(A) && istype(A.dna.species, /datum/species/human/xeno) )
|
||||
#define ismammal(A) (is_species(A, /datum/species/mammal))
|
||||
#define isavian(A) (is_species(A, /datum/species/avian))
|
||||
#define isaquatic(A) (is_species(A, /datum/species/aquatic))
|
||||
#define isinsect(A) (is_species(A, /datum/species/insect))
|
||||
#define isxenoperson(A) (is_species(A, /datum/species/xeno))
|
||||
|
||||
#define CITADEL_MENTOR_OOC_COLOUR "#224724"
|
||||
|
||||
@@ -130,5 +131,7 @@
|
||||
//component stuff
|
||||
#define COMSIG_COMBAT_TOGGLED "combatmode_toggled" //called by combat mode toggle on all equipped items. args: (mob/user, combatmode)
|
||||
|
||||
#define COMSIG_VORE_TOGGLED "voremode_toggled" // totally not copypasta
|
||||
|
||||
//belly sound pref things
|
||||
#define NORMIE_HEARCHECK 4
|
||||
|
||||
@@ -25,3 +25,10 @@ When using time2text(), please use "DDD" to find the weekday. Refrain from using
|
||||
#define DS2TICKS(DS) ((DS)/world.tick_lag)
|
||||
|
||||
#define TICKS2DS(T) ((T) TICKS)
|
||||
|
||||
#define GAMETIMESTAMP(format, wtime) time2text(wtime, format)
|
||||
#define WORLDTIME2TEXT(format) GAMETIMESTAMP(format, world.time)
|
||||
#define WORLDTIMEOFDAY2TEXT(format) GAMETIMESTAMP(format, world.timeofday)
|
||||
#define TIME_STAMP(format, showds) showds ? "[WORLDTIMEOFDAY2TEXT(format)]:[world.timeofday % 10]" : WORLDTIMEOFDAY2TEXT(format)
|
||||
#define STATION_TIME(display_only) ((((world.time - SSticker.round_start_time) * SSticker.station_time_rate_multiplier) + SSticker.gametime_offset) % 864000) - (display_only? GLOB.timezoneOffset : 0)
|
||||
#define STATION_TIME_TIMESTAMP(format) time2text(STATION_TIME(TRUE), format)
|
||||
+16
-107
@@ -18,39 +18,6 @@
|
||||
/* // removing sizeplay again
|
||||
GLOBAL_LIST_INIT(player_sizes_list, list("Macro" = SIZESCALE_HUGE, "Big" = SIZESCALE_BIG, "Normal" = SIZESCALE_NORMAL, "Small" = SIZESCALE_SMALL, "Tiny" = SIZESCALE_TINY))
|
||||
// Edited to make the new travis check go away
|
||||
|
||||
|
||||
GLOBAL_LIST_INIT(digest_pred, list(
|
||||
'sound/vore/pred/digest_01.ogg',
|
||||
'sound/vore/pred/digest_02.ogg',
|
||||
'sound/vore/pred/digest_03.ogg',
|
||||
'sound/vore/pred/digest_04.ogg',
|
||||
'sound/vore/pred/digest_05.ogg',
|
||||
'sound/vore/pred/digest_06.ogg',
|
||||
'sound/vore/pred/digest_07.ogg',
|
||||
'sound/vore/pred/digest_08.ogg',
|
||||
'sound/vore/pred/digest_09.ogg',
|
||||
'sound/vore/pred/digest_10.ogg',
|
||||
'sound/vore/pred/digest_11.ogg',
|
||||
'sound/vore/pred/digest_12.ogg',
|
||||
'sound/vore/pred/digest_13.ogg',
|
||||
'sound/vore/pred/digest_14.ogg',
|
||||
'sound/vore/pred/digest_15.ogg',
|
||||
'sound/vore/pred/digest_16.ogg',
|
||||
'sound/vore/pred/digest_17.ogg',
|
||||
'sound/vore/pred/digest_18.ogg'))
|
||||
|
||||
GLOBAL_LIST_INIT(death_pred, list(
|
||||
'sound/vore/pred/death_01.ogg',
|
||||
'sound/vore/pred/death_02.ogg',
|
||||
'sound/vore/pred/death_03.ogg',
|
||||
'sound/vore/pred/death_04.ogg',
|
||||
'sound/vore/pred/death_05.ogg',
|
||||
'sound/vore/pred/death_06.ogg',
|
||||
'sound/vore/pred/death_07.ogg',
|
||||
'sound/vore/pred/death_08.ogg',
|
||||
'sound/vore/pred/death_09.ogg',
|
||||
'sound/vore/pred/death_10.ogg'))
|
||||
*/
|
||||
|
||||
GLOBAL_LIST_INIT(vore_sounds, list(
|
||||
@@ -66,79 +33,21 @@ GLOBAL_LIST_INIT(vore_sounds, list(
|
||||
"Squish3" = 'sound/vore/pred/squish_03.ogg',
|
||||
"Squish4" = 'sound/vore/pred/squish_04.ogg',
|
||||
"Rustle (cloth)" = 'sound/effects/rustle5.ogg',
|
||||
"rustle2(cloth)" = 'sound/effects/rustle2.ogg',
|
||||
"rustle3(cloth)" = 'sound/effects/rustle3.ogg',
|
||||
"rustle4(cloth)" = 'sound/effects/rustle4.ogg',
|
||||
"rustle5(cloth)" = 'sound/effects/rustle5.ogg',
|
||||
"None" = null))
|
||||
/*
|
||||
GLOBAL_LIST_INIT(pred_struggle_sounds, list(
|
||||
"Struggle1" = 'sound/vore/pred/struggle_01.ogg',
|
||||
"Struggle2" = 'sound/vore/pred/struggle_02.ogg',
|
||||
"Struggle3" = 'sound/vore/pred/struggle_03.ogg',
|
||||
"Struggle4" = 'sound/vore/pred/struggle_04.ogg',
|
||||
"Struggle5" = 'sound/vore/pred/struggle_05.ogg'))
|
||||
|
||||
GLOBAL_LIST_INIT(prey_vore_sounds, list(
|
||||
"Gulp" = 'sound/vore/prey/swallow_01.ogg',
|
||||
"Swallow" = 'sound/vore/prey/swallow_02.ogg',
|
||||
"Insertion1" = 'sound/vore/prey/insertion_01.ogg',
|
||||
"Insertion2" = 'sound/vore/prey/insertion_02.ogg',
|
||||
"Tauric Swallow" = 'sound/vore/prey/taurswallow.ogg',
|
||||
"Schlorp" = 'sound/vore/prey/schlorp.ogg',
|
||||
"Squish1" = 'sound/vore/prey/squish_01.ogg',
|
||||
"Squish2" = 'sound/vore/prey/squish_02.ogg',
|
||||
"Squish3" = 'sound/vore/prey/squish_03.ogg',
|
||||
"Squish4" = 'sound/vore/prey/squish_04.ogg'))
|
||||
|
||||
|
||||
GLOBAL_LIST_INIT(prey_struggle_sounds, list(
|
||||
"Struggle1" = 'sound/vore/prey/struggle_01.ogg',
|
||||
"Struggle2" = 'sound/vore/prey/struggle_02.ogg',
|
||||
"Struggle3" = 'sound/vore/prey/struggle_03.ogg',
|
||||
"Struggle4" = 'sound/vore/prey/struggle_04.ogg',
|
||||
"Struggle5" = 'sound/vore/prey/struggle_05.ogg'))
|
||||
|
||||
GLOBAL_LIST_INIT(digest_prey, list(
|
||||
"digest1" = 'sound/vore/prey/digest_01.ogg',
|
||||
"digest2" = 'sound/vore/prey/digest_02.ogg',
|
||||
"digest3" = 'sound/vore/prey/digest_03.ogg',
|
||||
"digest4" = 'sound/vore/prey/digest_04.ogg',
|
||||
"digest5" = 'sound/vore/prey/digest_05.ogg',
|
||||
"digest6" = 'sound/vore/prey/digest_06.ogg',
|
||||
"digest7" = 'sound/vore/prey/digest_07.ogg',
|
||||
"digest8" = 'sound/vore/prey/digest_08.ogg',
|
||||
"digest9" = 'sound/vore/prey/digest_09.ogg',
|
||||
"digest10" = 'sound/vore/prey/digest_10.ogg',
|
||||
"digest11" = 'sound/vore/prey/digest_11.ogg',
|
||||
"digest12" = 'sound/vore/prey/digest_12.ogg',
|
||||
"digest13" = 'sound/vore/prey/digest_13.ogg',
|
||||
"digest14" = 'sound/vore/prey/digest_14.ogg',
|
||||
"digest15" = 'sound/vore/prey/digest_15.ogg',
|
||||
"digest16" = 'sound/vore/prey/digest_16.ogg',
|
||||
"digest17" = 'sound/vore/prey/digest_17.ogg',
|
||||
"digest18" = 'sound/vore/prey/digest_18.ogg'))
|
||||
|
||||
GLOBAL_LIST_INIT(death_prey, list(
|
||||
"death1" = 'sound/vore/prey/death_01.ogg',
|
||||
"death2" = 'sound/vore/prey/death_02.ogg',
|
||||
"death3" = 'sound/vore/prey/death_03.ogg',
|
||||
"death4" = 'sound/vore/prey/death_04.ogg',
|
||||
"death5" = 'sound/vore/prey/death_05.ogg',
|
||||
"death6" = 'sound/vore/prey/death_06.ogg',
|
||||
"death7" = 'sound/vore/prey/death_07.ogg',
|
||||
"death8" = 'sound/vore/prey/death_08.ogg',
|
||||
"death9" = 'sound/vore/prey/death_09.ogg',
|
||||
"death10" = 'sound/vore/prey/death_10.ogg'))
|
||||
*/
|
||||
"Rustle 2 (cloth)" = 'sound/effects/rustle2.ogg',
|
||||
"Rustle 3 (cloth)" = 'sound/effects/rustle3.ogg',
|
||||
"Rustle 4 (cloth)" = 'sound/effects/rustle4.ogg',
|
||||
"Rustle 5 (cloth)" = 'sound/effects/rustle5.ogg',
|
||||
"None" = null
|
||||
))
|
||||
|
||||
GLOBAL_LIST_INIT(release_sounds, list(
|
||||
"rustle (cloth)" = 'sound/effects/rustle1.ogg',
|
||||
"rustle2 (cloth)" = 'sound/effects/rustle2.ogg',
|
||||
"rustle3 (cloth)" = 'sound/effects/rustle3.ogg',
|
||||
"rustle4 (cloth)" = 'sound/effects/rustle4.ogg',
|
||||
"rustle5 (cloth)" = 'sound/effects/rustle5.ogg',
|
||||
"Stomach Move" = 'sound/vore/pred/stomachmove.ogg',
|
||||
"Pred Escape" = 'sound/vore/pred/escape.ogg',
|
||||
"Splatter" = 'sound/effects/splat.ogg',
|
||||
"None" = null))
|
||||
"Rustle (cloth)" = 'sound/effects/rustle1.ogg',
|
||||
"Rustle 2 (cloth)" = 'sound/effects/rustle2.ogg',
|
||||
"Rustle 3 (cloth)" = 'sound/effects/rustle3.ogg',
|
||||
"Rustle 4 (cloth)" = 'sound/effects/rustle4.ogg',
|
||||
"Rustle 5 (cloth)" = 'sound/effects/rustle5.ogg',
|
||||
"Stomach Move" = 'sound/vore/pred/stomachmove.ogg',
|
||||
"Pred Escape" = 'sound/vore/pred/escape.ogg',
|
||||
"Splatter" = 'sound/effects/splat.ogg',
|
||||
"None" = null
|
||||
))
|
||||
|
||||
@@ -90,10 +90,6 @@ GLOBAL_LIST_INIT(dildo_colors, list(//mostly neon colors
|
||||
"Purple" = "#e300ff"//purple
|
||||
))
|
||||
|
||||
//Looc stuff
|
||||
GLOBAL_VAR_INIT(looc_allowed, 1)
|
||||
GLOBAL_VAR_INIT(dlooc_allowed, 1)
|
||||
|
||||
//Crew objective and miscreants stuff
|
||||
GLOBAL_VAR_INIT(miscreants_allowed, FALSE)
|
||||
|
||||
@@ -124,36 +120,6 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE)
|
||||
src << "You will [(prefs.chat_toggles & CHAT_LOOC) ? "now" : "no longer"] see messages on the LOOC channel."
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "TLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/datum/admins/proc/togglelooc()
|
||||
set category = "Server"
|
||||
set desc="Fukken metagamers"
|
||||
set name="Toggle LOOC"
|
||||
toggle_looc()
|
||||
log_admin("[key_name(usr)] toggled LOOC.")
|
||||
message_admins("[key_name_admin(usr)] toggled LOOC.")
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "TLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/proc/toggle_looc(toggle = null)
|
||||
if(toggle != null) //if we're specifically en/disabling ooc
|
||||
if(toggle != GLOB.looc_allowed)
|
||||
GLOB.looc_allowed = toggle
|
||||
else
|
||||
return
|
||||
else //otherwise just toggle it
|
||||
GLOB.looc_allowed = !GLOB.looc_allowed
|
||||
world << "<B>The LOOC channel has been globally [GLOB.looc_allowed ? "enabled" : "disabled"].</B>"
|
||||
|
||||
/datum/admins/proc/toggleloocdead()
|
||||
set category = "Server"
|
||||
set desc="Toggle dis bitch"
|
||||
set name="Toggle Dead LOOC"
|
||||
GLOB.dlooc_allowed = !( GLOB.dlooc_allowed )
|
||||
|
||||
log_admin("[key_name(usr)] toggled Dead LOOC.")
|
||||
message_admins("[key_name_admin(usr)] toggled Dead LOOC.")
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "TDLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
|
||||
/mob/living/carbon/proc/has_penis()
|
||||
if(getorganslot("penis"))//slot shared with ovipositor
|
||||
if(istype(getorganslot("penis"), /obj/item/organ/genital/penis))
|
||||
|
||||
@@ -413,7 +413,8 @@
|
||||
var/list/candidates = list()
|
||||
|
||||
for(var/mob/dead/observer/G in GLOB.player_list)
|
||||
candidates += G
|
||||
if(G.can_reenter_round)
|
||||
candidates += G
|
||||
|
||||
return pollCandidates(Question, jobbanType, gametypeCheck, be_special_flag, poll_time, ignore_category, flashwindow, candidates)
|
||||
|
||||
|
||||
+42
-24
@@ -94,43 +94,61 @@
|
||||
if(!GLOB.mam_snouts_list.len)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_snouts, GLOB.mam_snouts_list)
|
||||
|
||||
// if(ishuman(src))
|
||||
// var/mob/living/carbon/human/H = src
|
||||
/* if(H.gender == MALE) Fuck if I know how to fix this.
|
||||
penis = 1
|
||||
balls = 1
|
||||
vagina = 0
|
||||
womb = 0
|
||||
breasts = 0
|
||||
if(H.gender == FEMALE)
|
||||
penis = 0
|
||||
balls = 0
|
||||
vagina = 1
|
||||
womb = 1
|
||||
breasts = 1 */
|
||||
//snowflake check so people's ckey features don't get randomly put on unmonkeys/spawns
|
||||
var/list/snowflake_mam_tails_list = list()
|
||||
for(var/mtpath in GLOB.mam_tails_list)
|
||||
var/datum/sprite_accessory/mam_tails/instance = GLOB.mam_tails_list[mtpath]
|
||||
if(istype(instance, /datum/sprite_accessory))
|
||||
var/datum/sprite_accessory/S = instance
|
||||
if(!S.ckeys_allowed)
|
||||
snowflake_mam_tails_list[S.name] = mtpath
|
||||
var/list/snowflake_markings_list = list()
|
||||
for(var/mmpath in GLOB.mam_body_markings_list)
|
||||
var/datum/sprite_accessory/mam_body_markings/instance = GLOB.mam_body_markings_list[mmpath]
|
||||
if(istype(instance, /datum/sprite_accessory))
|
||||
var/datum/sprite_accessory/S = instance
|
||||
if(!S.ckeys_allowed)
|
||||
snowflake_markings_list[S.name] = mmpath
|
||||
var/list/snowflake_ears_list = list()
|
||||
for(var/mepath in GLOB.mam_ears_list)
|
||||
var/datum/sprite_accessory/mam_ears/instance = GLOB.mam_ears_list[mepath]
|
||||
if(istype(instance, /datum/sprite_accessory))
|
||||
var/datum/sprite_accessory/S = instance
|
||||
if(!S.ckeys_allowed)
|
||||
snowflake_ears_list[S.name] = mepath
|
||||
var/list/snowflake_mam_snouts_list = list()
|
||||
for(var/mspath in GLOB.mam_snouts_list)
|
||||
var/datum/sprite_accessory/mam_snouts/instance = GLOB.mam_snouts_list[mspath]
|
||||
if(istype(instance, /datum/sprite_accessory))
|
||||
var/datum/sprite_accessory/S = instance
|
||||
if(!S.ckeys_allowed)
|
||||
snowflake_mam_snouts_list[S.name] = mspath
|
||||
var/color1 = random_short_color()
|
||||
var/color2 = random_short_color()
|
||||
var/color3 = random_short_color()
|
||||
|
||||
//CIT CHANGE - changes this entire return to support cit's snowflake parts
|
||||
return(list(
|
||||
"mcolor" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"),
|
||||
"mcolor2" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"),
|
||||
"mcolor3" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"),
|
||||
"mcolor" = color1,
|
||||
"mcolor2" = color2,
|
||||
"mcolor3" = color3,
|
||||
"tail_lizard" = pick(GLOB.tails_list_lizard),
|
||||
"tail_human" = pick(GLOB.tails_list_human),
|
||||
"tail_human" = "None",
|
||||
"wings" = "None",
|
||||
"snout" = pick(GLOB.snouts_list),
|
||||
"horns" = pick(GLOB.horns_list),
|
||||
"ears" = pick(GLOB.ears_list),
|
||||
"ears" = "None",
|
||||
"frills" = pick(GLOB.frills_list),
|
||||
"spines" = pick(GLOB.spines_list),
|
||||
"body_markings" = pick(GLOB.body_markings_list),
|
||||
"legs" = "Normal Legs",
|
||||
"legs" = pick("Normal Legs","Digitigrade Legs"),
|
||||
"caps" = pick(GLOB.caps_list),
|
||||
"moth_wings" = pick(GLOB.moth_wings_list),
|
||||
"taur" = "None",
|
||||
"mam_body_markings" = pick(GLOB.mam_body_markings_list),
|
||||
"mam_ears" = pick(GLOB.mam_ears_list),
|
||||
"mam_snouts" = pick(GLOB.mam_snouts_list),
|
||||
"mam_tail" = pick(GLOB.mam_tails_list),
|
||||
"mam_body_markings" = pick(snowflake_markings_list),
|
||||
"mam_ears" = pick(snowflake_ears_list),
|
||||
"mam_snouts" = pick(snowflake_mam_snouts_list),
|
||||
"mam_tail" = pick(snowflake_mam_tails_list),
|
||||
"mam_tail_animated" = "None",
|
||||
"xenodorsal" = "Standard",
|
||||
"xenohead" = "Standard",
|
||||
|
||||
@@ -24,8 +24,8 @@ GLOBAL_LIST_EMPTY(whitelisted_species_list)
|
||||
|
||||
/proc/log_mentor(text)
|
||||
GLOB.mentorlog.Add(text)
|
||||
WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]MENTOR: [text]")
|
||||
WRITE_FILE(GLOB.world_game_log, "\[[TIME_STAMP("hh:mm:ss", FALSE)]]MENTOR: [text]")
|
||||
|
||||
/proc/log_looc(text)
|
||||
if (CONFIG_GET(flag/log_ooc))
|
||||
WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]LOOC: [text]")
|
||||
WRITE_FILE(GLOB.world_game_log, "\[[TIME_STAMP("hh:mm:ss", FALSE)]]LOOC: [text]")
|
||||
@@ -1,22 +1,3 @@
|
||||
//Returns the world time in english
|
||||
/proc/worldtime2text()
|
||||
return gameTimestamp("hh:mm:ss", world.time)
|
||||
|
||||
/proc/time_stamp(format = "hh:mm:ss", show_ds)
|
||||
var/time_string = time2text(world.timeofday, format)
|
||||
return show_ds ? "[time_string]:[world.timeofday % 10]" : time_string
|
||||
|
||||
/proc/gameTimestamp(format = "hh:mm:ss", wtime=null)
|
||||
if(!wtime)
|
||||
wtime = world.time
|
||||
return time2text(wtime - GLOB.timezoneOffset, format)
|
||||
|
||||
/proc/station_time(display_only = FALSE)
|
||||
return ((((world.time - SSticker.round_start_time) * SSticker.station_time_rate_multiplier) + SSticker.gametime_offset) % 864000) - (display_only? GLOB.timezoneOffset : 0)
|
||||
|
||||
/proc/station_time_timestamp(format = "hh:mm:ss")
|
||||
return time2text(station_time(TRUE), format)
|
||||
|
||||
/proc/station_time_debug(force_set)
|
||||
if(isnum(force_set))
|
||||
SSticker.gametime_offset = force_set
|
||||
|
||||
@@ -9,6 +9,7 @@ GLOBAL_VAR_INIT(changelog_hash, "")
|
||||
GLOBAL_VAR_INIT(hub_visibility, FALSE)
|
||||
|
||||
GLOBAL_VAR_INIT(ooc_allowed, TRUE) // used with admin verbs to disable ooc - not a config option apparently
|
||||
GLOBAL_VAR_INIT(looc_allowed, TRUE)
|
||||
GLOBAL_VAR_INIT(dooc_allowed, TRUE)
|
||||
GLOBAL_VAR_INIT(aooc_allowed, FALSE)
|
||||
GLOBAL_VAR_INIT(enter_allowed, TRUE)
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
if(mob && LAZYLEN(mob.mousemove_intercept_objects))
|
||||
for(var/datum/D in mob.mousemove_intercept_objects)
|
||||
D.onMouseMove(object, location, control, params)
|
||||
if(mob) //CIT CHANGE - passes onmousemove() to mobs
|
||||
if(!show_popup_menus && mob) //CIT CHANGE - passes onmousemove() to mobs
|
||||
mob.onMouseMove(object, location, control, params) //CIT CHANGE - ditto
|
||||
..()
|
||||
|
||||
|
||||
@@ -85,6 +85,7 @@
|
||||
#define ui_crafting "EAST-5:20,SOUTH:5"//CIT CHANGE - moves this over one tile to accommodate for combat mode toggle
|
||||
#define ui_building "EAST-5:20,SOUTH:21"//CIT CHANGE - ditto
|
||||
#define ui_language_menu "EAST-5:4,SOUTH:21"//CIT CHANGE - ditto
|
||||
#define ui_voremode "EAST-5:20,SOUTH:5"
|
||||
|
||||
#define ui_borg_pull "EAST-2:26,SOUTH+1:7"
|
||||
#define ui_borg_radio "EAST-1:28,SOUTH+1:7"
|
||||
|
||||
@@ -162,6 +162,8 @@
|
||||
return
|
||||
|
||||
var/button_number = 0
|
||||
var/list/cview = getviewsize(client.view)
|
||||
var/supportedcolumns = cview[1]-2
|
||||
|
||||
if(hud_used.action_buttons_hidden)
|
||||
for(var/datum/action/A in actions)
|
||||
@@ -177,7 +179,7 @@
|
||||
if(B.moved)
|
||||
B.screen_loc = B.moved
|
||||
else
|
||||
B.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number)
|
||||
B.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number, supportedcolumns)
|
||||
if(reload_screen)
|
||||
client.screen += B
|
||||
|
||||
@@ -186,30 +188,26 @@
|
||||
return
|
||||
|
||||
if(!hud_used.hide_actions_toggle.moved)
|
||||
hud_used.hide_actions_toggle.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number+1)
|
||||
hud_used.hide_actions_toggle.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number+1, supportedcolumns)
|
||||
else
|
||||
hud_used.hide_actions_toggle.screen_loc = hud_used.hide_actions_toggle.moved
|
||||
if(reload_screen)
|
||||
client.screen += hud_used.hide_actions_toggle
|
||||
|
||||
|
||||
|
||||
#define AB_MAX_COLUMNS 10
|
||||
|
||||
/datum/hud/proc/ButtonNumberToScreenCoords(number) // TODO : Make this zero-indexed for readabilty
|
||||
var/row = round((number - 1)/AB_MAX_COLUMNS)
|
||||
var/col = ((number - 1)%(AB_MAX_COLUMNS)) + 1
|
||||
/datum/hud/proc/ButtonNumberToScreenCoords(number, supportedcolumns) // TODO : Make this zero-indexed for readabilty
|
||||
var/row = round((number - 1)/supportedcolumns)
|
||||
var/col = ((number - 1)%(supportedcolumns)) + 1
|
||||
|
||||
var/coord_col = "+[col-1]"
|
||||
var/coord_col_offset = 4 + 2 * col
|
||||
var/coord_col_offset = 2 + 2 * col
|
||||
|
||||
var/coord_row = "[row ? -row : "+0"]"
|
||||
|
||||
return "WEST[coord_col]:[coord_col_offset],NORTH[coord_row]:-6"
|
||||
|
||||
/datum/hud/proc/SetButtonCoords(obj/screen/button,number)
|
||||
var/row = round((number-1)/AB_MAX_COLUMNS)
|
||||
var/col = ((number - 1)%(AB_MAX_COLUMNS)) + 1
|
||||
/datum/hud/proc/SetButtonCoords(obj/screen/button,number, supportedcolumns)
|
||||
var/row = round((number-1)/supportedcolumns)
|
||||
var/col = ((number - 1)%(supportedcolumns)) + 1
|
||||
var/x_offset = 32*(col-1) + 4 + 2*col
|
||||
var/y_offset = -32*(row+1) + 26
|
||||
|
||||
|
||||
@@ -109,6 +109,13 @@
|
||||
using.screen_loc = ui_boxarea // CIT CHANGE
|
||||
static_inventory += using
|
||||
|
||||
using = new /obj/screen/voretoggle() //We fancy Vore now
|
||||
using.icon = tg_ui_icon_to_cit_ui(ui_style)
|
||||
using.screen_loc = ui_voremode
|
||||
if(!widescreenlayout)
|
||||
using.screen_loc = ui_boxvore
|
||||
static_inventory += using
|
||||
|
||||
action_intent = new /obj/screen/act_intent/segmented
|
||||
action_intent.icon_state = mymob.a_intent
|
||||
static_inventory += action_intent
|
||||
|
||||
@@ -32,8 +32,11 @@ SUBSYSTEM_DEF(input)
|
||||
"default" = list(
|
||||
"Tab" = "\".winset \\\"input.focus=true?map.focus=true input.background-color=[COLOR_INPUT_DISABLED]:input.focus=true input.background-color=[COLOR_INPUT_ENABLED]\\\"\"",
|
||||
"O" = "ooc",
|
||||
"Ctrl+O" = "looc",
|
||||
"T" = "say",
|
||||
"Ctrl+T" = "whisper",
|
||||
"M" = "me",
|
||||
"Ctrl+M" = "subtle",
|
||||
"Back" = "\".winset \\\"input.text=\\\"\\\"\\\"\"", // This makes it so backspace can remove default inputs
|
||||
"Any" = "\"KeyDown \[\[*\]\]\"",
|
||||
"Any+UP" = "\"KeyUp \[\[*\]\]\"",
|
||||
|
||||
@@ -26,7 +26,7 @@ SUBSYSTEM_DEF(nightshift)
|
||||
/datum/controller/subsystem/nightshift/proc/check_nightshift()
|
||||
var/emergency = GLOB.security_level >= SEC_LEVEL_RED
|
||||
var/announcing = TRUE
|
||||
var/time = station_time()
|
||||
var/time = STATION_TIME(FALSE)
|
||||
var/night_time = (time < nightshift_end_time) || (time > nightshift_start_time)
|
||||
if(high_security_mode != emergency)
|
||||
high_security_mode = emergency
|
||||
|
||||
@@ -54,6 +54,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
var/lockdown = FALSE //disallow transit after nuke goes off
|
||||
|
||||
var/auto_call = 72000 //CIT CHANGE - time before in deciseconds in which the shuttle is auto called. Default is 2ish hours plus 15 for the shuttle. So total is 3.
|
||||
var/realtimeofstart = 0
|
||||
|
||||
/datum/controller/subsystem/shuttle/Initialize(timeofday)
|
||||
ordernum = rand(1, 9000)
|
||||
@@ -74,6 +75,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
WARNING("No /obj/docking_port/mobile/emergency/backup placed on the map!")
|
||||
if(!supply)
|
||||
WARNING("No /obj/docking_port/mobile/supply placed on the map!")
|
||||
realtimeofstart = world.realtime
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/initial_load()
|
||||
|
||||
@@ -304,6 +304,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
to_chat(world, "<h4>[holiday.greet()]</h4>")
|
||||
|
||||
PostSetup()
|
||||
SSshuttle.realtimeofstart = world.realtime
|
||||
|
||||
return TRUE
|
||||
|
||||
@@ -655,7 +656,8 @@ SUBSYSTEM_DEF(ticker)
|
||||
'sound/roundend/its_only_game.ogg',
|
||||
'sound/roundend/yeehaw.ogg',
|
||||
'sound/roundend/disappointed.ogg',
|
||||
'sound/roundend/gondolabridge.ogg'\
|
||||
'sound/roundend/gondolabridge.ogg',
|
||||
'sound/roundend/haveabeautifultime.ogg'\
|
||||
)
|
||||
|
||||
SEND_SOUND(world, sound(round_end_sound))
|
||||
|
||||
@@ -130,7 +130,7 @@
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.gloves)
|
||||
hasgloves = "(gloves)"
|
||||
var/current_time = time_stamp()
|
||||
var/current_time = TIME_STAMP("hh:mm:ss", FALSE)
|
||||
if(!LAZYACCESS(hiddenprints, M.key))
|
||||
LAZYSET(hiddenprints, M.key, "First: [M.real_name]\[[current_time]\][hasgloves]. Ckey: [M.ckey]")
|
||||
else
|
||||
|
||||
@@ -297,7 +297,7 @@
|
||||
ND.number++
|
||||
|
||||
//This proc determines the size of the inventory to be displayed. Please touch it only if you know what you're doing.
|
||||
/datum/component/storage/proc/orient2hud()
|
||||
/datum/component/storage/proc/orient2hud(mob/user, maxcolumns)
|
||||
var/atom/real_location = real_location()
|
||||
var/adjusted_contents = real_location.contents.len
|
||||
|
||||
@@ -307,7 +307,7 @@
|
||||
numbered_contents = _process_numerical_display()
|
||||
adjusted_contents = numbered_contents.len
|
||||
|
||||
var/columns = CLAMP(max_items, 1, screen_max_columns)
|
||||
var/columns = CLAMP(max_items, 1, maxcolumns ? maxcolumns : screen_max_columns)
|
||||
var/rows = CLAMP(CEILING(adjusted_contents / columns, 1), 1, screen_max_rows)
|
||||
standard_orient_objs(rows, columns, numbered_contents)
|
||||
|
||||
@@ -351,6 +351,8 @@
|
||||
/datum/component/storage/proc/show_to(mob/M)
|
||||
if(!M.client)
|
||||
return FALSE
|
||||
var/list/cview = getviewsize(M.client.view)
|
||||
var/maxallowedscreensize = cview[1]-8
|
||||
var/atom/real_location = real_location()
|
||||
if(M.active_storage != src && (M.stat == CONSCIOUS))
|
||||
for(var/obj/item/I in real_location)
|
||||
@@ -358,7 +360,7 @@
|
||||
return FALSE
|
||||
if(M.active_storage)
|
||||
M.active_storage.hide_from(M)
|
||||
orient2hud()
|
||||
orient2hud(M, (isliving(M) ? maxallowedscreensize : 7))
|
||||
M.client.screen |= boxes
|
||||
M.client.screen |= closer
|
||||
M.client.screen |= real_location.contents
|
||||
|
||||
@@ -92,7 +92,7 @@ GLOBAL_LIST_EMPTY(explosions)
|
||||
var/y0 = epicenter.y
|
||||
var/z0 = epicenter.z
|
||||
var/area/areatype = get_area(epicenter)
|
||||
SSblackbox.record_feedback("associative", "explosion", 1, list("dev" = devastation_range, "heavy" = heavy_impact_range, "light" = light_impact_range, "flash" = flash_range, "flame" = flame_range, "orig_dev" = orig_dev_range, "orig_heavy" = orig_heavy_range, "orig_light" = orig_light_range, "x" = x0, "y" = y0, "z" = z0, "area" = areatype.type, "time" = time_stamp("YYYY-MM-DD hh:mm:ss", 1)))
|
||||
SSblackbox.record_feedback("associative", "explosion", 1, list("dev" = devastation_range, "heavy" = heavy_impact_range, "light" = light_impact_range, "flash" = flash_range, "flame" = flame_range, "orig_dev" = orig_dev_range, "orig_heavy" = orig_heavy_range, "orig_light" = orig_light_range, "x" = x0, "y" = y0, "z" = z0, "area" = areatype.type, "time" = TIME_STAMP("YYYY-MM-DD hh:mm:ss", 1)))
|
||||
|
||||
// Play sounds; we want sounds to be different depending on distance so we will manually do it ourselves.
|
||||
// Stereo users will also hear the direction of the explosion!
|
||||
|
||||
@@ -156,3 +156,16 @@
|
||||
mob_trait = TRAIT_VORACIOUS
|
||||
gain_text = "<span class='notice'>You feel HONGRY.</span>"
|
||||
lose_text = "<span class='danger'>You no longer feel HONGRY.</span>"
|
||||
|
||||
/datum/quirk/trandening
|
||||
name = "High Luminosity Eyes"
|
||||
desc = "When the next big fancy implant came out you had to buy one on impluse!"
|
||||
value = 1
|
||||
gain_text = "<span class='notice'>You have to keep up with the next big thing!.</span>"
|
||||
lose_text = "<span class='danger'>High-tech gizmos are a scam...</span>"
|
||||
|
||||
/datum/quirk/trandening/on_spawn()
|
||||
var/mob/living/carbon/human/H = quirk_holder
|
||||
var/obj/item/autosurgeon/gloweyes/gloweyes = new(get_turf(H))
|
||||
H.equip_to_slot(gloweyes, SLOT_IN_BACKPACK)
|
||||
H.regenerate_icons()
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
if(!A.secondsElectrified)
|
||||
A.set_electrified(30)
|
||||
if(usr)
|
||||
LAZYADD(A.shockedby, text("\[[time_stamp()]\] [key_name(usr)]"))
|
||||
LAZYADD(A.shockedby, text("\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(usr)]"))
|
||||
log_combat(usr, A, "electrified")
|
||||
if(WIRE_SAFETY)
|
||||
A.safe = !A.safe
|
||||
@@ -134,7 +134,7 @@
|
||||
if(A.secondsElectrified != -1)
|
||||
A.set_electrified(-1)
|
||||
if(usr)
|
||||
LAZYADD(A.shockedby, text("\[[time_stamp()]\] [key_name(usr)]"))
|
||||
LAZYADD(A.shockedby, text("\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(usr)]"))
|
||||
log_combat(usr, A, "electrified")
|
||||
if(WIRE_SAFETY) // Cut to disable safeties, mend to re-enable.
|
||||
A.safe = mend
|
||||
|
||||
@@ -131,9 +131,9 @@ Credit where due:
|
||||
config_tag = "clockwork_cult"
|
||||
antag_flag = ROLE_SERVANT_OF_RATVAR
|
||||
false_report_weight = 10
|
||||
required_players = 20
|
||||
required_enemies = 2
|
||||
recommended_enemies = 4
|
||||
required_players = 30
|
||||
required_enemies = 3
|
||||
recommended_enemies = 5
|
||||
enemy_minimum_age = 7
|
||||
protected_jobs = list("AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Captain") //Silicons can eventually be converted
|
||||
restricted_jobs = list("Chaplain", "Captain")
|
||||
|
||||
@@ -37,9 +37,9 @@
|
||||
false_report_weight = 10
|
||||
restricted_jobs = list("Chaplain","AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel")
|
||||
protected_jobs = list()
|
||||
required_players = 20
|
||||
required_enemies = 2
|
||||
recommended_enemies = 4
|
||||
required_players = 30
|
||||
required_enemies = 3
|
||||
recommended_enemies = 5
|
||||
enemy_minimum_age = 7
|
||||
|
||||
announce_span = "cult"
|
||||
|
||||
@@ -197,7 +197,7 @@
|
||||
|
||||
/obj/machinery/computer/apc_control/proc/log_activity(log_text)
|
||||
var/op_string = operator && !(obj_flags & EMAGGED) ? operator : "\[NULL OPERATOR\]"
|
||||
LAZYADD(logs, "<b>([station_time_timestamp()])</b> [op_string] [log_text]")
|
||||
LAZYADD(logs, "<b>([STATION_TIME_TIMESTAMP("hh:mm:ss")])</b> [op_string] [log_text]")
|
||||
|
||||
/mob/proc/using_power_flow_console()
|
||||
for(var/obj/machinery/computer/apc_control/A in range(1, src))
|
||||
|
||||
@@ -202,7 +202,7 @@
|
||||
state = STATE_CANCELSHUTTLE
|
||||
if("cancelshuttle2")
|
||||
if(authenticated)
|
||||
if(world.time > SSshuttle.auto_call) //Citadel Edit Removing auto_call caused recall.
|
||||
if((world.realtime - SSshuttle.realtimeofstart) > SSshuttle.auto_call) //Citadel Edit Removing auto_call caused recall.
|
||||
say("Warning: Emergency shuttle recalls have been blocked by Central Command due to ongoing crew transfer procedures.")
|
||||
else
|
||||
SSshuttle.cancelEvac(usr)
|
||||
|
||||
@@ -493,7 +493,7 @@
|
||||
var/counter = 1
|
||||
while(src.active2.fields[text("com_[]", counter)])
|
||||
counter++
|
||||
src.active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], []<BR>[]", src.authenticated, src.rank, station_time_timestamp(), time2text(world.realtime, "MMM DD"), GLOB.year_integer+540, t1)
|
||||
src.active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], []<BR>[]", src.authenticated, src.rank, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer+540, t1)
|
||||
|
||||
else if(href_list["del_c"])
|
||||
if((istype(src.active2, /datum/data/record) && src.active2.fields[text("com_[]", href_list["del_c"])]))
|
||||
|
||||
@@ -474,7 +474,7 @@ What a mess.*/
|
||||
var/counter = 1
|
||||
while(active2.fields[text("com_[]", counter)])
|
||||
counter++
|
||||
active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], []<BR>[]", src.authenticated, src.rank, station_time_timestamp(), time2text(world.realtime, "MMM DD"), GLOB.year_integer+540, t1)
|
||||
active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], []<BR>[]", src.authenticated, src.rank, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer+540, t1)
|
||||
|
||||
if("Delete Record (ALL)")
|
||||
if(active1)
|
||||
@@ -652,7 +652,7 @@ What a mess.*/
|
||||
var/t2 = stripped_input(usr, "Please input minor crime details:", "Secure. records", "", null)
|
||||
if(!canUseSecurityRecordsConsole(usr, t1, null, a2))
|
||||
return
|
||||
var/crime = GLOB.data_core.createCrimeEntry(t1, t2, authenticated, station_time_timestamp())
|
||||
var/crime = GLOB.data_core.createCrimeEntry(t1, t2, authenticated, STATION_TIME_TIMESTAMP("hh:mm:ss"))
|
||||
GLOB.data_core.addMinorCrime(active1.fields["id"], crime)
|
||||
investigate_log("New Minor Crime: <strong>[t1]</strong>: [t2] | Added to [active1.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS)
|
||||
if("mi_crim_delete")
|
||||
@@ -667,7 +667,7 @@ What a mess.*/
|
||||
var/t2 = stripped_input(usr, "Please input major crime details:", "Secure. records", "", null)
|
||||
if(!canUseSecurityRecordsConsole(usr, t1, null, a2))
|
||||
return
|
||||
var/crime = GLOB.data_core.createCrimeEntry(t1, t2, authenticated, station_time_timestamp())
|
||||
var/crime = GLOB.data_core.createCrimeEntry(t1, t2, authenticated, STATION_TIME_TIMESTAMP("hh:mm:ss"))
|
||||
GLOB.data_core.addMajorCrime(active1.fields["id"], crime)
|
||||
investigate_log("New Major Crime: <strong>[t1]</strong>: [t2] | Added to [active1.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS)
|
||||
if("ma_crim_delete")
|
||||
|
||||
@@ -136,7 +136,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
|
||||
var/list/transferlog = list()
|
||||
|
||||
/obj/machinery/computer/telecrystals/boss/proc/logTransfer(logmessage)
|
||||
transferlog += ("<b>[station_time_timestamp()]</b> [logmessage]")
|
||||
transferlog += ("<b>[STATION_TIME_TIMESTAMP("hh:mm:ss")]</b> [logmessage]")
|
||||
|
||||
/obj/machinery/computer/telecrystals/boss/proc/scanUplinkers()
|
||||
for(var/obj/machinery/computer/telecrystals/uplinker/A in urange(scanrange, src.loc))
|
||||
|
||||
@@ -1327,7 +1327,7 @@
|
||||
bolt() //Bolt it!
|
||||
set_electrified(ELECTRIFIED_PERMANENT) //Shock it!
|
||||
if(origin)
|
||||
LAZYADD(shockedby, "\[[time_stamp()]\] [key_name(origin)]")
|
||||
LAZYADD(shockedby, "\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(origin)]")
|
||||
|
||||
|
||||
/obj/machinery/door/airlock/disable_lockdown()
|
||||
@@ -1596,7 +1596,7 @@
|
||||
if(wires.is_cut(WIRE_SHOCK))
|
||||
to_chat(user, "The electrification wire has been cut")
|
||||
else
|
||||
LAZYADD(shockedby, "\[[time_stamp()]\] [key_name(user)]")
|
||||
LAZYADD(shockedby, "\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(user)]")
|
||||
log_combat(user, src, "electrified")
|
||||
set_electrified(AI_ELECTRIFY_DOOR_TIME)
|
||||
|
||||
@@ -1606,7 +1606,7 @@
|
||||
if(wires.is_cut(WIRE_SHOCK))
|
||||
to_chat(user, "The electrification wire has been cut")
|
||||
else
|
||||
LAZYADD(shockedby, text("\[[time_stamp()]\] [key_name(user)]"))
|
||||
LAZYADD(shockedby, text("\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(user)]"))
|
||||
log_combat(user, src, "electrified")
|
||||
set_electrified(ELECTRIFIED_PERMANENT)
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
return
|
||||
|
||||
if(timing)
|
||||
if(world.time - activation_time >= timer_duration)
|
||||
if(world.realtime - activation_time >= timer_duration)
|
||||
timer_end() // open doors, reset timer, clear status screen
|
||||
update_icon()
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return 0
|
||||
|
||||
activation_time = world.time
|
||||
activation_time = world.realtime
|
||||
timing = TRUE
|
||||
|
||||
for(var/obj/machinery/door/window/brigdoor/door in targets)
|
||||
@@ -136,7 +136,7 @@
|
||||
|
||||
|
||||
/obj/machinery/door_timer/proc/time_left(seconds = FALSE)
|
||||
. = max(0,timer_duration - (activation_time ? world.time - activation_time : 0))
|
||||
. = max(0,timer_duration - (activation_time ? world.realtime - activation_time : 0))
|
||||
if(seconds)
|
||||
. /= 10
|
||||
|
||||
@@ -240,7 +240,7 @@
|
||||
preset_time = PRESET_LONG
|
||||
. = set_timer(preset_time)
|
||||
if(timing)
|
||||
activation_time = world.time
|
||||
activation_time = world.realtime
|
||||
else
|
||||
. = FALSE
|
||||
|
||||
|
||||
@@ -223,7 +223,7 @@
|
||||
if(prob(severity*10 - 20))
|
||||
if(secondsElectrified == 0)
|
||||
secondsElectrified = -1
|
||||
LAZYADD(shockedby, "\[[time_stamp()]\]EM Pulse")
|
||||
LAZYADD(shockedby, "\[[TIME_STAMP("hh:mm:ss", FALSE)]\]EM Pulse")
|
||||
addtimer(CALLBACK(src, .proc/unelectrify), 300)
|
||||
|
||||
/obj/machinery/door/proc/unelectrify()
|
||||
|
||||
@@ -122,7 +122,7 @@ GLOBAL_LIST_EMPTY(allCasters)
|
||||
var/datum/newscaster/feed_message/newMsg = new /datum/newscaster/feed_message
|
||||
newMsg.author = author
|
||||
newMsg.body = msg
|
||||
newMsg.time_stamp = "[station_time_timestamp()]"
|
||||
newMsg.time_stamp = "[STATION_TIME_TIMESTAMP("hh:mm:ss")]"
|
||||
newMsg.is_admin_message = adminMessage
|
||||
newMsg.locked = !allow_comments
|
||||
if(picture)
|
||||
@@ -696,7 +696,7 @@ GLOBAL_LIST_EMPTY(allCasters)
|
||||
var/datum/newscaster/feed_comment/FC = new/datum/newscaster/feed_comment
|
||||
FC.author = scanned_user
|
||||
FC.body = cominput
|
||||
FC.time_stamp = station_time_timestamp()
|
||||
FC.time_stamp = STATION_TIME_TIMESTAMP("hh:mm:ss")
|
||||
FM.comments += FC
|
||||
usr.log_message("(as [scanned_user]) commented on message [FM.returnBody(-1)] -- [FC.body]", LOG_COMMENT)
|
||||
updateUsrDialog()
|
||||
|
||||
@@ -1017,7 +1017,7 @@
|
||||
|
||||
/obj/mecha/log_message(message as text, message_type=LOG_GAME, color=null, log_globally)
|
||||
log.len++
|
||||
log[log.len] = list("time"="[station_time_timestamp()]","date","year"="[GLOB.year_integer+540]","message"="[color?"<font color='[color]'>":null][message][color?"</font>":null]")
|
||||
log[log.len] = list("time"="[STATION_TIME_TIMESTAMP("hh:mm:ss")]","date","year"="[GLOB.year_integer+540]","message"="[color?"<font color='[color]'>":null][message][color?"</font>":null]")
|
||||
..()
|
||||
return log.len
|
||||
|
||||
|
||||
@@ -379,6 +379,26 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
/obj/item/proc/on_found(mob/finder)
|
||||
return
|
||||
|
||||
/obj/item/MouseDrop(atom/over, src_location, over_location, src_control, over_control, params) //Copypaste of /atom/MouseDrop() since this requires code in a very specific spot
|
||||
if(!usr || !over)
|
||||
return
|
||||
if(SEND_SIGNAL(src, COMSIG_MOUSEDROP_ONTO, over, usr) & COMPONENT_NO_MOUSEDROP) //Whatever is receiving will verify themselves for adjacency.
|
||||
return
|
||||
if(over == src)
|
||||
return usr.client.Click(src, src_location, src_control, params)
|
||||
var/list/directaccess = usr.DirectAccess()
|
||||
if((usr.CanReach(src) || (src in directaccess)) && (usr.CanReach(over) || (over in directaccess)))
|
||||
if(!usr.get_active_held_item())
|
||||
usr.UnarmedAttack(src, TRUE)
|
||||
if(usr.get_active_held_item() == src)
|
||||
melee_attack_chain(usr, over)
|
||||
return
|
||||
if(!Adjacent(usr) || !over.Adjacent(usr))
|
||||
return // should stop you from dragging through windows
|
||||
|
||||
over.MouseDrop_T(src,usr)
|
||||
return
|
||||
|
||||
// called after an item is placed in an equipment slot
|
||||
// user is mob that equipped it
|
||||
// slot uses the slot_X defines found in setup.dm
|
||||
|
||||
@@ -23,6 +23,10 @@
|
||||
var/obj/item/stock_parts/cell/high/cell
|
||||
var/combat = FALSE //can we revive through space suits?
|
||||
var/grab_ghost = FALSE // Do we pull the ghost back into their body?
|
||||
var/healdisk = FALSE // Will we shock people dragging the body?
|
||||
var/pullshocksafely = FALSE //Dose the unit have the healdisk upgrade?
|
||||
var/primetime = 0 // is the defib faster
|
||||
var/timedeath = 10
|
||||
|
||||
/obj/item/defibrillator/get_cell()
|
||||
return cell
|
||||
@@ -441,7 +445,9 @@
|
||||
return (!H.suiciding && !(H.has_trait(TRAIT_NOCLONE)) && !H.hellbound && ((world.time - H.timeofdeath) < tlimit) && (H.getBruteLoss() < 180) && (H.getFireLoss() < 180) && H.getorgan(/obj/item/organ/heart) && BR && !BR.damaged_brain)
|
||||
|
||||
/obj/item/twohanded/shockpaddles/proc/shock_touching(dmg, mob/H)
|
||||
if(isliving(H.pulledby)) //CLEAR!
|
||||
if(defib.pullshocksafely && isliving(H.pulledby))
|
||||
H.visible_message("<span class='danger'>The defibrillator safely discharges the excessive charge into the floor!</span>")
|
||||
else
|
||||
var/mob/living/M = H.pulledby
|
||||
if(M.electrocute_act(30, src))
|
||||
M.visible_message("<span class='danger'>[M] is electrocuted by [M.p_their()] contact with [H]!</span>")
|
||||
@@ -534,7 +540,7 @@
|
||||
user.visible_message("<span class='warning'>[user] begins to place [src] on [H]'s chest.</span>", "<span class='warning'>You begin to place [src] on [H]'s chest...</span>")
|
||||
busy = TRUE
|
||||
update_icon()
|
||||
if(do_after(user, 30, target = H)) //beginning to place the paddles on patient's chest to allow some time for people to move away to stop the process
|
||||
if(do_after(user, 30 - defib.primetime, target = H)) //beginning to place the paddles on patient's chest to allow some time for people to move away to stop the process
|
||||
user.visible_message("<span class='notice'>[user] places [src] on [H]'s chest.</span>", "<span class='warning'>You place [src] on [H]'s chest.</span>")
|
||||
playsound(src, 'sound/machines/defib_charge.ogg', 75, 0)
|
||||
var/tplus = world.time - H.timeofdeath
|
||||
@@ -542,10 +548,10 @@
|
||||
// (in deciseconds)
|
||||
// brain damage starts setting in on the patient after
|
||||
// some time left rotting
|
||||
var/tloss = DEFIB_TIME_LOSS * 10
|
||||
var/tloss = DEFIB_TIME_LOSS * defib.timedeath
|
||||
var/total_burn = 0
|
||||
var/total_brute = 0
|
||||
if(do_after(user, 20, target = H)) //placed on chest and short delay to shock for dramatic effect, revive time is 5sec total
|
||||
if(do_after(user, 20 - defib.primetime, target = H)) //placed on chest and short delay to shock for dramatic effect, revive time is 5sec total
|
||||
for(var/obj/item/carried_item in H.contents)
|
||||
if(istype(carried_item, /obj/item/clothing/suit/space))
|
||||
if((!combat && !req_defib) || (req_defib && !defib.combat))
|
||||
@@ -605,6 +611,8 @@
|
||||
if(tplus > tloss)
|
||||
H.adjustBrainLoss( max(0, min(99, ((tlimit - tplus) / tlimit * 100))), 150)
|
||||
log_combat(user, H, "revived", defib)
|
||||
if(defib.healdisk)
|
||||
H.heal_overall_damage(25, 25)
|
||||
if(req_defib)
|
||||
defib.deductcharge(revivecost)
|
||||
cooldown = 1
|
||||
@@ -628,6 +636,37 @@
|
||||
busy = FALSE
|
||||
update_icon()
|
||||
|
||||
/obj/item/defibrillator/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/disk/medical/defib_heal))
|
||||
if(healdisk)
|
||||
to_chat(user, "<span class='notice'>This unit is already upgraded with this disk!</span>")
|
||||
return TRUE
|
||||
to_chat(user, "<span class='notice'>You upgrade the unit with Heal upgrade disk!</span>")
|
||||
healdisk = TRUE
|
||||
return TRUE
|
||||
if(istype(I, /obj/item/disk/medical/defib_shock))
|
||||
if(pullshocksafely)
|
||||
to_chat(user, "<span class='notice'>This unit is already upgraded with this disk!</span>")
|
||||
return TRUE
|
||||
to_chat(user, "<span class='notice'>You upgrade the unit with Shock Safety upgrade disk!</span>")
|
||||
pullshocksafely = TRUE
|
||||
return TRUE
|
||||
if(istype(I, /obj/item/disk/medical/defib_speed))
|
||||
if(!primetime == initial(primetime))
|
||||
to_chat(user, "<span class='notice'>This unit is already upgraded with this disk!</span>")
|
||||
return TRUE
|
||||
to_chat(user, "<span class='notice'>You upgrade the unit with Speed upgrade disk!</span>")
|
||||
primetime = 10
|
||||
return TRUE
|
||||
if(istype(I, /obj/item/disk/medical/defib_decay))
|
||||
if(!timedeath == initial(timedeath))
|
||||
to_chat(user, "<span class='notice'>This unit is already upgraded with this disk!</span>")
|
||||
return TRUE
|
||||
to_chat(user, "<span class='notice'>You upgrade the unit with Longer Decay upgrade disk!</span>")
|
||||
timedeath = 20
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/item/twohanded/shockpaddles/cyborg
|
||||
name = "cyborg defibrillator paddles"
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
@@ -656,4 +695,40 @@
|
||||
item_state = "defibpaddles0"
|
||||
req_defib = FALSE
|
||||
|
||||
///////////////////////////////////////////
|
||||
/////////Dedibrillators Disks//////////////
|
||||
///////////////////////////////////////////
|
||||
|
||||
/obj/item/disk/medical
|
||||
name = "Defibrillator Upgrade Disk"
|
||||
desc = "A blank defibrillator disk..."
|
||||
icon = 'modular_citadel/icons/obj/defib_disks.dmi'
|
||||
icon_state = "upgrade_disk"
|
||||
item_state = "heal_disk"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
|
||||
/obj/item/disk/medical/defib_heal
|
||||
name = "Defibrillator Healing Disk"
|
||||
desc = "A disk alowing for grater amounts of healing"
|
||||
icon_state = "heal_disk"
|
||||
materials = list(MAT_METAL=16000, MAT_GLASS = 18000, MAT_GOLD = 6000, MAT_SILVER = 6000)
|
||||
|
||||
/obj/item/disk/medical/defib_shock
|
||||
name = "Defibrillator Anti-Shock Disk"
|
||||
desc = "A disk that helps agains shocking anyone, other then the intented target"
|
||||
icon_state = "zap_disk"
|
||||
materials = list(MAT_METAL=16000, MAT_GLASS = 18000, MAT_GOLD = 6000, MAT_SILVER = 6000)
|
||||
|
||||
/obj/item/disk/medical/defib_decay
|
||||
name = "Defibrillator Body-Decay Extender Disk"
|
||||
desc = "A disk that helps defibrillators revive the longer decayed"
|
||||
icon_state = "body_disk"
|
||||
materials = list(MAT_METAL=16000, MAT_GLASS = 18000, MAT_GOLD = 16000, MAT_SILVER = 6000, MAT_TITANIUM = 2000)
|
||||
|
||||
/obj/item/disk/medical/defib_speed
|
||||
name = "Defibrllator Pre-Primer Disk"
|
||||
desc = "A disk that cuts the time charg time in half for defibrillator use"
|
||||
icon_state = "fast_disk"
|
||||
materials = list(MAT_METAL=16000, MAT_GLASS = 8000, MAT_GOLD = 26000, MAT_SILVER = 26000)
|
||||
|
||||
#undef HALFWAYCRITDEATH
|
||||
|
||||
@@ -220,7 +220,7 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
dat += text("ID: <a href='?src=[REF(src)];choice=Authenticate'>[id ? "[id.registered_name], [id.assignment]" : "----------"]")
|
||||
dat += text("<br><a href='?src=[REF(src)];choice=UpdateInfo'>[id ? "Update PDA Info" : ""]</A><br><br>")
|
||||
|
||||
dat += "[station_time_timestamp()]<br>" //:[world.time / 100 % 6][world.time / 100 % 10]"
|
||||
dat += "[STATION_TIME_TIMESTAMP("hh:mm:ss")]<br>" //:[world.time / 100 % 6][world.time / 100 % 10]"
|
||||
dat += "[time2text(world.realtime, "MMM DD")] [GLOB.year_integer+540]"
|
||||
|
||||
dat += "<br><br>"
|
||||
@@ -391,6 +391,7 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
//BASIC FUNCTIONS===================================
|
||||
|
||||
if("Refresh")//Refresh, goes to the end of the proc.
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
|
||||
if ("Toggle_Font")
|
||||
//CODE REVISION 2
|
||||
@@ -405,12 +406,16 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
font_mode = FONT_ORBITRON
|
||||
if (MODE_VT)
|
||||
font_mode = FONT_VT
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
|
||||
if ("Change_Color")
|
||||
var/new_color = input("Please enter a color name or hex value (Default is \'#808000\').",background_color)as color
|
||||
background_color = new_color
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
|
||||
if ("Toggle_Underline")
|
||||
underline_flag = !underline_flag
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
|
||||
if("Return")//Return
|
||||
if(mode<=9)
|
||||
@@ -419,13 +424,19 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
mode = round(mode/10)
|
||||
if(mode==4 || mode == 5)//Fix for cartridges. Redirects to hub.
|
||||
mode = 0
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
|
||||
if ("Authenticate")//Checks for ID
|
||||
id_check(U)
|
||||
|
||||
if("UpdateInfo")
|
||||
ownjob = id.assignment
|
||||
if(istype(id, /obj/item/card/id/syndicate))
|
||||
owner = id.registered_name
|
||||
update_label()
|
||||
playsound(src, 'sound/machines/terminal_processing.ogg', 50, 1)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/playsound, src, 'sound/machines/terminal_success.ogg', 50, 1), 13)
|
||||
|
||||
if("Eject")//Ejects the cart, only done from hub.
|
||||
if (!isnull(cartridge))
|
||||
U.put_in_hands(cartridge)
|
||||
@@ -434,55 +445,74 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
cartridge.host_pda = null
|
||||
cartridge = null
|
||||
update_icon()
|
||||
playsound(src, 'sound/machines/terminal_eject_disc.ogg', 50, 1)
|
||||
|
||||
//MENU FUNCTIONS===================================
|
||||
|
||||
if("0")//Hub
|
||||
mode = 0
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
if("1")//Notes
|
||||
mode = 1
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
if("2")//Messenger
|
||||
mode = 2
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
if("21")//Read messeges
|
||||
mode = 21
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
if("3")//Atmos scan
|
||||
mode = 3
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
if("4")//Redirects to hub
|
||||
mode = 0
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
|
||||
|
||||
//MAIN FUNCTIONS===================================
|
||||
|
||||
if("Light")
|
||||
toggle_light()
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
|
||||
if("Medical Scan")
|
||||
if(scanmode == PDA_SCANNER_MEDICAL)
|
||||
scanmode = PDA_SCANNER_NONE
|
||||
else if((!isnull(cartridge)) && (cartridge.access & CART_MEDICAL))
|
||||
scanmode = PDA_SCANNER_MEDICAL
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
|
||||
if("Reagent Scan")
|
||||
if(scanmode == PDA_SCANNER_REAGENT)
|
||||
scanmode = PDA_SCANNER_NONE
|
||||
else if((!isnull(cartridge)) && (cartridge.access & CART_REAGENT_SCANNER))
|
||||
scanmode = PDA_SCANNER_REAGENT
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
|
||||
if("Halogen Counter")
|
||||
if(scanmode == PDA_SCANNER_HALOGEN)
|
||||
scanmode = PDA_SCANNER_NONE
|
||||
else if((!isnull(cartridge)) && (cartridge.access & CART_ENGINE))
|
||||
scanmode = PDA_SCANNER_HALOGEN
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
|
||||
if("Honk")
|
||||
if ( !(last_noise && world.time < last_noise + 20) )
|
||||
playsound(src, 'sound/items/bikehorn.ogg', 50, 1)
|
||||
last_noise = world.time
|
||||
|
||||
if("Trombone")
|
||||
if ( !(last_noise && world.time < last_noise + 20) )
|
||||
playsound(src, 'sound/misc/sadtrombone.ogg', 50, 1)
|
||||
last_noise = world.time
|
||||
|
||||
if("Gas Scan")
|
||||
if(scanmode == PDA_SCANNER_GAS)
|
||||
scanmode = PDA_SCANNER_NONE
|
||||
else if((!isnull(cartridge)) && (cartridge.access & CART_ATMOS))
|
||||
scanmode = PDA_SCANNER_GAS
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
|
||||
if("Drone Phone")
|
||||
var/alert_s = input(U,"Alert severity level","Ping Drones",null) as null|anything in list("Low","Medium","High","Critical")
|
||||
var/area/A = get_area(U)
|
||||
@@ -490,6 +520,7 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
var/msg = "<span class='boldnotice'>NON-DRONE PING: [U.name]: [alert_s] priority alert in [A.name]!</span>"
|
||||
_alert_drones(msg, TRUE, U)
|
||||
to_chat(U, msg)
|
||||
playsound(src, 'sound/machines/terminal_success.ogg', 50, 1)
|
||||
|
||||
|
||||
//NOTEKEEPER FUNCTIONS===================================
|
||||
@@ -641,6 +672,7 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
if (!signal.data["done"])
|
||||
to_chat(user, "<span class='notice'>ERROR: Server isn't responding.</span>")
|
||||
return
|
||||
playsound(src, 'sound/machines/terminal_error.ogg', 50, 1)
|
||||
|
||||
var/target_text = signal.format_target()
|
||||
// Log it in our logs
|
||||
@@ -653,6 +685,7 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
// Log in the talk log
|
||||
user.log_talk(message, LOG_PDA, tag="PDA: [initial(name)] to [target_text]")
|
||||
to_chat(user, "<span class='info'>Message sent to [target_text]: \"[message]\"</span>")
|
||||
playsound(src, 'sound/machines/terminal_success.ogg', 50, 1)
|
||||
// Reset the photo
|
||||
picture = null
|
||||
last_text = world.time
|
||||
@@ -699,8 +732,10 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
|
||||
if(id)
|
||||
remove_id()
|
||||
playsound(src, 'sound/machines/terminal_eject_disc.ogg', 50, 1)
|
||||
else
|
||||
remove_pen()
|
||||
playsound(src, 'sound/machines/button4.ogg', 50, 1)
|
||||
|
||||
/obj/item/pda/CtrlClick()
|
||||
..()
|
||||
@@ -776,6 +811,7 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
if(old_id)
|
||||
user.put_in_hands(old_id)
|
||||
update_icon()
|
||||
playsound(src, 'sound/machines/button.ogg', 50, 1)
|
||||
return TRUE
|
||||
|
||||
// access to status display signals
|
||||
@@ -787,17 +823,21 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
cartridge.host_pda = src
|
||||
to_chat(user, "<span class='notice'>You insert [cartridge] into [src].</span>")
|
||||
update_icon()
|
||||
playsound(src, 'sound/machines/button.ogg', 50, 1)
|
||||
|
||||
else if(istype(C, /obj/item/card/id))
|
||||
var/obj/item/card/id/idcard = C
|
||||
if(!idcard.registered_name)
|
||||
to_chat(user, "<span class='warning'>\The [src] rejects the ID!</span>")
|
||||
return
|
||||
playsound(src, 'sound/machines/terminal_error.ogg', 50, 1)
|
||||
|
||||
if(!owner)
|
||||
owner = idcard.registered_name
|
||||
ownjob = idcard.assignment
|
||||
update_label()
|
||||
to_chat(user, "<span class='notice'>Card scanned.</span>")
|
||||
playsound(src, 'sound/machines/terminal_success.ogg', 50, 1)
|
||||
else
|
||||
//Basic safety check. If either both objects are held by user or PDA is on ground and card is in hand.
|
||||
if(((src in user.contents) || (isturf(loc) && in_range(src, user))) && (C in user.contents))
|
||||
@@ -823,6 +863,8 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
to_chat(user, "<span class='notice'>You slide \the [C] into \the [src].</span>")
|
||||
inserted_item = C
|
||||
update_icon()
|
||||
playsound(src, 'sound/machines/button.ogg', 50, 1)
|
||||
|
||||
else if(istype(C, /obj/item/photo))
|
||||
var/obj/item/photo/P = C
|
||||
picture = P.picture
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
/obj/item/pda/heads/rd
|
||||
name = "research director PDA"
|
||||
default_cartridge = /obj/item/cartridge/rd
|
||||
inserted_item = /obj/item/pen/fountain
|
||||
inserted_item = /obj/item/pen/fourcolor
|
||||
icon_state = "pda-rd"
|
||||
|
||||
/obj/item/pda/captain
|
||||
@@ -185,6 +185,12 @@
|
||||
desc = "A portable microcomputer by Thinktronic Systems, LTD. This model is a special edition with a transparent case."
|
||||
note = "Congratulations, you have chosen the Thinktronic 5230 Personal Data Assistant Deluxe Special Max Turbo Limited Edition!"
|
||||
|
||||
/obj/item/pda/neko
|
||||
name = "neko PDA"
|
||||
icon_state = "pda-neko"
|
||||
desc = "A portable microcomputer by Thinktronic Systems, LTD. This model is a special edition a feline fine case."
|
||||
note = "Congratulations, you have chosen the Thinktronic 5230 Personal Data Assistant Deluxe Special Mew Turbo Limited Edition NYA~!"
|
||||
|
||||
/obj/item/pda/cook
|
||||
name = "cook PDA"
|
||||
icon_state = "pda-cook"
|
||||
|
||||
@@ -580,6 +580,7 @@ Code:
|
||||
host_pda.mode = 441
|
||||
if(!active2)
|
||||
active1 = null
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
|
||||
if("Security Records")
|
||||
active1 = find_record("id", href_list["target"], GLOB.data_core.general)
|
||||
@@ -588,19 +589,23 @@ Code:
|
||||
host_pda.mode = 451
|
||||
if(!active3)
|
||||
active1 = null
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
|
||||
if("Send Signal")
|
||||
INVOKE_ASYNC(radio, /obj/item/integrated_signaler.proc/send_activation)
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
|
||||
if("Signal Frequency")
|
||||
var/new_frequency = sanitize_frequency(radio.frequency + text2num(href_list["sfreq"]))
|
||||
radio.set_frequency(new_frequency)
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
|
||||
if("Signal Code")
|
||||
radio.code += text2num(href_list["scode"])
|
||||
radio.code = round(radio.code)
|
||||
radio.code = min(100, radio.code)
|
||||
radio.code = max(1, radio.code)
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
|
||||
if("Status")
|
||||
switch(href_list["statdisp"])
|
||||
@@ -616,16 +621,21 @@ Code:
|
||||
updateSelfDialog()
|
||||
else
|
||||
post_status(href_list["statdisp"])
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
|
||||
if("Power Select")
|
||||
var/pnum = text2num(href_list["target"])
|
||||
powmonitor = powermonitors[pnum]
|
||||
host_pda.mode = 433
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
|
||||
if("Supply Orders")
|
||||
host_pda.mode =47
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
|
||||
if("Newscaster Access")
|
||||
host_pda.mode = 53
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
|
||||
if("Newscaster Message")
|
||||
var/host_pda_owner_name = host_pda.id ? "[host_pda.id.registered_name] ([host_pda.id.assignment])" : "Unknown"
|
||||
@@ -641,11 +651,13 @@ Code:
|
||||
GLOB.news_network.SubmitArticle(message,host_pda.owner,current_channel)
|
||||
host_pda.Topic(null,list("choice"=num2text(host_pda.mode)))
|
||||
return
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
|
||||
if("Newscaster Switch Channel")
|
||||
current_channel = host_pda.msg_input()
|
||||
host_pda.Topic(null,list("choice"=num2text(host_pda.mode)))
|
||||
return
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
|
||||
//Bot control section! Viciously ripped from radios for being laggy and terrible.
|
||||
if(href_list["op"])
|
||||
@@ -656,10 +668,13 @@ Code:
|
||||
|
||||
if("botlist")
|
||||
active_bot = null
|
||||
|
||||
if("summon") //Args are in the correct order, they are stated here just as an easy reminder.
|
||||
active_bot.bot_control(command= "summon", user_turf= get_turf(usr), user_access= host_pda.GetAccess())
|
||||
|
||||
else //Forward all other bot commands to the bot itself!
|
||||
active_bot.bot_control(command= href_list["op"], user= usr)
|
||||
playsound(src, 'sound/machines/terminal_select.ogg', 50, 1)
|
||||
|
||||
if(href_list["mule"]) //MULEbots are special snowflakes, and need different args due to how they work.
|
||||
|
||||
|
||||
@@ -34,6 +34,10 @@
|
||||
if(LAZYLEN(current_fields) >= max_fields)
|
||||
to_chat(user, "<span class='notice'>[src] cannot sustain any more forcefields!</span>")
|
||||
return
|
||||
var/obj/structure/projected_forcefield/same = locate() in T
|
||||
if(same)
|
||||
to_chat(user, "<span class='notice'>There is already a forcefield on [T]!</span>")
|
||||
return
|
||||
|
||||
playsound(src,'sound/weapons/resonator_fire.ogg',50,1)
|
||||
user.visible_message("<span class='warning'>[user] projects a forcefield!</span>","<span class='notice'>You project a forcefield.</span>")
|
||||
@@ -59,6 +63,8 @@
|
||||
|
||||
/obj/item/forcefield_projector/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
for(var/i in current_fields)
|
||||
qdel(i)
|
||||
return ..()
|
||||
|
||||
/obj/item/forcefield_projector/process()
|
||||
|
||||
@@ -504,6 +504,31 @@
|
||||
var/obj/item/surgical_processor/SP = locate() in R.module
|
||||
R.module.remove_module(SP, TRUE)
|
||||
|
||||
/obj/item/borg/upgrade/advhealth
|
||||
name = "advanced cyborg health scanner"
|
||||
desc = "An upgrade to the Medical modules, installing a built-in \
|
||||
advanced health scanner, for better readings on patients."
|
||||
icon_state = "cyborg_upgrade3"
|
||||
require_module = 1
|
||||
module_type = list(
|
||||
/obj/item/robot_module/medical,
|
||||
/obj/item/robot_module/syndicate_medical,
|
||||
/obj/item/robot_module/medihound,
|
||||
/obj/item/robot_module/borgi)
|
||||
|
||||
/obj/item/borg/upgrade/advhealth/action(mob/living/silicon/robot/R, user = usr)
|
||||
. = ..()
|
||||
if(.)
|
||||
var/obj/item/healthanalyzer/advanced/AH = new(R.module)
|
||||
R.module.basic_modules += AH
|
||||
R.module.add_module(AH, FALSE, TRUE)
|
||||
|
||||
/obj/item/borg/upgrade/processor/deactivate(mob/living/silicon/robot/R, user = usr)
|
||||
. = ..()
|
||||
if (.)
|
||||
var/obj/item/healthanalyzer/advanced/AH = locate() in R.module
|
||||
R.module.remove_module(AH, TRUE)
|
||||
|
||||
/obj/item/borg/upgrade/ai
|
||||
name = "B.O.R.I.S. module"
|
||||
desc = "Bluespace Optimized Remote Intelligence Synchronization. An uplink device which takes the place of an MMI in cyborg endoskeletons, creating a robotic shell controlled by an AI."
|
||||
@@ -638,4 +663,4 @@
|
||||
name = "borg module picker (Clown)"
|
||||
desc = "Allows you to to turn a cyborg into a clown, honk."
|
||||
icon_state = "cyborg_upgrade3"
|
||||
new_module = /obj/item/robot_module/clown
|
||||
new_module = /obj/item/robot_module/clown
|
||||
|
||||
@@ -170,4 +170,7 @@
|
||||
|
||||
/obj/item/stack/medical/ointment/suicide_act(mob/living/user)
|
||||
user.visible_message("<span class='suicide'>[user] is squeezing \the [src] into [user.p_their()] mouth! [user.p_do(TRUE)]n't [user.p_they()] know that stuff is toxic?</span>")
|
||||
return TOXLOSS
|
||||
return TOXLOSS
|
||||
|
||||
/obj/item/stack/medical/get_belt_overlay()
|
||||
return mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "pouch")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* These absorb the functionality of the plant bag, ore satchel, etc.
|
||||
* These absorb the functionality of the plant bag, ore satchel, etc
|
||||
* They use the use_to_pickup, quick_gather, and quick_empty functions
|
||||
* that were already defined in weapon/storage, but which had been
|
||||
* re-implemented in other classes.
|
||||
@@ -162,6 +162,26 @@
|
||||
/obj/item/storage/bag/ore/cyborg
|
||||
name = "cyborg mining satchel"
|
||||
|
||||
/obj/item/storage/bag/ore/cyborg/ComponentInitialize()
|
||||
. = ..()
|
||||
GET_COMPONENT(STR, /datum/component/storage/concrete/stack)
|
||||
STR.allow_quick_empty = TRUE
|
||||
STR.can_hold = typecacheof(list(/obj/item/stack/ore))
|
||||
STR.max_w_class = WEIGHT_CLASS_HUGE
|
||||
STR.max_combined_stack_amount = 150
|
||||
|
||||
/obj/item/storage/bag/ore/large
|
||||
name = "large mining satchel"
|
||||
desc = "This bag can hold three times the ore in many small pockets. Shockingly foldable and compact for its volume."
|
||||
|
||||
/obj/item/storage/bag/ore/large/ComponentInitialize()
|
||||
. = ..()
|
||||
GET_COMPONENT(STR, /datum/component/storage/concrete/stack)
|
||||
STR.allow_quick_empty = TRUE
|
||||
STR.can_hold = typecacheof(list(/obj/item/stack/ore))
|
||||
STR.max_w_class = WEIGHT_CLASS_HUGE
|
||||
STR.max_combined_stack_amount = 150
|
||||
|
||||
/obj/item/storage/bag/ore/holding //miners, your messiah has arrived
|
||||
name = "mining satchel of holding"
|
||||
desc = "A revolution in convenience, this satchel allows for huge amounts of ore storage. It's been outfitted with anti-malfunction safety measures."
|
||||
@@ -365,3 +385,15 @@
|
||||
STR.max_items = 25
|
||||
STR.insert_preposition = "in"
|
||||
STR.can_hold = typecacheof(list(/obj/item/slime_extract, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/blood, /obj/item/reagent_containers/hypospray/medipen, /obj/item/reagent_containers/food/snacks/deadmouse, /obj/item/reagent_containers/food/snacks/monkeycube))
|
||||
|
||||
/obj/item/storage/bag/bio/holding
|
||||
name = "bio bag of holding"
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon_state = "bspace_biobag"
|
||||
desc = "A bag for the safe transportation and disposal of biowaste and other biological materials."
|
||||
|
||||
/obj/item/storage/bag/bio/holding/ComponentInitialize()
|
||||
. = ..()
|
||||
GET_COMPONENT(STR, /datum/component/storage)
|
||||
STR.max_combined_w_class = INFINITY
|
||||
STR.max_items = 100
|
||||
|
||||
@@ -115,6 +115,7 @@
|
||||
desc = "Can hold various medical equipment."
|
||||
icon_state = "medicalbelt"
|
||||
item_state = "medical"
|
||||
content_overlays = TRUE
|
||||
|
||||
/obj/item/storage/belt/medical/ComponentInitialize()
|
||||
. = ..()
|
||||
@@ -136,6 +137,7 @@
|
||||
/obj/item/flashlight/pen,
|
||||
/obj/item/extinguisher/mini,
|
||||
/obj/item/reagent_containers/hypospray,
|
||||
/obj/item/hypospray/mkii,
|
||||
/obj/item/sensor_device,
|
||||
/obj/item/radio,
|
||||
/obj/item/clothing/gloves/,
|
||||
@@ -172,6 +174,7 @@
|
||||
/obj/item/storage/belt/medical/surgery_belt_adv
|
||||
name = "surgical supply belt"
|
||||
desc = "A specialized belt designed for holding surgical equipment. It seems to have specific pockets for each and every surgical tool you can think of."
|
||||
content_overlays = FALSE
|
||||
|
||||
/obj/item/storage/belt/medical/surgery_belt_adv/PopulateContents()
|
||||
new /obj/item/hemostat/adv(src)
|
||||
@@ -357,7 +360,7 @@
|
||||
/obj/item/reagent_containers/food/snacks,
|
||||
/obj/item/reagent_containers/food/drinks
|
||||
))
|
||||
|
||||
|
||||
var/amount = 5
|
||||
var/rig_snacks
|
||||
while(contents.len <= amount)
|
||||
|
||||
@@ -112,12 +112,17 @@
|
||||
/obj/item/storage/firstaid/radbgone/PopulateContents()
|
||||
if(empty)
|
||||
return
|
||||
if(prob(50))
|
||||
new /obj/item/reagent_containers/pill/mutarad(src)
|
||||
if(prob(80))
|
||||
new /obj/item/reagent_containers/pill/antirad_plus(src)
|
||||
new /obj/item/reagent_containers/syringe/charcoal(src)
|
||||
new /obj/item/storage/pill_bottle/charcoal(src)
|
||||
new /obj/item/reagent_containers/pill/mutadone(src)
|
||||
new /obj/item/reagent_containers/pill/antirad(src)
|
||||
new /obj/item/reagent_containers/food/drinks/bottle/vodka(src)
|
||||
new /obj/item/healthanalyzer(src)
|
||||
|
||||
|
||||
/obj/item/storage/firstaid/o2
|
||||
name = "oxygen deprivation treatment kit"
|
||||
@@ -291,3 +296,19 @@
|
||||
/obj/item/storage/pill_bottle/aranesp/PopulateContents()
|
||||
for(var/i in 1 to 5)
|
||||
new /obj/item/reagent_containers/pill/aranesp(src)
|
||||
|
||||
/obj/item/storage/pill_bottle/antirad_plus
|
||||
name = "anti radiation deluxe pill bottle"
|
||||
desc = "The label says 'Med-Co branded pills'."
|
||||
|
||||
/obj/item/storage/pill_bottle/antirad_plus/PopulateContents()
|
||||
for(var/i in 1 to 7)
|
||||
new /obj/item/reagent_containers/pill/antirad_plus(src)
|
||||
|
||||
/obj/item/storage/pill_bottle/mutarad
|
||||
name = "radiation treatment deluxe pill bottle"
|
||||
desc = "The label says 'Med-Co branded pills' and below that 'Contains Mutadone in each pill!`."
|
||||
|
||||
/obj/item/storage/pill_bottle/mutarad/PopulateContents()
|
||||
for(var/i in 1 to 7)
|
||||
new /obj/item/reagent_containers/pill/mutarad(src)
|
||||
|
||||
@@ -1089,7 +1089,7 @@
|
||||
|
||||
/obj/item/toy/clockwork_watch/examine(mob/user)
|
||||
..()
|
||||
to_chat(user, "<span class='info'>Station Time: [station_time_timestamp()]")
|
||||
to_chat(user, "<span class='info'>Station Time: [STATION_TIME_TIMESTAMP("hh:mm:ss")]")
|
||||
|
||||
/*
|
||||
* Toy Dagger
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
/obj/structure/closet/secure_closet/quartermaster/PopulateContents()
|
||||
..()
|
||||
new /obj/item/clothing/neck/cloak/qm(src)
|
||||
new /obj/item/clothing/head/beret/qm(src)
|
||||
new /obj/item/storage/lockbox/medal/cargo(src)
|
||||
new /obj/item/clothing/under/rank/cargo(src)
|
||||
new /obj/item/clothing/shoes/sneakers/brown(src)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
/obj/structure/closet/secure_closet/engineering_chief/PopulateContents()
|
||||
..()
|
||||
new /obj/item/clothing/neck/cloak/ce(src)
|
||||
new /obj/item/clothing/head/beret/ce(src)
|
||||
new /obj/item/clothing/under/rank/chief_engineer(src)
|
||||
new /obj/item/clothing/head/hardhat/white(src)
|
||||
new /obj/item/clothing/head/welding(src)
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
/obj/structure/closet/secure_closet/CMO/PopulateContents()
|
||||
..()
|
||||
new /obj/item/clothing/neck/cloak/cmo(src)
|
||||
new /obj/item/clothing/head/beret/cmo(src)
|
||||
new /obj/item/storage/backpack/duffelbag/med(src)
|
||||
new /obj/item/clothing/suit/bio_suit/cmo(src)
|
||||
new /obj/item/clothing/head/bio_hood/cmo(src)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
/obj/structure/closet/secure_closet/RD/PopulateContents()
|
||||
..()
|
||||
new /obj/item/clothing/neck/cloak/rd(src)
|
||||
new /obj/item/clothing/head/beret/rd(src)
|
||||
new /obj/item/clothing/suit/bio_suit/scientist(src)
|
||||
new /obj/item/clothing/head/bio_hood/scientist(src)
|
||||
new /obj/item/clothing/suit/toggle/labcoat(src)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
new /obj/item/clothing/under/captainparade(src)
|
||||
new /obj/item/clothing/suit/armor/vest/capcarapace/alt(src)
|
||||
new /obj/item/clothing/head/caphat/parade(src)
|
||||
new /obj/item/clothing/head/caphat/beret(src)
|
||||
new /obj/item/clothing/suit/captunic(src)
|
||||
new /obj/item/clothing/under/rank/captain/femformal(src) //citadel edit
|
||||
new /obj/item/clothing/head/crown/fancy(src)
|
||||
@@ -44,6 +45,7 @@
|
||||
new /obj/item/clothing/neck/cloak/hop(src)
|
||||
new /obj/item/clothing/under/rank/head_of_personnel(src)
|
||||
new /obj/item/clothing/head/hopcap(src)
|
||||
new /obj/item/clothing/head/hopcap/beret(src)
|
||||
new /obj/item/cartridge/hop(src)
|
||||
new /obj/item/radio/headset/heads/hop(src)
|
||||
new /obj/item/clothing/shoes/sneakers/brown(src)
|
||||
|
||||
@@ -213,6 +213,9 @@
|
||||
'sound/vore/prey/death_04.ogg','sound/vore/prey/death_05.ogg','sound/vore/prey/death_06.ogg',
|
||||
'sound/vore/prey/death_07.ogg','sound/vore/prey/death_08.ogg','sound/vore/prey/death_09.ogg',
|
||||
'sound/vore/prey/death_10.ogg')
|
||||
if("hunger_sounds")
|
||||
soundin = pick( 'sound/vore/growl1.ogg','sound/vore/growl2.ogg','sound/vore/growl3.ogg','sound/vore/growl4.ogg',
|
||||
'sound/vore/growl5.ogg')
|
||||
if("clang")
|
||||
soundin = pick('sound/effects/clang1.ogg', 'sound/effects/clang2.ogg')
|
||||
if("clangsmall")
|
||||
|
||||
+4
-4
@@ -6,7 +6,7 @@ GLOBAL_VAR(restart_counter)
|
||||
//So subsystems globals exist, but are not initialised
|
||||
/world/New()
|
||||
|
||||
log_world("World loaded at [time_stamp()]!")
|
||||
log_world("World loaded at [TIME_STAMP("hh:mm:ss", FALSE)]!")
|
||||
|
||||
SetupExternalRSC()
|
||||
|
||||
@@ -90,7 +90,7 @@ GLOBAL_VAR(restart_counter)
|
||||
GLOB.picture_logging_prefix += "R_[GLOB.round_id]_"
|
||||
GLOB.picture_log_directory += "[GLOB.round_id]"
|
||||
else
|
||||
var/timestamp = replacetext(time_stamp(), ":", ".")
|
||||
var/timestamp = replacetext(TIME_STAMP("hh:mm:ss", FALSE), ":", ".")
|
||||
GLOB.log_directory += "[timestamp]"
|
||||
GLOB.picture_log_directory += "[timestamp]"
|
||||
GLOB.picture_logging_prefix += "T_[timestamp]_"
|
||||
@@ -226,11 +226,11 @@ GLOBAL_VAR(restart_counter)
|
||||
do_hard_reboot = FALSE
|
||||
|
||||
if(do_hard_reboot)
|
||||
log_world("World hard rebooted at [time_stamp()]")
|
||||
log_world("World hard rebooted at [TIME_STAMP("hh:mm:ss", FALSE)]")
|
||||
shutdown_logging() // See comment below.
|
||||
TgsEndProcess()
|
||||
|
||||
log_world("World rebooted at [time_stamp()]")
|
||||
log_world("World rebooted at [TIME_STAMP("hh:mm:ss", FALSE)]")
|
||||
shutdown_logging() // Past this point, no logging procs can be used, at risk of data loss.
|
||||
..()
|
||||
|
||||
|
||||
@@ -133,14 +133,14 @@
|
||||
return FALSE
|
||||
|
||||
/datum/ntnet/proc/log_data_transfer(datum/netdata/data)
|
||||
logs += "[station_time_timestamp()] - [data.generate_netlog()]"
|
||||
logs += "[STATION_TIME_TIMESTAMP("hh:mm:ss")] - [data.generate_netlog()]"
|
||||
if(logs.len > setting_maxlogcount)
|
||||
logs = logs.Copy(logs.len - setting_maxlogcount, 0)
|
||||
return
|
||||
|
||||
// Simplified logging: Adds a log. log_string is mandatory parameter, source is optional.
|
||||
/datum/ntnet/proc/add_log(log_string, obj/item/computer_hardware/network_card/source = null)
|
||||
var/log_text = "[station_time_timestamp()] - "
|
||||
var/log_text = "[STATION_TIME_TIMESTAMP("hh:mm:ss")] - "
|
||||
if(source)
|
||||
log_text += "[source.get_network_tag()] - "
|
||||
else
|
||||
|
||||
@@ -538,13 +538,22 @@
|
||||
message_admins("[key_name_admin(usr)] toggled OOC.")
|
||||
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle OOC", "[GLOB.ooc_allowed ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/datum/admins/proc/toggleooclocal()
|
||||
set category = "Server"
|
||||
set desc="Toggle dat bitch"
|
||||
set name="Toggle Local OOC"
|
||||
toggle_looc()
|
||||
log_admin("[key_name(usr)] toggled LOOC.")
|
||||
message_admins("[key_name_admin(usr)] toggled LOOC.")
|
||||
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Local OOC", "[GLOB.ooc_allowed ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/datum/admins/proc/toggleoocdead()
|
||||
set category = "Server"
|
||||
set desc="Toggle dis bitch"
|
||||
set name="Toggle Dead OOC"
|
||||
toggle_dooc()
|
||||
|
||||
log_admin("[key_name(usr)] toggled OOC.")
|
||||
log_admin("[key_name(usr)] toggled Dead OOC.")
|
||||
message_admins("[key_name_admin(usr)] toggled Dead OOC.")
|
||||
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Dead OOC", "[GLOB.dooc_allowed ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
if(!message || !subject)
|
||||
return
|
||||
var/F = file("[GLOB.log_directory]/[subject].html")
|
||||
WRITE_FILE(F, "<small>[time_stamp()] [REF(src)] ([x],[y],[z])</small> || [src] [message]<br>")
|
||||
WRITE_FILE(F, "<small>[TIME_STAMP("hh:mm:ss", FALSE)] [REF(src)] ([x],[y],[z])</small> || [src] [message]<br>")
|
||||
|
||||
/client/proc/investigate_show(subject in list("notes, memos, watchlist", INVESTIGATE_RESEARCH, INVESTIGATE_EXONET, INVESTIGATE_PORTAL, INVESTIGATE_SINGULO, INVESTIGATE_WIRES, INVESTIGATE_TELESCI, INVESTIGATE_GRAVITY, INVESTIGATE_RECORDS, INVESTIGATE_CARGO, INVESTIGATE_SUPERMATTER, INVESTIGATE_ATMOS, INVESTIGATE_EXPERIMENTOR, INVESTIGATE_BOTANY, INVESTIGATE_HALLUCINATIONS, INVESTIGATE_RADIATION, INVESTIGATE_CIRCUIT, INVESTIGATE_NANITES) )
|
||||
set name = "Investigate"
|
||||
|
||||
@@ -24,6 +24,7 @@ GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin())
|
||||
/client/proc/game_panel, /*game panel, allows to change game-mode etc*/
|
||||
/client/proc/check_ai_laws, /*shows AI and borg laws*/
|
||||
/datum/admins/proc/toggleooc, /*toggles ooc on/off for everyone*/
|
||||
/datum/admins/proc/toggleooclocal, /*toggles looc on/off for everyone*/
|
||||
/datum/admins/proc/toggleoocdead, /*toggles ooc on/off for everyone who is dead*/
|
||||
/datum/admins/proc/toggleaooc, /*toggles antag ooc on/off*/
|
||||
/datum/admins/proc/toggleenter, /*toggles whether people can join the current game*/
|
||||
|
||||
@@ -126,3 +126,18 @@ GLOBAL_LIST(round_end_notifiees)
|
||||
/datum/tgs_chat_command/reload_admins/proc/ReloadAsync()
|
||||
set waitfor = FALSE
|
||||
load_admins()
|
||||
|
||||
/datum/tgs_chat_command/addbunkerbypass
|
||||
name = "whitelist"
|
||||
help_text = "whitelist <ckey>"
|
||||
admin_only = TRUE
|
||||
|
||||
/datum/tgs_chat_command/addbunkerbypass/Run(datum/tgs_chat_user/sender, params)
|
||||
if(!CONFIG_GET(flag/sql_enabled))
|
||||
return "The Database is not enabled!"
|
||||
|
||||
GLOB.bunker_passthrough |= ckey(params)
|
||||
|
||||
log_admin("[sender.friendly_name] has added [params] to the current round's bunker bypass list.")
|
||||
message_admins("[sender.friendly_name] has added [params] to the current round's bunker bypass list.")
|
||||
return "[params] has been added to the current round's bunker bypass list."
|
||||
@@ -214,7 +214,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
|
||||
if(heard_by_no_admins && usr && usr.ckey != initiator_ckey)
|
||||
heard_by_no_admins = FALSE
|
||||
send2irc(initiator_ckey, "Ticket #[id]: Answered by [key_name(usr)]")
|
||||
_interactions += "[time_stamp()]: [formatted_message]"
|
||||
_interactions += "[TIME_STAMP("hh:mm:ss", FALSE)]: [formatted_message]"
|
||||
|
||||
//Removes the ahelp verb and returns it after 2 minutes
|
||||
/datum/admin_help/proc/TimeoutVerb()
|
||||
@@ -416,9 +416,9 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
|
||||
dat += "</b>[GLOB.TAB][TicketHref("Refresh", ref_src)][GLOB.TAB][TicketHref("Re-Title", ref_src, "retitle")]"
|
||||
if(state != AHELP_ACTIVE)
|
||||
dat += "[GLOB.TAB][TicketHref("Reopen", ref_src, "reopen")]"
|
||||
dat += "<br><br>Opened at: [gameTimestamp(wtime = opened_at)] (Approx [DisplayTimeText(world.time - opened_at)] ago)"
|
||||
dat += "<br><br>Opened at: [GAMETIMESTAMP("hh:mm:ss", closed_at)] (Approx [DisplayTimeText(world.time - opened_at)] ago)"
|
||||
if(closed_at)
|
||||
dat += "<br>Closed at: [gameTimestamp(wtime = closed_at)] (Approx [DisplayTimeText(world.time - closed_at)] ago)"
|
||||
dat += "<br>Closed at: [GAMETIMESTAMP("hh:mm:ss", closed_at)] (Approx [DisplayTimeText(world.time - closed_at)] ago)"
|
||||
dat += "<br><br>"
|
||||
if(initiator)
|
||||
dat += "<b>Actions:</b> [FullMonty(ref_src)]<br>"
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
if (new_pb && !SSdbcore.Connect())
|
||||
message_admins("The Database is not connected! Panic bunker will not work until the connection is reestablished.")
|
||||
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Panic Bunker", "[new_pb ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
send2irc("Panic Bunker", "[key_name(usr)] has toggled the Panic Bunker, it is now [new_pb ? "enabled" : "disabled"].")
|
||||
|
||||
/client/proc/addbunkerbypass(ckeytobypass as text)
|
||||
set category = "Special Verbs"
|
||||
@@ -24,7 +25,8 @@
|
||||
|
||||
GLOB.bunker_passthrough |= ckey(ckeytobypass)
|
||||
log_admin("[key_name(usr)] has added [ckeytobypass] to the current round's bunker bypass list.")
|
||||
message_admins("[key_name(usr)] has added [ckeytobypass] to the current round's bunker bypass list.")
|
||||
message_admins("[key_name_admin(usr)] has added [ckeytobypass] to the current round's bunker bypass list.")
|
||||
send2irc("Panic Bunker", "[key_name(usr)] has added [ckeytobypass] to the current round's bunker bypass list.")
|
||||
|
||||
/client/proc/revokebunkerbypass(ckeytobypass as text)
|
||||
set category = "Special Verbs"
|
||||
@@ -36,5 +38,5 @@
|
||||
|
||||
GLOB.bunker_passthrough -= ckey(ckeytobypass)
|
||||
log_admin("[key_name(usr)] has removed [ckeytobypass] from the current round's bunker bypass list.")
|
||||
message_admins("[key_name(usr)] has removed [ckeytobypass] from the current round's bunker bypass list.")
|
||||
|
||||
message_admins("[key_name_admin(usr)] has removed [ckeytobypass] from the current round's bunker bypass list.")
|
||||
send2irc("Panic Bunker", "[key_name(usr)] has removed [ckeytobypass] from the current round's bunker bypass list.")
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
to_chat(user, "<span class='notice'>We begin our stasis, preparing energy to arise once more.</span>")
|
||||
if(user.stat != DEAD)
|
||||
user.emote("deathgasp")
|
||||
user.tod = station_time_timestamp()
|
||||
user.tod = STATION_TIME_TIMESTAMP("hh:mm:ss")
|
||||
user.fakedeath("changeling") //play dead
|
||||
user.update_stat()
|
||||
user.update_canmove()
|
||||
|
||||
@@ -112,7 +112,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
var/list/invokers = list() //people eligible to invoke the rune
|
||||
if(user)
|
||||
invokers += user
|
||||
if(req_cultists > 1 || istype(src, /obj/effect/rune/convert))
|
||||
if(req_cultists > 1 || istype(src, /obj/effect/rune/narsie) || istype(src, /obj/effect/rune/convert))
|
||||
var/list/things_in_range = range(1, src)
|
||||
var/obj/item/toy/plush/narplush/plushsie = locate() in things_in_range
|
||||
if(istype(plushsie) && plushsie.is_invoker)
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
if(specialfunctions & SHOCK)
|
||||
if(D.secondsElectrified)
|
||||
D.secondsElectrified = -1
|
||||
LAZYADD(D.shockedby, "\[[time_stamp()]\] [key_name(usr)]")
|
||||
LAZYADD(D.shockedby, "\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(usr)]")
|
||||
log_combat(usr, D, "electrified")
|
||||
else
|
||||
D.secondsElectrified = 0
|
||||
|
||||
@@ -29,6 +29,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
|
||||
var/last_share = 0
|
||||
var/list/reaction_results
|
||||
var/list/analyzer_results //used for analyzer feedback - not initialized until its used
|
||||
var/gc_share = FALSE // Whether to call garbage_collect() on the sharer during shares, used for immutable mixtures
|
||||
|
||||
/datum/gas_mixture/New(volume)
|
||||
gases = new
|
||||
@@ -143,9 +144,6 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
|
||||
//Performs air sharing calculations between two gas_mixtures assuming only 1 boundary length
|
||||
//Returns: amount of gas exchanged (+ if sharer received)
|
||||
|
||||
/datum/gas_mixture/proc/after_share(datum/gas_mixture/sharer)
|
||||
//called on share's sharer to let it know it just got some gases
|
||||
|
||||
/datum/gas_mixture/proc/temperature_share(datum/gas_mixture/sharer, conduction_coefficient)
|
||||
//Performs temperature sharing calculations (via conduction) between two gas_mixtures assuming only 1 boundary length
|
||||
//Returns: new temperature of the sharer
|
||||
@@ -343,7 +341,8 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
|
||||
if(length(cached_gases ^ sharer_gases)) //if all gases were present in both mixtures, we know that no gases are 0
|
||||
garbage_collect(cached_gases - sharer_gases) //any gases the sharer had, we are guaranteed to have. gases that it didn't have we are not.
|
||||
sharer.garbage_collect(sharer_gases - cached_gases) //the reverse is equally true
|
||||
sharer.after_share(src, atmos_adjacent_turfs)
|
||||
if (initial(sharer.gc_share))
|
||||
sharer.garbage_collect()
|
||||
if(temperature_delta > MINIMUM_TEMPERATURE_TO_MOVE || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE)
|
||||
var/our_moles
|
||||
TOTAL_MOLES(cached_gases,our_moles)
|
||||
@@ -351,9 +350,6 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
|
||||
TOTAL_MOLES(sharer_gases,their_moles)
|
||||
return (temperature_archived*(our_moles + moved_moles) - sharer.temperature_archived*(their_moles - moved_moles)) * R_IDEAL_GAS_EQUATION / volume
|
||||
|
||||
/datum/gas_mixture/after_share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4)
|
||||
return
|
||||
|
||||
/datum/gas_mixture/temperature_share(datum/gas_mixture/sharer, conduction_coefficient, sharer_temperature, sharer_heat_capacity)
|
||||
//transfer of thermal energy (via conduction) between self and sharer
|
||||
if(sharer)
|
||||
|
||||
@@ -1,73 +1,71 @@
|
||||
//"immutable" gas mixture used for immutable calculations
|
||||
//it can be changed, but any changes will ultimately be undone before they can have any effect
|
||||
|
||||
/datum/gas_mixture/immutable
|
||||
var/initial_temperature
|
||||
|
||||
/datum/gas_mixture/immutable/New()
|
||||
..()
|
||||
garbage_collect()
|
||||
|
||||
/datum/gas_mixture/immutable/garbage_collect()
|
||||
temperature = initial_temperature
|
||||
temperature_archived = initial_temperature
|
||||
gases.Cut()
|
||||
|
||||
/datum/gas_mixture/immutable/archive()
|
||||
return 1 //nothing changes, so we do nothing and the archive is successful
|
||||
|
||||
/datum/gas_mixture/immutable/merge()
|
||||
return 0 //we're immutable.
|
||||
|
||||
/datum/gas_mixture/immutable/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4)
|
||||
. = ..(sharer, 0)
|
||||
garbage_collect()
|
||||
|
||||
/datum/gas_mixture/immutable/after_share()
|
||||
garbage_collect()
|
||||
|
||||
/datum/gas_mixture/immutable/react()
|
||||
return 0 //we're immutable.
|
||||
|
||||
/datum/gas_mixture/immutable/copy()
|
||||
return new type //we're immutable, so we can just return a new instance.
|
||||
|
||||
/datum/gas_mixture/immutable/copy_from()
|
||||
return 0 //we're immutable.
|
||||
|
||||
/datum/gas_mixture/immutable/copy_from_turf()
|
||||
return 0 //we're immutable.
|
||||
|
||||
/datum/gas_mixture/immutable/parse_gas_string()
|
||||
return 0 //we're immutable.
|
||||
|
||||
/datum/gas_mixture/immutable/temperature_share(datum/gas_mixture/sharer, conduction_coefficient, sharer_temperature, sharer_heat_capacity)
|
||||
. = ..()
|
||||
temperature = initial_temperature
|
||||
|
||||
|
||||
//used by space tiles
|
||||
/datum/gas_mixture/immutable/space
|
||||
initial_temperature = TCMB
|
||||
|
||||
/datum/gas_mixture/immutable/space/heat_capacity()
|
||||
return HEAT_CAPACITY_VACUUM
|
||||
|
||||
/datum/gas_mixture/immutable/space/remove()
|
||||
return copy() //we're always empty, so we can just return a copy.
|
||||
|
||||
/datum/gas_mixture/immutable/space/remove_ratio()
|
||||
return copy() //we're always empty, so we can just return a copy.
|
||||
|
||||
|
||||
//used by cloners
|
||||
/datum/gas_mixture/immutable/cloner
|
||||
initial_temperature = T20C
|
||||
|
||||
/datum/gas_mixture/immutable/cloner/garbage_collect()
|
||||
..()
|
||||
ADD_GAS(/datum/gas/nitrogen, gases)
|
||||
gases[/datum/gas/nitrogen][MOLES] = MOLES_O2STANDARD + MOLES_N2STANDARD
|
||||
|
||||
/datum/gas_mixture/immutable/cloner/heat_capacity()
|
||||
return (MOLES_O2STANDARD + MOLES_N2STANDARD)*20 //specific heat of nitrogen is 20
|
||||
//"immutable" gas mixture used for immutable calculations
|
||||
//it can be changed, but any changes will ultimately be undone before they can have any effect
|
||||
|
||||
/datum/gas_mixture/immutable
|
||||
var/initial_temperature
|
||||
gc_share = TRUE
|
||||
|
||||
/datum/gas_mixture/immutable/New()
|
||||
..()
|
||||
garbage_collect()
|
||||
|
||||
/datum/gas_mixture/immutable/garbage_collect()
|
||||
temperature = initial_temperature
|
||||
temperature_archived = initial_temperature
|
||||
gases.Cut()
|
||||
|
||||
/datum/gas_mixture/immutable/archive()
|
||||
return 1 //nothing changes, so we do nothing and the archive is successful
|
||||
|
||||
/datum/gas_mixture/immutable/merge()
|
||||
return 0 //we're immutable.
|
||||
|
||||
/datum/gas_mixture/immutable/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4)
|
||||
. = ..(sharer, 0)
|
||||
garbage_collect()
|
||||
|
||||
/datum/gas_mixture/immutable/react()
|
||||
return 0 //we're immutable.
|
||||
|
||||
/datum/gas_mixture/immutable/copy()
|
||||
return new type //we're immutable, so we can just return a new instance.
|
||||
|
||||
/datum/gas_mixture/immutable/copy_from()
|
||||
return 0 //we're immutable.
|
||||
|
||||
/datum/gas_mixture/immutable/copy_from_turf()
|
||||
return 0 //we're immutable.
|
||||
|
||||
/datum/gas_mixture/immutable/parse_gas_string()
|
||||
return 0 //we're immutable.
|
||||
|
||||
/datum/gas_mixture/immutable/temperature_share(datum/gas_mixture/sharer, conduction_coefficient, sharer_temperature, sharer_heat_capacity)
|
||||
. = ..()
|
||||
temperature = initial_temperature
|
||||
|
||||
|
||||
//used by space tiles
|
||||
/datum/gas_mixture/immutable/space
|
||||
initial_temperature = TCMB
|
||||
|
||||
/datum/gas_mixture/immutable/space/heat_capacity()
|
||||
return HEAT_CAPACITY_VACUUM
|
||||
|
||||
/datum/gas_mixture/immutable/space/remove()
|
||||
return copy() //we're always empty, so we can just return a copy.
|
||||
|
||||
/datum/gas_mixture/immutable/space/remove_ratio()
|
||||
return copy() //we're always empty, so we can just return a copy.
|
||||
|
||||
|
||||
//used by cloners
|
||||
/datum/gas_mixture/immutable/cloner
|
||||
initial_temperature = T20C
|
||||
|
||||
/datum/gas_mixture/immutable/cloner/garbage_collect()
|
||||
..()
|
||||
ADD_GAS(/datum/gas/nitrogen, gases)
|
||||
gases[/datum/gas/nitrogen][MOLES] = MOLES_O2STANDARD + MOLES_N2STANDARD
|
||||
|
||||
/datum/gas_mixture/immutable/cloner/heat_capacity()
|
||||
return (MOLES_O2STANDARD + MOLES_N2STANDARD)*20 //specific heat of nitrogen is 20
|
||||
|
||||
@@ -221,13 +221,16 @@
|
||||
if(!P)
|
||||
continue
|
||||
GL += P.return_air()
|
||||
for(var/obj/machinery/atmospherics/components/binary/valve/V in P.other_atmosmch)
|
||||
if(V.on)
|
||||
PL |= V.parents[1]
|
||||
PL |= V.parents[2]
|
||||
for(var/obj/machinery/atmospherics/components/unary/portables_connector/C in P.other_atmosmch)
|
||||
if(C.connected_device)
|
||||
GL += C.portableConnectorReturnAir()
|
||||
for(var/atmosmch in P.other_atmosmch)
|
||||
if (istype(atmosmch, /obj/machinery/atmospherics/components/binary/valve))
|
||||
var/obj/machinery/atmospherics/components/binary/valve/V = atmosmch
|
||||
if(V.on)
|
||||
PL |= V.parents[1]
|
||||
PL |= V.parents[2]
|
||||
else if (istype(atmosmch, /obj/machinery/atmospherics/components/unary/portables_connector))
|
||||
var/obj/machinery/atmospherics/components/unary/portables_connector/C = atmosmch
|
||||
if(C.connected_device)
|
||||
GL += C.portableConnectorReturnAir()
|
||||
|
||||
var/total_thermal_energy = 0
|
||||
var/total_heat_capacity = 0
|
||||
|
||||
@@ -41,6 +41,11 @@
|
||||
return
|
||||
if(QDELETED(src) || QDELETED(user))
|
||||
return
|
||||
if(isobserver(user))
|
||||
var/mob/dead/observer/O = user
|
||||
if(!O.can_reenter_round)
|
||||
to_chat(user, "<span class='warning'>You are unable to reenter the round.</span>")
|
||||
return
|
||||
var/ghost_role = alert(latejoinercalling ? "Latejoin as [mob_name]? (This is a ghost role, and as such, it's very likely to be off-station.)" : "Become [mob_name]? (Warning, You can no longer be cloned!)",,"Yes","No")
|
||||
if(ghost_role == "No" || !loc)
|
||||
return
|
||||
|
||||
@@ -81,6 +81,21 @@
|
||||
crate_name = "emergency crate"
|
||||
crate_type = /obj/structure/closet/crate/internals
|
||||
|
||||
/datum/supply_pack/emergency/radiatione_emergency
|
||||
name = "Emergenc Radiation Protection Crate"
|
||||
desc = "Survive the Nuclear Apocalypse and Supermatter Engine alike with two sets of Radiation suits. Each set contains a helmet, suit, and Geiger counter. We'll even throw in a few pill bottles that are able to handles radiation and the affects of the poisoning."
|
||||
cost = 2500
|
||||
contains = list(/obj/item/clothing/head/radiation,
|
||||
/obj/item/clothing/head/radiation,
|
||||
/obj/item/clothing/suit/radiation,
|
||||
/obj/item/clothing/suit/radiation,
|
||||
/obj/item/geiger_counter,
|
||||
/obj/item/geiger_counter,
|
||||
/obj/item/storage/pill_bottle/mutarad,
|
||||
/obj/item/storage/firstaid/radbgone)
|
||||
crate_name = "radiation protection crate"
|
||||
crate_type = /obj/structure/closet/crate/radiation
|
||||
|
||||
/datum/supply_pack/emergency/rcds
|
||||
name = "Emergency RCDs"
|
||||
desc = "Bombs going off on station? SME blown and now you need to fix the hole it left behind? Well this crate has a pare of Rcds to be able to easily fix up any problem you may have!"
|
||||
@@ -512,6 +527,14 @@
|
||||
/obj/item/storage/belt/bandolier)
|
||||
crate_name = "combat shotguns crate"
|
||||
|
||||
/datum/supply_pack/security/armory/dragnetgun
|
||||
name = "DRAGnet gun Crate"
|
||||
desc = "Contains two DRAGnet gun. A Dynamic Rapid-Apprehension of the Guilty net the revolution in law enforcement technology that YOU Want! Requires Armory access to open."
|
||||
cost = 3500
|
||||
contains = list(/obj/item/gun/energy/e_gun/dragnet,
|
||||
/obj/item/gun/energy/e_gun/dragnet)
|
||||
crate_name = "anti riot net guns crate"
|
||||
|
||||
/datum/supply_pack/security/armory/energy
|
||||
name = "Energy Guns Crate"
|
||||
desc = "Contains three Energy Guns, capable of firing both nonlethal and lethal blasts of light. Requires Armory access to open."
|
||||
@@ -545,7 +568,7 @@
|
||||
|
||||
/datum/supply_pack/security/armory/fire
|
||||
name = "Incendiary Weapons Crate"
|
||||
desc = "Burn, baby burn. Contains three incendiary grenades, three plasma canisters, and a flamethrower. Requires Armory access to open."
|
||||
desc = "Burn, baby burn. Contains three incendiary grenades, three plasma canisters, and a flamethrower. Requires Brige access to open."
|
||||
cost = 1500
|
||||
access = ACCESS_HEADS
|
||||
contains = list(/obj/item/flamethrower/full,
|
||||
@@ -559,6 +582,16 @@
|
||||
crate_type = /obj/structure/closet/crate/secure/plasma
|
||||
dangerous = TRUE
|
||||
|
||||
/datum/supply_pack/security/armory/miniguns
|
||||
name = "Personal Miniature Energy Guns"
|
||||
desc = "Contains three miniature energy guns. Each gun has a disabler and a lethal option. Requires Armory access to open."
|
||||
cost = 5000
|
||||
contains = list(/obj/item/gun/energy/e_gun/mini,
|
||||
/obj/item/gun/energy/e_gun/mini,
|
||||
/obj/item/gun/energy/e_gun/mini)
|
||||
crate_name = "personal energy guns crate"
|
||||
crate_type = /obj/structure/closet/crate/secure/plasma
|
||||
|
||||
/datum/supply_pack/security/armory/laserarmor
|
||||
name = "Reflector Vest Crate"
|
||||
desc = "Contains two vests of highly reflective material. Each armor piece diffuses a laser's energy by over half, as well as offering a good chance to reflect the laser entirely. Requires Armory access to open."
|
||||
@@ -620,6 +653,13 @@
|
||||
/obj/item/clothing/gloves/combat)
|
||||
crate_name = "swat crate"
|
||||
|
||||
/datum/supply_pack/security/armory/swattasers //Lesser AEG tbh
|
||||
name = "SWAT tatical tasers Crate"
|
||||
desc = "Contains two tactical energy gun, these guns are able to tase, disable and lethal as well as hold a seclight. Requires Armory access to open."
|
||||
cost = 8000
|
||||
contains = list(/obj/item/gun/energy/e_gun/stun,
|
||||
/obj/item/gun/energy/e_gun/stun)
|
||||
crate_name = "swat taser crate"
|
||||
|
||||
/datum/supply_pack/security/armory/wt550
|
||||
name = "WT-550 Semi-Auto Rifle Crate"
|
||||
@@ -1332,6 +1372,19 @@
|
||||
/obj/item/storage/firstaid/o2)
|
||||
crate_name = "oxygen deprivation kit crate"
|
||||
|
||||
/datum/supply_pack/medical/advrad
|
||||
name = "Radiation Treatment Crate Deluxe"
|
||||
desc = "A crate for when radiation is out of hand... Contains two rad-b-gone kits, one bottle of anti radiation deluxe pill bottle, as well as a radiation treatment deluxe pill bottle!"
|
||||
cost = 3500
|
||||
contains = list(/obj/item/storage/pill_bottle/antirad_plus,
|
||||
/obj/item/storage/pill_bottle/mutarad,
|
||||
/obj/item/storage/firstaid/radbgone,
|
||||
/obj/item/storage/firstaid/radbgone,
|
||||
/obj/item/geiger_counter,
|
||||
/obj/item/geiger_counter)
|
||||
crate_name = "radiation protection crate"
|
||||
crate_type = /obj/structure/closet/crate/radiation
|
||||
|
||||
/datum/supply_pack/medical/surgery
|
||||
name = "Surgical Supplies Crate"
|
||||
desc = "Do you want to perform surgery, but don't have one of those fancy shmancy degrees? Just get started with this crate containing a medical duffelbag, Sterilizine spray and collapsible roller bed."
|
||||
|
||||
@@ -1385,48 +1385,32 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
|
||||
if("hair_style")
|
||||
var/new_hair_style
|
||||
if(gender == MALE)
|
||||
new_hair_style = input(user, "Choose your character's hair style:", "Character Preference") as null|anything in GLOB.hair_styles_male_list
|
||||
else
|
||||
new_hair_style = input(user, "Choose your character's hair style:", "Character Preference") as null|anything in GLOB.hair_styles_female_list
|
||||
new_hair_style = input(user, "Choose your character's hair style:", "Character Preference") as null|anything in GLOB.hair_styles_list
|
||||
if(new_hair_style)
|
||||
hair_style = new_hair_style
|
||||
|
||||
if("next_hair_style")
|
||||
if (gender == MALE)
|
||||
hair_style = next_list_item(hair_style, GLOB.hair_styles_male_list)
|
||||
else
|
||||
hair_style = next_list_item(hair_style, GLOB.hair_styles_female_list)
|
||||
hair_style = next_list_item(hair_style, GLOB.hair_styles_list)
|
||||
|
||||
if("previous_hair_style")
|
||||
if (gender == MALE)
|
||||
hair_style = previous_list_item(hair_style, GLOB.hair_styles_male_list)
|
||||
else
|
||||
hair_style = previous_list_item(hair_style, GLOB.hair_styles_female_list)
|
||||
hair_style = previous_list_item(hair_style, GLOB.hair_styles_list)
|
||||
|
||||
if("facial")
|
||||
var/new_facial = input(user, "Choose your character's facial-hair colour:", "Character Preference","#"+facial_hair_color) as color|null
|
||||
if(new_facial)
|
||||
facial_hair_color = sanitize_hexcolor(new_facial)
|
||||
if("facial_hair_style")
|
||||
var/new_facial_hair_style
|
||||
if(gender == MALE)
|
||||
new_facial_hair_style = input(user, "Choose your character's facial-hair style:", "Character Preference") as null|anything in GLOB.facial_hair_styles_male_list
|
||||
else
|
||||
new_facial_hair_style = input(user, "Choose your character's facial-hair style:", "Character Preference") as null|anything in GLOB.facial_hair_styles_female_list
|
||||
if(new_facial_hair_style)
|
||||
facial_hair_style = new_facial_hair_style
|
||||
|
||||
if("facial_hair_style")
|
||||
var/new_facial_hair_style
|
||||
new_facial_hair_style = input(user, "Choose your character's facial-hair style:", "Character Preference") as null|anything in GLOB.facial_hair_styles_list
|
||||
if(new_facial_hair_style)
|
||||
facial_hair_style = new_facial_hair_style
|
||||
|
||||
if("next_facehair_style")
|
||||
if (gender == MALE)
|
||||
facial_hair_style = next_list_item(facial_hair_style, GLOB.facial_hair_styles_male_list)
|
||||
else
|
||||
facial_hair_style = next_list_item(facial_hair_style, GLOB.facial_hair_styles_female_list)
|
||||
if("previous_facehair_style")
|
||||
if (gender == MALE)
|
||||
facial_hair_style = previous_list_item(facial_hair_style, GLOB.facial_hair_styles_male_list)
|
||||
else
|
||||
facial_hair_style = previous_list_item(facial_hair_style, GLOB.facial_hair_styles_female_list)
|
||||
facial_hair_style = next_list_item(facial_hair_style, GLOB.facial_hair_styles_list)
|
||||
|
||||
if("previous_facehair_style")
|
||||
facial_hair_style = previous_list_item(facial_hair_style, GLOB.facial_hair_styles_list)
|
||||
|
||||
if("underwear")
|
||||
var/new_underwear
|
||||
@@ -1584,14 +1568,28 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
features["tail_lizard"] = "None"
|
||||
|
||||
if("snout")
|
||||
var/list/snowflake_snouts_list = list()
|
||||
for(var/path in GLOB.snouts_list)
|
||||
var/datum/sprite_accessory/mam_snouts/instance = GLOB.snouts_list[path]
|
||||
if(istype(instance, /datum/sprite_accessory))
|
||||
var/datum/sprite_accessory/S = instance
|
||||
if((!S.ckeys_allowed) || (S.ckeys_allowed.Find(user.client.ckey)))
|
||||
snowflake_snouts_list[S.name] = path
|
||||
var/new_snout
|
||||
new_snout = input(user, "Choose your character's snout:", "Character Preference") as null|anything in GLOB.snouts_list
|
||||
new_snout = input(user, "Choose your character's snout:", "Character Preference") as null|anything in snowflake_snouts_list
|
||||
if(new_snout)
|
||||
features["snout"] = new_snout
|
||||
|
||||
if("mam_snouts")
|
||||
var/list/snowflake_mam_snouts_list = list()
|
||||
for(var/path in GLOB.mam_snouts_list)
|
||||
var/datum/sprite_accessory/mam_snouts/instance = GLOB.mam_snouts_list[path]
|
||||
if(istype(instance, /datum/sprite_accessory))
|
||||
var/datum/sprite_accessory/S = instance
|
||||
if((!S.ckeys_allowed) || (S.ckeys_allowed.Find(user.client.ckey)))
|
||||
snowflake_mam_snouts_list[S.name] = path
|
||||
var/new_mam_snouts
|
||||
new_mam_snouts = input(user, "Choose your character's snout:", "Character Preference") as null|anything in GLOB.mam_snouts_list
|
||||
new_mam_snouts = input(user, "Choose your character's snout:", "Character Preference") as null|anything in snowflake_mam_snouts_list
|
||||
if(new_mam_snouts)
|
||||
features["mam_snouts"] = new_mam_snouts
|
||||
|
||||
@@ -1601,12 +1599,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(new_horns)
|
||||
features["horns"] = new_horns
|
||||
|
||||
if("ears")
|
||||
var/new_ears
|
||||
new_ears = input(user, "Choose your character's ears:", "Character Preference") as null|anything in GLOB.ears_list
|
||||
if(new_ears)
|
||||
features["ears"] = new_ears
|
||||
|
||||
if("wings")
|
||||
var/new_wings
|
||||
new_wings = input(user, "Choose your character's wings:", "Character Preference") as null|anything in GLOB.r_wings_list
|
||||
@@ -2152,31 +2144,25 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
|
||||
if("tail_lizard" in pref_species.default_features)
|
||||
character.dna.species.mutant_bodyparts |= "tail_lizard"
|
||||
else if("mam_tail" in pref_species.default_features)
|
||||
if("mam_tail" in pref_species.default_features)
|
||||
character.dna.species.mutant_bodyparts |= "mam_tail"
|
||||
else if("xenotail" in pref_species.default_features)
|
||||
if("xenotail" in pref_species.default_features)
|
||||
character.dna.species.mutant_bodyparts |= "xenotail"
|
||||
|
||||
if("legs" in pref_species.default_features)
|
||||
if(character.dna.features["legs"] == "Digitigrade Legs")
|
||||
pref_species.species_traits += DIGITIGRADE
|
||||
character.Digitigrade_Leg_Swap(FALSE)
|
||||
|
||||
if(character.dna.features["legs"] == "Normal Legs" && DIGITIGRADE in pref_species.species_traits)
|
||||
pref_species.species_traits -= DIGITIGRADE
|
||||
character.Digitigrade_Leg_Swap(TRUE)
|
||||
|
||||
else if((!"legs" in pref_species.default_features) && DIGITIGRADE in pref_species.species_traits)
|
||||
if(("legs" in character.dna.species.mutant_bodyparts) && character.dna.features["legs"] == "Digitigrade Legs")
|
||||
pref_species.species_traits |= DIGITIGRADE
|
||||
else
|
||||
pref_species.species_traits -= DIGITIGRADE
|
||||
character.Digitigrade_Leg_Swap(TRUE)
|
||||
|
||||
if(DIGITIGRADE in pref_species.species_traits)
|
||||
character.Digitigrade_Leg_Swap(FALSE)
|
||||
else
|
||||
character.Digitigrade_Leg_Swap(TRUE)
|
||||
|
||||
if(icon_updates)
|
||||
character.update_body()
|
||||
character.update_hair()
|
||||
character.update_body_parts()
|
||||
//let's be sure the character updates
|
||||
character.update_body()
|
||||
character.update_hair()
|
||||
character.update_body_parts()
|
||||
|
||||
/datum/preferences/proc/get_default_name(name_id)
|
||||
switch(name_id)
|
||||
|
||||
@@ -24,11 +24,8 @@
|
||||
return
|
||||
|
||||
if(!holder)
|
||||
if(!GLOB.ooc_allowed)
|
||||
to_chat(src, "<span class='danger'> OOC is globally muted</span>")
|
||||
return
|
||||
if(!GLOB.dooc_allowed && (mob.stat == DEAD))
|
||||
to_chat(usr, "<span class='danger'> OOC for dead mobs has been turned off.</span>")
|
||||
if(!GLOB.looc_allowed)
|
||||
to_chat(src, "<span class='danger'> LOOC is globally muted</span>")
|
||||
return
|
||||
if(prefs.muted & MUTE_OOC)
|
||||
to_chat(src, "<span class='danger'> You cannot use OOC (muted).</span>")
|
||||
|
||||
@@ -80,6 +80,16 @@
|
||||
GLOB.ooc_allowed = !GLOB.ooc_allowed
|
||||
to_chat(world, "<B>The OOC channel has been globally [GLOB.ooc_allowed ? "enabled" : "disabled"].</B>")
|
||||
|
||||
/proc/toggle_looc(toggle = null)
|
||||
if(toggle != null)
|
||||
if(toggle != GLOB.looc_allowed)
|
||||
GLOB.looc_allowed = toggle
|
||||
else
|
||||
return
|
||||
else
|
||||
GLOB.looc_allowed = !GLOB.looc_allowed
|
||||
|
||||
|
||||
/proc/toggle_dooc(toggle = null)
|
||||
if(toggle != null)
|
||||
if(toggle != GLOB.dooc_allowed)
|
||||
|
||||
@@ -198,11 +198,13 @@
|
||||
|
||||
death(0)
|
||||
|
||||
/mob/living/proc/suicide_log()
|
||||
log_game("[key_name(src)] committed suicide at [AREACOORD(src)] as [src.type].")
|
||||
/mob/living/proc/suicide_log(ghosting)
|
||||
log_game("[key_name(src)] [ghosting ? "ghosted" : "committed suicide"] at [AREACOORD(src)] as [src.type].")
|
||||
message_admins("[key_name(src)] [ghosting ? "ghosted" : "committed suicide"] at [AREACOORD(src)].")
|
||||
|
||||
/mob/living/carbon/human/suicide_log()
|
||||
log_game("[key_name(src)] (job: [src.job ? "[src.job]" : "None"]) committed suicide at [AREACOORD(src)].")
|
||||
/mob/living/carbon/human/suicide_log(ghosting)
|
||||
log_game("[key_name(src)] (job: [src.job ? "[src.job]" : "None"]) [is_special_character(src) ? "(ANTAG!) " : ""][ghosting ? "ghosted" : "committed suicide"] at [AREACOORD(src)].")
|
||||
message_admins("[key_name(src)] (job: [src.job ? "[src.job]" : "None"]) [is_special_character(src) ? "(ANTAG!) " : ""][ghosting ? "ghosted" : "committed suicide"] at [AREACOORD(src)].")
|
||||
|
||||
/mob/living/proc/canSuicide()
|
||||
switch(stat)
|
||||
|
||||
@@ -38,6 +38,12 @@
|
||||
|
||||
dog_fashion = null
|
||||
|
||||
/obj/item/clothing/head/caphat/beret
|
||||
name = "captain's beret"
|
||||
desc = "A beret fit for a leader."
|
||||
icon_state = "capberet"
|
||||
|
||||
dog_fashion = null
|
||||
|
||||
//Head of Personnel
|
||||
/obj/item/clothing/head/hopcap
|
||||
@@ -47,6 +53,13 @@
|
||||
armor = list("melee" = 25, "bullet" = 15, "laser" = 25, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
|
||||
dog_fashion = /datum/dog_fashion/head/hop
|
||||
|
||||
/obj/item/clothing/head/hopcap/beret
|
||||
name = "head of personnel's beret"
|
||||
desc = "The symbol of true bureaucratic micromanagement, although in a fancy form."
|
||||
icon_state = "hopberet"
|
||||
|
||||
dog_fashion = null
|
||||
|
||||
//Chaplain
|
||||
/obj/item/clothing/head/nun_hood
|
||||
name = "nun hood"
|
||||
@@ -164,3 +177,27 @@
|
||||
name = "treasure hunter's fedora"
|
||||
desc = "You got red text today kid, but it doesn't mean you have to like it."
|
||||
icon_state = "curator"
|
||||
|
||||
//Chief Medical Officer
|
||||
/obj/item/clothing/head/beret/cmo
|
||||
name = "chief medical officer's beret"
|
||||
desc = "A fancy beret with a green cross, signifying your status in the station's medbay."
|
||||
icon_state = "cmoberet"
|
||||
|
||||
//Research Director
|
||||
/obj/item/clothing/head/beret/rd
|
||||
name = "research director's beret"
|
||||
desc = "A beret worn only by highly intelligent people."
|
||||
icon_state = "rdberet"
|
||||
|
||||
//Chief Engineer
|
||||
/obj/item/clothing/head/beret/ce
|
||||
name = "chief engineer's beret"
|
||||
desc = "A beret that will surely make you look way cooler than a hard hat, although lack of protection is the price."
|
||||
icon_state = "ceberet"
|
||||
|
||||
//Quartermaster
|
||||
/obj/item/clothing/head/beret/qm
|
||||
name = "quartermaster's beret"
|
||||
desc = "This headwear shows off your Cargonian leadership"
|
||||
icon_state = "qmberet"
|
||||
@@ -712,7 +712,10 @@
|
||||
/obj/item/clothing/suit/space/hardsuit/shielded/worn_overlays(isinhands)
|
||||
. = list()
|
||||
if(!isinhands)
|
||||
. += mutable_appearance('icons/effects/effects.dmi', shield_state, MOB_LAYER + 0.01)
|
||||
if(taurmode >= SNEK_TAURIC)
|
||||
. += mutable_appearance('modular_citadel/icons/mob/64x32_effects.dmi', shield_state, MOB_LAYER + 0.01)
|
||||
else
|
||||
. += mutable_appearance('icons/effects/effects.dmi', shield_state, MOB_LAYER + 0.01)
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/shielded
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
if(tauric == TRUE)
|
||||
center = TRUE
|
||||
dimension_x = 64
|
||||
else if(H.dna.features["taur"] in list("Fox", "Wolf", "Otie", "Drake", "Lab", "Shepherd", "Husky", "Eevee", "Panther", "Tajaran", "Horse", "Cow"))
|
||||
else if(H.dna.features["taur"] in list("Fox","Wolf","Otie","Drake","Lab","Shepherd","Husky","Eevee","Panther","Horse","Cow","Tiger"))
|
||||
taurmode = PAW_TAURIC
|
||||
if(tauric == TRUE)
|
||||
center = TRUE
|
||||
@@ -61,7 +61,10 @@
|
||||
if(damaged_clothes)
|
||||
. += mutable_appearance('icons/effects/item_damage.dmi', "damaged[blood_overlay_type]")
|
||||
IF_HAS_BLOOD_DNA(src)
|
||||
. += mutable_appearance('icons/effects/blood.dmi', "[blood_overlay_type]blood")
|
||||
if(taurmode >= SNEK_TAURIC)
|
||||
. += mutable_appearance('modular_citadel/icons/mob/64x32_effects.dmi', "[blood_overlay_type]blood")
|
||||
else
|
||||
. += mutable_appearance('icons/effects/blood.dmi', "[blood_overlay_type]blood")
|
||||
var/mob/living/carbon/human/M = loc
|
||||
if(ishuman(M) && M.w_uniform)
|
||||
var/obj/item/clothing/under/U = M.w_uniform
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
// We gathered everything. Create a fork and slowly display the results to the holder of the scanner.
|
||||
|
||||
var/found_something = 0
|
||||
add_log("<B>[station_time_timestamp()][get_timestamp()] - [target_name]</B>", 0)
|
||||
add_log("<B>[STATION_TIME_TIMESTAMP("hh:mm:ss")][get_timestamp()] - [target_name]</B>", 0)
|
||||
|
||||
// Fingerprints
|
||||
if(length(fingerprints))
|
||||
|
||||
@@ -76,7 +76,7 @@ GLOBAL_VAR_INIT(total_runtimes_skipped, 0)
|
||||
var/skipcount = abs(error_cooldown[erroruid]) - 1
|
||||
error_cooldown[erroruid] = 0
|
||||
if(skipcount > 0)
|
||||
SEND_TEXT(world.log, "\[[time_stamp()]] Skipped [skipcount] runtimes in [E.file],[E.line].")
|
||||
SEND_TEXT(world.log, "\[[TIME_STAMP("hh:mm:ss", FALSE)]] Skipped [skipcount] runtimes in [E.file],[E.line].")
|
||||
GLOB.error_cache.log_error(E, skip_count = skipcount)
|
||||
|
||||
error_last_seen[erroruid] = world.time
|
||||
@@ -113,7 +113,7 @@ GLOBAL_VAR_INIT(total_runtimes_skipped, 0)
|
||||
if(GLOB.error_cache)
|
||||
GLOB.error_cache.log_error(E, desclines)
|
||||
|
||||
var/main_line = "\[[time_stamp()]] Runtime in [E.file],[E.line]: [E]"
|
||||
var/main_line = "\[[TIME_STAMP("hh:mm:ss", FALSE)]] Runtime in [E.file],[E.line]: [E]"
|
||||
SEND_TEXT(world.log, main_line)
|
||||
for(var/line in desclines)
|
||||
SEND_TEXT(world.log, line)
|
||||
|
||||
@@ -131,10 +131,10 @@ GLOBAL_DATUM(error_cache, /datum/error_viewer/error_cache)
|
||||
|
||||
/datum/error_viewer/error_source/New(exception/e)
|
||||
if (!istype(e))
|
||||
name = "\[[time_stamp()]] Uncaught exceptions"
|
||||
name = "\[[TIME_STAMP("hh:mm:ss", FALSE)]] Uncaught exceptions"
|
||||
return
|
||||
|
||||
name = "<b>\[[time_stamp()]]</b> Runtime in <b>[e.file]</b>, line <b>[e.line]</b>: <b>[html_encode(e.name)]</b>"
|
||||
name = "<b>\[[TIME_STAMP("hh:mm:ss", FALSE)]]</b> Runtime in <b>[e.file]</b>, line <b>[e.line]</b>: <b>[html_encode(e.name)]</b>"
|
||||
|
||||
/datum/error_viewer/error_source/show_to(user, datum/error_viewer/back_to, linear)
|
||||
if (!istype(back_to))
|
||||
@@ -156,15 +156,15 @@ GLOBAL_DATUM(error_cache, /datum/error_viewer/error_cache)
|
||||
|
||||
/datum/error_viewer/error_entry/New(exception/e, list/desclines, skip_count)
|
||||
if (!istype(e))
|
||||
name = "<b>\[[time_stamp()]]</b> Uncaught exception: <b>[html_encode(e.name)]</b>"
|
||||
name = "<b>\[[TIME_STAMP("hh:mm:ss", FALSE)]]</b> Uncaught exception: <b>[html_encode(e.name)]</b>"
|
||||
return
|
||||
|
||||
if(skip_count)
|
||||
name = "\[[time_stamp()]] Skipped [skip_count] runtimes in [e.file],[e.line]."
|
||||
name = "\[[TIME_STAMP("hh:mm:ss", FALSE)]] Skipped [skip_count] runtimes in [e.file],[e.line]."
|
||||
is_skip_count = TRUE
|
||||
return
|
||||
|
||||
name = "<b>\[[time_stamp()]]</b> Runtime in <b>[e.file]</b>, line <b>[e.line]</b>: <b>[html_encode(e.name)]</b>"
|
||||
name = "<b>\[[TIME_STAMP("hh:mm:ss", FALSE)]]</b> Runtime in <b>[e.file]</b>, line <b>[e.line]</b>: <b>[html_encode(e.name)]</b>"
|
||||
exc = e
|
||||
if (istype(desclines))
|
||||
for (var/line in desclines)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#define PIZZA_DELIVERY 6
|
||||
#define ITS_HIP_TO 7
|
||||
#define MY_GOD_JC 8
|
||||
|
||||
#define DELTA_CRATES 9
|
||||
|
||||
/datum/round_event_control/shuttle_loan
|
||||
name = "Shuttle Loan"
|
||||
@@ -118,6 +118,18 @@
|
||||
P.info = "Cargo: We have discovered an active Syndicate bomb near our VIP shuttle's fuel lines. If you feel up to the task, we will pay you for defusing it."
|
||||
P.update_icon()
|
||||
bonus_points = 45000 //If you mess up, people die and the shuttle gets turned into swiss cheese
|
||||
if(DELTA_CRATES)
|
||||
if(prob(50))
|
||||
priority_announce("Cargo: We have discovered a warehouse of DELTA locked crates, we cant store any more of them at CC can you take them for us?.", "CentCom Security Division")
|
||||
else
|
||||
priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/ai/commandreport.ogg') // CITADEL EDIT metabreak
|
||||
for(var/obj/machinery/computer/communications/C in GLOB.machines)
|
||||
if(!(C.stat & (BROKEN|NOPOWER)) && is_station_level(C.z))
|
||||
var/obj/item/paper/P = new(C.loc)
|
||||
P.name = "Cargo Report"
|
||||
P.info = "Cargo: We have discovered a warehouse of DELTA locked crates, we cant store any more of them at CC can you take them for us?."
|
||||
P.update_icon()
|
||||
bonus_points = 25000 //If you mess up, people die and the shuttle gets turned into swiss cheese
|
||||
|
||||
/datum/round_event/shuttle_loan/proc/loan_shuttle()
|
||||
priority_announce(thanks_msg, "Cargo shuttle commandeered by CentCom.")
|
||||
@@ -147,6 +159,8 @@
|
||||
SSshuttle.centcom_message += "Biohazard cleanup incoming."
|
||||
if(MY_GOD_JC)
|
||||
SSshuttle.centcom_message += "Live explosive ordnance incoming. Exercise extreme caution."
|
||||
if(DELTA_CRATES)
|
||||
SSshuttle.centcom_message += "DELTA Locked crates incoming. Exercise extreme caution."
|
||||
|
||||
/datum/round_event/shuttle_loan/tick()
|
||||
if(dispatched)
|
||||
@@ -291,6 +305,15 @@
|
||||
else
|
||||
shuttle_spawns.Add(/obj/item/paper/fluff/cargo/bomb/allyourbase)
|
||||
|
||||
if(DELTA_CRATES) //Delta crates can stack on eacher, and are basicly a 1/3/5 bombs
|
||||
for(var/i in 1 to 7) //7 seems fair
|
||||
shuttle_spawns.Add(/obj/structure/closet/crate/secure/loot)
|
||||
|
||||
for(var/i in 1 to 5)
|
||||
var/turf/T = pick_n_take(empty_shuttle_turfs)
|
||||
new /obj/structure/spider/stickyweb(T)
|
||||
new /obj/effect/decal/cleanable/ash(T)
|
||||
|
||||
var/false_positive = 0
|
||||
while(shuttle_spawns.len && empty_shuttle_turfs.len)
|
||||
var/turf/T = pick_n_take(empty_shuttle_turfs)
|
||||
@@ -334,3 +357,4 @@
|
||||
#undef PIZZA_DELIVERY
|
||||
#undef ITS_HIP_TO
|
||||
#undef MY_GOD_JC
|
||||
#undef DELTA_CRATES
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
reagentsAmount = 250
|
||||
|
||||
/datum/round_event_control/vent_clog/beer
|
||||
name = "Foamy beer stationwide"
|
||||
name = "Clogged Vents: Beer"
|
||||
typepath = /datum/round_event/vent_clog/beer
|
||||
max_occurrences = 0
|
||||
|
||||
@@ -83,12 +83,12 @@
|
||||
reagentsAmount = 100
|
||||
|
||||
/datum/round_event_control/vent_clog/plasma_decon
|
||||
name = "Plasma decontamination"
|
||||
name = "Anti-Plasma Flood"
|
||||
typepath = /datum/round_event/vent_clog/plasma_decon
|
||||
max_occurrences = 0
|
||||
|
||||
/datum/round_event_control/vent_clog/female
|
||||
name = "FemCum stationwide"
|
||||
name = "Clogged Vents; Girlcum"
|
||||
typepath = /datum/round_event/vent_clog/female
|
||||
max_occurrences = 0
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
reagentsAmount = 100
|
||||
|
||||
/datum/round_event_control/vent_clog/male
|
||||
name = "Semen stationwide"
|
||||
name = "Clogged Vents: Semen"
|
||||
typepath = /datum/round_event/vent_clog/male
|
||||
max_occurrences = 0
|
||||
|
||||
@@ -118,6 +118,9 @@
|
||||
foam.start()
|
||||
CHECK_TICK
|
||||
|
||||
/datum/round_event/vent_clog/male/announce()
|
||||
priority_announce("The scrubbers network is experiencing a backpressure surge. Some ejaculation of contents may occur.", "Atmospherics alert")
|
||||
|
||||
/datum/round_event/vent_clog/male/start()
|
||||
for(var/obj/machinery/atmospherics/components/unary/vent in vents)
|
||||
if(vent && vent.loc)
|
||||
@@ -130,6 +133,9 @@
|
||||
foam.start()
|
||||
CHECK_TICK
|
||||
|
||||
/datum/round_event/vent_clog/female/announce()
|
||||
priority_announce("The scrubbers network is experiencing a backpressure squirt. Some ejection of contents may occur.", "Atmospherics alert")
|
||||
|
||||
/datum/round_event/vent_clog/female/start()
|
||||
for(var/obj/machinery/atmospherics/components/unary/vent in vents)
|
||||
if(vent && vent.loc)
|
||||
|
||||
@@ -184,6 +184,15 @@
|
||||
tastes = list("the jungle" = 1, "bananas" = 1)
|
||||
foodtype = MEAT | SUGAR
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/monkeycube/On_Consume(mob/living/carbon/M)
|
||||
if(iscarbon(M))
|
||||
M.visible_message("[src] bursts out of [M]!</span>")
|
||||
M.emote("scream")
|
||||
M.Knockdown(40)
|
||||
M.adjustBruteLoss(60)
|
||||
Expand()
|
||||
return ..()
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/monkeycube/proc/Expand()
|
||||
var/mob/spammer = get_mob_by_key(fingerprintslast)
|
||||
var/mob/living/carbon/monkey/bananas = new(drop_location(), TRUE, spammer)
|
||||
|
||||
@@ -160,6 +160,15 @@
|
||||
tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "pineapple" = 6, "ham" = 2)
|
||||
foodtype = PINEAPPLE //Over powering tast of gods fruit
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/pizza/pineapple/anomaly
|
||||
desc = "A anomaly made pizza with pineapple..."
|
||||
bonus_reagents = list("nutriment" = 16, "vitamin" = 16)
|
||||
tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "pineapple" = 6, "ham" = 2, "good" = 10)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/pizzaslice/pineapple/anomaly
|
||||
desc = "A slice of good tasting pizza. But has pineapple on it, what a anomaly!"
|
||||
tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "pineapple" = 6, "ham" = 2, "good" = 10)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/pizza/arnold
|
||||
name = "\improper Arnold pizza"
|
||||
desc = "Hello, you've reached Arnold's pizza shop. I'm not here now, I'm out killing pepperoni."
|
||||
|
||||
@@ -692,3 +692,15 @@
|
||||
id = "pwr_game"
|
||||
results = list("pwr_game" = 5)
|
||||
required_reagents = list("sodawater" = 1, "blackcrayonpowder" = 1, "sodiumchloride" = 1)
|
||||
|
||||
/datum/chemical_reaction/pinkmilk
|
||||
name = "Strawberry Milk"
|
||||
id = "pinkmilk"
|
||||
results = list("pinkmilk" = 5)
|
||||
required_reagents = list("aphro+" = 1, "milk" = 1)
|
||||
|
||||
/datum/chemical_reaction/pinktea
|
||||
name = "Strawberry Tea"
|
||||
id = "pinktea"
|
||||
results = list("pinktea" = 5)
|
||||
required_reagents = list("aphro" = 1, "arnold_palmer" = 1, "sugar" = 1)
|
||||
|
||||
@@ -101,3 +101,22 @@
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/pizza/pineapple
|
||||
subcategory = CAT_PIZZA
|
||||
|
||||
/datum/crafting_recipe/food/pineapplepizza/anomaly
|
||||
name = "Anomaly Hawaiian pizza"
|
||||
reqs = list(
|
||||
/obj/item/assembly/signaler/anomaly = 1,
|
||||
/obj/item/reagent_containers/food/snacks/pizza/pineapple = 1
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/pizza/pineapple/anomaly
|
||||
subcategory = CAT_PIZZA
|
||||
|
||||
/datum/crafting_recipe/food/anomalypizzaboy
|
||||
name = "Anomaly pizza box"
|
||||
reqs = list(
|
||||
/obj/item/pizzabox = 5,
|
||||
/obj/item/assembly/signaler/anomaly = 1
|
||||
)
|
||||
tools = list(TOOL_WELDER, TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
|
||||
result = /obj/item/pizzabox/infinite
|
||||
subcategory = CAT_PIZZA
|
||||
|
||||
@@ -245,96 +245,41 @@ function output(message, flag) {
|
||||
|
||||
message = byondDecode(message).trim();
|
||||
|
||||
//The behemoth of filter-code (for Admin message filters)
|
||||
//Note: This is proooobably hella inefficient
|
||||
var filteredOut = false;
|
||||
if (opts.hasOwnProperty('showMessagesFilters') && !opts.showMessagesFilters['All'].show) {
|
||||
//Get this filter type (defined by class on message)
|
||||
var messageHtml = $.parseHTML(message),
|
||||
messageClasses;
|
||||
if (opts.hasOwnProperty('filterHideAll') && opts.filterHideAll) {
|
||||
var internal = false;
|
||||
messageClasses = (!!$(messageHtml).attr('class') ? $(messageHtml).attr('class').split(/\s+/) : false);
|
||||
if (messageClasses) {
|
||||
for (var i = 0; i < messageClasses.length; i++) { //Every class
|
||||
if (messageClasses[i] == 'internal') {
|
||||
internal = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!internal) {
|
||||
filteredOut = 'All';
|
||||
}
|
||||
} else {
|
||||
//If the element or it's child have any classes
|
||||
if (!!$(messageHtml).attr('class') || !!$(messageHtml).children().attr('class')) {
|
||||
messageClasses = $(messageHtml).attr('class').split(/\s+/);
|
||||
if (!!$(messageHtml).children().attr('class')) {
|
||||
messageClasses = messageClasses.concat($(messageHtml).children().attr('class').split(/\s+/));
|
||||
}
|
||||
var tempCount = 0;
|
||||
for (var i = 0; i < messageClasses.length; i++) { //Every class
|
||||
var thisClass = messageClasses[i];
|
||||
$.each(opts.showMessagesFilters, function(key, val) { //Every filter
|
||||
if (key !== 'All' && val.show === false && typeof val.match != 'undefined') {
|
||||
for (var i = 0; i < val.match.length; i++) {
|
||||
var matchClass = val.match[i];
|
||||
if (matchClass == thisClass) {
|
||||
filteredOut = key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (filteredOut) return false;
|
||||
});
|
||||
if (filteredOut) break;
|
||||
tempCount++;
|
||||
}
|
||||
} else {
|
||||
if (!opts.showMessagesFilters['Misc'].show) {
|
||||
filteredOut = 'Misc';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Stuff we do along with appending a message
|
||||
var atBottom = false;
|
||||
if (!filteredOut) {
|
||||
var bodyHeight = $('body').height();
|
||||
var messagesHeight = $messages.outerHeight();
|
||||
var scrollPos = $('body,html').scrollTop();
|
||||
var bodyHeight = $('body').height();
|
||||
var messagesHeight = $messages.outerHeight();
|
||||
var scrollPos = $('body,html').scrollTop();
|
||||
|
||||
//Should we snap the output to the bottom?
|
||||
if (bodyHeight + scrollPos >= messagesHeight - opts.scrollSnapTolerance) {
|
||||
atBottom = true;
|
||||
if ($('#newMessages').length) {
|
||||
$('#newMessages').remove();
|
||||
//Should we snap the output to the bottom?
|
||||
if (bodyHeight + scrollPos >= messagesHeight - opts.scrollSnapTolerance) {
|
||||
atBottom = true;
|
||||
if ($('#newMessages').length) {
|
||||
$('#newMessages').remove();
|
||||
}
|
||||
//If not, put the new messages box in
|
||||
} else {
|
||||
if ($('#newMessages').length) {
|
||||
var messages = $('#newMessages .number').text();
|
||||
messages = parseInt(messages);
|
||||
messages++;
|
||||
$('#newMessages .number').text(messages);
|
||||
if (messages == 2) {
|
||||
$('#newMessages .messageWord').append('s');
|
||||
}
|
||||
//If not, put the new messages box in
|
||||
} else {
|
||||
if ($('#newMessages').length) {
|
||||
var messages = $('#newMessages .number').text();
|
||||
messages = parseInt(messages);
|
||||
messages++;
|
||||
$('#newMessages .number').text(messages);
|
||||
if (messages == 2) {
|
||||
$('#newMessages .messageWord').append('s');
|
||||
}
|
||||
} else {
|
||||
$messages.after('<a href="#" id="newMessages"><span class="number">1</span> new <span class="messageWord">message</span> <i class="icon-double-angle-down"></i></a>');
|
||||
}
|
||||
$messages.after('<a href="#" id="newMessages"><span class="number">1</span> new <span class="messageWord">message</span> <i class="icon-double-angle-down"></i></a>');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
opts.messageCount++;
|
||||
|
||||
//Pop the top message off if history limit reached
|
||||
if (opts.messageCount >= opts.messageLimit) {
|
||||
$messages.children('div.entry:first-child').remove();
|
||||
opts.messageCount--; //I guess the count should only ever equal the limit
|
||||
}
|
||||
//if (opts.messageCount >= opts.messageLimit) {
|
||||
//$messages.children('div.entry:first-child').remove();
|
||||
//opts.messageCount--; //I guess the count should only ever equal the limit
|
||||
//}
|
||||
|
||||
// Create the element - if combining is off, we use it, and if it's on, we
|
||||
// might discard it bug need to check its text content. Some messages vary
|
||||
@@ -372,11 +317,6 @@ function output(message, flag) {
|
||||
//Actually append the message
|
||||
entry.className = 'entry';
|
||||
|
||||
if (filteredOut) {
|
||||
entry.className += ' hidden';
|
||||
entry.setAttribute('data-filter', filteredOut);
|
||||
}
|
||||
|
||||
$last_message = trimmed_message;
|
||||
$messages[0].appendChild(entry);
|
||||
$(entry).find("img.icon").error(iconError);
|
||||
@@ -401,7 +341,7 @@ function output(message, flag) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!filteredOut && atBottom) {
|
||||
if (atBottom) {
|
||||
$('body,html').scrollTop($messages.outerHeight());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#define IC_TOPIC_UNHANDLED 0
|
||||
#define IC_TOPIC_HANDLED 1
|
||||
#define IC_TOPIC_REFRESH 2
|
||||
#define IC_FLAG_ANCHORABLE 1
|
||||
#define IC_FLAG_CAN_FIRE 2
|
||||
@@ -0,0 +1,762 @@
|
||||
#define SOURCE_TO_TARGET 0
|
||||
#define TARGET_TO_SOURCE 1
|
||||
#define PUMP_EFFICIENCY 0.6
|
||||
#define TANK_FAILURE_PRESSURE (ONE_ATMOSPHERE*25)
|
||||
#define PUMP_MAX_PRESSURE (ONE_ATMOSPHERE*24)
|
||||
#define PUMP_MAX_VOLUME 100
|
||||
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics
|
||||
category_text = "Atmospherics"
|
||||
cooldown_per_use = 2 SECONDS
|
||||
complexity = 10
|
||||
size = 7
|
||||
outputs = list(
|
||||
"self reference" = IC_PINTYPE_SELFREF,
|
||||
"pressure" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
var/datum/gas_mixture/air_contents
|
||||
var/volume = 2 //Pretty small, I know
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/Initialize()
|
||||
air_contents = new(volume)
|
||||
..()
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/return_air()
|
||||
return air_contents
|
||||
|
||||
//Check if the gas container is adjacent and of the right type
|
||||
/obj/item/integrated_circuit/atmospherics/proc/check_gassource(atom/gasholder)
|
||||
if(!gasholder)
|
||||
return FALSE
|
||||
if(!gasholder.Adjacent(get_object()))
|
||||
return FALSE
|
||||
if(!istype(gasholder, /obj/item/tank) && !istype(gasholder, /obj/machinery/portable_atmospherics) && !istype(gasholder, /obj/item/integrated_circuit/atmospherics))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
//Needed in circuits where source and target types differ
|
||||
/obj/item/integrated_circuit/atmospherics/proc/check_gastarget(atom/gasholder)
|
||||
return check_gassource(gasholder)
|
||||
|
||||
|
||||
// - gas pump - // **works**
|
||||
/obj/item/integrated_circuit/atmospherics/pump
|
||||
name = "gas pump"
|
||||
desc = "Somehow moves gases between two tanks, canisters, and other gas containers."
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
inputs = list(
|
||||
"source" = IC_PINTYPE_REF,
|
||||
"target" = IC_PINTYPE_REF,
|
||||
"target pressure" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
activators = list(
|
||||
"transfer" = IC_PINTYPE_PULSE_IN,
|
||||
"on transfer" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
var/direction = SOURCE_TO_TARGET
|
||||
var/target_pressure = PUMP_MAX_PRESSURE
|
||||
power_draw_per_use = 20
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/pump/Initialize()
|
||||
air_contents = new(volume)
|
||||
extended_desc += " Use negative pressure to move air from target to source. \
|
||||
Note that only part of the gas is moved on each transfer, \
|
||||
so multiple activations will be necessary to achieve target pressure. \
|
||||
The pressure limit for circuit pumps is [round(PUMP_MAX_PRESSURE)] kPa."
|
||||
. = ..()
|
||||
|
||||
// This proc gets the direction of the gas flow depending on its value, by calling update target
|
||||
/obj/item/integrated_circuit/atmospherics/pump/on_data_written()
|
||||
var/amt = get_pin_data(IC_INPUT, 3)
|
||||
update_target(amt)
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/pump/proc/update_target(new_amount)
|
||||
if(!isnum(new_amount))
|
||||
new_amount = 0
|
||||
// See in which direction the gas moves
|
||||
if(new_amount < 0)
|
||||
direction = TARGET_TO_SOURCE
|
||||
else
|
||||
direction = SOURCE_TO_TARGET
|
||||
target_pressure = min(round(PUMP_MAX_PRESSURE),abs(new_amount))
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/pump/do_work()
|
||||
var/obj/source = get_pin_data_as_type(IC_INPUT, 1, /obj)
|
||||
var/obj/target = get_pin_data_as_type(IC_INPUT, 2, /obj)
|
||||
perform_magic(source, target)
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/pump/proc/perform_magic(atom/source, atom/target)
|
||||
//Check if both atoms are of the right type: atmos circuits/gas tanks/canisters. If one is the same, use the circuit var
|
||||
if(!check_gassource(source))
|
||||
source = src
|
||||
|
||||
if(!check_gastarget(target))
|
||||
target = src
|
||||
|
||||
// If both are the same, this whole proc would do nothing and just waste performance
|
||||
if(source == target)
|
||||
return
|
||||
|
||||
var/datum/gas_mixture/source_air = source.return_air()
|
||||
var/datum/gas_mixture/target_air = target.return_air()
|
||||
|
||||
if(!source_air || !target_air)
|
||||
return
|
||||
|
||||
// Swapping both source and target
|
||||
if(direction == TARGET_TO_SOURCE)
|
||||
var/temp = source_air
|
||||
source_air = target_air
|
||||
target_air = temp
|
||||
|
||||
// If what you are pumping is empty, use the circuit's storage
|
||||
if(source_air.total_moles() <= 0)
|
||||
source_air = air_contents
|
||||
|
||||
// Move gas from one place to another
|
||||
move_gas(source_air, target_air)
|
||||
air_update_turf()
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/pump/proc/move_gas(datum/gas_mixture/source_air, datum/gas_mixture/target_air)
|
||||
|
||||
// No moles = nothing to pump
|
||||
if(source_air.total_moles() <= 0 || target_air.return_pressure() >= PUMP_MAX_PRESSURE)
|
||||
return
|
||||
|
||||
// Negative Kelvin temperatures should never happen and if they do, normalize them
|
||||
if(source_air.temperature < TCMB)
|
||||
source_air.temperature = TCMB
|
||||
|
||||
var/pressure_delta = target_pressure - target_air.return_pressure()
|
||||
if(pressure_delta > 0.1)
|
||||
var/transfer_moles = (pressure_delta*target_air.volume/(source_air.temperature * R_IDEAL_GAS_EQUATION))*PUMP_EFFICIENCY
|
||||
var/datum/gas_mixture/removed = source_air.remove(transfer_moles)
|
||||
target_air.merge(removed)
|
||||
|
||||
|
||||
// - volume pump - // **Works**
|
||||
/obj/item/integrated_circuit/atmospherics/pump/volume
|
||||
name = "volume pump"
|
||||
desc = "Moves gases between two tanks, canisters, and other gas containers by using their volume, up to 200 L/s."
|
||||
extended_desc = " Use negative volume to move air from target to source. Note that only part of the gas is moved on each transfer. Its maximum pumping volume is capped at 1000kPa."
|
||||
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
inputs = list(
|
||||
"source" = IC_PINTYPE_REF,
|
||||
"target" = IC_PINTYPE_REF,
|
||||
"transfer volume" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
activators = list(
|
||||
"transfer" = IC_PINTYPE_PULSE_IN,
|
||||
"on transfer" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
direction = SOURCE_TO_TARGET
|
||||
var/transfer_rate = PUMP_MAX_VOLUME
|
||||
power_draw_per_use = 20
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/pump/volume/update_target(new_amount)
|
||||
if(!isnum(new_amount))
|
||||
new_amount = 0
|
||||
// See in which direction the gas moves
|
||||
if(new_amount < 0)
|
||||
direction = TARGET_TO_SOURCE
|
||||
else
|
||||
direction = SOURCE_TO_TARGET
|
||||
target_pressure = min(PUMP_MAX_VOLUME,abs(new_amount))
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/pump/volume/move_gas(datum/gas_mixture/source_air, datum/gas_mixture/target_air)
|
||||
// No moles = nothing to pump
|
||||
if(source_air.total_moles() <= 0)
|
||||
return
|
||||
|
||||
// Negative Kelvin temperatures should never happen and if they do, normalize them
|
||||
if(source_air.temperature < TCMB)
|
||||
source_air.temperature = TCMB
|
||||
|
||||
if((source_air.return_pressure() < 0.01) || (target_air.return_pressure() >= PUMP_MAX_PRESSURE))
|
||||
return
|
||||
|
||||
//The second part of the min caps the pressure built by the volume pumps to the max pump pressure
|
||||
var/transfer_ratio = min(transfer_rate,target_air.volume*PUMP_MAX_PRESSURE/source_air.return_pressure())/source_air.volume
|
||||
|
||||
var/datum/gas_mixture/removed = source_air.remove_ratio(transfer_ratio * PUMP_EFFICIENCY)
|
||||
|
||||
target_air.merge(removed)
|
||||
|
||||
|
||||
// - gas vent - // **works**
|
||||
/obj/item/integrated_circuit/atmospherics/pump/vent
|
||||
name = "gas vent"
|
||||
extended_desc = "Use negative volume to move air from target to environment. Note that only part of the gas is moved on each transfer. Unlike the gas pump, this one keeps pumping even further to pressures of 9000 pKa and it is not advised to use it on tank circuits."
|
||||
desc = "Moves gases between the environment and adjacent gas containers."
|
||||
inputs = list(
|
||||
"container" = IC_PINTYPE_REF,
|
||||
"target pressure" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/pump/vent/on_data_written()
|
||||
var/amt = get_pin_data(IC_INPUT, 2)
|
||||
update_target(amt)
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/pump/vent/do_work()
|
||||
var/turf/source = get_turf(src)
|
||||
var/obj/target = get_pin_data_as_type(IC_INPUT, 1, /obj)
|
||||
perform_magic(source, target)
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/pump/vent/check_gastarget(atom/gasholder)
|
||||
if(!gasholder)
|
||||
return FALSE
|
||||
if(!gasholder.Adjacent(get_object()))
|
||||
return FALSE
|
||||
if(!istype(gasholder, /obj/item/tank) && !istype(gasholder, /obj/machinery/portable_atmospherics) && !istype(gasholder, /obj/item/integrated_circuit/atmospherics))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/pump/vent/check_gassource(atom/target)
|
||||
if(!target)
|
||||
return FALSE
|
||||
if(!istype(target, /turf))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
|
||||
// - integrated connector - // Can connect and disconnect properly
|
||||
/obj/item/integrated_circuit/atmospherics/connector
|
||||
name = "integrated connector"
|
||||
desc = "Creates an airtight seal with standard connectors found on the floor, \
|
||||
allowing the assembly to exchange gases with a pipe network."
|
||||
extended_desc = "This circuit will automatically attempt to locate and connect to ports on the floor beneath it when activated. \
|
||||
You <b>must</b> set a target before connecting."
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
inputs = list(
|
||||
"target" = IC_PINTYPE_REF
|
||||
)
|
||||
activators = list(
|
||||
"toggle connection" = IC_PINTYPE_PULSE_IN,
|
||||
"on connected" = IC_PINTYPE_PULSE_OUT,
|
||||
"on connection failed" = IC_PINTYPE_PULSE_OUT,
|
||||
"on disconnected" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
|
||||
var/obj/machinery/atmospherics/components/unary/portables_connector/connector
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/connector/Initialize()
|
||||
air_contents = new(volume)
|
||||
START_PROCESSING(SSobj, src)
|
||||
. = ..()
|
||||
|
||||
//Sucks up the gas from the connector
|
||||
/obj/item/integrated_circuit/atmospherics/connector/process()
|
||||
set_pin_data(IC_OUTPUT, 2, air_contents.return_pressure())
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/connector/check_gassource(atom/gasholder)
|
||||
if(!gasholder)
|
||||
return FALSE
|
||||
if(!istype(gasholder,/obj/machinery/atmospherics/components/unary/portables_connector))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
//If the assembly containing this is moved from the tile the connector pipe is in, the connection breaks
|
||||
/obj/item/integrated_circuit/atmospherics/connector/ext_moved()
|
||||
if(connector)
|
||||
if(get_dist(get_object(), connector) > 0)
|
||||
// The assembly is set as connected device and the connector handles the rest
|
||||
connector.connected_device = null
|
||||
connector = null
|
||||
activate_pin(4)
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/connector/do_work()
|
||||
// If there is a connection, disconnect
|
||||
if(connector)
|
||||
connector.connected_device = null
|
||||
connector = null
|
||||
activate_pin(4)
|
||||
return
|
||||
|
||||
var/obj/machinery/atmospherics/components/unary/portables_connector/PC = locate() in get_turf(src)
|
||||
// If no connector can't connect
|
||||
if(!PC)
|
||||
activate_pin(3)
|
||||
return
|
||||
connector = PC
|
||||
connector.connected_device = src
|
||||
activate_pin(2)
|
||||
|
||||
// Required for making the connector port script work
|
||||
obj/item/integrated_circuit/atmospherics/connector/portableConnectorReturnAir()
|
||||
return air_contents
|
||||
|
||||
|
||||
// - gas filter - // **works**
|
||||
/obj/item/integrated_circuit/atmospherics/pump/filter
|
||||
name = "gas filter"
|
||||
desc = "Filters one gas out of a mixture."
|
||||
complexity = 20
|
||||
size = 8
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
inputs = list(
|
||||
"source" = IC_PINTYPE_REF,
|
||||
"filtered output" = IC_PINTYPE_REF,
|
||||
"contaminants output" = IC_PINTYPE_REF,
|
||||
"wanted gases" = IC_PINTYPE_LIST,
|
||||
"target pressure" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
power_draw_per_use = 30
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/pump/filter/on_data_written()
|
||||
var/amt = get_pin_data(IC_INPUT, 5)
|
||||
target_pressure = CLAMP(amt, 0, PUMP_MAX_PRESSURE)
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/pump/filter/do_work()
|
||||
activate_pin(2)
|
||||
var/obj/source = get_pin_data_as_type(IC_INPUT, 1, /obj)
|
||||
var/obj/filtered = get_pin_data_as_type(IC_INPUT, 2, /obj)
|
||||
var/obj/contaminants = get_pin_data_as_type(IC_INPUT, 3, /obj)
|
||||
|
||||
var/wanted = get_pin_data(IC_INPUT, 4)
|
||||
|
||||
// If there is no filtered output, this whole thing makes no sense
|
||||
if(!check_gassource(filtered))
|
||||
return
|
||||
|
||||
var/datum/gas_mixture/filtered_air = filtered.return_air()
|
||||
if(!filtered_air)
|
||||
return
|
||||
|
||||
// If no source is set, the source is possibly this circuit's content
|
||||
if(!check_gassource(source))
|
||||
source = src
|
||||
var/datum/gas_mixture/source_air = source.return_air()
|
||||
|
||||
//No source air: source is this circuit
|
||||
if(!source_air)
|
||||
source_air = air_contents
|
||||
|
||||
// If no filtering tank is set, filter through itself
|
||||
if(!check_gassource(contaminants))
|
||||
contaminants = src
|
||||
var/datum/gas_mixture/contaminated_air = contaminants.return_air()
|
||||
|
||||
//If there is no gas mixture datum for unfiltered, pump the contaminants back into the circuit
|
||||
if(!contaminated_air)
|
||||
contaminated_air = air_contents
|
||||
|
||||
if(contaminated_air.return_pressure() >= PUMP_MAX_PRESSURE || filtered_air.return_pressure() >= PUMP_MAX_PRESSURE)
|
||||
return
|
||||
|
||||
var/pressure_delta = target_pressure - contaminated_air.return_pressure()
|
||||
var/transfer_moles
|
||||
|
||||
//Negative Kelvins are an anomaly and should be normalized if encountered
|
||||
if(source_air.temperature < TCMB)
|
||||
source_air.temperature = TCMB
|
||||
|
||||
transfer_moles = (pressure_delta*contaminated_air.volume/(source_air.temperature * R_IDEAL_GAS_EQUATION))*PUMP_EFFICIENCY
|
||||
|
||||
//If there is nothing to transfer, just return
|
||||
if(transfer_moles <= 0)
|
||||
return
|
||||
|
||||
//This is the var that holds the currently filtered part of the gas
|
||||
var/datum/gas_mixture/removed = source_air.remove(transfer_moles)
|
||||
if(!removed)
|
||||
return
|
||||
|
||||
//This is the gas that will be moved from source to filtered
|
||||
var/datum/gas_mixture/filtered_out = new
|
||||
|
||||
for(var/filtered_gas in removed.gases)
|
||||
//Get the name of the gas and see if it is in the list
|
||||
if(removed.gases[filtered_gas][GAS_META][META_GAS_NAME] in wanted)
|
||||
//The gas that is put in all the filtered out gases
|
||||
filtered_out.temperature = removed.temperature
|
||||
filtered_out.add_gas(filtered_gas)
|
||||
filtered_out.gases[filtered_gas][MOLES] = removed.gases[filtered_gas][MOLES]
|
||||
|
||||
//The filtered out gas is entirely removed from the currently filtered gases
|
||||
removed.gases[filtered_gas][MOLES] = 0
|
||||
removed.garbage_collect()
|
||||
|
||||
//Check if the pressure is high enough to put stuff in filtered, or else just put it back in the source
|
||||
var/datum/gas_mixture/target = (filtered_air.return_pressure() < target_pressure ? filtered_air : source_air)
|
||||
target.merge(filtered_out)
|
||||
contaminated_air.merge(removed)
|
||||
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/pump/filter/Initialize()
|
||||
air_contents = new(volume)
|
||||
. = ..()
|
||||
extended_desc = "Remember to properly spell and capitalize the filtered gas name. \
|
||||
Note that only part of the gas is moved on each transfer, \
|
||||
so multiple activations will be necessary to achieve target pressure. \
|
||||
The pressure limit for circuit pumps is [round(PUMP_MAX_PRESSURE)] kPa."
|
||||
|
||||
|
||||
// - gas mixer - // **works**
|
||||
/obj/item/integrated_circuit/atmospherics/pump/mixer
|
||||
name = "gas mixer"
|
||||
desc = "Mixes 2 different types of gases."
|
||||
complexity = 20
|
||||
size = 8
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
inputs = list(
|
||||
"first source" = IC_PINTYPE_REF,
|
||||
"second source" = IC_PINTYPE_REF,
|
||||
"output" = IC_PINTYPE_REF,
|
||||
"first source percentage" = IC_PINTYPE_NUMBER,
|
||||
"target pressure" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
power_draw_per_use = 30
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/pump/mixer/do_work()
|
||||
activate_pin(2)
|
||||
var/obj/source_1 = get_pin_data(IC_INPUT, 1)
|
||||
var/obj/source_2 = get_pin_data(IC_INPUT, 2)
|
||||
var/obj/gas_output = get_pin_data(IC_INPUT, 3)
|
||||
if(!check_gassource(source_1))
|
||||
source_1 = src
|
||||
|
||||
if(!check_gassource(source_2))
|
||||
source_2 = src
|
||||
|
||||
if(!check_gassource(gas_output))
|
||||
gas_output = src
|
||||
|
||||
if(source_1 == gas_output || source_2 == gas_output)
|
||||
return
|
||||
|
||||
var/datum/gas_mixture/source_1_gases = source_1.return_air()
|
||||
var/datum/gas_mixture/source_2_gases = source_2.return_air()
|
||||
var/datum/gas_mixture/output_gases = gas_output.return_air()
|
||||
|
||||
if(!source_1_gases || !source_2_gases || !output_gases)
|
||||
return
|
||||
|
||||
if(output_gases.return_pressure() >= PUMP_MAX_PRESSURE)
|
||||
return
|
||||
|
||||
if(source_1_gases.return_pressure() <= 0 || source_2_gases.return_pressure() <= 0)
|
||||
return
|
||||
|
||||
//This calculates how much should be sent
|
||||
var/gas_percentage = round(max(min(get_pin_data(IC_INPUT, 4),100),0) / 100)
|
||||
|
||||
//Basically: number of moles = percentage of pressure filled up * efficiency coefficient * (pressure from both gases * volume of output) / (R * Temperature)
|
||||
var/transfer_moles = (get_pin_data(IC_INPUT, 5) / max(1,output_gases.return_pressure())) * PUMP_EFFICIENCY * (source_1_gases.return_pressure() * gas_percentage + source_2_gases.return_pressure() * (1 - gas_percentage)) * output_gases.volume/ (R_IDEAL_GAS_EQUATION * max(output_gases.temperature,TCMB))
|
||||
|
||||
|
||||
if(transfer_moles <= 0)
|
||||
return
|
||||
|
||||
var/datum/gas_mixture/mix = source_1_gases.remove(transfer_moles * gas_percentage)
|
||||
output_gases.merge(mix)
|
||||
mix = source_2_gases.remove(transfer_moles * (1-gas_percentage))
|
||||
output_gases.merge(mix)
|
||||
|
||||
|
||||
// - integrated tank - // **works**
|
||||
/obj/item/integrated_circuit/atmospherics/tank
|
||||
name = "integrated tank"
|
||||
desc = "A small tank for the storage of gases."
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
size = 4
|
||||
activators = list(
|
||||
"push ref" = IC_PINTYPE_PULSE_IN
|
||||
)
|
||||
volume = 3 //emergency tank sized
|
||||
var/broken = FALSE
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/tank/Initialize()
|
||||
air_contents = new(volume)
|
||||
START_PROCESSING(SSobj, src)
|
||||
extended_desc = "Take care not to pressurize it above [round(TANK_FAILURE_PRESSURE)] kPa, or else it will break."
|
||||
. = ..()
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/tank/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
. = ..()
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/tank/do_work()
|
||||
set_pin_data(IC_OUTPUT, 1, WEAKREF(src))
|
||||
push_data()
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/tank/process()
|
||||
var/tank_pressure = air_contents.return_pressure()
|
||||
set_pin_data(IC_OUTPUT, 2, tank_pressure)
|
||||
push_data()
|
||||
|
||||
//Check if tank broken
|
||||
if(!broken && tank_pressure > TANK_FAILURE_PRESSURE)
|
||||
broken = TRUE
|
||||
to_chat(view(2),"<span class='notice'>The [name] ruptures, releasing its gases!</span>")
|
||||
if(broken)
|
||||
release()
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/tank/proc/release()
|
||||
if(air_contents.total_moles() > 0)
|
||||
playsound(loc, 'sound/effects/spray.ogg', 10, 1, -3)
|
||||
var/datum/gas_mixture/expelled_gas = air_contents.remove(air_contents.total_moles())
|
||||
var/turf/current_turf = get_turf(src)
|
||||
var/datum/gas_mixture/exterior_gas
|
||||
if(!current_turf)
|
||||
return
|
||||
|
||||
exterior_gas = current_turf.return_air()
|
||||
exterior_gas.merge(expelled_gas)
|
||||
|
||||
|
||||
// - large integrated tank - // **works**
|
||||
/obj/item/integrated_circuit/atmospherics/tank/large
|
||||
name = "large integrated tank"
|
||||
desc = "A less small tank for the storage of gases."
|
||||
volume = 9
|
||||
size = 12
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
|
||||
|
||||
// - freezer tank - // **works**
|
||||
/obj/item/integrated_circuit/atmospherics/tank/freezer
|
||||
name = "freezer tank"
|
||||
desc = "Cools the gas it contains to a preset temperature."
|
||||
volume = 6
|
||||
size = 8
|
||||
inputs = list(
|
||||
"target temperature" = IC_PINTYPE_NUMBER,
|
||||
"on" = IC_PINTYPE_BOOLEAN
|
||||
)
|
||||
inputs_default = list("1" = 300)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
var/temperature = 293.15
|
||||
var/heater_coefficient = 0.1
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/tank/freezer/on_data_written()
|
||||
temperature = max(73.15,min(293.15,get_pin_data(IC_INPUT, 1)))
|
||||
if(get_pin_data(IC_INPUT, 2))
|
||||
power_draw_idle = 30
|
||||
else
|
||||
power_draw_idle = 0
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/tank/freezer/process()
|
||||
var/tank_pressure = air_contents.return_pressure()
|
||||
set_pin_data(IC_OUTPUT, 2, tank_pressure)
|
||||
push_data()
|
||||
|
||||
//Cool the tank if the power is on and the temp is above
|
||||
if(!power_draw_idle || air_contents.temperature < temperature)
|
||||
return
|
||||
|
||||
air_contents.temperature = max(73.15,air_contents.temperature - (air_contents.temperature - temperature) * heater_coefficient)
|
||||
|
||||
|
||||
// - heater tank - // **works**
|
||||
/obj/item/integrated_circuit/atmospherics/tank/freezer/heater
|
||||
name = "heater tank"
|
||||
desc = "Heats the gas it contains to a preset temperature."
|
||||
volume = 6
|
||||
inputs = list(
|
||||
"target temperature" = IC_PINTYPE_NUMBER,
|
||||
"on" = IC_PINTYPE_BOOLEAN
|
||||
)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/tank/freezer/heater/on_data_written()
|
||||
temperature = max(293.15,min(573.15,get_pin_data(IC_INPUT, 1)))
|
||||
if(get_pin_data(IC_INPUT, 2))
|
||||
power_draw_idle = 30
|
||||
else
|
||||
power_draw_idle = 0
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/tank/freezer/heater/process()
|
||||
var/tank_pressure = air_contents.return_pressure()
|
||||
set_pin_data(IC_OUTPUT, 2, tank_pressure)
|
||||
push_data()
|
||||
|
||||
//Heat the tank if the power is on or its temperature is below what is set
|
||||
if(!power_draw_idle || air_contents.temperature > temperature)
|
||||
return
|
||||
|
||||
air_contents.temperature = min(573.15,air_contents.temperature + (temperature - air_contents.temperature) * heater_coefficient)
|
||||
|
||||
|
||||
// - atmospheric cooler - // **works**
|
||||
/obj/item/integrated_circuit/atmospherics/cooler
|
||||
name = "atmospheric cooler circuit"
|
||||
desc = "Cools the air around it."
|
||||
volume = 6
|
||||
size = 13
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
inputs = list(
|
||||
"target temperature" = IC_PINTYPE_NUMBER,
|
||||
"on" = IC_PINTYPE_BOOLEAN
|
||||
)
|
||||
var/temperature = 293.15
|
||||
var/heater_coefficient = 0.1
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/cooler/Initialize()
|
||||
air_contents = new(volume)
|
||||
START_PROCESSING(SSobj, src)
|
||||
. = ..()
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/cooler/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
. = ..()
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/cooler/on_data_written()
|
||||
temperature = max(243.15,min(293.15,get_pin_data(IC_INPUT, 1)))
|
||||
if(get_pin_data(IC_INPUT, 2))
|
||||
power_draw_idle = 30
|
||||
else
|
||||
power_draw_idle = 0
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/cooler/process()
|
||||
set_pin_data(IC_OUTPUT, 2, air_contents.return_pressure())
|
||||
push_data()
|
||||
|
||||
|
||||
//Get the turf you're on and its gas mixture
|
||||
var/turf/current_turf = get_turf(src)
|
||||
if(!current_turf)
|
||||
return
|
||||
|
||||
var/datum/gas_mixture/turf_air = current_turf.return_air()
|
||||
if(!power_draw_idle || turf_air.temperature < temperature)
|
||||
return
|
||||
|
||||
//Cool the gas
|
||||
turf_air.temperature = max(243.15,turf_air.temperature - (turf_air.temperature - temperature) * heater_coefficient)
|
||||
|
||||
|
||||
// - atmospheric heater - // **works**
|
||||
/obj/item/integrated_circuit/atmospherics/cooler/heater
|
||||
name = "atmospheric heater circuit"
|
||||
desc = "Heats the air around it."
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/cooler/heater/on_data_written()
|
||||
temperature = max(293.15,min(323.15,get_pin_data(IC_INPUT, 1)))
|
||||
if(get_pin_data(IC_INPUT, 2))
|
||||
power_draw_idle = 30
|
||||
else
|
||||
power_draw_idle = 0
|
||||
|
||||
/obj/item/integrated_circuit/atmospherics/cooler/heater/process()
|
||||
set_pin_data(IC_OUTPUT, 2, air_contents.return_pressure())
|
||||
push_data()
|
||||
|
||||
//Get the turf and its air mixture
|
||||
var/turf/current_turf = get_turf(src)
|
||||
if(!current_turf)
|
||||
return
|
||||
|
||||
var/datum/gas_mixture/turf_air = current_turf.return_air()
|
||||
if(!power_draw_idle || turf_air.temperature > temperature)
|
||||
return
|
||||
|
||||
//Heat the gas
|
||||
turf_air.temperature = min(323.15,turf_air.temperature + (temperature - turf_air.temperature) * heater_coefficient)
|
||||
|
||||
|
||||
// - tank slot - // **works**
|
||||
/obj/item/integrated_circuit/input/tank_slot
|
||||
category_text = "Atmospherics"
|
||||
cooldown_per_use = 1
|
||||
name = "tank slot"
|
||||
desc = "Lets you add a tank to your assembly and remove it even when the assembly is closed."
|
||||
extended_desc = "It can help you extract gases easier."
|
||||
complexity = 25
|
||||
size = 30
|
||||
inputs = list()
|
||||
outputs = list(
|
||||
"pressure used" = IC_PINTYPE_NUMBER,
|
||||
"current tank" = IC_PINTYPE_REF
|
||||
)
|
||||
activators = list(
|
||||
"push ref" = IC_PINTYPE_PULSE_IN,
|
||||
"on insert" = IC_PINTYPE_PULSE_OUT,
|
||||
"on remove" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
can_be_asked_input = TRUE
|
||||
demands_object_input = TRUE
|
||||
can_input_object_when_closed = TRUE
|
||||
|
||||
var/obj/item/tank/internals/current_tank
|
||||
|
||||
/obj/item/integrated_circuit/input/tank_slot/Initialize()
|
||||
START_PROCESSING(SSobj, src)
|
||||
. = ..()
|
||||
|
||||
/obj/item/integrated_circuit/input/tank_slot/process()
|
||||
push_pressure()
|
||||
|
||||
/obj/item/integrated_circuit/input/tank_slot/attackby(var/obj/item/tank/internals/I, var/mob/living/user)
|
||||
//Check if it truly is a tank
|
||||
if(!istype(I,/obj/item/tank/internals))
|
||||
to_chat(user,"<span class='warning'>The [I.name] doesn't seem to fit in here.</span>")
|
||||
return
|
||||
|
||||
//Check if there is no other tank already inside
|
||||
if(current_tank)
|
||||
to_chat(user,"<span class='warning'>There is already a gas tank inside.</span>")
|
||||
return
|
||||
|
||||
//The current tank is the one we just attached, its location is inside the circuit
|
||||
current_tank = I
|
||||
user.transferItemToLoc(I,src)
|
||||
to_chat(user,"<span class='warning'>You put the [I.name] inside the tank slot.</span>")
|
||||
|
||||
//Set the pin to a weak reference of the current tank
|
||||
push_pressure()
|
||||
set_pin_data(IC_OUTPUT, 2, WEAKREF(current_tank))
|
||||
push_data()
|
||||
do_work(1)
|
||||
|
||||
|
||||
/obj/item/integrated_circuit/input/tank_slot/ask_for_input(mob/user)
|
||||
attack_self(user)
|
||||
|
||||
/obj/item/integrated_circuit/input/tank_slot/attack_self(mob/user)
|
||||
//Check if no tank attached
|
||||
if(!current_tank)
|
||||
to_chat(user, "<span class='notice'>There is currently no tank attached.</span>")
|
||||
return
|
||||
|
||||
//Remove tank and put in user's hands/location
|
||||
to_chat(user, "<span class='notice'>You take [current_tank] out of the tank slot.</span>")
|
||||
user.put_in_hands(current_tank)
|
||||
current_tank = null
|
||||
|
||||
//Remove tank reference
|
||||
push_pressure()
|
||||
set_pin_data(IC_OUTPUT, 2, null)
|
||||
push_data()
|
||||
do_work(2)
|
||||
|
||||
/obj/item/integrated_circuit/input/tank_slot/do_work()
|
||||
set_pin_data(IC_OUTPUT, 2, WEAKREF(current_tank))
|
||||
push_data()
|
||||
|
||||
/obj/item/integrated_circuit/input/tank_slot/proc/push_pressure()
|
||||
if(!current_tank)
|
||||
set_pin_data(IC_OUTPUT, 1, 0)
|
||||
return
|
||||
|
||||
var/datum/gas_mixture/tank_air = current_tank.return_air()
|
||||
if(!tank_air)
|
||||
set_pin_data(IC_OUTPUT, 1, 0)
|
||||
return
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, tank_air.return_pressure())
|
||||
push_data()
|
||||
|
||||
|
||||
#undef SOURCE_TO_TARGET
|
||||
#undef TARGET_TO_SOURCE
|
||||
#undef PUMP_EFFICIENCY
|
||||
#undef TANK_FAILURE_PRESSURE
|
||||
#undef PUMP_MAX_PRESSURE
|
||||
#undef PUMP_MAX_VOLUME
|
||||
@@ -1218,4 +1218,95 @@
|
||||
activate_pin(2)
|
||||
else
|
||||
return FALSE
|
||||
return TRUE
|
||||
return TRUE
|
||||
|
||||
|
||||
//Hippie Ported Code--------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//Adding some color to cards aswell, because why not
|
||||
/obj/item/card/data/attackby(obj/item/I, mob/living/user)
|
||||
if(istype(I, /obj/item/integrated_electronics/detailer))
|
||||
var/obj/item/integrated_electronics/detailer/D = I
|
||||
detail_color = D.detail_color
|
||||
update_icon()
|
||||
return ..()
|
||||
|
||||
|
||||
|
||||
// -Inputlist- //
|
||||
/obj/item/integrated_circuit/input/selection
|
||||
name = "selection circuit"
|
||||
desc = "This circuit lets you choose between different strings from a selection."
|
||||
extended_desc = "This circuit lets you choose between up to 4 different values from selection of up to 8 strings that you can set. Null values are ignored and the chosen value is put out in selected."
|
||||
icon_state = "addition"
|
||||
can_be_asked_input = 1
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
inputs = list(
|
||||
"A" = IC_PINTYPE_STRING,
|
||||
"B" = IC_PINTYPE_STRING,
|
||||
"C" = IC_PINTYPE_STRING,
|
||||
"D" = IC_PINTYPE_STRING,
|
||||
"E" = IC_PINTYPE_STRING,
|
||||
"F" = IC_PINTYPE_STRING,
|
||||
"G" = IC_PINTYPE_STRING,
|
||||
"H" = IC_PINTYPE_STRING
|
||||
)
|
||||
activators = list(
|
||||
"on selected" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
outputs = list(
|
||||
"selected" = IC_PINTYPE_STRING
|
||||
)
|
||||
|
||||
/obj/item/integrated_circuit/input/selection/ask_for_input(mob/user)
|
||||
var/list/selection = list()
|
||||
for(var/k in 1 to inputs.len)
|
||||
var/I = get_pin_data(IC_INPUT, k)
|
||||
if(istext(I))
|
||||
selection.Add(I)
|
||||
var/selected = input(user,"Choose input.","Selection") in selection
|
||||
if(!selected)
|
||||
return
|
||||
set_pin_data(IC_OUTPUT, 1, selected)
|
||||
push_data()
|
||||
activate_pin(1)
|
||||
|
||||
|
||||
// -storage examiner- // **works**
|
||||
/obj/item/integrated_circuit/input/storage_examiner
|
||||
name = "storage examiner circuit"
|
||||
desc = "This circuit lets you scan a storage's content. (backpacks, toolboxes etc.)"
|
||||
extended_desc = "The items are put out as reference, which makes it possible to interact with them. Additionally also gives the amount of items."
|
||||
icon_state = "grabber"
|
||||
can_be_asked_input = 1
|
||||
complexity = 6
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
inputs = list(
|
||||
"storage" = IC_PINTYPE_REF
|
||||
)
|
||||
activators = list(
|
||||
"examine" = IC_PINTYPE_PULSE_IN,
|
||||
"on examined" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
outputs = list(
|
||||
"item amount" = IC_PINTYPE_NUMBER,
|
||||
"item list" = IC_PINTYPE_LIST
|
||||
)
|
||||
power_draw_per_use = 85
|
||||
|
||||
/obj/item/integrated_circuit/input/storage_examiner/do_work()
|
||||
var/obj/item/storage = get_pin_data_as_type(IC_INPUT, 1, /obj/item)
|
||||
if(!istype(storage,/obj/item/storage))
|
||||
return
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, storage.contents.len)
|
||||
|
||||
var/list/regurgitated_contents = list()
|
||||
for(var/obj/o in storage.contents)
|
||||
regurgitated_contents.Add(WEAKREF(o))
|
||||
|
||||
|
||||
set_pin_data(IC_OUTPUT, 2, regurgitated_contents)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
@@ -677,3 +677,140 @@
|
||||
GET_COMPONENT(materials, /datum/component/material_container)
|
||||
materials.retrieve_all()
|
||||
.=..()
|
||||
|
||||
|
||||
//Hippie Ported Code--------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// - inserter circuit - //
|
||||
/obj/item/integrated_circuit/manipulation/inserter
|
||||
name = "inserter"
|
||||
desc = "A nimble circuit that puts stuff inside a storage like a backpack and can take it out aswell."
|
||||
icon_state = "grabber"
|
||||
extended_desc = "This circuit accepts a reference to an object to be inserted or extracted depending on mode. If a storage is given for extraction, the extracted item will be put in the new storage. Modes: 1 insert, 0 to extract."
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
size = 3
|
||||
cooldown_per_use = 5
|
||||
complexity = 10
|
||||
inputs = list("target object" = IC_PINTYPE_REF, "target container" = IC_PINTYPE_REF,"mode" = IC_PINTYPE_NUMBER)
|
||||
activators = list("pulse in" = IC_PINTYPE_PULSE_IN,"pulse out" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
action_flags = IC_ACTION_COMBAT
|
||||
power_draw_per_use = 20
|
||||
var/max_items = 10
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/inserter/do_work()
|
||||
//There shouldn't be any target required to eject all contents
|
||||
var/obj/item/target_obj = get_pin_data_as_type(IC_INPUT, 1, /obj/item)
|
||||
if(!target_obj)
|
||||
return
|
||||
|
||||
var/distance = get_dist(get_turf(src),get_turf(target_obj))
|
||||
if(distance > 1 || distance < 0)
|
||||
return
|
||||
|
||||
var/obj/item/storage/container = get_pin_data_as_type(IC_INPUT, 2, /obj/item)
|
||||
var/mode = get_pin_data(IC_INPUT, 3)
|
||||
switch(mode)
|
||||
if(1) //Not working
|
||||
if(!container || !istype(container,/obj/item/storage) || !Adjacent(container))
|
||||
return
|
||||
|
||||
GET_COMPONENT_FROM(STR, /datum/component/storage, container)
|
||||
if(!STR)
|
||||
return
|
||||
|
||||
STR.attackby(src, target_obj)
|
||||
|
||||
else
|
||||
GET_COMPONENT_FROM(STR, /datum/component/storage, target_obj.loc)
|
||||
if(!STR)
|
||||
return
|
||||
|
||||
if(!container || !istype(container,/obj/item/storage) || !Adjacent(container))
|
||||
STR.remove_from_storage(target_obj,drop_location())
|
||||
else
|
||||
STR.remove_from_storage(target_obj,container)
|
||||
|
||||
// Renamer circuit. Renames the assembly it is in. Useful in cooperation with telecomms-based circuits.
|
||||
/obj/item/integrated_circuit/manipulation/renamer
|
||||
name = "renamer"
|
||||
desc = "A small circuit that renames the assembly it is in. Useful paired with speech-based circuits."
|
||||
icon_state = "internalbm"
|
||||
extended_desc = "This circuit accepts a string as input, and can be pulsed to rewrite the current assembly's name with said string. On success, it pulses the default pulse-out wire."
|
||||
inputs = list("name" = IC_PINTYPE_STRING)
|
||||
outputs = list("current name" = IC_PINTYPE_STRING)
|
||||
activators = list("rename" = IC_PINTYPE_PULSE_IN,"get name" = IC_PINTYPE_PULSE_IN,"pulse out" = IC_PINTYPE_PULSE_OUT)
|
||||
power_draw_per_use = 1
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/renamer/do_work(var/n)
|
||||
if(!assembly)
|
||||
return
|
||||
switch(n)
|
||||
if(1)
|
||||
var/new_name = get_pin_data(IC_INPUT, 1)
|
||||
if(new_name)
|
||||
assembly.name = new_name
|
||||
|
||||
else
|
||||
set_pin_data(IC_OUTPUT, 1, assembly.name)
|
||||
push_data()
|
||||
|
||||
activate_pin(3)
|
||||
|
||||
|
||||
|
||||
// - redescribing circuit - //
|
||||
/obj/item/integrated_circuit/manipulation/redescribe
|
||||
name = "redescriber"
|
||||
desc = "Takes any string as an input and will set it as the assembly's description."
|
||||
extended_desc = "Strings should can be of any length."
|
||||
icon_state = "speaker"
|
||||
cooldown_per_use = 10
|
||||
complexity = 3
|
||||
inputs = list("text" = IC_PINTYPE_STRING)
|
||||
outputs = list("description" = IC_PINTYPE_STRING)
|
||||
activators = list("redescribe" = IC_PINTYPE_PULSE_IN,"get description" = IC_PINTYPE_PULSE_IN,"pulse out" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/redescribe/do_work(var/n)
|
||||
if(!assembly)
|
||||
return
|
||||
|
||||
switch(n)
|
||||
if(1)
|
||||
assembly.desc = get_pin_data(IC_INPUT, 1)
|
||||
|
||||
else
|
||||
set_pin_data(IC_OUTPUT, 1, assembly.desc)
|
||||
push_data()
|
||||
|
||||
activate_pin(3)
|
||||
|
||||
// - repainting circuit - //
|
||||
/obj/item/integrated_circuit/manipulation/repaint
|
||||
name = "auto-repainter"
|
||||
desc = "There's an oddly high amount of spraying cans fitted right inside this circuit."
|
||||
extended_desc = "Takes a value in hexadecimal and uses it to repaint the assembly it is in."
|
||||
cooldown_per_use = 10
|
||||
complexity = 3
|
||||
inputs = list("color" = IC_PINTYPE_COLOR)
|
||||
outputs = list("current color" = IC_PINTYPE_COLOR)
|
||||
activators = list("repaint" = IC_PINTYPE_PULSE_IN,"get color" = IC_PINTYPE_PULSE_IN,"pulse out" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/repaint/do_work(var/n)
|
||||
if(!assembly)
|
||||
return
|
||||
|
||||
switch(n)
|
||||
if(1)
|
||||
assembly.detail_color = get_pin_data(IC_INPUT, 1)
|
||||
assembly.update_icon()
|
||||
|
||||
else
|
||||
set_pin_data(IC_OUTPUT, 1, assembly.detail_color)
|
||||
push_data()
|
||||
|
||||
activate_pin(3)
|
||||
@@ -385,4 +385,30 @@
|
||||
else
|
||||
assembly.prefered_hud_icon = "hudstat"
|
||||
//update the diagnostic hud
|
||||
assembly.diag_hud_set_circuitstat()
|
||||
assembly.diag_hud_set_circuitstat()
|
||||
|
||||
|
||||
//Hippie Ported Code--------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
/obj/item/radio/headset/integrated
|
||||
|
||||
/obj/item/integrated_circuit/output/screen/large
|
||||
name = "medium screen"
|
||||
|
||||
/obj/item/integrated_circuit/output/screen/extralarge // the subtype is called "extralarge" because tg brought back medium screens and they named the subtype /screen/large
|
||||
name = "large screen"
|
||||
desc = "Takes any data type as an input and displays it to the user upon examining, and to all nearby beings when pulsed."
|
||||
icon_state = "screen_large"
|
||||
power_draw_per_use = 40
|
||||
cooldown_per_use = 10
|
||||
|
||||
/obj/item/integrated_circuit/output/screen/extralarge/do_work()
|
||||
..()
|
||||
var/obj/O = assembly ? get_turf(assembly) : loc
|
||||
O.visible_message("<span class='notice'>[icon2html(O.icon, world, O.icon_state)] [stuff_to_display]</span>")
|
||||
if(assembly)
|
||||
assembly.investigate_log("displayed \"[html_encode(stuff_to_display)]\" with [type].", INVESTIGATE_CIRCUIT)
|
||||
else
|
||||
investigate_log("displayed \"[html_encode(stuff_to_display)]\" as [type].", INVESTIGATE_CIRCUIT)
|
||||
@@ -538,3 +538,250 @@
|
||||
reagents.handle_reactions()
|
||||
set_pin_data(IC_OUTPUT, 3, reagents.chem_temp)
|
||||
push_data()
|
||||
|
||||
|
||||
//Hippie Ported Code--------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/obj/item/integrated_circuit/reagent/smoke
|
||||
name = "smoke generator"
|
||||
desc = "Unlike most electronics, creating smoke is completely intentional."
|
||||
icon_state = "smoke"
|
||||
extended_desc = "This smoke generator creates clouds of smoke on command. It can also hold liquids inside, which will go \
|
||||
into the smoke clouds when activated. The reagents are consumed when the smoke is made."
|
||||
ext_cooldown = 1
|
||||
volume = 100
|
||||
complexity = 20
|
||||
cooldown_per_use = 1 SECONDS
|
||||
inputs = list()
|
||||
outputs = list(
|
||||
"volume used" = IC_PINTYPE_NUMBER,
|
||||
"self reference" = IC_PINTYPE_SELFREF
|
||||
)
|
||||
activators = list(
|
||||
"create smoke" = IC_PINTYPE_PULSE_IN,
|
||||
"on smoked" = IC_PINTYPE_PULSE_OUT,
|
||||
"push ref" = IC_PINTYPE_PULSE_IN
|
||||
)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 20
|
||||
var/smoke_radius = 5
|
||||
var/notified = FALSE
|
||||
|
||||
/obj/item/integrated_circuit/reagent/smoke/on_reagent_change(changetype)
|
||||
//reset warning only if we have reagents now
|
||||
if(changetype == ADD_REAGENT)
|
||||
notified = FALSE
|
||||
push_vol()
|
||||
/obj/item/integrated_circuit/reagent/smoke/do_work(ord)
|
||||
switch(ord)
|
||||
if(1)
|
||||
if(!reagents || (reagents.total_volume < IC_SMOKE_REAGENTS_MINIMUM_UNITS))
|
||||
return
|
||||
var/location = get_turf(src)
|
||||
var/datum/effect_system/smoke_spread/chem/S = new
|
||||
S.attach(location)
|
||||
playsound(location, 'sound/effects/smoke.ogg', 50, 1, -3)
|
||||
if(S)
|
||||
S.set_up(reagents, smoke_radius, location, notified)
|
||||
if(!notified)
|
||||
notified = TRUE
|
||||
S.start()
|
||||
reagents.clear_reagents()
|
||||
activate_pin(2)
|
||||
if(3)
|
||||
set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
|
||||
push_data()
|
||||
|
||||
// - Integrated extinguisher - //
|
||||
/obj/item/integrated_circuit/reagent/extinguisher
|
||||
name = "integrated extinguisher"
|
||||
desc = "This circuit sprays any of its contents out like an extinguisher."
|
||||
icon_state = "injector"
|
||||
extended_desc = "This circuit can hold up to 30 units of any given chemicals. On each use, it sprays these reagents like a fire extinguisher."
|
||||
|
||||
volume = 30
|
||||
|
||||
complexity = 20
|
||||
cooldown_per_use = 6 SECONDS
|
||||
inputs = list(
|
||||
"target X rel" = IC_PINTYPE_NUMBER,
|
||||
"target Y rel" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
outputs = list(
|
||||
"volume" = IC_PINTYPE_NUMBER,
|
||||
"self reference" = IC_PINTYPE_SELFREF
|
||||
)
|
||||
activators = list(
|
||||
"spray" = IC_PINTYPE_PULSE_IN,
|
||||
"on sprayed" = IC_PINTYPE_PULSE_OUT,
|
||||
"on fail" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 15
|
||||
var/busy = FALSE
|
||||
|
||||
/obj/item/integrated_circuit/reagent/extinguisher/Initialize()
|
||||
.=..()
|
||||
set_pin_data(IC_OUTPUT,2, src)
|
||||
|
||||
/obj/item/integrated_circuit/reagent/extinguisher/on_reagent_change(changetype)
|
||||
push_vol()
|
||||
|
||||
/obj/item/integrated_circuit/reagent/extinguisher/do_work()
|
||||
//Check if enough volume
|
||||
set_pin_data(IC_OUTPUT, 1, reagents.total_volume)
|
||||
if(!reagents || reagents.total_volume < 5 || busy)
|
||||
push_data()
|
||||
activate_pin(3)
|
||||
return
|
||||
|
||||
playsound(loc, 'sound/effects/extinguish.ogg', 75, 1, -3)
|
||||
//Get the tile on which the water particle spawns
|
||||
var/turf/Spawnpoint = get_turf(src)
|
||||
if(!Spawnpoint)
|
||||
push_data()
|
||||
activate_pin(3)
|
||||
return
|
||||
|
||||
//Get direction and target turf for each water particle
|
||||
var/turf/T = locate(Spawnpoint.x + get_pin_data(IC_INPUT, 1),Spawnpoint.y + get_pin_data(IC_INPUT, 2),Spawnpoint.z)
|
||||
if(!T)
|
||||
push_data()
|
||||
activate_pin(3)
|
||||
return
|
||||
var/direction = get_dir(Spawnpoint, T)
|
||||
var/turf/T1 = get_step(T,turn(direction, 90))
|
||||
var/turf/T2 = get_step(T,turn(direction, -90))
|
||||
var/list/the_targets = list(T,T1,T2)
|
||||
busy = TRUE
|
||||
|
||||
// Create list with particles and their targets
|
||||
var/list/water_particles=list()
|
||||
for(var/a=0, a<5, a++)
|
||||
var/obj/effect/particle_effect/water/W = new /obj/effect/particle_effect/water(get_turf(src))
|
||||
water_particles[W] = pick(the_targets)
|
||||
var/datum/reagents/R = new/datum/reagents(5)
|
||||
W.reagents = R
|
||||
R.my_atom = W
|
||||
reagents.trans_to(W,1)
|
||||
|
||||
//Make em move dat ass, hun
|
||||
addtimer(CALLBACK(src, /obj/item/integrated_circuit/reagent/extinguisher/proc/move_particles, water_particles), 2)
|
||||
|
||||
//This whole proc is a loop
|
||||
/obj/item/integrated_circuit/reagent/extinguisher/proc/move_particles(var/list/particles, var/repetitions=0)
|
||||
//Check if there's anything in here first
|
||||
if(!particles || particles.len == 0)
|
||||
return
|
||||
// Second loop: Get all the water particles and make them move to their target
|
||||
for(var/obj/effect/particle_effect/water/W in particles)
|
||||
var/turf/my_target = particles[W]
|
||||
if(!W)
|
||||
continue
|
||||
step_towards(W,my_target)
|
||||
if(!W.reagents)
|
||||
continue
|
||||
W.reagents.reaction(get_turf(W))
|
||||
for(var/A in get_turf(W))
|
||||
W.reagents.reaction(A)
|
||||
if(W.loc == my_target)
|
||||
break
|
||||
if(repetitions < 4)
|
||||
repetitions++ //Can't have math operations in addtimer(CALLBACK())
|
||||
addtimer(CALLBACK(src, /obj/item/integrated_circuit/reagent/extinguisher/proc/move_particles, particles, repetitions), 2)
|
||||
else
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
busy = FALSE
|
||||
|
||||
// - Beaker Connector - //
|
||||
/obj/item/integrated_circuit/input/beaker_connector
|
||||
category_text = "Reagent"
|
||||
cooldown_per_use = 1
|
||||
name = "beaker slot"
|
||||
desc = "Lets you add a beaker to your assembly and remove it even when the assembly is closed."
|
||||
icon_state = "reagent_storage"
|
||||
extended_desc = "It can help you extract reagents easier."
|
||||
complexity = 4
|
||||
|
||||
inputs = list()
|
||||
outputs = list(
|
||||
"volume used" = IC_PINTYPE_NUMBER,
|
||||
"current beaker" = IC_PINTYPE_REF
|
||||
)
|
||||
activators = list(
|
||||
"on insert" = IC_PINTYPE_PULSE_OUT,
|
||||
"on remove" = IC_PINTYPE_PULSE_OUT,
|
||||
"push ref" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
can_be_asked_input = TRUE
|
||||
demands_object_input = TRUE
|
||||
can_input_object_when_closed = TRUE
|
||||
|
||||
var/obj/item/reagent_containers/glass/beaker/current_beaker
|
||||
|
||||
|
||||
/obj/item/integrated_circuit/input/beaker_connector/attackby(var/obj/item/reagent_containers/I, var/mob/living/user)
|
||||
//Check if it truly is a reagent container
|
||||
if(!istype(I,/obj/item/reagent_containers/glass/beaker))
|
||||
to_chat(user,"<span class='warning'>The [I.name] doesn't seem to fit in here.</span>")
|
||||
return
|
||||
|
||||
//Check if there is no other beaker already inside
|
||||
if(current_beaker)
|
||||
to_chat(user,"<span class='notice'>There is already a reagent container inside.</span>")
|
||||
return
|
||||
|
||||
//The current beaker is the one we just attached, its location is inside the circuit
|
||||
current_beaker = I
|
||||
user.transferItemToLoc(I,src)
|
||||
|
||||
to_chat(user,"<span class='warning'>You put the [I.name] inside the beaker connector.</span>")
|
||||
|
||||
//Set the pin to a weak reference of the current beaker
|
||||
push_vol()
|
||||
set_pin_data(IC_OUTPUT, 2, WEAKREF(current_beaker))
|
||||
push_data()
|
||||
activate_pin(1)
|
||||
activate_pin(3)
|
||||
|
||||
|
||||
/obj/item/integrated_circuit/input/beaker_connector/ask_for_input(mob/user)
|
||||
attack_self(user)
|
||||
|
||||
|
||||
/obj/item/integrated_circuit/input/beaker_connector/attack_self(mob/user)
|
||||
//Check if no beaker attached
|
||||
if(!current_beaker)
|
||||
to_chat(user, "<span class='notice'>There is currently no beaker attached.</span>")
|
||||
return
|
||||
|
||||
//Remove beaker and put in user's hands/location
|
||||
to_chat(user, "<span class='notice'>You take [current_beaker] out of the beaker connector.</span>")
|
||||
user.put_in_hands(current_beaker)
|
||||
current_beaker = null
|
||||
//Remove beaker reference
|
||||
push_vol()
|
||||
set_pin_data(IC_OUTPUT, 2, null)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
activate_pin(3)
|
||||
|
||||
|
||||
/obj/item/integrated_circuit/input/beaker_connector/proc/push_vol()
|
||||
var/beakerVolume = 0
|
||||
if(current_beaker)
|
||||
beakerVolume = current_beaker.reagents.total_volume
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, beakerVolume)
|
||||
push_data()
|
||||
|
||||
|
||||
/obj/item/reagent_containers/glass/beaker/on_reagent_change()
|
||||
..()
|
||||
if(istype(loc,/obj/item/integrated_circuit/input/beaker_connector))
|
||||
var/obj/item/integrated_circuit/input/beaker_connector/current_circuit = loc
|
||||
current_circuit.push_vol()
|
||||
@@ -114,3 +114,262 @@
|
||||
set_pin_data(IC_OUTPUT, 2, Yn)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
|
||||
//Hippie Ported Code--------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
// - MMI Tank - //
|
||||
/obj/item/integrated_circuit/input/mmi_tank
|
||||
name = "man-machine interface tank"
|
||||
desc = "This circuit is just a jar filled with an artificial liquid mimicking the cerebrospinal fluid."
|
||||
extended_desc = "This jar can hold 1 man-machine interface and let it take control of some basic functions of the assembly."
|
||||
complexity = 29
|
||||
inputs = list("laws" = IC_PINTYPE_LIST)
|
||||
outputs = list(
|
||||
"man-machine interface" = IC_PINTYPE_REF,
|
||||
"direction" = IC_PINTYPE_DIR,
|
||||
"click target" = IC_PINTYPE_REF
|
||||
)
|
||||
activators = list(
|
||||
"move" = IC_PINTYPE_PULSE_OUT,
|
||||
"left" = IC_PINTYPE_PULSE_OUT,
|
||||
"right" = IC_PINTYPE_PULSE_OUT,
|
||||
"up" = IC_PINTYPE_PULSE_OUT,
|
||||
"down" = IC_PINTYPE_PULSE_OUT,
|
||||
"leftclick" = IC_PINTYPE_PULSE_OUT,
|
||||
"shiftclick" = IC_PINTYPE_PULSE_OUT,
|
||||
"altclick" = IC_PINTYPE_PULSE_OUT,
|
||||
"ctrlclick" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 150
|
||||
can_be_asked_input = TRUE
|
||||
demands_object_input = TRUE
|
||||
|
||||
var/obj/item/mmi/installed_brain
|
||||
|
||||
/obj/item/integrated_circuit/input/mmi_tank/attackby(var/obj/item/mmi/O, var/mob/user)
|
||||
if(!istype(O,/obj/item/mmi))
|
||||
to_chat(user,"<span class='warning'>You can't put that inside.</span>")
|
||||
return
|
||||
if(installed_brain)
|
||||
to_chat(user,"<span class='warning'>There's already a brain inside.</span>")
|
||||
return
|
||||
user.transferItemToLoc(O,src)
|
||||
installed_brain = O
|
||||
can_be_asked_input = FALSE
|
||||
to_chat(user, "<span class='notice'>You gently place \the man-machine interface inside the tank.</span>")
|
||||
to_chat(O, "<span class='notice'>You are slowly being placed inside the man-machine-interface tank.</span>")
|
||||
O.brainmob.remote_control=src
|
||||
set_pin_data(IC_OUTPUT, 1, O)
|
||||
|
||||
/obj/item/integrated_circuit/input/mmi_tank/attack_self(var/mob/user)
|
||||
if(installed_brain)
|
||||
RemoveBrain()
|
||||
to_chat(user, "<span class='notice'>You slowly lift [installed_brain] out of the MMI tank.</span>")
|
||||
playsound(src, 'sound/items/Crowbar.ogg', 50, 1)
|
||||
installed_brain = null
|
||||
push_data()
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You don't see any brain swimming in the tank.</span>")
|
||||
|
||||
/obj/item/integrated_circuit/input/mmi_tank/Destroy()
|
||||
RemoveBrain()
|
||||
..()
|
||||
|
||||
/obj/item/integrated_circuit/input/mmi_tank/relaymove(var/n,var/dir)
|
||||
set_pin_data(IC_OUTPUT, 2, dir)
|
||||
do_work(1)
|
||||
switch(dir)
|
||||
if(8) activate_pin(2)
|
||||
if(4) activate_pin(3)
|
||||
if(1) activate_pin(4)
|
||||
if(2) activate_pin(5)
|
||||
|
||||
/obj/item/integrated_circuit/input/mmi_tank/do_work(var/n)
|
||||
push_data()
|
||||
activate_pin(n)
|
||||
|
||||
/obj/item/integrated_circuit/input/mmi_tank/proc/RemoveBrain()
|
||||
if(installed_brain)
|
||||
can_be_asked_input = TRUE
|
||||
installed_brain.forceMove(drop_location())
|
||||
set_pin_data(IC_OUTPUT, 1, WEAKREF(null))
|
||||
if(installed_brain.brainmob)
|
||||
installed_brain.brainmob.remote_control = null
|
||||
..()
|
||||
|
||||
|
||||
//Brain changes
|
||||
/mob/living/brain/var/check_bot_self = FALSE
|
||||
|
||||
/mob/living/brain/ClickOn(atom/A, params)
|
||||
..()
|
||||
if(!istype(remote_control,/obj/item/integrated_circuit/input/mmi_tank))
|
||||
return
|
||||
var/obj/item/integrated_circuit/input/mmi_tank/brainholder=remote_control
|
||||
brainholder.set_pin_data(IC_OUTPUT, 3, A)
|
||||
var/list/modifiers = params2list(params)
|
||||
|
||||
if(modifiers["shift"])
|
||||
brainholder.do_work(7)
|
||||
return
|
||||
if(modifiers["alt"])
|
||||
brainholder.do_work(8)
|
||||
return
|
||||
if(modifiers["ctrl"])
|
||||
brainholder.do_work(9)
|
||||
return
|
||||
|
||||
if(istype(A,/obj/item/electronic_assembly))
|
||||
var/obj/item/electronic_assembly/CheckedAssembly = A
|
||||
|
||||
if(brainholder in CheckedAssembly.assembly_components)
|
||||
var/obj/item/electronic_assembly/holdingassembly=A
|
||||
check_bot_self=TRUE
|
||||
|
||||
if(holdingassembly.opened)
|
||||
holdingassembly.ui_interact(src)
|
||||
holdingassembly.attack_self(src)
|
||||
check_bot_self=FALSE
|
||||
return
|
||||
|
||||
brainholder.do_work(6)
|
||||
|
||||
/mob/living/brain/canUseTopic()
|
||||
return check_bot_self
|
||||
|
||||
/obj/item/integrated_circuit/smart/advanced_pathfinder/proc/hippie_xor_decrypt()
|
||||
var/Ps = get_pin_data(IC_INPUT, 4)
|
||||
if(!Ps)
|
||||
return
|
||||
var/list/Pl = json_decode(XorEncrypt(hextostr(Ps, TRUE), SScircuit.cipherkey))
|
||||
if(Pl&&islist(Pl))
|
||||
idc.access = Pl
|
||||
|
||||
// - pAI connector circuit - //
|
||||
/obj/item/integrated_circuit/input/pAI_connector
|
||||
name = "pAI connector circuit"
|
||||
desc = "This circuit lets you fit in a personal artificial intelligence to give it some form of control over the bot."
|
||||
extended_desc = "You can wire various functions to it."
|
||||
complexity = 29
|
||||
inputs = list("laws" = IC_PINTYPE_LIST)
|
||||
outputs = list(
|
||||
"personal artificial intelligence" = IC_PINTYPE_REF,
|
||||
"direction" = IC_PINTYPE_DIR,
|
||||
"click target" = IC_PINTYPE_REF
|
||||
)
|
||||
activators = list(
|
||||
"move" = IC_PINTYPE_PULSE_OUT,
|
||||
"left" = IC_PINTYPE_PULSE_OUT,
|
||||
"right" = IC_PINTYPE_PULSE_OUT,
|
||||
"up" = IC_PINTYPE_PULSE_OUT,
|
||||
"down" = IC_PINTYPE_PULSE_OUT,
|
||||
"leftclick" = IC_PINTYPE_PULSE_OUT,
|
||||
"shiftclick" = IC_PINTYPE_PULSE_OUT,
|
||||
"altclick" = IC_PINTYPE_PULSE_OUT,
|
||||
"ctrlclick" = IC_PINTYPE_PULSE_OUT,
|
||||
"shiftctrlclick" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 150
|
||||
can_be_asked_input = TRUE
|
||||
demands_object_input = TRUE
|
||||
|
||||
var/obj/item/paicard/installed_pai
|
||||
|
||||
/obj/item/integrated_circuit/input/pAI_connector/attackby(var/obj/item/paicard/O, var/mob/user)
|
||||
if(!istype(O,/obj/item/paicard))
|
||||
to_chat(user,"<span class='warning'>You can't put that inside.</span>")
|
||||
return
|
||||
if(installed_pai)
|
||||
to_chat(user,"<span class='warning'>There's already a pAI connected to this.</span>")
|
||||
return
|
||||
user.transferItemToLoc(O,src)
|
||||
installed_pai = O
|
||||
can_be_asked_input = FALSE
|
||||
to_chat(user, "<span class='notice'>You slowly connect the circuit's pins to the [installed_pai].</span>")
|
||||
to_chat(O, "<span class='notice'>You are slowly being connected to the pAI connector.</span>")
|
||||
O.pai.remote_control=src
|
||||
set_pin_data(IC_OUTPUT, 1, O)
|
||||
|
||||
/obj/item/integrated_circuit/input/pAI_connector/attack_self(var/mob/user)
|
||||
if(installed_pai)
|
||||
RemovepAI()
|
||||
to_chat(user, "<span class='notice'>You slowly disconnect the circuit's pins from the [installed_pai].</span>")
|
||||
playsound(src, 'sound/items/Crowbar.ogg', 50, 1)
|
||||
installed_pai = null
|
||||
push_data()
|
||||
else
|
||||
to_chat(user, "<span class='notice'>The connection port is empty.</span>")
|
||||
|
||||
/obj/item/integrated_circuit/input/pAI_connector/relaymove(var/n,var/dir)
|
||||
set_pin_data(IC_OUTPUT, 2, dir)
|
||||
do_work(1)
|
||||
switch(dir)
|
||||
if(8) activate_pin(2)
|
||||
if(4) activate_pin(3)
|
||||
if(1) activate_pin(4)
|
||||
if(2) activate_pin(5)
|
||||
|
||||
/obj/item/integrated_circuit/input/pAI_connector/do_work(var/n)
|
||||
push_data()
|
||||
activate_pin(n)
|
||||
|
||||
|
||||
/obj/item/integrated_circuit/input/pAI_connector/Destroy()
|
||||
RemovepAI()
|
||||
..()
|
||||
|
||||
/obj/item/integrated_circuit/input/pAI_connector/proc/RemovepAI()
|
||||
if(installed_pai)
|
||||
can_be_asked_input = TRUE
|
||||
installed_pai.forceMove(drop_location())
|
||||
set_pin_data(IC_OUTPUT, 1, WEAKREF(null))
|
||||
installed_pai.pai.remote_control = null
|
||||
..()
|
||||
|
||||
|
||||
//pAI changes
|
||||
/mob/living/silicon/pai/var/check_bot_self = FALSE
|
||||
|
||||
/mob/living/silicon/pai/ClickOn(atom/A, params)
|
||||
..()
|
||||
if(!istype(remote_control,/obj/item/integrated_circuit/input/pAI_connector))
|
||||
return
|
||||
var/obj/item/integrated_circuit/input/pAI_connector/paiholder=remote_control
|
||||
paiholder.set_pin_data(IC_OUTPUT, 3, A)
|
||||
var/list/modifiers = params2list(params)
|
||||
|
||||
if(modifiers["shift"] && modifiers["ctrl"])
|
||||
paiholder.do_work(10)
|
||||
return
|
||||
if(modifiers["shift"])
|
||||
paiholder.do_work(7)
|
||||
return
|
||||
if(modifiers["alt"])
|
||||
paiholder.do_work(8)
|
||||
return
|
||||
if(modifiers["ctrl"])
|
||||
paiholder.do_work(9)
|
||||
return
|
||||
|
||||
if(istype(A,/obj/item/electronic_assembly))
|
||||
var/obj/item/electronic_assembly/CheckedAssembly = A
|
||||
|
||||
if(paiholder in CheckedAssembly.assembly_components)
|
||||
var/obj/item/electronic_assembly/holdingassembly=A
|
||||
check_bot_self=TRUE
|
||||
|
||||
if(holdingassembly.opened)
|
||||
holdingassembly.ui_interact(src)
|
||||
holdingassembly.attack_self(src)
|
||||
check_bot_self=FALSE
|
||||
return
|
||||
|
||||
paiholder.do_work(6)
|
||||
|
||||
/mob/living/silicon/pai/canUseTopic()
|
||||
return check_bot_self
|
||||
@@ -175,7 +175,7 @@
|
||||
desc = "Tells you what the time is, in terms and adjusted for your local station or planet"
|
||||
|
||||
/obj/item/integrated_circuit/time/clock/station/get_time()
|
||||
return station_time()
|
||||
return STATION_TIME(FALSE)
|
||||
|
||||
/obj/item/integrated_circuit/time/clock/bluespace
|
||||
name = "integrated clock (Bluespace Absolute Time)"
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
//this needs to come after the job_types subfolder to keep the correct ordering
|
||||
|
||||
#include "..\..\..\..\_maps\map_files\OmegaStation\job_changes.dm"
|
||||
#undef JOB_MODIFICATION_MAP_NAME
|
||||
#include "..\..\..\..\_maps\map_files\PubbyStation\job_changes.dm"
|
||||
//this needs to come after the job_types subfolder to keep the correct ordering
|
||||
|
||||
#include "..\..\..\..\_maps\map_files\PubbyStation\job_changes.dm"
|
||||
#undef JOB_MODIFICATION_MAP_NAME
|
||||
@@ -1,298 +1,311 @@
|
||||
// This is where the fun begins.
|
||||
// These are the main datums that emit light.
|
||||
|
||||
/datum/light_source
|
||||
var/atom/top_atom // The atom we're emitting light from (for example a mob if we're from a flashlight that's being held).
|
||||
var/atom/source_atom // The atom that we belong to.
|
||||
|
||||
var/turf/source_turf // The turf under the above.
|
||||
var/turf/pixel_turf // The turf the top_atom appears to over.
|
||||
var/light_power // Intensity of the emitter light.
|
||||
var/light_range // The range of the emitted light.
|
||||
var/light_color // The colour of the light, string, decomposed by parse_light_color()
|
||||
|
||||
// Variables for keeping track of the colour.
|
||||
var/lum_r
|
||||
var/lum_g
|
||||
var/lum_b
|
||||
|
||||
// The lumcount values used to apply the light.
|
||||
var/tmp/applied_lum_r
|
||||
var/tmp/applied_lum_g
|
||||
var/tmp/applied_lum_b
|
||||
|
||||
var/list/datum/lighting_corner/effect_str // List used to store how much we're affecting corners.
|
||||
var/list/turf/affecting_turfs
|
||||
|
||||
var/applied = FALSE // Whether we have applied our light yet or not.
|
||||
|
||||
var/needs_update = LIGHTING_NO_UPDATE // Whether we are queued for an update.
|
||||
|
||||
|
||||
/datum/light_source/New(var/atom/owner, var/atom/top)
|
||||
source_atom = owner // Set our new owner.
|
||||
LAZYADD(source_atom.light_sources, src)
|
||||
top_atom = top
|
||||
if (top_atom != source_atom)
|
||||
LAZYADD(top_atom.light_sources, src)
|
||||
|
||||
source_turf = top_atom
|
||||
pixel_turf = get_turf_pixel(top_atom) || source_turf
|
||||
|
||||
light_power = source_atom.light_power
|
||||
light_range = source_atom.light_range
|
||||
light_color = source_atom.light_color
|
||||
|
||||
parse_light_color()
|
||||
|
||||
update()
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/light_source/Destroy(force)
|
||||
remove_lum()
|
||||
if (source_atom)
|
||||
LAZYREMOVE(source_atom.light_sources, src)
|
||||
|
||||
if (top_atom)
|
||||
LAZYREMOVE(top_atom.light_sources, src)
|
||||
|
||||
if (needs_update)
|
||||
GLOB.lighting_update_lights -= src
|
||||
|
||||
. = ..()
|
||||
|
||||
// Yes this doesn't align correctly on anything other than 4 width tabs.
|
||||
// If you want it to go switch everybody to elastic tab stops.
|
||||
// Actually that'd be great if you could!
|
||||
#define EFFECT_UPDATE(level) \
|
||||
if (needs_update == LIGHTING_NO_UPDATE) \
|
||||
GLOB.lighting_update_lights += src; \
|
||||
if (needs_update < level) \
|
||||
needs_update = level; \
|
||||
|
||||
|
||||
// This proc will cause the light source to update the top atom, and add itself to the update queue.
|
||||
/datum/light_source/proc/update(var/atom/new_top_atom)
|
||||
// This top atom is different.
|
||||
if (new_top_atom && new_top_atom != top_atom)
|
||||
if(top_atom != source_atom && top_atom.light_sources) // Remove ourselves from the light sources of that top atom.
|
||||
LAZYREMOVE(top_atom.light_sources, src)
|
||||
|
||||
top_atom = new_top_atom
|
||||
|
||||
if (top_atom != source_atom)
|
||||
LAZYADD(top_atom.light_sources, src) // Add ourselves to the light sources of our new top atom.
|
||||
|
||||
EFFECT_UPDATE(LIGHTING_CHECK_UPDATE)
|
||||
|
||||
// Will force an update without checking if it's actually needed.
|
||||
/datum/light_source/proc/force_update()
|
||||
EFFECT_UPDATE(LIGHTING_FORCE_UPDATE)
|
||||
|
||||
// Will cause the light source to recalculate turfs that were removed or added to visibility only.
|
||||
/datum/light_source/proc/vis_update()
|
||||
EFFECT_UPDATE(LIGHTING_VIS_UPDATE)
|
||||
|
||||
// Decompile the hexadecimal colour into lumcounts of each perspective.
|
||||
/datum/light_source/proc/parse_light_color()
|
||||
if (light_color)
|
||||
lum_r = GetRedPart (light_color) / 255
|
||||
lum_g = GetGreenPart (light_color) / 255
|
||||
lum_b = GetBluePart (light_color) / 255
|
||||
else
|
||||
lum_r = 1
|
||||
lum_g = 1
|
||||
lum_b = 1
|
||||
|
||||
// Macro that applies light to a new corner.
|
||||
// It is a macro in the interest of speed, yet not having to copy paste it.
|
||||
// If you're wondering what's with the backslashes, the backslashes cause BYOND to not automatically end the line.
|
||||
// As such this all gets counted as a single line.
|
||||
// The braces and semicolons are there to be able to do this on a single line.
|
||||
#define LUM_FALLOFF(C, T) (1 - CLAMP01(sqrt((C.x - T.x) ** 2 + (C.y - T.y) ** 2 + LIGHTING_HEIGHT) / max(1, light_range)))
|
||||
|
||||
#define APPLY_CORNER(C) \
|
||||
. = LUM_FALLOFF(C, pixel_turf); \
|
||||
. *= light_power; \
|
||||
var/OLD = effect_str[C]; \
|
||||
effect_str[C] = .; \
|
||||
\
|
||||
C.update_lumcount \
|
||||
( \
|
||||
(. * lum_r) - (OLD * applied_lum_r), \
|
||||
(. * lum_g) - (OLD * applied_lum_g), \
|
||||
(. * lum_b) - (OLD * applied_lum_b) \
|
||||
);
|
||||
|
||||
#define REMOVE_CORNER(C) \
|
||||
. = -effect_str[C]; \
|
||||
C.update_lumcount \
|
||||
( \
|
||||
. * applied_lum_r, \
|
||||
. * applied_lum_g, \
|
||||
. * applied_lum_b \
|
||||
);
|
||||
|
||||
// This is the define used to calculate falloff.
|
||||
|
||||
/datum/light_source/proc/remove_lum()
|
||||
applied = FALSE
|
||||
var/thing
|
||||
for (thing in affecting_turfs)
|
||||
var/turf/T = thing
|
||||
LAZYREMOVE(T.affecting_lights, src)
|
||||
|
||||
affecting_turfs = null
|
||||
|
||||
var/datum/lighting_corner/C
|
||||
for (thing in effect_str)
|
||||
C = thing
|
||||
REMOVE_CORNER(C)
|
||||
|
||||
LAZYREMOVE(C.affecting, src)
|
||||
|
||||
effect_str = null
|
||||
|
||||
/datum/light_source/proc/recalc_corner(var/datum/lighting_corner/C)
|
||||
LAZYINITLIST(effect_str)
|
||||
if (effect_str[C]) // Already have one.
|
||||
REMOVE_CORNER(C)
|
||||
effect_str[C] = 0
|
||||
|
||||
APPLY_CORNER(C)
|
||||
UNSETEMPTY(effect_str)
|
||||
|
||||
/datum/light_source/proc/update_corners()
|
||||
var/update = FALSE
|
||||
var/atom/source_atom = src.source_atom
|
||||
|
||||
if (QDELETED(source_atom))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if (source_atom.light_power != light_power)
|
||||
light_power = source_atom.light_power
|
||||
update = TRUE
|
||||
|
||||
if (source_atom.light_range != light_range)
|
||||
light_range = source_atom.light_range
|
||||
update = TRUE
|
||||
|
||||
if (!top_atom)
|
||||
top_atom = source_atom
|
||||
update = TRUE
|
||||
|
||||
if (!light_range || !light_power)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if (isturf(top_atom))
|
||||
if (source_turf != top_atom)
|
||||
source_turf = top_atom
|
||||
pixel_turf = source_turf
|
||||
update = TRUE
|
||||
else if (top_atom.loc != source_turf)
|
||||
source_turf = top_atom.loc
|
||||
pixel_turf = get_turf_pixel(top_atom)
|
||||
update = TRUE
|
||||
else
|
||||
var/P = get_turf_pixel(top_atom)
|
||||
if (P != pixel_turf)
|
||||
pixel_turf = P
|
||||
update = TRUE
|
||||
|
||||
if (!isturf(source_turf))
|
||||
if (applied)
|
||||
remove_lum()
|
||||
return
|
||||
|
||||
if (light_range && light_power && !applied)
|
||||
update = TRUE
|
||||
|
||||
if (source_atom.light_color != light_color)
|
||||
light_color = source_atom.light_color
|
||||
parse_light_color()
|
||||
update = TRUE
|
||||
|
||||
else if (applied_lum_r != lum_r || applied_lum_g != lum_g || applied_lum_b != lum_b)
|
||||
update = TRUE
|
||||
|
||||
if (update)
|
||||
needs_update = LIGHTING_CHECK_UPDATE
|
||||
applied = TRUE
|
||||
else if (needs_update == LIGHTING_CHECK_UPDATE)
|
||||
return //nothing's changed
|
||||
|
||||
var/list/datum/lighting_corner/corners = list()
|
||||
var/list/turf/turfs = list()
|
||||
var/thing
|
||||
var/datum/lighting_corner/C
|
||||
var/turf/T
|
||||
if (source_turf)
|
||||
var/oldlum = source_turf.luminosity
|
||||
source_turf.luminosity = CEILING(light_range, 1)
|
||||
for(T in view(CEILING(light_range, 1), source_turf))
|
||||
for (thing in T.get_corners(source_turf))
|
||||
C = thing
|
||||
corners[C] = 0
|
||||
turfs += T
|
||||
source_turf.luminosity = oldlum
|
||||
|
||||
LAZYINITLIST(affecting_turfs)
|
||||
var/list/L = turfs - affecting_turfs // New turfs, add us to the affecting lights of them.
|
||||
affecting_turfs += L
|
||||
for (thing in L)
|
||||
T = thing
|
||||
LAZYADD(T.affecting_lights, src)
|
||||
|
||||
L = affecting_turfs - turfs // Now-gone turfs, remove us from the affecting lights.
|
||||
affecting_turfs -= L
|
||||
for (thing in L)
|
||||
T = thing
|
||||
LAZYREMOVE(T.affecting_lights, src)
|
||||
|
||||
LAZYINITLIST(effect_str)
|
||||
if (needs_update == LIGHTING_VIS_UPDATE)
|
||||
for (thing in corners - effect_str) // New corners
|
||||
C = thing
|
||||
LAZYADD(C.affecting, src)
|
||||
if (!C.active)
|
||||
effect_str[C] = 0
|
||||
continue
|
||||
APPLY_CORNER(C)
|
||||
else
|
||||
L = corners - effect_str
|
||||
for (thing in L) // New corners
|
||||
C = thing
|
||||
LAZYADD(C.affecting, src)
|
||||
if (!C.active)
|
||||
effect_str[C] = 0
|
||||
continue
|
||||
APPLY_CORNER(C)
|
||||
|
||||
for (thing in corners - L) // Existing corners
|
||||
C = thing
|
||||
if (!C.active)
|
||||
effect_str[C] = 0
|
||||
continue
|
||||
APPLY_CORNER(C)
|
||||
|
||||
L = effect_str - corners
|
||||
for (thing in L) // Old, now gone, corners.
|
||||
C = thing
|
||||
REMOVE_CORNER(C)
|
||||
LAZYREMOVE(C.affecting, src)
|
||||
effect_str -= L
|
||||
|
||||
applied_lum_r = lum_r
|
||||
applied_lum_g = lum_g
|
||||
applied_lum_b = lum_b
|
||||
|
||||
UNSETEMPTY(effect_str)
|
||||
UNSETEMPTY(affecting_turfs)
|
||||
|
||||
#undef EFFECT_UPDATE
|
||||
#undef LUM_FALLOFF
|
||||
#undef REMOVE_CORNER
|
||||
#undef APPLY_CORNER
|
||||
// This is where the fun begins.
|
||||
// These are the main datums that emit light.
|
||||
|
||||
/datum/light_source
|
||||
var/atom/top_atom // The atom we're emitting light from (for example a mob if we're from a flashlight that's being held).
|
||||
var/atom/source_atom // The atom that we belong to.
|
||||
|
||||
var/turf/source_turf // The turf under the above.
|
||||
var/turf/pixel_turf // The turf the top_atom appears to over.
|
||||
var/light_power // Intensity of the emitter light.
|
||||
var/light_range // The range of the emitted light.
|
||||
var/light_color // The colour of the light, string, decomposed by parse_light_color()
|
||||
|
||||
// Variables for keeping track of the colour.
|
||||
var/lum_r
|
||||
var/lum_g
|
||||
var/lum_b
|
||||
|
||||
// The lumcount values used to apply the light.
|
||||
var/tmp/applied_lum_r
|
||||
var/tmp/applied_lum_g
|
||||
var/tmp/applied_lum_b
|
||||
|
||||
var/list/datum/lighting_corner/effect_str // List used to store how much we're affecting corners.
|
||||
var/list/turf/affecting_turfs
|
||||
|
||||
var/applied = FALSE // Whether we have applied our light yet or not.
|
||||
|
||||
var/needs_update = LIGHTING_NO_UPDATE // Whether we are queued for an update.
|
||||
|
||||
// Thanks to Lohikar for flinging this tiny bit of code at me, increasing my brain cell count from 1 to 2 in the process.
|
||||
// This macro will only offset up to 1 tile, but anything with a greater offset is an outlier and probably should handle its own lighting offsets.
|
||||
// Anything pixelshifted 16px or more will be considered on the next tile.
|
||||
#define GET_APPROXIMATE_PIXEL_DIR(PX, PY) ((!(PX) ? 0 : ((PX >= 16 ? EAST : (PX <= -16 ? WEST : 0)))) | (!PY ? 0 : (PY >= 16 ? NORTH : (PY <= -16 ? SOUTH : 0))))
|
||||
#define UPDATE_APPROXIMATE_PIXEL_TURF var/_mask = GET_APPROXIMATE_PIXEL_DIR(top_atom.pixel_x, top_atom.pixel_y); pixel_turf = _mask ? (get_step(source_turf, _mask) || source_turf) : source_turf
|
||||
|
||||
/datum/light_source/New(var/atom/owner, var/atom/top)
|
||||
source_atom = owner // Set our new owner.
|
||||
LAZYADD(source_atom.light_sources, src)
|
||||
top_atom = top
|
||||
if (top_atom != source_atom)
|
||||
LAZYADD(top_atom.light_sources, src)
|
||||
|
||||
source_turf = top_atom
|
||||
UPDATE_APPROXIMATE_PIXEL_TURF
|
||||
|
||||
light_power = source_atom.light_power
|
||||
light_range = source_atom.light_range
|
||||
light_color = source_atom.light_color
|
||||
|
||||
parse_light_color()
|
||||
|
||||
update()
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/light_source/Destroy(force)
|
||||
remove_lum()
|
||||
if (source_atom)
|
||||
LAZYREMOVE(source_atom.light_sources, src)
|
||||
|
||||
if (top_atom)
|
||||
LAZYREMOVE(top_atom.light_sources, src)
|
||||
|
||||
if (needs_update)
|
||||
GLOB.lighting_update_lights -= src
|
||||
|
||||
. = ..()
|
||||
|
||||
// Yes this doesn't align correctly on anything other than 4 width tabs.
|
||||
// If you want it to go switch everybody to elastic tab stops.
|
||||
// Actually that'd be great if you could!
|
||||
#define EFFECT_UPDATE(level) \
|
||||
if (needs_update == LIGHTING_NO_UPDATE) \
|
||||
GLOB.lighting_update_lights += src; \
|
||||
if (needs_update < level) \
|
||||
needs_update = level; \
|
||||
|
||||
|
||||
// This proc will cause the light source to update the top atom, and add itself to the update queue.
|
||||
/datum/light_source/proc/update(var/atom/new_top_atom)
|
||||
// This top atom is different.
|
||||
if (new_top_atom && new_top_atom != top_atom)
|
||||
if(top_atom != source_atom && top_atom.light_sources) // Remove ourselves from the light sources of that top atom.
|
||||
LAZYREMOVE(top_atom.light_sources, src)
|
||||
|
||||
top_atom = new_top_atom
|
||||
|
||||
if (top_atom != source_atom)
|
||||
LAZYADD(top_atom.light_sources, src) // Add ourselves to the light sources of our new top atom.
|
||||
|
||||
EFFECT_UPDATE(LIGHTING_CHECK_UPDATE)
|
||||
|
||||
// Will force an update without checking if it's actually needed.
|
||||
/datum/light_source/proc/force_update()
|
||||
EFFECT_UPDATE(LIGHTING_FORCE_UPDATE)
|
||||
|
||||
// Will cause the light source to recalculate turfs that were removed or added to visibility only.
|
||||
/datum/light_source/proc/vis_update()
|
||||
EFFECT_UPDATE(LIGHTING_VIS_UPDATE)
|
||||
|
||||
// Decompile the hexadecimal colour into lumcounts of each perspective.
|
||||
/datum/light_source/proc/parse_light_color()
|
||||
if (light_color)
|
||||
lum_r = GetRedPart (light_color) / 255
|
||||
lum_g = GetGreenPart (light_color) / 255
|
||||
lum_b = GetBluePart (light_color) / 255
|
||||
else
|
||||
lum_r = 1
|
||||
lum_g = 1
|
||||
lum_b = 1
|
||||
|
||||
// Macro that applies light to a new corner.
|
||||
// It is a macro in the interest of speed, yet not having to copy paste it.
|
||||
// If you're wondering what's with the backslashes, the backslashes cause BYOND to not automatically end the line.
|
||||
// As such this all gets counted as a single line.
|
||||
// The braces and semicolons are there to be able to do this on a single line.
|
||||
|
||||
//Original lighting falloff calculation. This looks the best out of the three. However, this is also the most expensive.
|
||||
//#define LUM_FALLOFF(C, T) (1 - CLAMP01(sqrt((C.x - T.x) ** 2 + (C.y - T.y) ** 2 + LIGHTING_HEIGHT) / max(1, light_range)))
|
||||
|
||||
//Cubic lighting falloff. This has the *exact* same range as the original lighting falloff calculation, down to the exact decimal, but it looks a little unnatural due to the harsher falloff and how it's generally brighter across the board.
|
||||
//#define LUM_FALLOFF(C, T) (1 - CLAMP01((((C.x - T.x) * (C.x - T.x)) + ((C.y - T.y) * (C.y - T.y)) + LIGHTING_HEIGHT) / max(1, light_range*light_range)))
|
||||
|
||||
//Linear lighting falloff. This resembles the original lighting falloff calculation the best, but results in lights having a slightly larger range, which is most noticable with large light sources. This also results in lights being diamond-shaped, fuck. This looks the darkest out of the three due to how lights are brighter closer to the source compared to the original falloff algorithm. This falloff method also does not at all take into account lighting height, as it acts as a flat reduction to light range with this method.
|
||||
//#define LUM_FALLOFF(C, T) (1 - CLAMP01(((abs(C.x - T.x) + abs(C.y - T.y))) / max(1, light_range+1)))
|
||||
|
||||
//Linear lighting falloff but with an octagonal shape in place of a diamond shape. Lummox JR please add pointer support.
|
||||
#define GET_LUM_DIST(DISTX, DISTY) (DISTX + DISTY + abs(DISTX - DISTY)*0.4)
|
||||
#define LUM_FALLOFF(C, T) (1 - CLAMP01(max(GET_LUM_DIST(abs(C.x - T.x), abs(C.y - T.y)),LIGHTING_HEIGHT) / max(1, light_range+1)))
|
||||
|
||||
#define APPLY_CORNER(C) \
|
||||
. = LUM_FALLOFF(C, pixel_turf); \
|
||||
. *= light_power; \
|
||||
var/OLD = effect_str[C]; \
|
||||
effect_str[C] = .; \
|
||||
\
|
||||
C.update_lumcount \
|
||||
( \
|
||||
(. * lum_r) - (OLD * applied_lum_r), \
|
||||
(. * lum_g) - (OLD * applied_lum_g), \
|
||||
(. * lum_b) - (OLD * applied_lum_b) \
|
||||
);
|
||||
|
||||
#define REMOVE_CORNER(C) \
|
||||
. = -effect_str[C]; \
|
||||
C.update_lumcount \
|
||||
( \
|
||||
. * applied_lum_r, \
|
||||
. * applied_lum_g, \
|
||||
. * applied_lum_b \
|
||||
);
|
||||
|
||||
// This is the define used to calculate falloff.
|
||||
|
||||
/datum/light_source/proc/remove_lum()
|
||||
applied = FALSE
|
||||
var/thing
|
||||
for (thing in affecting_turfs)
|
||||
var/turf/T = thing
|
||||
LAZYREMOVE(T.affecting_lights, src)
|
||||
|
||||
affecting_turfs = null
|
||||
|
||||
var/datum/lighting_corner/C
|
||||
for (thing in effect_str)
|
||||
C = thing
|
||||
REMOVE_CORNER(C)
|
||||
|
||||
LAZYREMOVE(C.affecting, src)
|
||||
|
||||
effect_str = null
|
||||
|
||||
/datum/light_source/proc/recalc_corner(var/datum/lighting_corner/C)
|
||||
LAZYINITLIST(effect_str)
|
||||
if (effect_str[C]) // Already have one.
|
||||
REMOVE_CORNER(C)
|
||||
effect_str[C] = 0
|
||||
|
||||
APPLY_CORNER(C)
|
||||
UNSETEMPTY(effect_str)
|
||||
|
||||
/datum/light_source/proc/update_corners()
|
||||
var/update = FALSE
|
||||
var/atom/source_atom = src.source_atom
|
||||
|
||||
if (QDELETED(source_atom))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if (source_atom.light_power != light_power)
|
||||
light_power = source_atom.light_power
|
||||
update = TRUE
|
||||
|
||||
if (source_atom.light_range != light_range)
|
||||
light_range = source_atom.light_range
|
||||
update = TRUE
|
||||
|
||||
if (!top_atom)
|
||||
top_atom = source_atom
|
||||
update = TRUE
|
||||
|
||||
if (!light_range || !light_power)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if (isturf(top_atom))
|
||||
if (source_turf != top_atom)
|
||||
source_turf = top_atom
|
||||
UPDATE_APPROXIMATE_PIXEL_TURF
|
||||
update = TRUE
|
||||
else if (top_atom.loc != source_turf)
|
||||
source_turf = top_atom.loc
|
||||
UPDATE_APPROXIMATE_PIXEL_TURF
|
||||
update = TRUE
|
||||
|
||||
if (!isturf(source_turf))
|
||||
if (applied)
|
||||
remove_lum()
|
||||
return
|
||||
|
||||
if (light_range && light_power && !applied)
|
||||
update = TRUE
|
||||
|
||||
if (source_atom.light_color != light_color)
|
||||
light_color = source_atom.light_color
|
||||
parse_light_color()
|
||||
update = TRUE
|
||||
|
||||
else if (applied_lum_r != lum_r || applied_lum_g != lum_g || applied_lum_b != lum_b)
|
||||
update = TRUE
|
||||
|
||||
if (update)
|
||||
needs_update = LIGHTING_CHECK_UPDATE
|
||||
applied = TRUE
|
||||
else if (needs_update == LIGHTING_CHECK_UPDATE)
|
||||
return //nothing's changed
|
||||
|
||||
var/list/datum/lighting_corner/corners = list()
|
||||
var/list/turf/turfs = list()
|
||||
var/thing
|
||||
var/datum/lighting_corner/C
|
||||
var/turf/T
|
||||
if (source_turf)
|
||||
var/oldlum = source_turf.luminosity
|
||||
source_turf.luminosity = CEILING(light_range, 1)
|
||||
for(T in view(CEILING(light_range, 1), source_turf))
|
||||
for (thing in T.get_corners(source_turf))
|
||||
C = thing
|
||||
corners[C] = 0
|
||||
turfs += T
|
||||
source_turf.luminosity = oldlum
|
||||
|
||||
LAZYINITLIST(affecting_turfs)
|
||||
var/list/L = turfs - affecting_turfs // New turfs, add us to the affecting lights of them.
|
||||
affecting_turfs += L
|
||||
for (thing in L)
|
||||
T = thing
|
||||
LAZYADD(T.affecting_lights, src)
|
||||
|
||||
L = affecting_turfs - turfs // Now-gone turfs, remove us from the affecting lights.
|
||||
affecting_turfs -= L
|
||||
for (thing in L)
|
||||
T = thing
|
||||
LAZYREMOVE(T.affecting_lights, src)
|
||||
|
||||
LAZYINITLIST(effect_str)
|
||||
if (needs_update == LIGHTING_VIS_UPDATE)
|
||||
for (thing in corners - effect_str) // New corners
|
||||
C = thing
|
||||
LAZYADD(C.affecting, src)
|
||||
if (!C.active)
|
||||
effect_str[C] = 0
|
||||
continue
|
||||
APPLY_CORNER(C)
|
||||
else
|
||||
L = corners - effect_str
|
||||
for (thing in L) // New corners
|
||||
C = thing
|
||||
LAZYADD(C.affecting, src)
|
||||
if (!C.active)
|
||||
effect_str[C] = 0
|
||||
continue
|
||||
APPLY_CORNER(C)
|
||||
|
||||
for (thing in corners - L) // Existing corners
|
||||
C = thing
|
||||
if (!C.active)
|
||||
effect_str[C] = 0
|
||||
continue
|
||||
APPLY_CORNER(C)
|
||||
|
||||
L = effect_str - corners
|
||||
for (thing in L) // Old, now gone, corners.
|
||||
C = thing
|
||||
REMOVE_CORNER(C)
|
||||
LAZYREMOVE(C.affecting, src)
|
||||
effect_str -= L
|
||||
|
||||
applied_lum_r = lum_r
|
||||
applied_lum_g = lum_g
|
||||
applied_lum_b = lum_b
|
||||
|
||||
UNSETEMPTY(effect_str)
|
||||
UNSETEMPTY(affecting_turfs)
|
||||
|
||||
#undef EFFECT_UPDATE
|
||||
#undef LUM_FALLOFF
|
||||
#undef GET_LUM_DIST
|
||||
#undef REMOVE_CORNER
|
||||
#undef APPLY_CORNER
|
||||
|
||||
@@ -197,7 +197,7 @@ GLOBAL_LIST_EMPTY(silo_access_logs)
|
||||
var/list/materials
|
||||
|
||||
/datum/ore_silo_log/New(obj/machinery/M, _action, _amount, _noun, list/mats=list())
|
||||
timestamp = station_time_timestamp()
|
||||
timestamp = STATION_TIME_TIMESTAMP("hh:mm:ss")
|
||||
machine_name = M.name
|
||||
area_name = get_area_name(M, TRUE)
|
||||
action = _action
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
new /datum/data/mining_equipment("Shelter Capsule", /obj/item/survivalcapsule, 400),
|
||||
new /datum/data/mining_equipment("GAR Meson Scanners", /obj/item/clothing/glasses/meson/gar, 500),
|
||||
new /datum/data/mining_equipment("Explorer's Webbing", /obj/item/storage/belt/mining, 500),
|
||||
new /datum/data/mining_equipment("Larger Ore Bag", /obj/item/storage/bag/ore/large, 500),
|
||||
new /datum/data/mining_equipment("500 Point Transfer Card", /obj/item/card/mining_point_card/mp500, 500),
|
||||
new /datum/data/mining_equipment("Brute First-Aid Kit", /obj/item/storage/firstaid/brute, 600),
|
||||
new /datum/data/mining_equipment("Tracking Implant Kit", /obj/item/storage/box/minertracker, 600),
|
||||
@@ -42,9 +43,9 @@
|
||||
new /datum/data/mining_equipment("Lazarus Injector", /obj/item/lazarus_injector, 1000),
|
||||
new /datum/data/mining_equipment("Silver Pickaxe", /obj/item/pickaxe/silver, 1000),
|
||||
new /datum/data/mining_equipment("Mining Conscription Kit", /obj/item/storage/backpack/duffelbag/mining_conscript, 1000),
|
||||
new /datum/data/mining_equipment("1000 Point Transfer Card", /obj/item/card/mining_point_card/mp1000, 1000),
|
||||
new /datum/data/mining_equipment("1500 Point Transfer Card", /obj/item/card/mining_point_card/mp1500, 1500),
|
||||
new /datum/data/mining_equipment("2000 Point Transfer Card", /obj/item/card/mining_point_card/mp2000, 2000),
|
||||
new /datum/data/mining_equipment("1000 Point Transfer Card", /obj/item/card/mining_point_card/mp1000, 1000),
|
||||
new /datum/data/mining_equipment("1500 Point Transfer Card", /obj/item/card/mining_point_card/mp1500, 1500),
|
||||
new /datum/data/mining_equipment("2000 Point Transfer Card", /obj/item/card/mining_point_card/mp2000, 2000),
|
||||
new /datum/data/mining_equipment("Jetpack Upgrade", /obj/item/tank/jetpack/suit, 2000),
|
||||
new /datum/data/mining_equipment("Space Cash", /obj/item/stack/spacecash/c1000, 2000),
|
||||
new /datum/data/mining_equipment("Mining Hardsuit", /obj/item/clothing/suit/space/hardsuit/mining, 2000),
|
||||
@@ -66,7 +67,10 @@
|
||||
new /datum/data/mining_equipment("KA Damage Increase", /obj/item/borg/upgrade/modkit/damage, 1000),
|
||||
new /datum/data/mining_equipment("KA Cooldown Decrease", /obj/item/borg/upgrade/modkit/cooldown, 1000),
|
||||
new /datum/data/mining_equipment("KA AoE Damage", /obj/item/borg/upgrade/modkit/aoe/mobs, 2000),
|
||||
new /datum/data/mining_equipment("Premium Accelerator", /obj/item/gun/energy/kinetic_accelerator/premiumka, 8000)
|
||||
new /datum/data/mining_equipment("Premium Accelerator", /obj/item/gun/energy/kinetic_accelerator/premiumka, 8000),
|
||||
new /datum/data/mining_equipment("Miner Full Replacement", /obj/item/storage/backpack/duffelbag/mining_cloned, 12000),
|
||||
new /datum/data/mining_equipment("Spare Suit Voucher", /obj/item/suit_voucher, 15000)
|
||||
|
||||
)
|
||||
|
||||
/datum/data/mining_equipment
|
||||
@@ -320,9 +324,29 @@
|
||||
new /obj/item/clothing/mask/gas/explorer(src)
|
||||
new /obj/item/card/mining_access_card(src)
|
||||
|
||||
|
||||
//CITADEL ADDITIONS BELOW
|
||||
|
||||
/obj/item/storage/backpack/duffelbag/mining_cloned
|
||||
name = "mining replacement kit"
|
||||
desc = "A large bag that has advance tools and a spare jumpsuit, boots, and gloves for a newly cloned miner to get back in the field. Even as a new Id!"
|
||||
|
||||
/obj/item/storage/backpack/duffelbag/mining_cloned/PopulateContents()
|
||||
new /obj/item/pickaxe/mini(src)
|
||||
new /obj/item/clothing/under/rank/miner/lavaland(src)
|
||||
new /obj/item/clothing/shoes/workboots/mining(src)
|
||||
new /obj/item/clothing/gloves/color/black(src)
|
||||
new /obj/item/implanter/tracking/gps(src)
|
||||
new /obj/item/kitchen/knife/combat/survival(src)
|
||||
new /obj/item/storage/firstaid/regular(src)
|
||||
new /obj/item/reagent_containers/hypospray/medipen/survival(src)
|
||||
new /obj/item/t_scanner/adv_mining_scanner(src)
|
||||
new /obj/item/clothing/suit/hooded/explorer(src)
|
||||
new /obj/item/encryptionkey/headset_cargo(src)
|
||||
new /obj/item/clothing/mask/gas/explorer(src)
|
||||
new /obj/item/card/id/mining(src)
|
||||
new /obj/item/storage/bag/ore(src)
|
||||
new /obj/item/clothing/glasses/meson/prescription(src)
|
||||
|
||||
/obj/machinery/mineral/equipment_vendor/proc/RedeemSVoucher(obj/item/suit_voucher/voucher, mob/redeemer)
|
||||
var/items = list("Exo-suit", "SEVA suit")
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
|
||||
invisibility = INVISIBILITY_OBSERVER
|
||||
hud_type = /datum/hud/ghost
|
||||
var/can_reenter_corpse
|
||||
var/can_reenter_round = TRUE
|
||||
var/datum/hud/living/carbon/hud = null // hud
|
||||
var/bootime = 0
|
||||
var/started_as_observer //This variable is set to 1 when you enter the game as an observer.
|
||||
@@ -266,6 +267,7 @@ Works together with spawning an observer, noted above.
|
||||
var/mob/dead/observer/ghost = new(src) // Transfer safety to observer spawning proc.
|
||||
SStgui.on_transfer(src, ghost) // Transfer NanoUIs.
|
||||
ghost.can_reenter_corpse = can_reenter_corpse
|
||||
ghost.can_reenter_round = (can_reenter_corpse && !suiciding)
|
||||
ghost.key = key
|
||||
return ghost
|
||||
|
||||
@@ -280,7 +282,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
|
||||
// CITADEL EDIT
|
||||
if(istype(loc, /obj/machinery/cryopod))
|
||||
var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst still alive you may not play again this round! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body")
|
||||
var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst still alive you won't be able to re-enter this round! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body")
|
||||
if(response != "Ghost")//darn copypaste
|
||||
return
|
||||
var/obj/machinery/cryopod/C = loc
|
||||
@@ -293,17 +295,18 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
if(stat == DEAD)
|
||||
ghostize(1)
|
||||
else
|
||||
var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst still alive you may not play again this round! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body")
|
||||
var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst still alive you won't be able to re-enter this round! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body")
|
||||
if(response != "Ghost")
|
||||
return //didn't want to ghost after-all
|
||||
ghostize(0) //0 parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3
|
||||
suicide_log(TRUE)
|
||||
|
||||
/mob/camera/verb/ghost()
|
||||
set category = "OOC"
|
||||
set name = "Ghost"
|
||||
set desc = "Relinquish your life and enter the land of the dead."
|
||||
|
||||
var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst still alive you may not play again this round! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body")
|
||||
var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst still alive you won't be able to re-enter this round! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body")
|
||||
if(response != "Ghost")
|
||||
return
|
||||
ghostize(0)
|
||||
@@ -617,6 +620,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
to_chat(src, "<span class='warning'>This isn't really a creature, now is it!</span>")
|
||||
return 0
|
||||
|
||||
if(!can_reenter_round)
|
||||
to_chat(src, "<span class='warning'>You are unable to re-enter the round.</span>")
|
||||
return FALSE
|
||||
|
||||
if(can_reenter_corpse && mind && mind.current)
|
||||
if(alert(src, "Your soul is still tied to your former life as [mind.current.name], if you go forward there is no going back to that life. Are you sure you wish to continue?", "Move On", "Yes", "No") == "No")
|
||||
return 0
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user