Merge branch 'master' into fairylights

This commit is contained in:
Dahlular
2022-05-04 14:12:41 -06:00
111 changed files with 3251 additions and 611 deletions
@@ -0,0 +1,658 @@
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
"a" = (
/obj/effect/mapping_helpers/no_lava,
/turf/open/chasm/lavaland,
/area/template_noop)
"b" = (
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/template_noop)
"c" = (
/turf/closed/wall/mineral/plastitanium,
/area/ruin/unpowered/reactor)
"d" = (
/turf/open/floor/plating,
/area/template_noop)
"e" = (
/turf/closed/wall/mineral/titanium,
/area/ruin/unpowered/reactor)
"f" = (
/turf/closed/wall/mineral/titanium/nodiagonal,
/area/ruin/unpowered/reactor)
"g" = (
/obj/structure/alien/weeds,
/turf/open/floor/plasteel,
/area/ruin/unpowered/reactor)
"h" = (
/obj/machinery/door/airlock/public/glass,
/obj/machinery/door/poddoor/shutters/radiation,
/turf/open/floor/plasteel,
/area/ruin/unpowered/reactor)
"i" = (
/turf/open/floor/plating,
/area/ruin/unpowered/reactor)
"j" = (
/obj/structure/fluff/destroyed_nuclear_reactor,
/turf/open/floor/plating,
/area/ruin/unpowered/reactor)
"k" = (
/obj/effect/spawner/structure/window/reinforced,
/turf/open/floor/plating,
/area/ruin/unpowered/reactor)
"l" = (
/obj/effect/decal/nuclear_waste,
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/template_noop)
"m" = (
/obj/structure/alien/weeds/node,
/turf/open/floor/plasteel,
/area/ruin/unpowered/reactor)
"n" = (
/obj/machinery/door/airlock/public/glass,
/obj/structure/alien/weeds,
/turf/open/floor/plasteel,
/area/ruin/unpowered/reactor)
"o" = (
/obj/structure/alien/weeds,
/obj/structure/alien/resin/wall,
/turf/open/floor/plasteel,
/area/ruin/unpowered/reactor)
"p" = (
/obj/structure/alien/gelpod,
/obj/structure/alien/weeds,
/turf/open/floor/plasteel,
/area/ruin/unpowered/reactor)
"q" = (
/obj/structure/alien/resin/membrane,
/obj/machinery/door/poddoor/shutters/radiation,
/turf/open/floor/plating,
/area/ruin/unpowered/reactor)
"r" = (
/obj/structure/alien/weeds,
/obj/structure/alien/resin/wall,
/turf/open/floor/plating,
/area/ruin/unpowered/reactor)
"s" = (
/obj/structure/alien/weeds,
/obj/structure/alien/gelpod,
/turf/open/floor/plasteel,
/area/ruin/unpowered/reactor)
"t" = (
/obj/structure/alien/weeds,
/obj/structure/alien/egg/grown,
/turf/open/floor/plasteel,
/area/ruin/unpowered/reactor)
"u" = (
/obj/structure/alien/weeds,
/obj/structure/alien/egg/burst,
/turf/open/floor/plasteel,
/area/ruin/unpowered/reactor)
"v" = (
/obj/effect/mob_spawn/human/corpse/charredskeleton,
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/template_noop)
"w" = (
/obj/structure/alien/weeds,
/mob/living/simple_animal/hostile/alien/drone,
/turf/open/floor/plasteel,
/area/ruin/unpowered/reactor)
"x" = (
/obj/structure/alien/weeds,
/mob/living/simple_animal/hostile/alien/sentinel,
/turf/open/floor/plasteel,
/area/ruin/unpowered/reactor)
"y" = (
/obj/effect/decal/nuclear_waste,
/turf/open/floor/plating,
/area/template_noop)
"z" = (
/obj/effect/decal/nuclear_waste,
/turf/open/floor/plating,
/area/ruin/unpowered/reactor)
"A" = (
/turf/closed/mineral/volcanic/lava_land_surface,
/area/template_noop)
"B" = (
/turf/open/chasm/lavaland,
/area/ruin/unpowered/reactor)
"C" = (
/obj/effect/mob_spawn/human/corpse/charredskeleton,
/turf/open/floor/plating,
/area/template_noop)
"D" = (
/obj/effect/gibspawner/robot,
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/template_noop)
"F" = (
/obj/structure/alien/weeds,
/obj/effect/gibspawner/robot,
/turf/open/floor/plasteel,
/area/ruin/unpowered/reactor)
(1,1,1) = {"
A
A
A
A
A
A
A
A
A
A
A
A
A
c
c
c
a
a
a
a
a
a
"}
(2,1,1) = {"
A
l
A
A
A
A
l
D
v
A
l
A
c
c
c
c
c
a
a
a
a
a
"}
(3,1,1) = {"
A
l
l
l
A
A
l
b
b
l
l
A
c
c
c
c
c
c
a
a
a
a
"}
(4,1,1) = {"
A
A
l
A
A
l
l
b
A
l
A
A
e
c
e
e
e
e
c
a
a
a
"}
(5,1,1) = {"
A
A
D
A
A
l
b
A
A
l
l
A
f
e
f
u
s
e
c
c
a
a
"}
(6,1,1) = {"
A
A
b
A
A
l
b
A
A
l
d
C
h
o
s
m
u
e
c
c
c
a
"}
(7,1,1) = {"
A
v
b
b
l
l
b
b
l
l
k
k
f
o
t
g
f
e
c
c
c
a
"}
(8,1,1) = {"
A
l
l
b
b
b
b
b
A
B
B
z
z
f
p
g
e
c
c
c
c
a
"}
(9,1,1) = {"
A
A
l
A
b
v
A
A
A
B
B
B
z
z
f
n
f
e
c
c
a
a
"}
(10,1,1) = {"
A
l
l
l
b
b
y
z
B
i
i
i
B
B
q
g
r
c
c
c
a
a
"}
(11,1,1) = {"
A
l
A
l
b
b
k
z
B
i
j
i
B
B
q
F
r
c
c
c
c
a
"}
(12,1,1) = {"
A
A
A
A
A
d
k
B
B
i
i
i
B
z
q
g
r
c
c
c
a
a
"}
(13,1,1) = {"
A
c
c
e
f
h
f
z
z
B
B
B
z
z
f
n
f
e
c
c
a
a
"}
(14,1,1) = {"
c
c
c
c
e
g
o
f
z
z
B
B
z
f
s
x
e
c
c
c
c
a
"}
(15,1,1) = {"
c
c
c
e
f
w
u
o
f
q
q
q
f
s
o
g
f
e
c
c
c
a
"}
(16,1,1) = {"
c
c
c
e
u
m
g
g
n
g
F
g
n
g
g
m
u
e
c
c
c
a
"}
(17,1,1) = {"
a
c
c
e
o
u
f
e
f
r
r
r
f
e
f
s
o
e
c
c
a
a
"}
(18,1,1) = {"
a
a
c
e
e
e
e
c
e
c
c
c
e
c
e
e
e
e
c
a
a
a
"}
(19,1,1) = {"
a
a
a
c
c
c
c
c
c
c
c
c
c
c
c
c
c
c
a
a
a
a
"}
(20,1,1) = {"
a
a
a
a
c
c
c
c
c
c
c
c
c
c
c
c
c
a
a
a
a
a
"}
(21,1,1) = {"
a
a
a
a
a
c
c
c
a
a
c
a
a
c
c
c
a
a
a
a
a
a
"}
(22,1,1) = {"
a
a
a
a
a
a
a
a
a
a
a
a
a
a
a
a
a
a
a
a
a
a
"}
+1 -3
View File
@@ -10943,9 +10943,6 @@
/turf/open/floor/plasteel,
/area/tdome/arena)
"kjW" = (
/obj/item/twohanded/required/kirbyplants{
icon_state = "plant-22"
},
/obj/effect/turf_decal/tile{
color = "#630000";
dir = 1
@@ -10961,6 +10958,7 @@
/obj/effect/turf_decal/tile{
color = "#630000"
},
/obj/structure/jacuzzi,
/turf/open/floor/mineral/basaltstone_floor,
/area/centcom/ferry)
"kke" = (
+3
View File
@@ -31,18 +31,21 @@
/area/survivalpod)
"f" = (
/obj/machinery/chem_dispenser/drinks/beer{
density = 0;
pixel_y = 24
},
/turf/open/floor/carpet/black,
/area/survivalpod)
"g" = (
/obj/machinery/chem_dispenser/drinks{
density = 0;
pixel_y = 24
},
/turf/open/floor/carpet/black,
/area/survivalpod)
"h" = (
/obj/machinery/vending/boozeomat/all_access{
density = 0;
pixel_y = 32
},
/turf/open/floor/carpet/black,
+3
View File
@@ -736,6 +736,9 @@
///from datum/action/cyborg_small_sprite and sends when a cyborg changes modules
#define COMSIG_CYBORG_MODULE_CHANGE "cyborg_module_change"
// /datum/element/ventcrawling signals
#define COMSIG_HANDLE_VENTCRAWL "handle_ventcrawl" //when atom with ventcrawling element attempts to ventcrawl
#define COMSIG_CHECK_VENTCRAWL "check_ventcrawl" //to check an atom's ventcrawling element tier (if applicable)
/* Attack signals. They should share the returned flags, to standardize the attack chain. */
/// tool_act -> pre_attack -> target.attackby (item.attack) -> afterattack
+8
View File
@@ -0,0 +1,8 @@
#define BELLY_MIN_SIZE 0
#define BELLY_MAX_SIZE 8
#define BELLY_STRAIN_SIZE 3 // for flavor text
#define BELLY_STRETCH_SIZE 6 // for flavor text
#define BUTT_MIN_SIZE 0
#define BUTT_MAX_SIZE 5
+4
View File
@@ -285,3 +285,7 @@
#define HUMAN_CARRY_SLOWDOWN 0
#define TYPING_INDICATOR_TIMEOUT 10 MINUTES
//Gremlins
#define NPC_TAMPER_ACT_FORGET 1 //Don't try to tamper with this again
#define NPC_TAMPER_ACT_NOMSG 2 //Don't produce a visible message
+1
View File
@@ -36,6 +36,7 @@ Ask ninjanomnom if they're around
#define RAD_MEDIUM_INSULATION 0.7 // What common walls have
#define RAD_HEAVY_INSULATION 0.6 // What reinforced walls have
#define RAD_EXTREME_INSULATION 0.5 // What rad collectors have
#define RAD_NEAR_FULL_INSULATION 0.2 // What radiation shutters and specialised walls for the RBMK use.
#define RAD_FULL_INSULATION 0 // Unused
// WARNING: The deines below could have disastrous consequences if tweaked incorrectly. See: The great SM purge of Oct.6.2017
+1
View File
@@ -58,6 +58,7 @@
#define SPAN_COMMAND "command_headset"
#define SPAN_CLOWN "clown"
#define SPAN_SINGING "singing"
#define SPAN_SMALL "small"
//bitflag #defines for return value of the radio() proc.
#define ITALICS 1
+2
View File
@@ -206,6 +206,8 @@
#define TRAIT_ZAOCORP_NOGUNS "zao_no_guns"
#define INNATE_TRAIT "innate"
// common trait sources
#define TRAIT_GENERIC "generic"
#define EYE_DAMAGE "eye_damage"
+61
View File
@@ -0,0 +1,61 @@
#define MAXIMUM_MARKOV_LENGTH 25000
/proc/markov_chain(var/text, var/order = 4, var/length = 250)
if(!text || order < 0 || order > 20 || length < 1 || length > MAXIMUM_MARKOV_LENGTH)
return
var/table = markov_table(text, order)
var/markov = markov_text(length, table, order)
return markov
/proc/markov_table(var/text, var/look_forward = 4)
if(!text)
return
var/list/table = list()
for(var/i = 1, i <= length(text), i++)
var/char = copytext(text, i, look_forward+i)
if(!table[char])
table[char] = list()
for(var/i = 1, i <= (length(text) - look_forward), i++)
var/char_index = copytext(text, i, look_forward+i)
var/char_count = copytext(text, i+look_forward, (look_forward*2)+i)
if(table[char_index][char_count])
table[char_index][char_count]++
else
table[char_index][char_count] = 1
return table
/proc/markov_text(var/length = 250, var/table, var/look_forward = 4)
if(!table)
return
var/char = pick(table)
var/o = char
for(var/i = 0, i <= (length / look_forward), i++)
var/newchar = markov_weighted_char(table[char])
if(newchar)
char = newchar
o += "[newchar]"
else
char = pick(table)
return o
/proc/markov_weighted_char(var/list/array)
if(!array || !array.len)
return
var/total = 0
for(var/i in array)
total += array[i]
var/r = rand(1, total)
for(var/i in array)
var/weight = array[i]
if(r <= weight)
return i
r -= weight
+10 -2
View File
@@ -1109,7 +1109,7 @@ B --><-- A
/proc/get_random_station_turf()
return safepick(get_area_turfs(pick(GLOB.the_station_areas)))
/proc/get_safe_random_station_turf()
for (var/i in 1 to 5)
var/list/L = get_area_turfs(pick(GLOB.the_station_areas))
@@ -1273,6 +1273,14 @@ GLOBAL_REAL_VAR(list/stack_trace_storage)
animate(src, transform = M, time = halftime, easing = ELASTIC_EASING)
animate(src, transform = OM, time = halftime, easing = ELASTIC_EASING)
/atom/proc/do_twist(targetangle = 45, timer = 20)
var/matrix/OM = matrix(transform)
var/matrix/M = matrix(transform)
var/halftime = timer * 0.5
M.Turn(pick(-targetangle, targetangle))
animate(src, transform = M, time = halftime, easing = ELASTIC_EASING)
animate(src, transform = OM, time = halftime, easing = QUAD_EASING)
/atom/proc/do_squish(squishx = 1.2, squishy = 0.6, timer = 20)
var/matrix/OM = matrix(transform)
var/matrix/M = matrix(transform)
@@ -1526,7 +1534,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
blocked |= typesof(/obj/item/reagent_containers/food/drinks/prospacillin,
/obj/item/reagent_containers/food/drinks/diminicillin
)
return pick(subtypesof(/obj/item/reagent_containers/food/drinks) - blocked)
//For these two procs refs MUST be ref = TRUE format like typecaches!
+36
View File
@@ -0,0 +1,36 @@
/datum/element/ventcrawling
element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH
id_arg_index = 2
var/tier
/datum/element/ventcrawling/Attach(datum/target, duration = 0, given_tier = VENTCRAWLER_NUDE)
. = ..()
var/mob/living/person = target
if(!istype(person))
return FALSE
src.tier = given_tier
RegisterSignal(target, COMSIG_HANDLE_VENTCRAWL, .proc/handle_ventcrawl)
RegisterSignal(target, COMSIG_CHECK_VENTCRAWL, .proc/check_ventcrawl)
to_chat(target, "<span class='notice'>You can ventcrawl! Use alt+click on vents to quickly travel about the station.</span>")
if(duration!=0)
addtimer(CALLBACK(src, .proc/Detach, target), duration)
/datum/element/ventcrawling/Detach(datum/target)
UnregisterSignal(target, list(COMSIG_HANDLE_VENTCRAWL, COMSIG_CHECK_VENTCRAWL))
to_chat(target, "<span class='notice'>You can no longer ventcrawl.</span>")
return ..()
/datum/element/ventcrawling/proc/handle_ventcrawl(datum/target,atom/A)
var/mob/living/person = target
if(!istype(person))
return FALSE
person.handle_ventcrawl(A,tier)
/datum/element/ventcrawling/proc/check_ventcrawl()
return tier
+8
View File
@@ -255,3 +255,11 @@
suffix = "lavaland_surface_cozy_cabin.dmm"
allow_duplicates = FALSE
cost = 0
/datum/map_template/ruin/lavaland/jettisoned_reactor
name = "Jettisoned Reactor"
id = "jettreactor"
description = "An incredibly dangerous ruin, filled with radiation and unknown lifeforms."
suffix = "lavaland_surface_jettisoned_reactor.dmm"
allow_duplicates = FALSE
cost = 15//Not too important, if you disregard the rads and facehugger.
+12
View File
@@ -295,3 +295,15 @@
to_chat(L, "<span class='warning'>You need an attachable assembly!</span>")
#undef MAXIMUM_EMP_WIRES
//gremlins
/datum/wires/proc/npc_tamper(mob/living/L)
if(!wires.len)
return
var/wire_to_screw = pick(wires)
if(is_color_cut(wire_to_screw) || prob(50)) //CutWireColour() proc handles both cutting and mending wires. If the wire is already cut, always mend it back. Otherwise, 50% to cut it and 50% to pulse it
cut(wire_to_screw)
else
pulse(wire_to_screw, L)
+5 -2
View File
@@ -81,7 +81,6 @@
icon_state = "red"
//Xeno Nest
/area/ruin/unpowered/xenonest
name = "The Hive"
always_unpowered = TRUE
@@ -90,6 +89,10 @@
power_light = FALSE
poweralm = FALSE
//ash walker nest
//Ash Walker Nest
/area/ruin/unpowered/ash_walkers
icon_state = "red"
//Jettisoned Reactor
/area/ruin/unpowered/reactor
icon_state = "red"
@@ -844,7 +844,7 @@
typepath = /datum/round_event/spontaneous_appendicitis
enemy_roles = list("Medical Doctor","Chief Medical Officer")
required_enemies = list(2,2,2,2,2,2,2,1,1,1)
requirements = list(5,5,5,5,5,5,5,5,0,0)
requirements = list(101,101,20,18,16,14,12,10,8,6)
high_population_requirement = 10
weight = 5
cost = 6
+52
View File
@@ -91,3 +91,55 @@
/obj/machinery/door/poddoor/try_to_crowbar(obj/item/I, mob/user)
if(stat & NOPOWER)
open(1)
//Multi-tile poddoors don't turn invisible automatically, so we change the opacity of the turfs below instead one by one.
/obj/machinery/door/poddoor/multi_tile/proc/apply_opacity_to_my_turfs(var/new_opacity)
for(var/turf/T in locs)
T.opacity = new_opacity
T.has_opaque_atom = new_opacity
T.reconsider_lights()
T.air_update_turf(1)
update_freelook_sight()
/obj/machinery/door/poddoor/multi_tile
rad_insulation = RAD_NEAR_FULL_INSULATION
/obj/machinery/door/poddoor/multi_tile/open()
. = ..()
rad_insulation = RAD_NO_INSULATION
apply_opacity_to_my_turfs(0)
/obj/machinery/door/poddoor/multi_tile/close()
. = ..()
rad_insulation = RAD_NEAR_FULL_INSULATION
apply_opacity_to_my_turfs(1)
/obj/machinery/door/poddoor/multi_tile/four_tile_ver/
icon = 'icons/obj/doors/1x4blast_vert.dmi'
bound_height = 128
dir = NORTH
/obj/machinery/door/poddoor/multi_tile/three_tile_ver/
icon = 'icons/obj/doors/1x3blast_vert.dmi'
bound_height = 96
dir = NORTH
/obj/machinery/door/poddoor/multi_tile/two_tile_ver/
icon = 'icons/obj/doors/1x2blast_vert.dmi'
bound_height = 64
dir = NORTH
/obj/machinery/door/poddoor/multi_tile/four_tile_hor/
icon = 'icons/obj/doors/1x4blast_hor.dmi'
bound_width = 128
dir = EAST
/obj/machinery/door/poddoor/multi_tile/three_tile_hor/
icon = 'icons/obj/doors/1x3blast_hor.dmi'
bound_width = 96
dir = EAST
/obj/machinery/door/poddoor/multi_tile/two_tile_hor/
icon = 'icons/obj/doors/1x2blast_hor.dmi'
bound_width = 64
dir = EAST
+9 -11
View File
@@ -42,23 +42,21 @@
desc = "Lead-lined shutters painted yellow with a radioactive hazard symbol on it. Blocks out most radiation"
icon = 'icons/obj/doors/shutters_radiation.dmi'
icon_state = "closed"
rad_insulation = 0.2
rad_insulation = RAD_NEAR_FULL_INSULATION
/obj/machinery/door/poddoor/shutters/radiation/preopen
icon_state = "open"
density = FALSE
opacity = 0
rad_insulation = 1
opacity = FALSE
rad_insulation = RAD_NO_INSULATION
/obj/machinery/door/poddoor/shutters/radiation/do_animate(animation)
..()
switch(animation)
if("opening")
rad_insulation = 1
if("closing")
rad_insulation = -0.5
/obj/machinery/door/poddoor/shutters/radiation/open()
. = ..()
rad_insulation = RAD_NO_INSULATION
// A 3x3 N2 SM setup won't irradiate you if you're behind the shutter at -0.9 insulation. If it starts to delam, it'll start irradiating you slowly. Keep the value between -0.1 to -0.9
/obj/machinery/door/poddoor/shutters/radiation/close()
. = ..()
rad_insulation = RAD_NEAR_FULL_INSULATION
/obj/machinery/door/poddoor/shutters/window
name = "windowed shutters"
@@ -249,6 +249,7 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \
new/datum/stack_recipe("display case chassis", /obj/structure/displaycase_chassis, 5, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("loom", /obj/structure/loom, 10, time = 15, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("apiary", /obj/structure/beebox, 40, time = 50),\
new/datum/stack_recipe("nestbox", /obj/structure/nestbox, 4, time = 30, one_per_turf = TRUE, on_floor = TRUE),\
null, \
new/datum/stack_recipe("picture frame", /obj/item/wallframe/picture, 1, time = 10),\
new/datum/stack_recipe("mortar", /obj/item/reagent_containers/glass/mortar, 3), \
@@ -485,8 +486,8 @@ GLOBAL_LIST_INIT(cardboard_recipes, list ( \
null, \
new/datum/stack_recipe("colored brown", /obj/item/storage/box/brown), \
new/datum/stack_recipe("colored green", /obj/item/storage/box/green), \
new/datum/stack_recipe("colored red", /obj/item/storage/box/blue), \
new/datum/stack_recipe("colored blue", /obj/item/storage/box/red), \
new/datum/stack_recipe("colored red", /obj/item/storage/box/red), \
new/datum/stack_recipe("colored blue", /obj/item/storage/box/blue), \
new/datum/stack_recipe("colored yellow", /obj/item/storage/box/yellow), \
new/datum/stack_recipe("colored pink", /obj/item/storage/box/pink), \
new/datum/stack_recipe("colored purple", /obj/item/storage/box/purple), \
+40 -214
View File
@@ -613,12 +613,11 @@
if(prob(5))
name = "drone (760) action figure"
desc = "An action figure modeled after 'drone (760)', it seems to be a bit dusty."
/*
|| A Deck of Cards for playing various games of chance ||
*/
/obj/item/toy/cards
resistance_flags = FLAMMABLE
max_integrity = 50
@@ -636,7 +635,8 @@
playsound(src, 'sound/items/cardshuffle.ogg', 50, 1)
return BRUTELOSS
/obj/item/toy/cards/proc/apply_card_vars(obj/item/toy/cards/newobj, obj/item/toy/cards/sourceobj) // Applies variables for supporting multiple types of card deck
/obj/item/toy/cards/proc/apply_card_vars(obj/item/toy/cards/newobj, obj/item/toy/cards/sourceobj)
// Applies variables for supporting multiple types of card deck
if(!istype(sourceobj))
return
@@ -658,53 +658,24 @@
/obj/item/toy/cards/deck/proc/populate_deck()
icon_state = "deck_[deckstyle]_full"
for(var/i in 2 to 10)
cards += "[i] of Hearts"
cards += "[i] of Spades"
cards += "[i] of Clubs"
cards += "[i] of Diamonds"
cards += "King of Hearts"
cards += "King of Spades"
cards += "King of Clubs"
cards += "King of Diamonds"
cards += "Queen of Hearts"
cards += "Queen of Spades"
cards += "Queen of Clubs"
cards += "Queen of Diamonds"
cards += "Jack of Hearts"
cards += "Jack of Spades"
cards += "Jack of Clubs"
cards += "Jack of Diamonds"
cards += "Ace of Hearts"
cards += "Ace of Spades"
cards += "Ace of Clubs"
cards += "Ace of Diamonds"
var/_suits = list("Hearts", "Spades", "Clubs", "Diamonds")
var/_faces = list("Ace", "King", "Queen", "Jack")
for(var/suit in _suits)
for(var/i in 2 to 10)
cards += list(list(
"name" = "[i] of [suit]",
"icon_state" = "[i]of[lowertext(suit)]",
"rotation" = null,
"face_up" = null
))
for(var/i in _faces)
cards += list(list(
"name" = "[i] of [suit]",
"icon_state" = "[lowertext(i)]of[lowertext(suit)]",
"rotation" = null,
"face_up" = null
))
//ATTACK HAND IGNORING PARENT RETURN VALUE
//ATTACK HAND NOT CALLING PARENT
/obj/item/toy/cards/deck/attack_hand(mob/user)
draw_card(user)
/obj/item/toy/cards/deck/proc/draw_card(mob/user)
if(user.lying)
return
var/choice = null
if(cards.len == 0)
to_chat(user, "<span class='warning'>There are no more cards to draw!</span>")
return
var/obj/item/toy/cards/singlecard/H = new/obj/item/toy/cards/singlecard(user.loc)
if(holo)
holo.spawned += H // track them leaving the holodeck
choice = cards[1]
H.cardname = choice
H.parentdeck = src
var/O = src
H.apply_card_vars(H,O)
src.cards.Cut(1,2) //Removes the top card from the list
H.pickup(user)
user.put_in_hands(H)
user.visible_message("[user] draws a card from the deck.", "<span class='notice'>You draw a card from the deck.</span>")
update_icon()
/obj/item/toy/cards/deck/update_icon()
if(cards.len > original_size/2)
@@ -716,60 +687,6 @@
else if(cards.len == 0)
icon_state = "deck_[deckstyle]_empty"
/obj/item/toy/cards/deck/attack_self(mob/user)
if(cooldown < world.time - 50)
cards = shuffle(cards)
playsound(src, 'sound/items/cardshuffle.ogg', 50, 1)
user.visible_message("[user] shuffles the deck.", "<span class='notice'>You shuffle the deck.</span>")
cooldown = world.time
/obj/item/toy/cards/deck/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/toy/cards/singlecard))
var/obj/item/toy/cards/singlecard/SC = I
if(SC.parentdeck == src)
if(!user.temporarilyRemoveItemFromInventory(SC))
to_chat(user, "<span class='warning'>The card is stuck to your hand, you can't add it to the deck!</span>")
return
cards += SC.cardname
user.visible_message("[user] adds a card to the bottom of the deck.","<span class='notice'>You add the card to the bottom of the deck.</span>")
qdel(SC)
else
to_chat(user, "<span class='warning'>You can't mix cards from other decks!</span>")
update_icon()
else if(istype(I, /obj/item/toy/cards/cardhand))
var/obj/item/toy/cards/cardhand/CH = I
if(CH.parentdeck == src)
if(!user.temporarilyRemoveItemFromInventory(CH))
to_chat(user, "<span class='warning'>The hand of cards is stuck to your hand, you can't add it to the deck!</span>")
return
cards += CH.currenthand
user.visible_message("[user] puts [user.p_their()] hand of cards in the deck.", "<span class='notice'>You put the hand of cards in the deck.</span>")
qdel(CH)
else
to_chat(user, "<span class='warning'>You can't mix cards from other decks!</span>")
update_icon()
else
return ..()
/obj/item/toy/cards/deck/MouseDrop(atom/over_object)
. = ..()
var/mob/living/M = usr
if(!istype(M) || usr.incapacitated() || usr.lying)
return
if(Adjacent(usr))
if(over_object == M && loc != M)
M.put_in_hands(src)
to_chat(usr, "<span class='notice'>You pick up the deck.</span>")
else if(istype(over_object, /obj/screen/inventory/hand))
var/obj/screen/inventory/hand/H = over_object
if(M.putItemFromInventoryInHandIfPossible(src, H.held_index))
to_chat(usr, "<span class='notice'>You pick up the deck.</span>")
else
to_chat(usr, "<span class='warning'>You can't reach it from here!</span>")
/obj/item/toy/cards/cardhand
name = "hand of cards"
@@ -780,59 +697,9 @@
var/list/currenthand = list()
var/choice = null
/obj/item/toy/cards/cardhand/attack_self(mob/user)
var/list/handradial = list()
interact(user)
for(var/t in currenthand)
handradial[t] = image(icon = src.icon, icon_state = "sc_[t]_[deckstyle]")
if(usr.stat || !ishuman(usr))
return
var/mob/living/carbon/human/cardUser = usr
var/O = src
var/choice = show_radial_menu(usr,src, handradial, custom_check = CALLBACK(src, .proc/check_menu, user), radius = 36, require_near = TRUE)
if(!choice)
return FALSE
var/obj/item/toy/cards/singlecard/C = new/obj/item/toy/cards/singlecard(cardUser.loc)
currenthand -= choice
handradial -= choice
C.parentdeck = parentdeck
C.cardname = choice
C.apply_card_vars(C,O)
C.pickup(cardUser)
cardUser.put_in_hands(C)
cardUser.visible_message("<span class='notice'>[cardUser] draws a card from [cardUser.p_their()] hand.</span>", "<span class='notice'>You take the [C.cardname] from your hand.</span>")
interact(cardUser)
update_sprite()
if(length(currenthand) == 1)
var/obj/item/toy/cards/singlecard/N = new/obj/item/toy/cards/singlecard(loc)
N.parentdeck = parentdeck
N.cardname = currenthand[1]
N.apply_card_vars(N,O)
qdel(src)
N.pickup(cardUser)
cardUser.put_in_hands(N)
to_chat(cardUser, "<span class='notice'>You also take [currenthand[1]] and hold it.</span>")
/obj/item/toy/cards/cardhand/attackby(obj/item/toy/cards/singlecard/C, mob/living/user, params)
if(istype(C))
if(C.parentdeck == src.parentdeck)
src.currenthand += C.cardname
user.visible_message("<span class='notice'>[user] adds a card to [user.p_their()] hand.</span>", "<span class='notice'>You add the [C.cardname] to your hand.</span>")
qdel(C)
interact(user)
update_sprite(src)
else
to_chat(user, "<span class='warning'>You can't mix cards from other decks!</span>")
else
return ..()
/obj/item/toy/cards/cardhand/apply_card_vars(obj/item/toy/cards/newobj,obj/item/toy/cards/sourceobj)
..()
newobj.deckstyle = sourceobj.deckstyle
update_sprite()
newobj.card_hitsound = sourceobj.card_hitsound
newobj.card_force = sourceobj.card_force
newobj.card_throwforce = sourceobj.card_throwforce
@@ -840,6 +707,7 @@
newobj.card_throw_range = sourceobj.card_throw_range
newobj.card_attack_verb = sourceobj.card_attack_verb
newobj.resistance_flags = sourceobj.resistance_flags
update_icon()
/**
* check_menu: Checks if we are allowed to interact with a radial menu
@@ -857,13 +725,23 @@
/**
* This proc updates the sprite for when you create a hand of cards
*/
/obj/item/toy/cards/cardhand/proc/update_sprite()
/obj/item/toy/cards/cardhand/update_icon()
cut_overlays()
var/overlay_cards = currenthand.len
if(overlay_cards)
var/k = overlay_cards == 2 ? 1 : overlay_cards - 2
for(var/i = k; i <= overlay_cards; i++)
var/card_overlay = image(icon=src.icon,icon_state="sc_[currenthand[i]]_[deckstyle]",pixel_x=(1-i+k)*3,pixel_y=(1-i+k)*3)
var/_card = currenthand[i]
var/_angle = _card["rotation"] || rotation
var/matrix/rot_matrix = matrix()
rot_matrix.Turn(GetAngle(_angle))
var/image/card_overlay = image(
icon = src.icon,
icon_state = "sc_[_card["icon_state"] || _card["name"]]_[deckstyle]",
pixel_x = (1 - i + k)*3,
pixel_y = (1 - i + k)*3,
)
card_overlay.transform = rot_matrix
add_overlay(card_overlay)
/obj/item/toy/cards/singlecard
@@ -872,8 +750,7 @@
icon = 'icons/obj/toy.dmi'
icon_state = "singlecard_down_nanotrasen"
w_class = WEIGHT_CLASS_TINY
var/cardname = null
var/flipped = 0
var/card = null
pixel_x = -5
@@ -882,7 +759,9 @@
if(ishuman(user))
var/mob/living/carbon/human/cardUser = user
if(cardUser.is_holding(src))
cardUser.visible_message("[cardUser] checks [cardUser.p_their()] card.", "<span class='notice'>The card reads: [cardname].</span>")
cardUser.visible_message(
"[cardUser] checks [cardUser.p_their()] card.",
"<span class='notice'>The card reads: [card["name"]]. [card["desc"] || ""]</span>")
else
. += "<span class='warning'>You need to have the card in your hand to check it!</span>"
@@ -892,65 +771,11 @@
set src in range(1)
if(!ishuman(usr) || !usr.canUseTopic(src, BE_CLOSE))
return
if(!flipped)
src.flipped = 1
if (cardname)
src.icon_state = "sc_[cardname]_[deckstyle]"
src.name = src.cardname
else
src.icon_state = "sc_Ace of Spades_[deckstyle]"
src.name = "What Card"
src.pixel_x = 5
else if(flipped)
src.flipped = 0
src.icon_state = "singlecard_down_[deckstyle]"
src.name = "card"
src.pixel_x = -5
/obj/item/toy/cards/singlecard/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/toy/cards/singlecard/))
var/obj/item/toy/cards/singlecard/C = I
if(C.parentdeck == src.parentdeck)
var/obj/item/toy/cards/cardhand/H = new/obj/item/toy/cards/cardhand(user.loc)
H.currenthand += C.cardname
H.currenthand += src.cardname
H.parentdeck = C.parentdeck
H.apply_card_vars(H,C)
to_chat(user, "<span class='notice'>You combine the [C.cardname] and the [src.cardname] into a hand.</span>")
qdel(C)
qdel(src)
H.pickup(user)
user.put_in_active_hand(H)
else
to_chat(user, "<span class='warning'>You can't mix cards from other decks!</span>")
if(istype(I, /obj/item/toy/cards/cardhand/))
var/obj/item/toy/cards/cardhand/H = I
if(H.parentdeck == parentdeck)
H.currenthand += cardname
user.visible_message("[user] adds a card to [user.p_their()] hand.", "<span class='notice'>You add the [cardname] to your hand.</span>")
qdel(src)
H.interact(user)
if(H.currenthand.len > 4)
H.icon_state = "[deckstyle]_hand5"
else if(H.currenthand.len > 3)
H.icon_state = "[deckstyle]_hand4"
else if(H.currenthand.len > 2)
H.icon_state = "[deckstyle]_hand3"
else
to_chat(user, "<span class='warning'>You can't mix cards from other decks!</span>")
else
return ..()
/obj/item/toy/cards/singlecard/attack_self(mob/user)
if(usr.stat || !ishuman(usr) || !usr.canmove || usr.restrained())
return
Flip()
FlipCard()
/obj/item/toy/cards/singlecard/apply_card_vars(obj/item/toy/cards/singlecard/newobj,obj/item/toy/cards/sourceobj)
..()
newobj.deckstyle = sourceobj.deckstyle
newobj.icon_state = "singlecard_down_[deckstyle]" // Without this the card is invisible until flipped. It's an ugly hack, but it works.
newobj.card_hitsound = sourceobj.card_hitsound
newobj.hitsound = newobj.card_hitsound
newobj.card_force = sourceobj.card_force
@@ -963,6 +788,7 @@
newobj.throw_range = newobj.card_throw_range
newobj.card_attack_verb = sourceobj.card_attack_verb
newobj.attack_verb = newobj.card_attack_verb
newobj.update_icon()
/*
|| Syndicate playing cards, for pretending you're Gambit and playing poker for the nuke disk. ||
@@ -209,3 +209,15 @@
sheet_type = /obj/item/stack/tile/bronze
sheet_amount = 2
girder_type = /obj/structure/girder/bronze
/turf/closed/wall/mineral/lead
name = "lead lined metal wall"
desc = "A hefty wall with lead inserts."
icon = 'icons/turf/walls/riveted.dmi'
icon_state = "riveted"
sheet_type = /obj/item/stack/rods
hardness = 10
girder_type = /obj/structure/girder/reinforced
explosion_block = 2
rad_insulation = RAD_NEAR_FULL_INSULATION
canSmoothWith = list(/turf/closed/wall/mineral/lead)
+7 -7
View File
@@ -2435,14 +2435,14 @@ GLOBAL_LIST_EMPTY(preferences_datums)
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
if("belly_size")
var/new_bellysize = input(user, "Belly size :\n(1-3)", "Character Preference") as num|null
if(new_bellysize)
features["belly_size"] = clamp(new_bellysize, 1, 3)
var/new_bellysize = input(user, "Belly size :\n([BELLY_MIN_SIZE]-[BELLY_MAX_SIZE])", "Character Preference") as num|null
if(new_bellysize != null)
features["belly_size"] = clamp(new_bellysize, BELLY_MIN_SIZE, BELLY_MAX_SIZE)
if("butt_size")
var/new_buttsize = input(user, "Butt size :\n(0-5)", "Character Preference") as num|null
if(new_buttsize)
features["butt_size"] = clamp(new_buttsize, 0, 5)
var/new_buttsize = input(user, "Butt size :\n([BUTT_MIN_SIZE]-[BUTT_MAX_SIZE])", "Character Preference") as num|null
if(new_buttsize != null)
features["butt_size"] = clamp(new_buttsize, BUTT_MIN_SIZE, BUTT_MAX_SIZE)
if("vag_shape")
var/new_shape
@@ -2577,7 +2577,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(features["has_belly"] == FALSE)
features["hide_belly"] = FALSE
features["inflatable_belly"] = FALSE
features["belly_size"] = 1
features["belly_size"] = 0
if("inflatable_belly")
features["inflatable_belly"] = !features["inflatable_belly"]
+1 -1
View File
@@ -438,7 +438,7 @@
resistance_flags = NONE
armor = list("melee" = 5, "bullet" = 5, "laser" = 5, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
clothing_flags = BLOCK_GAS_SMOKE_EFFECT | ALLOWINTERNALS
flags_inv = HIDEEARS|HIDEEYES|HIDEFACE|HIDEFACIALHAIR
flags_inv = HIDEEYES|HIDEFACE|HIDEFACIALHAIR
gas_transfer_coefficient = 0.01
permeability_coefficient = 0.01
flags_cover = MASKCOVERSEYES | MASKCOVERSMOUTH
+1 -1
View File
@@ -3,7 +3,7 @@
desc = "A face-covering mask that can be connected to an air supply. While good for concealing your identity, it isn't good for blocking gas flow." //More accurate
icon_state = "gas_alt"
clothing_flags = BLOCK_GAS_SMOKE_EFFECT | ALLOWINTERNALS
flags_inv = HIDEEARS|HIDEEYES|HIDEFACE|HIDEFACIALHAIR|HIDESNOUT
flags_inv = HIDEEYES|HIDEFACE|HIDEFACIALHAIR|HIDESNOUT
w_class = WEIGHT_CLASS_NORMAL
item_state = "gas_alt"
gas_transfer_coefficient = 0.01
+1 -1
View File
@@ -27,7 +27,7 @@
icon_state = "swat"
item_state = "swat"
aggressiveness = 3
flags_inv = HIDEFACIALHAIR|HIDEFACE|HIDEEYES|HIDEEARS|HIDEHAIR
flags_inv = HIDEFACIALHAIR|HIDEFACE|HIDEEYES|HIDEHAIR
visor_flags_inv = 0
/obj/item/clothing/mask/gas/sechailer/cyborg
+54 -88
View File
@@ -2,39 +2,36 @@
// This is a parody of Cards Against Humanity (https://en.wikipedia.org/wiki/Cards_Against_Humanity)
// which is licensed under CC BY-NC-SA 2.0, the full text of which can be found at the following URL:
// https://creativecommons.org/licenses/by-nc-sa/2.0/legalcode
// Original code by Zuhayr, Polaris Station, ported with modifications
/datum/playingcard
var/name = "playing card"
var/card_icon = "card_back"
var/suit
var/number
// Original code by Zuhayr, Polaris Station, ported with modifications
// April 2022: modified by sarcoph for hyperstation
/obj/item/toy/cards/deck/cas
name = "\improper CAS deck (white)"
desc = "A deck for the game Cards Against Spess, still popular after all these centuries. Warning: may include traces of broken fourth wall. This is the white deck."
icon = 'icons/obj/toy.dmi'
icon_state = "deck_caswhite_full"
deckstyle = "caswhite"
var/card_face = "cas_white"
deckstyle = "cas"
var/card_face = "white"
var/blanks = 25
var/decksize = 150
var/card_text_file = "strings/cas_white.txt"
var/list/allcards = list()
/obj/item/toy/cards/deck/cas/black
name = "\improper CAS deck (black)"
desc = "A deck for the game Cards Against Spess, still popular after all these centuries. Warning: may include traces of broken fourth wall. This is the black deck."
icon_state = "deck_casblack_full"
deckstyle = "casblack"
card_face = "cas_black"
card_face = "black"
blanks = 0
decksize = 50
card_text_file = "strings/cas_black.txt"
/obj/item/toy/cards/deck/cas/populate_deck()
var/static/list/cards_against_space = list("cas_white" = world.file2list("strings/cas_white.txt"),"cas_black" = world.file2list("strings/cas_black.txt"))
allcards = cards_against_space[card_face]
var/list/possiblecards = allcards.Copy()
var/static/list/cards_against_space = list(
"white" = world.file2list("strings/cas_white.txt"),
"black" = world.file2list("strings/cas_black.txt")
)
var/list/_cards = cards_against_space[card_face]
var/list/possiblecards = _cards.Copy()
if(possiblecards.len < decksize) // sanity check
decksize = (possiblecards.len - 1)
var/list/randomcards = list()
@@ -42,105 +39,74 @@
randomcards += pick_n_take(possiblecards)
for(var/x in 1 to randomcards.len)
var/cardtext = randomcards[x]
var/datum/playingcard/P
P = new()
P.name = "[cardtext]"
P.card_icon = "[src.card_face]"
cards += P
cards += list(list(
"name" = cardtext,
"icon_state" = src.card_face,
"rotation" = null,
"face_up" = null
))
if(!blanks)
return
for(var/x in 1 to blanks)
var/datum/playingcard/P
P = new()
P.name = "Blank Card"
P.card_icon = "cas_white"
cards += P
shuffle_inplace(cards) // distribute blank cards throughout deck
cards += list(list(
"name" = "Blank Card",
"icon_state" = "white",
"rotation" = null,
"face_up" = null
))
/obj/item/toy/cards/deck/cas/draw_card(mob/user)
if(user.lying)
return
if(cards.len == 0)
to_chat(user, "<span class='warning'>There are no more cards to draw!</span>")
return
var/obj/item/toy/cards/singlecard/cas/H = new/obj/item/toy/cards/singlecard/cas(user.loc)
var/datum/playingcard/choice = cards[1]
if (choice.name == "Blank Card")
H.blank = 1
H.name = choice.name
H.buffertext = choice.name
H.icon_state = choice.card_icon
H.card_face = choice.card_icon
H.parentdeck = src
src.cards -= choice
H.pickup(user)
user.put_in_hands(H)
user.visible_message("[user] draws a card from the deck.", "<span class='notice'>You draw a card from the deck.</span>")
update_icon()
/obj/item/toy/cards/deck/cas/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/toy/cards/singlecard/cas))
var/obj/item/toy/cards/singlecard/cas/SC = I
if(!user.temporarilyRemoveItemFromInventory(SC))
to_chat(user, "<span class='warning'>The card is stuck to your hand, you can't add it to the deck!</span>")
return
var/datum/playingcard/RC // replace null datum for the re-added card
RC = new()
RC.name = "[SC.name]"
RC.card_icon = SC.card_face
cards += RC
user.visible_message("[user] adds a card to the bottom of the deck.","<span class='notice'>You add the card to the bottom of the deck.</span>")
qdel(SC)
/obj/item/toy/cards/deck/cas/DrawOneCard(list/card_indices)
var/obj/item/toy/cards/singlecard/cas/S = new/obj/item/toy/cards/singlecard/cas(usr.loc)
var/_card = cards[card_indices[1]]
_card["rotation"] = rotation
_card["face_up"] = face_up
if(_card["name"] == "Blank Card")
S.blank = TRUE
S.card = _card
S.card_face = card_face
S.rotation = _card["rotation"]
S.face_up = _card["face_up"]
S.parentdeck = src
S.apply_card_vars(S,src)
cards -= list(_card)
update_icon()
return S
/obj/item/toy/cards/deck/cas/update_icon()
if(cards.len < 26)
icon_state = "deck_[deckstyle]_low"
icon_state = "deck_[deckstyle][card_face]_low"
// ----------- SINGLE CARD -----------
/obj/item/toy/cards/singlecard/cas
name = "CAS card"
desc = "A CAS card."
icon_state = "cas_white"
flipped = 0
var/card_face = "cas_white"
icon_state = "sc_cas_white"
var/card_face = "white"
var/blank = 0
var/buffertext = "A funny bit of text."
/obj/item/toy/cards/singlecard/cas/examine(mob/user)
. = ..()
if (flipped)
if (!face_up)
. += "<span class='notice'>The card is face down.</span>"
else if (blank)
. += "<span class='notice'>The card is blank. Write on it with a pen.</span>"
else
. += "<span class='notice'>The card reads: [name]</span>"
. += "<span class='notice'>Alt-click to flip it.</span>"
/obj/item/toy/cards/singlecard/cas/Flip()
set name = "Flip Card"
set category = "Object"
set src in range(1)
if(!ishuman(usr) || !usr.canUseTopic(src, BE_CLOSE))
return
if(!flipped)
name = "CAS card"
else if(flipped)
name = buffertext
flipped = !flipped
update_icon()
/obj/item/toy/cards/singlecard/cas/AltClick(mob/living/user)
. = ..()
if(!ishuman(user) || !user.canUseTopic(src, BE_CLOSE))
return
Flip()
return TRUE
/obj/item/toy/cards/singlecard/cas/update_icon()
if(flipped)
icon_state = "[card_face]_flipped"
var/matrix/rot_matrix = matrix()
rot_matrix.Turn(GetAngle(rotation))
transform = rot_matrix
if(face_up)
icon_state = "sc_[deckstyle]_[card_face]"
name = card["name"]
else
icon_state = "[card_face]"
icon_state = "sc_[deckstyle]_[card_face]_flipped"
name = "CAS card"
/obj/item/toy/cards/singlecard/cas/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/pen))
@@ -181,147 +181,6 @@
else
..()
/mob/living/simple_animal/chick
name = "\improper chick"
desc = "Adorable! They make such a racket though."
icon_state = "chick"
icon_living = "chick"
icon_dead = "chick_dead"
icon_gib = "chick_gib"
gender = FEMALE
mob_biotypes = MOB_ORGANIC|MOB_BEAST
speak = list("Cherp.","Cherp?","Chirrup.","Cheep!")
speak_emote = list("cheeps")
emote_hear = list("cheeps.")
emote_see = list("pecks at the ground.","flaps its tiny wings.")
density = FALSE
speak_chance = 2
turns_per_move = 2
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/chicken = 1)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "kicks"
attacktext = "kicks"
health = 3
maxHealth = 3
ventcrawler = VENTCRAWLER_ALWAYS
var/amount_grown = 0
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
mob_size = MOB_SIZE_TINY
gold_core_spawnable = FRIENDLY_SPAWN
do_footstep = TRUE
/mob/living/simple_animal/chick/Initialize()
. = ..()
pixel_x = rand(-6, 6)
pixel_y = rand(0, 10)
/mob/living/simple_animal/chick/Life()
. =..()
if(!.)
return
if(!stat && !ckey)
amount_grown += rand(1,2)
if(amount_grown >= 100)
new /mob/living/simple_animal/chicken(src.loc)
qdel(src)
/mob/living/simple_animal/chick/holo/Life()
..()
amount_grown = 0
/mob/living/simple_animal/chicken
name = "\improper chicken"
desc = "Hopefully the eggs are good this season."
gender = FEMALE
mob_biotypes = MOB_ORGANIC|MOB_BEAST
icon_state = "chicken_brown"
icon_living = "chicken_brown"
icon_dead = "chicken_brown_dead"
speak = list("Cluck!","BWAAAAARK BWAK BWAK BWAK!","Bwaak bwak.")
speak_emote = list("clucks","croons")
emote_hear = list("clucks.")
emote_see = list("pecks at the ground.","flaps its wings viciously.")
density = FALSE
speak_chance = 2
turns_per_move = 3
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/chicken = 2)
var/egg_type = /obj/item/reagent_containers/food/snacks/egg
var/food_type = /obj/item/reagent_containers/food/snacks/grown/wheat
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "kicks"
attacktext = "kicks"
health = 15
maxHealth = 15
ventcrawler = VENTCRAWLER_ALWAYS
var/eggsleft = 0
var/eggsFertile = TRUE
var/body_color
var/icon_prefix = "chicken"
pass_flags = PASSTABLE | PASSMOB
mob_size = MOB_SIZE_SMALL
var/list/feedMessages = list("It clucks happily.","It clucks happily.")
var/list/layMessage = EGG_LAYING_MESSAGES
var/list/validColors = list("brown","black","white")
gold_core_spawnable = FRIENDLY_SPAWN
var/static/chicken_count = 0
do_footstep = TRUE
/mob/living/simple_animal/chicken/Initialize()
. = ..()
if(!body_color)
body_color = pick(validColors)
icon_state = "[icon_prefix]_[body_color]"
icon_living = "[icon_prefix]_[body_color]"
icon_dead = "[icon_prefix]_[body_color]_dead"
pixel_x = rand(-6, 6)
pixel_y = rand(0, 10)
++chicken_count
/mob/living/simple_animal/chicken/Destroy()
--chicken_count
return ..()
/mob/living/simple_animal/chicken/attackby(obj/item/O, mob/user, params)
if(istype(O, food_type)) //feedin' dem chickens
if(!stat && eggsleft < 8)
var/feedmsg = "[user] feeds [O] to [name]! [pick(feedMessages)]"
user.visible_message(feedmsg)
qdel(O)
eggsleft += rand(1, 4)
else
to_chat(user, "<span class='warning'>[name] doesn't seem hungry!</span>")
else
..()
/mob/living/simple_animal/chicken/Life()
. =..()
if(!.)
return
if((!stat && prob(3) && eggsleft > 0) && egg_type)
visible_message("<span class='alertalien'>[src] [pick(layMessage)]</span>")
eggsleft--
var/obj/item/E = new egg_type(get_turf(src))
E.pixel_x = rand(-6,6)
E.pixel_y = rand(-6,6)
if(eggsFertile)
if(chicken_count < MAX_CHICKENS && prob(25))
START_PROCESSING(SSobj, E)
/obj/item/reagent_containers/food/snacks/egg/var/amount_grown = 0
/obj/item/reagent_containers/food/snacks/egg/process()
if(isturf(loc))
amount_grown += rand(1,2)
if(amount_grown >= 100)
visible_message("[src] hatches with a quiet cracking sound.")
new /mob/living/simple_animal/chick(get_turf(src))
STOP_PROCESSING(SSobj, src)
qdel(src)
else
STOP_PROCESSING(SSobj, src)
// Space kiwis, ergo quite a copypasta of chickens.
@@ -0,0 +1,263 @@
#define GREMLIN_VENT_CHANCE 1.75
//Gremlins
//Small monsters that don't attack humans or other animals. Instead they mess with electronics, computers and machinery
//List of objects that gremlins can't tamper with (because nobody coded an interaction for it)
//List starts out empty. Whenever a gremlin finds a machine that it couldn't tamper with, the machine's type is added here, and all machines of such type are ignored from then on (NOT SUBTYPES)
GLOBAL_LIST(bad_gremlin_items)
/mob/living/simple_animal/hostile/gremlin
name = "gremlin"
desc = "This tiny creature finds great joy in discovering and using technology. Nothing excites it more than pushing random buttons on a computer to see what it might do."
icon = 'icons/mob/mob.dmi'
icon_state = "gremlin"
icon_living = "gremlin"
icon_dead = "gremlin_dead"
var/body_color
var/in_vent = FALSE
health = 20
maxHealth = 20
search_objects = 3 //Completely ignore mobs
//Tampering is handled by the 'npc_tamper()' obj proc
wanted_objects = list(
/obj/machinery,
/obj/item/reagent_containers/food,
/obj/structure/sink
)
var/obj/machinery/atmospherics/components/unary/vent_pump/entry_vent
var/obj/machinery/atmospherics/components/unary/vent_pump/exit_vent
dextrous = TRUE
possible_a_intents = list(INTENT_HELP, INTENT_GRAB, INTENT_DISARM, INTENT_HARM)
faction = list("meme", "gremlin")
speed = 0.5
gold_core_spawnable = 2
unique_name = TRUE
//Ensure gremlins don't attack other mobs
melee_damage_upper = 0
melee_damage_lower = 0
attack_sound = null
obj_damage = 0
environment_smash = ENVIRONMENT_SMASH_NONE
//List of objects that we don't even want to try to tamper with
//Subtypes of these are calculated too
var/list/unwanted_objects = list(/obj/machinery/atmospherics/pipe, /turf, /obj/structure) //ensure gremlins dont try to fuck with walls / normal pipes / glass / etc
var/min_next_vent = 0
//Amount of ticks spent pathing to the target. If it gets above a certain amount, assume that the target is unreachable and stop
var/time_chasing_target = 0
//If you're going to make gremlins slower, increase this value - otherwise gremlins will abandon their targets too early
var/max_time_chasing_target = 2
var/next_eat = 0
//Last 20 heard messages are remembered by gremlins, and will be used to generate messages for comms console tampering, etc...
var/list/hear_memory = list()
var/const/max_hear_memory = 20
/mob/living/simple_animal/hostile/gremlin/Initialize()
. = ..()
AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
ADD_TRAIT(src, TRAIT_SHOCKIMMUNE, INNATE_TRAIT)
access_card = new /obj/item/card/id(src)
var/datum/job/captain/C = new /datum/job/captain
access_card.access = C.get_access()
if(!body_color)
body_color = pick(list("orange","blue","purple", "green", "crystal"))
AddElement(/datum/element/mob_holder, "gremlin_[body_color]")
icon_state = "gremlin_[body_color]"
icon_living = "gremlin_[body_color]"
icon_dead = "gremlin_[body_color]_dead"
/mob/living/simple_animal/hostile/gremlin/AttackingTarget()
var/is_hungry = world.time >= next_eat || prob(25)
if(istype(target, /obj/item/reagent_containers/food) && is_hungry) //eat food if we're hungry or bored
visible_message("<span class='danger'>[src] hungrily devours [target]!</span>")
playsound(src, 'sound/items/eatfood.ogg', 50, 1)
qdel(target)
LoseTarget()
next_eat = world.time + rand(700, 3000) //anywhere from 70 seconds to 5 minutes until the gremlin is hungry again
return
if(istype(target, /obj))
var/obj/M = target
tamper(M)
if(prob(50)) //50% chance to move to the next machine
LoseTarget()
/mob/living/simple_animal/hostile/gremlin/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans, message_mode)
. = ..()
if(message)
hear_memory.Insert(1, raw_message)
if(hear_memory.len > max_hear_memory)
hear_memory.Cut(hear_memory.len)
/mob/living/simple_animal/hostile/gremlin/proc/generate_markov_input()
var/result = ""
for(var/memory in hear_memory)
result += memory + " "
return result
/mob/living/simple_animal/hostile/gremlin/proc/generate_markov_chain()
return markov_chain(generate_markov_input(), rand(2,5), rand(100,700)) //The numbers are chosen arbitarily
/mob/living/simple_animal/hostile/gremlin/proc/tamper(obj/M)
switch(M.npc_tamper_act(src))
if(NPC_TAMPER_ACT_FORGET)
visible_message(pick(
"<span class='notice'>\The [src] plays around with \the [M], but finds it rather boring.</span>",
"<span class='notice'>\The [src] tries to think of some more ways to screw \the [M] up, but fails miserably.</span>",
"<span class='notice'>\The [src] decides to ignore \the [M], and starts looking for something more fun.</span>"))
LAZYADD(GLOB.bad_gremlin_items,M.type)
return FALSE
if(NPC_TAMPER_ACT_NOMSG)
//Don't create a visible message
return TRUE
else
visible_message(pick(
"<span class='danger'>\The [src]'s eyes light up as \he tampers with \the [M].</span>",
"<span class='danger'>\The [src] twists some knobs around on \the [M] and bursts into laughter!</span>",
"<span class='danger'>\The [src] presses a few buttons on \the [M] and giggles mischievously.</span>",
"<span class='danger'>\The [src] rubs its hands devilishly and starts messing with \the [M].</span>",
"<span class='danger'>\The [src] turns a small valve on \the [M].</span>"))
//Add a clue for detectives to find. The clue is only added if no such clue already existed on that machine
return TRUE
/mob/living/simple_animal/hostile/gremlin/CanAttack(atom/new_target)
if(LAZYFIND(GLOB.bad_gremlin_items,new_target.type))
return FALSE
if(is_type_in_list(new_target, unwanted_objects))
return FALSE
if(istype(new_target, /obj/machinery))
var/obj/machinery/M = new_target
if(M.stat) //Unpowered or broken
return FALSE
else if(istype(new_target, /obj/machinery/door/firedoor))
var/obj/machinery/door/firedoor/F = new_target
//Only tamper with firelocks that are closed, opening them!
if(!F.density)
return FALSE
return ..()
/mob/living/simple_animal/hostile/gremlin/death(gibbed)
walk(src,0)
QDEL_NULL(access_card)
return ..()
/mob/living/simple_animal/hostile/gremlin/Life()
. = ..()
if(!health || stat == DEAD)
return
//Don't try to path to one target for too long. If it takes longer than a certain amount of time, assume it can't be reached and find a new one
if(!client) //don't do this shit if there's a client, they're capable of ventcrawling manually
if(in_vent)
target = null
if(entry_vent && get_dist(src, entry_vent) <= 1)
var/list/vents = list()
var/datum/pipeline/entry_vent_parent = entry_vent.parents[1]
for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in entry_vent_parent.other_atmosmch)
vents += temp_vent
if(!vents.len)
entry_vent = null
in_vent = FALSE
return
exit_vent = pick(vents)
visible_message("<span class='notice'>[src] crawls into the ventilation ducts!</span>")
loc = exit_vent
var/travel_time = round(get_dist(loc, exit_vent.loc) / 2)
addtimer(CALLBACK(src, .proc/exit_vents), travel_time) //come out at exit vent in 2 to 20 seconds
if(world.time > min_next_vent && !entry_vent && !in_vent && prob(GREMLIN_VENT_CHANCE)) //small chance to go into a vent
for(var/obj/machinery/atmospherics/components/unary/vent_pump/v in view(7,src))
if(!v.welded)
entry_vent = v
in_vent = TRUE
walk_to(src, entry_vent)
break
if(!target)
time_chasing_target = 0
else
if(++time_chasing_target > max_time_chasing_target)
LoseTarget()
time_chasing_target = 0
. = ..()
/mob/living/simple_animal/hostile/gremlin/EscapeConfinement()
if(istype(loc, /obj) && CanAttack(loc)) //If we're inside a machine, screw with it
var/obj/M = loc
tamper(M)
return ..()
/mob/living/simple_animal/hostile/gremlin/proc/exit_vents()
if(!exit_vent || exit_vent.welded)
loc = entry_vent
entry_vent = null
return
loc = exit_vent.loc
entry_vent = null
exit_vent = null
in_vent = FALSE
var/area/new_area = get_area(loc)
message_admins("[src] came out at [new_area][ADMIN_JMP(loc)]!")
if(new_area)
new_area.Entered(src)
visible_message("<span class='notice'>[src] climbs out of the ventilation ducts!</span>")
min_next_vent = world.time + 900 //90 seconds between ventcrawls
//This allows player-controlled gremlins to tamper with machinery
/mob/living/simple_animal/hostile/gremlin/UnarmedAttack(var/atom/A)
if(istype(A, /obj/machinery) || istype(A, /obj/structure))
tamper(A)
if(istype(target, /obj/item/reagent_containers/food)) //eat food
visible_message("<span class='danger'>[src] hungrily devours [target]!</span>", "<span class='danger'>You hungrily devour [target]!</span>")
playsound(src, 'sound/items/eatfood.ogg', 50, 1)
qdel(target)
LoseTarget()
next_eat = world.time + rand(700, 3000) //anywhere from 70 seconds to 5 minutes until the gremlin is hungry again
return ..()
/mob/living/simple_animal/hostile/gremlin/IsAdvancedToolUser()
return 1
/mob/living/simple_animal/hostile/gremlin/proc/divide()
//Health is halved and then reduced by 2. A new gremlin is spawned with the same health as the parent
//Need to have at least 6 health for this, otherwise resulting health would be less than 1
if(health < 7.5)
return
visible_message("<span class='notice'>\The [src] splits into two!</span>")
var/mob/living/simple_animal/hostile/gremlin/G = new /mob/living/simple_animal/hostile/gremlin(get_turf(src))
if(mind)
mind.transfer_to(G)
health = round(health * 0.5) - 2
maxHealth = health
resize *= 0.9
G.health = health
G.maxHealth = maxHealth
/mob/living/simple_animal/hostile/gremlin/traitor
health = 85
maxHealth = 85
gold_core_spawnable = 0
@@ -0,0 +1,214 @@
/obj/proc/npc_tamper_act(mob/living/L)
return NPC_TAMPER_ACT_FORGET
/obj/machinery/atmospherics/components/binary/passive_gate/npc_tamper_act(mob/living/L)
if(prob(50)) //Turn on/off
on = !on
investigate_log("was turned [on ? "on" : "off"] by [key_name(L)]", INVESTIGATE_ATMOS)
else //Change pressure
target_pressure = rand(0, MAX_OUTPUT_PRESSURE)
investigate_log("was set to [target_pressure] kPa by [key_name(L)]", INVESTIGATE_ATMOS)
update_icon()
/obj/machinery/atmospherics/components/binary/pump/npc_tamper_act(mob/living/L)
if(prob(50)) //Turn on/off
on = !on
investigate_log("was turned [on ? "on" : "off"] by [key_name(L)]", INVESTIGATE_ATMOS)
else //Change pressure
target_pressure = rand(0, MAX_OUTPUT_PRESSURE)
investigate_log("was set to [target_pressure] kPa by [key_name(L)]", INVESTIGATE_ATMOS)
update_icon()
/obj/machinery/atmospherics/components/binary/volume_pump/npc_tamper_act(mob/living/L)
if(prob(50)) //Turn on/off
on = !on
investigate_log("was turned [on ? "on" : "off"] by [key_name(L)]", INVESTIGATE_ATMOS)
else //Change pressure
transfer_rate = rand(0, MAX_TRANSFER_RATE)
investigate_log("was set to [transfer_rate] L/s by [key_name(L)]", INVESTIGATE_ATMOS)
update_icon()
/obj/machinery/atmospherics/components/binary/valve/npc_tamper_act(mob/living/L)
attack_hand(L)
/obj/machinery/space_heater/npc_tamper_act(mob/living/L)
var/list/choose_modes = list("standby", "heat", "cool")
if(prob(50))
choose_modes -= mode
mode = pick(choose_modes)
else
on = !on
update_icon()
/obj/machinery/shield_gen/npc_tamper_act(mob/living/L)
attack_hand(L)
/obj/machinery/firealarm/npc_tamper_act(mob/living/L)
alarm()
/obj/machinery/airalarm/npc_tamper_act(mob/living/L)
if(panel_open)
wires.npc_tamper(L)
else
panel_open = !panel_open
/obj/machinery/ignition_switch/npc_tamper_act(mob/living/L)
attack_hand(L)
/obj/machinery/flasher_button/npc_tamper_act(mob/living/L)
attack_hand(L)
/obj/machinery/crema_switch/npc_tamper_act(mob/living/L)
attack_hand(L)
/obj/machinery/camera/npc_tamper_act(mob/living/L)
if(!panel_open)
panel_open = !panel_open
if(wires)
wires.npc_tamper(L)
/obj/machinery/atmospherics/components/unary/cryo_cell/npc_tamper_act(mob/living/L)
if(prob(50))
if(beaker)
beaker.forceMove(loc)
beaker = null
else
if(occupant)
if(state_open)
if (close_machine() == usr)
on = TRUE
else
open_machine()
/obj/machinery/door_control/npc_tamper_act(mob/living/L)
attack_hand(L)
/obj/machinery/door/airlock/npc_tamper_act(mob/living/L)
//Open the firelocks as well, otherwise they block the way for our gremlin which isn't fun
for(var/obj/machinery/door/firedoor/F in get_turf(src))
if(F.density)
F.npc_tamper_act(L)
if(prob(40)) //40% - mess with wires
if(!panel_open)
panel_open = !panel_open
if(wires)
wires.npc_tamper(L)
else //60% - just open it
open()
/obj/machinery/gibber/npc_tamper_act(mob/living/L)
attack_hand(L)
/obj/machinery/light_switch/npc_tamper_act(mob/living/L)
attack_hand(L)
/obj/machinery/turretid/npc_tamper_act(mob/living/L)
enabled = rand(0, 1)
lethal = rand(0, 1)
updateTurrets()
/obj/machinery/vending/npc_tamper_act(mob/living/L)
if(!panel_open)
panel_open = !panel_open
if(wires)
wires.npc_tamper(L)
/obj/machinery/shower/npc_tamper_act(mob/living/L)
attack_hand(L)
/obj/machinery/deepfryer/npc_tamper_act(mob/living/L)
//Deepfry a random nearby item
var/list/pickable_items = list()
for(var/obj/item/I in range(1, L))
pickable_items.Add(I)
if(!pickable_items.len)
return
var/obj/item/I = pick(pickable_items)
attackby(I, L) //shove the item in, even if it can't be deepfried normally
/obj/machinery/power/apc/npc_tamper_act(mob/living/L)
if(!panel_open)
panel_open = !panel_open
if(wires)
wires.npc_tamper(L)
/obj/machinery/power/rad_collector/npc_tamper_act(mob/living/L)
attack_hand(L)
/obj/machinery/power/emitter/npc_tamper_act(mob/living/L)
attack_hand(L)
/obj/machinery/particle_accelerator/control_box/npc_tamper_act(mob/living/L)
if(!panel_open)
panel_open = !panel_open
if(wires)
wires.npc_tamper(L)
/obj/machinery/computer/communications/npc_tamper_act(mob/living/user)
if(!authenticated)
if(prob(20)) //20% chance to log in
authenticated = TRUE
else //Already logged in
if(prob(50)) //50% chance to log off
authenticated = FALSE
else if(istype(user, /mob/living/simple_animal/hostile/gremlin)) //make a hilarious public message
var/mob/living/simple_animal/hostile/gremlin/G = user
var/result = G.generate_markov_chain()
if(result)
if(prob(85))
SScommunications.make_announcement(G, FALSE, result)
var/turf/T = get_turf(G)
log_say("[key_name(usr)] ([ADMIN_JMP(T)]) has made a captain announcement: [result]")
message_admins("[key_name_admin(G)] has made a captain announcement.", 1)
else
if(SSshuttle.emergency.mode == SHUTTLE_IDLE)
SSshuttle.requestEvac(G, result)
else if(SSshuttle.emergency.mode == SHUTTLE_ESCAPE)
SSshuttle.cancelEvac(G)
/obj/machinery/button/door/npc_tamper_act(mob/living/L)
attack_hand(L)
/obj/machinery/sleeper/npc_tamper_act(mob/living/L)
if(prob(75))
inject_chem(pick(available_chems))
else
if(state_open)
close_machine()
else
open_machine()
/obj/machinery/power/smes/npc_tamper_act(mob/living/L)
if(prob(50)) //mess with input
input_level = rand(0, input_level_max)
else //mess with output
output_level = rand(0, output_level_max)
/obj/machinery/syndicatebomb/npc_tamper_act(mob/living/L) //suicide bomber gremlins
if(!open_panel)
open_panel = !open_panel
if(wires)
wires.npc_tamper(L)
/obj/machinery/computer/bank_machine/npc_tamper_act(mob/living/L)
siphoning = !siphoning
/obj/machinery/computer/slot_machine/npc_tamper_act(mob/living/L)
spin(L)
/obj/structure/sink/npc_tamper_act(mob/living/L)
if(istype(L, /mob/living/simple_animal/hostile/gremlin))
visible_message("<span class='danger'>\The [L] climbs into \the [src] and turns the faucet on!</span>")
var/mob/living/simple_animal/hostile/gremlin/G = L
G.divide()
return NPC_TAMPER_ACT_NOMSG
@@ -0,0 +1,44 @@
/datum/round_event_control/gremlin
name = "Spawn Gremlins"
typepath = /datum/round_event/gremlin
weight = 15
max_occurrences = 2
earliest_start = 20 MINUTES
min_players = 5
/datum/round_event/gremlin
var/static/list/acceptable_spawns = list("xeno_spawn", "generic event spawn", "blobstart", "Assistant")
/datum/round_event/gremlin/announce()
priority_announce("Bioscans indicate that some gremlins entered through the vents. Deal with them!", "Gremlin Alert", 'sound/ai/beep.ogg')
/datum/round_event/gremlin/start()
var/list/spawn_locs = list()
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
if(isturf(L.loc) && !isspaceturf(L.loc))
if(L.name in acceptable_spawns)
spawn_locs += L.loc
if(!spawn_locs.len) //If we can't find any gremlin spawns, try the xeno spawns
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
if(isturf(L.loc))
switch(L.name)
if("Assistant")
spawn_locs += L.loc
if(!spawn_locs.len) //If we can't find THAT, then just give up and cry
return MAP_ERROR
var/gremlins_to_spawn = rand(2,5)
var/list/gremlin_areas = list()
for(var/i = 0, i <= gremlins_to_spawn, i++)
var/spawnat = pick(spawn_locs)
spawn_locs -= spawnat
gremlin_areas += get_area(spawnat)
new /mob/living/simple_animal/hostile/gremlin(spawnat)
var/grems = gremlin_areas.Join(", ")
message_admins("Gremlins have been spawned at the areas: [grems]")
log_game("Gremlins have been spawned at the areas: [grems]")
return SUCCESSFUL_SPAWN
@@ -1001,3 +1001,5 @@
glass_desc = "A Summer time drink that can be frozen and eaten or Drinked from a glass!"
glass_name = "Orange Creamsicle"
hydration = 4
@@ -158,10 +158,10 @@
var/altered_height
altered_height = input(user, "Choose your desired sprite size:\n([MIN_BODYSIZE]-400%)", "Height Alteration") as num|null
if(altered_height)
H.size_multiplier = (max(min( round(text2num(altered_height)),400),MIN_BODYSIZE))/100
H.size_multiplier = (max(min( round(text2num(altered_height)),1000),MIN_BODYSIZE))/100
playsound(user.loc, pshoom_or_beepboopblorpzingshadashwoosh, 40, 1)
do_sparks(5, FALSE, user.loc)
H.visible_message("<span class='danger'>[pick("[H] shifts in size!", "[H] alters in height!", "[H] reshapes into a new stature!")]</span>")
else
return
return
+1 -1
View File
@@ -195,7 +195,7 @@
burn_dam += burn
if(status == BODYPART_ORGANIC) //pain is only applied to organic organs, because nerves.
pain_dam += (brute+burn)*1.2 //add the total damage applied to the limb as pain damage, build pain quicker, because sudden pain is more.. painful.
pain_dam += (brute+burn)*1.05 //add the total damage applied to the limb as pain damage, build pain quicker, because sudden pain is more.. painful.
//We've dealt the physical damages, if there's room lets apply the stamina damage.
var/current_damage = get_damage(TRUE) //This time around, count stamina loss too.
+2 -1
View File
@@ -111,7 +111,8 @@
/obj/item/clothing/ears/headphones = 2,
/obj/item/clothing/head/wig/random = 3,
/obj/item/clothing/suit/ran = 2,
/obj/item/clothing/head/ran = 2)
/obj/item/clothing/head/ran = 2,
/obj/item/clothing/under/vaultsuit = 3)
contraband = list(/obj/item/clothing/suit/judgerobe = 1,
/obj/item/clothing/head/powdered_wig = 1,
/obj/item/gun/magic/wand = 2,
+2
View File
@@ -111,6 +111,7 @@
/obj/item/clothing/suit/toggle/jacket_white = 3,
/obj/item/clothing/suit/jacket/letterman_red = 3,
/obj/item/clothing/suit/fluffyhalfcrop = 3,
/obj/item/clothing/under/officesexy = 3,
/obj/item/clothing/ears/headphones = 10,
/obj/item/clothing/suit/apron/purple_bartender = 4,
/obj/item/clothing/under/rank/bartender/purple = 4,
@@ -133,6 +134,7 @@
/obj/item/clothing/head/cowboyhat/pink = 3,
/obj/item/clothing/shoes/cowboyboots = 3,
/obj/item/clothing/shoes/cowboyboots/black = 3,
/obj/item/clothing/under/raccveralls = 3,
/obj/item/clothing/under/polychromic/vsweater = 3)
contraband = list(/obj/item/clothing/under/syndicate/tacticool = 3,
/obj/item/clothing/under/syndicate/tacticool/skirt = 3,
+2 -1
View File
@@ -46,7 +46,8 @@
/obj/item/seeds/tower = 3,
/obj/item/seeds/watermelon = 3,
/obj/item/seeds/wheat = 3,
/obj/item/seeds/whitebeet = 3)
/obj/item/seeds/whitebeet = 3,
/obj/item/seeds/kalyna = 3) //Hyperstation addition
contraband=list(/obj/item/seeds/amanita = 2,
/obj/item/seeds/glowshroom = 2,
@@ -0,0 +1,38 @@
//A spooky element, this can be added to pretty much anything, take your pick. It is effectively harmless however.
//target.AddElement(/datum/element/spooky) for example.
/datum/element/spooky
element_flags = ELEMENT_DETACH
var/datum/C
/datum/element/spooky/Attach(datum/target)
. = ..()
/*
if(!iscarbon(target))
return ELEMENT_INCOMPATIBLE //keeping this uncommented would make it so it only works with carbons, which is not really needed unless one adds procs that require the user to be a carbon in the future.
*/
C = target
START_PROCESSING(SSobj, src)
/datum/element/spooky/Detach(datum/source, force)
. = ..()
STOP_PROCESSING(SSobj, src)
/datum/element/spooky/process()
var/spookythings = rand(120)
switch(spookythings)
if(119 to 120) //Plays a spooky ambient sound as long as one hasn't been played in a while.
var/sound = pick(SPOOKY)
for(var/mob/living/carbon/L in view(6, C))
if(L.client && !L.client.played)
SEND_SOUND(L, sound(sound, repeat = 0, wait = 0, volume = 35, channel = CHANNEL_AMBIENCE))
L.client.played = TRUE
addtimer(CALLBACK(L.client, /client/proc/ResetAmbiencePlayed), 600)
if(65 to 70) //Lights flicker.
var/obj/machinery/light/L = locate(/obj/machinery/light) in view(4, C)
if(L)
L.flicker()
if(1 to 5) //Very small chance to cause an unburnt tile to change to its burnt sprite.
var/turf/open/floor/T = locate(/turf/open/floor) in view(4, C)
if(T && prob(5) && !isplatingturf(T) && !istype(T, /turf/open/floor/engine/cult) && !T.burnt)
T.burn_tile()
@@ -0,0 +1,464 @@
/*
* cards rework; uses TGUI and allows in-depth manipulation of cards, such as
* angles, flip states, drawing a number of cards at once, peeking, etc.
*
* sarcoph march 2022
*/
#define CARD_ROTATION_UP "upright"
#define CARD_ROTATION_SIDE "sideways"
#define CARD_ROTATION_DOWN "reversed"
// ================================= GENERAL CARDS =================================
/obj/item/toy/cards
var/face_up = FALSE
var/rotation = CARD_ROTATION_UP
var/merge_rank = 0
/obj/item/toy/cards/proc/GetAngle(_dir)
var/_angle = 0
switch(_dir)
if(CARD_ROTATION_UP)
_angle = 0
if(CARD_ROTATION_SIDE)
_angle = 90
if(CARD_ROTATION_DOWN)
_angle = 180
return _angle
/obj/item/toy/cards/proc/GetNextAngle(angle)
var/list/_rotations = list(CARD_ROTATION_UP, CARD_ROTATION_SIDE, CARD_ROTATION_DOWN)
var/list/_indexof = _rotations.Find(rotation)
return _rotations[_indexof%3 + 1]
/obj/item/toy/cards/proc/RotateCards(angle)
if(angle)
rotation = angle
else
rotation = GetNextAngle(angle)
update_icon()
/obj/item/toy/cards/proc/FlipCards(side)
if(side != null) face_up = side
else face_up = !face_up
update_icon()
/**
* Handles functionality for merging different types of cards.
*
* Arguments:
* * target - The "greater" card item that this object is going to merge into.
* * user - The mob that is performing this merge.
*
* Returns:
* * TRUE/FALSE: Whether or not this logic is considered "processed" - i.e., a merge
* was actually attempted.
*/
/obj/item/toy/cards/proc/MergeInto(obj/item/toy/cards/target, mob/living/user)
if(target.parentdeck != src && src.parentdeck != target && src.parentdeck != target.parentdeck)
to_chat(user, "<span class='warning'>You can't mix cards from other decks!</span>")
return TRUE
if(!user.temporarilyRemoveItemFromInventory(src))
to_chat(user, "<span class='warning'>\The [src] is stuck to your hand, you can't add it to \the [target]!</span>")
return TRUE
return FALSE
// unimplemented
/**
* Announces card(s) being added to a deck, and then deletes the card(s).
*/
/obj/item/toy/cards/proc/FinishMergingCards(obj/item/toy/cards/target, mob/living/user)
return FALSE // unimplemented
/obj/item/toy/cards/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/toy/cards))
var/obj/item/toy/cards/C = I
var/obj/item/toy/cards/greater = merge_rank > C.merge_rank ? src : C
var/obj/item/toy/cards/lesser = greater == src ? C : src
if(lesser.MergeInto(greater, user)) return
else
return ..()
// ================================= DECK OF CARDS =================================
/obj/item/toy/cards/deck
var/peeking = FALSE
var/dealing = FALSE
merge_rank = 3
/**
* Randomizes positions of all cards in a deck, plays a nice sound,
* and announces this to the `user`'s surroundings. There is a small
* cooldown.
*
* Arguments:
* * user - The `mob` shuffling this deck of cards.
*/
/obj/item/toy/cards/deck/proc/ShuffleCards(mob/user)
if(cooldown < world.time - 5 SECONDS)
cards = shuffle(cards)
playsound(src, 'sound/items/cardshuffle.ogg', 50, 1)
user.visible_message("[user] shuffles the deck.", "<span class='notice'>You shuffle the deck.</span>")
cooldown = world.time
/**
* Draws cards into a new hand from a list of indices, turning those new
* cards into a hand.
*
* Arguments:
* * card_indices - The `list` of card indices to remove from `cards`.
*
* Returns:
* * /obj/item/toy/cards/cardhand - A new hand containing the removed cards.
* OR
* * /obj/item/toy/cards/singlecard - A single card, if there is only one index.
*/
/obj/item/toy/cards/deck/proc/DrawCards(list/card_indices)
if(card_indices.len == 1) return DrawOneCard(card_indices)
var/obj/item/toy/cards/cardhand/H = new/obj/item/toy/cards/cardhand(usr.loc)
var/list/cards_to_remove = list()
for(var/C in card_indices)
var/card_to_add = cards[C]
card_to_add["rotation"] = rotation
card_to_add["face_up"] = face_up
H.currenthand += list(card_to_add)
cards_to_remove += list(card_to_add)
cards -= cards_to_remove
H.parentdeck = src
H.apply_card_vars(H,src)
update_icon()
return H
/obj/item/toy/cards/deck/proc/DrawOneCard(list/card_indices)
var/obj/item/toy/cards/singlecard/S = new/obj/item/toy/cards/singlecard(usr.loc)
var/_card = cards[card_indices[1]]
_card["rotation"] = rotation
_card["face_up"] = face_up
S.card = _card
S.rotation = _card["rotation"]
S.face_up = _card["face_up"]
S.parentdeck = src
S.apply_card_vars(S,src)
cards -= list(_card)
return S
/obj/item/toy/cards/deck/FinishMergingCards(obj/item/toy/cards/target, mob/living/user)
var/message = "[user] adds \the [target] to the bottom of \the [src]."
var/self_message = "<span class='notice'>You add \the [target] to the bottom of \the [src].</span>"
user.visible_message(message, self_message)
qdel(target)
update_icon()
/obj/item/toy/cards/deck/examine(mob/user)
. = ..()
. += "<span class='notice'>Alt-Click to quick-draw a card.</span>"
/obj/item/toy/cards/deck/AltClick(mob/user)
. = ..()
if(!ishuman(usr) || !usr.canUseTopic(src, BE_CLOSE))
return
var/obj/item/toy/cards/drawn = DrawCards(list(1))
drawn.pickup(user)
user.put_in_hands(drawn)
to_chat(user, "<span class='notice'>You draw \a [drawn] from \the [src].</span>")
// =================== TGUI stuff ===================
/obj/item/toy/cards/deck/ui_interact(mob/user, ui_key, datum/tgui/ui, force_open, datum/tgui/master_ui, datum/tgui_state/state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "CardsDeck", name, 300, 400, master_ui, state)
ui.open()
/obj/item/toy/cards/deck/ui_act(action, params)
if(..())
return
var/list/targets = list(usr, src)
switch(action)
if("deal")
var/n_cards = text2num(params["count"])
var/n_hands = text2num(params["hands"])
if(dealing) return FALSE
if(!n_cards || !n_hands) return FALSE
if(n_cards * n_hands > cards.len)
to_chat(usr, "<span class='warning'>You can't deal more cards than there are in the deck!</span>")
return FALSE
dealing = TRUE
to_chat(usr, "<span class='notice'>You get ready to deal cards...</span>")
if(do_after_mob(usr, targets, 1 SECONDS, progress=TRUE))
visible_message("[usr] begins dealing cards.")
var/list/holder = list()
var/broken = FALSE
for(var/C = 1, C <= n_cards, C++) holder += C // card indices placeholder
for(var/H = 1, H <= n_hands, H++)
if(do_after_mob(usr, targets, 0.5 SECONDS, progress=TRUE) && dealing)
var/obj/item/toy/cards/hand = DrawCards(holder)
step(hand, GLOB.alldirs[H])
else
broken = TRUE
break
if(broken)
visible_message("<span class='danger'>[usr] stops in the middle of dealing cards!</span>")
dealing = FALSE
if("draw")
if(!params["cards"]) return FALSE
var/list/P = splittext(params["cards"], ",")
var/list/P_cards = list()
for(var/T in P)
P_cards += text2num(T) + 1
var/obj/item/toy/cards/H = DrawCards(P_cards)
H.pickup(usr)
usr.put_in_hands(H)
if("flip")
var/P_side = params["side"]
var/flip_side = null
if(P_side)
flip_side = P_side == "face_down" ? FALSE : P_side == "face_up" ? TRUE : null
FlipCards(flip_side)
return TRUE
if("peek")
visible_message("<span class='warning'>[usr] is peeking in \the [name]!</span>")
if(do_after_mob(usr, targets, 3 SECONDS, progress=TRUE))
to_chat(usr, "<span class='notice'>You peek into \the [name].</span>")
peeking = TRUE
if("rotate")
RotateCards(params["angle"])
return TRUE
if("shuffle")
peeking = FALSE
ShuffleCards(usr)
update_icon()
return TRUE
/obj/item/toy/cards/deck/ui_data(mob/user)
var/list/data = list()
data["face_up"] = face_up
data["rotation"] = rotation
data["cards"] = cards
data["name"] = name
data["peeking"] = peeking
return data
/obj/item/toy/cards/deck/ui_static_data(mob/user)
var/list/data = list()
data["possible_rotations"] = list(CARD_ROTATION_UP, CARD_ROTATION_SIDE, CARD_ROTATION_DOWN)
return data
/obj/item/toy/cards/deck/ui_close()
dealing = FALSE
peeking = FALSE
// ================================= HAND OF CARDS =================================
/obj/item/toy/cards/cardhand
merge_rank = 2
face_up = TRUE
/obj/item/toy/cards/cardhand/proc/QuickAnnounce(mob/living/user)
if(!user.is_holding(src))
to_chat(user, "<span class='warning'>You need to be holding \the [src] to show it!</span>")
return
if(user.stat || user.restrained())
return
var/list/temp_cards = list()
var/facedown = 0
for(var/C in currenthand)
var/_flipped = C["face_up"] || face_up
var/_angle = C["rotation"] || rotation
if(_flipped)
if(is_all_same_direction())
temp_cards += "\a [C["name"]]"
else
temp_cards += "\a [_angle] [C["name"]]"
else
facedown++
if(facedown > 0)
temp_cards += "[facedown] unrevealed card\s"
visible_message("<span class='notice'>[user] shows [user.p_their()] hand: [english_list(temp_cards)].</span>")
/obj/item/toy/cards/cardhand/proc/is_all_same_direction()
var/compare_orient = currenthand[1]["rotation"]
for(var/list/C in currenthand)
var/_rotation = C["rotation"] || rotation
if(_rotation != compare_orient) return FALSE
return TRUE
/obj/item/toy/cards/cardhand/proc/DrawOneCard(list/card_indices)
var/obj/item/toy/cards/singlecard/S = new/obj/item/toy/cards/singlecard(usr.loc)
var/_card = currenthand[card_indices[1]]
S.card = _card
S.rotation = _card["rotation"]
S.face_up = _card["face_up"]
S.parentdeck = src.parentdeck
S.apply_card_vars(S,src)
currenthand -= list(_card)
S.update_icon()
update_icon()
return S
/obj/item/toy/cards/cardhand/MergeInto(obj/item/toy/cards/target, mob/living/user)
if(..())
return TRUE
if(istype(target, /obj/item/toy/cards/deck))
var/obj/item/toy/cards/deck/C = target
for(var/_card = 1, _card < currenthand.len, _card++)
currenthand[_card]["rotation"] = null
currenthand[_card]["face_up"] = null
C.cards += currenthand
C.FinishMergingCards(src, user)
else if(istype(target, /obj/item/toy/cards/cardhand))
if(do_after_mob(user, list(user,src,target), 0.5 SECONDS))
var/obj/item/toy/cards/cardhand/C = target
C.currenthand += currenthand
C.FinishMergingCards(src, user)
else
return FALSE
return TRUE
/obj/item/toy/cards/cardhand/FinishMergingCards(obj/item/toy/cards/target, mob/living/user)
user.visible_message("[user] combines \the [target] into [user.p_their()] hand.",\
"<span class='notice'>You combine \the [target] into the [src].</span>")
qdel(target)
update_icon()
/obj/item/toy/cards/cardhand/examine(mob/user)
. = ..()
. += "<span class='notice'>Alt-Click to quick-announce your deck.</span>"
/obj/item/toy/cards/cardhand/AltClick(mob/user)
. = ..()
QuickAnnounce(user)
// =================== TGUI stuff ===================
/obj/item/toy/cards/cardhand/ui_interact(mob/user, ui_key, datum/tgui/ui, force_open, datum/tgui/master_ui, datum/tgui_state/state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "CardsHand", name, 300, 400, master_ui, state)
ui.open()
/obj/item/toy/cards/cardhand/ui_act(action, params)
if(..())
return
switch(action)
if("draw")
if(!params["cards"]) return FALSE
var/list/P = splittext(params["cards"], ",")
var/list/P_cards = list()
for(var/T in P)
P_cards += text2num(T) + 1
var/obj/item/toy/cards/H = DrawOneCard(P_cards)
H.pickup(usr)
usr.put_in_hands(H)
if("flip")
if(!params["card"]) return FALSE
var/card = currenthand[text2num(params["card"]) + 1]
card["face_up"] = !card["face_up"]
if("rotate")
if(!params["card"]) return FALSE
var/card = currenthand[text2num(params["card"]) + 1]
if(params["angle"])
card["rotation"] = params["angle"]
update_icon()
return TRUE
/obj/item/toy/cards/cardhand/ui_data(mob/user)
var/list/data = list()
data["cards"] = currenthand
data["name"] = name
return data
/obj/item/toy/cards/cardhand/ui_static_data(mob/user)
var/list/data = list()
data["possible_rotations"] = list(CARD_ROTATION_UP, CARD_ROTATION_SIDE, CARD_ROTATION_DOWN)
return data
// ================================= SINGLE CARDS =================================
/obj/item/toy/cards/singlecard
merge_rank = 1
/obj/item/toy/cards/singlecard/MergeInto(obj/item/toy/cards/target, mob/living/user)
if(..())
return TRUE
if(istype(target, /obj/item/toy/cards/deck))
var/obj/item/toy/cards/deck/C = target
card["rotation"] = null
card["face_up"] = null
C.cards += list(card)
C.FinishMergingCards(src, user)
else if(istype(target, /obj/item/toy/cards/cardhand))
var/obj/item/toy/cards/cardhand/C = target
C.currenthand += list(card)
C.FinishMergingCards(src, user)
else if(istype(target, /obj/item/toy/cards/singlecard))
var/obj/item/toy/cards/singlecard/C = target
var/obj/item/toy/cards/cardhand/H = new/obj/item/toy/cards/cardhand(user.loc)
H.currenthand += list(C.card)
H.currenthand += list(src.card)
H.parentdeck = C.parentdeck
H.apply_card_vars(H,C)
H.pickup(user)
user.put_in_hands(H)
C.FinishMergingCards(src, user)
else
return FALSE
return TRUE
/obj/item/toy/cards/singlecard/proc/FlipCard(mob/user)
if(!ishuman(usr) || !usr.canUseTopic(src, BE_CLOSE))
return
FlipCards()
to_chat(user, "<span class='notice'>You flip \the [src] [(face_up ? "face-up" : "face-down")]</span>.")
/obj/item/toy/cards/singlecard/proc/RotateCard(mob/user, var/rotation_angle)
if(!ishuman(usr) || !usr.canUseTopic(src, BE_CLOSE))
return
to_chat(user, "<span class='notice'>You turn \the [src] to \a [rotation_angle] position.</span>")
RotateCards(rotation_angle)
/obj/item/toy/cards/singlecard/FinishMergingCards(obj/item/toy/cards/singlecard/target, mob/living/user)
to_chat(user, "<span class='notice'>You combine the [target.card["name"]] and the [src.card["name"]] into a hand.</span>")
qdel(target)
qdel(src)
update_icon()
/obj/item/toy/cards/singlecard/examine(mob/user)
. = ..()
. += "<span class='notice'>Click to flip. Alt-Click to rotate.</span>"
/obj/item/toy/cards/singlecard/attack_self(mob/user)
. = ..()
FlipCard(user)
/obj/item/toy/cards/singlecard/AltClick(mob/user)
. = ..()
RotateCard(user, GetNextAngle(rotation))
/obj/item/toy/cards/singlecard/update_icon()
. = ..()
var/matrix/rot_matrix = matrix()
rot_matrix.Turn(GetAngle(rotation))
transform = rot_matrix
var/rotation_name = (rotation == CARD_ROTATION_UP ? "" : rotation + " ")
if(face_up)
if(card)
src.icon_state = "sc_[card["icon_state"] || card["name"]]_[deckstyle]"
src.name = rotation_name + src.card["name"]
else
src.icon_state = "sc_aceofspades_[deckstyle]"
src.name = "What Card"
src.pixel_x = 5
else
src.icon_state = "singlecard_down_[deckstyle]"
src.name = rotation_name + "card"
src.pixel_x = -5
@@ -0,0 +1,92 @@
/*
lover's dice: based off a really funny yakuza gif i saw on tumblr years ago
these give suggestions for sex acts to perform. it's stupid but fun.
sarcoph mar 2022
*/
// dice bag
/obj/item/storage/pill_bottle/lovedice
name = "bag of love dice"
desc = "Contains all the intimate ideas you'll ever need. A game that everyone wins!"
icon = 'hyperstation/icons/obj/toy.dmi'
icon_state = "lovedicebag"
price = 1
/obj/item/storage/pill_bottle/lovedice/Initialize()
. = ..()
new /obj/item/dice/lover/d6_gesture(src)
new /obj/item/dice/lover/d6_location(src)
new /obj/item/dice/lover/d6_action(src)
new /obj/item/dice/lover/d6_bodypart(src)
// dice
/obj/item/dice/lover
desc = "A die with six sides to inspire some bedroom action."
icon = 'hyperstation/icons/obj/toy.dmi'
sides = 6
/obj/item/dice/lover/update_icon()
return // override the dice proc for this, there is no overlay
/obj/item/dice/lover/examine(mob/user)
. = ..() // again, no overlays
. += "<span class='notice'>The top reads [result].</span>"
// actual dice
/obj/item/dice/lover/d6_gesture
name = "lover's d6 (v1)"
desc = "A die with six sides to inspire some bedroom action. This one has intimate gestures."
icon_state = "loved6_1"
special_faces = list(
"Let's hug",
"Let's kiss",
"Let's play",
"Let's fuck", // it actually says "let's do it" on the irl ones lol
"Let's wrestle",
"Let's ?"
)
/obj/item/dice/lover/d6_location
name = "lover's d6 (v2)"
desc = "A die with six sides to inspire some bedroom action. This one has different locations."
icon_state = "loved6_2"
special_faces = list(
"On a chair",
"On the bed",
"On the floor",
"In the closet",
"In the bathtub",
"In the ?"
)
/obj/item/dice/lover/d6_action
name = "lover's d6 (v3)"
desc = "A die with six sides to inspire some bedroom action. This one has different actions."
icon_state = "loved6_3"
special_faces = list(
"Caress my",
"Kiss my",
"Grab my",
"Rub my",
"Tickle my",
"Surprise!"
)
/obj/item/dice/lover/d6_bodypart
name = "lover's d6 (v4)"
desc = "A die with six sides to inspire some bedroom action. This one has body parts."
icon_state = "loved6_4"
special_faces = list(
"Back",
"Chest",
"Face",
"Ass",
"Genitals",
"Surprise!"
)
+4 -1
View File
@@ -151,15 +151,18 @@
usr.visible_message("<span class='warning'>[user] starts climbing onto \the [src]!</span>")
if(!do_after(user, 20))
if(!do_after(user, 15, src))
return
if(get_turf(user) == get_turf(src))
usr.dir = get_dir(usr.loc, get_step(src, src.dir))//turn and face railing
usr.forceMove(get_step(src, src.dir))
else
usr.dir = get_dir(usr.loc, loc)//turn and face railing
usr.forceMove(get_turf(src))
usr.visible_message("<span class='warning'>[user] climbed over \the [src]!</span>")
usr.do_twist(targetangle = 45, timer = 8)
/obj/structure/railing/handrail
name = "handrail"
+3 -1
View File
@@ -7,7 +7,8 @@
icon_state = "crystal"
icon_living = "crystal"
icon_dead = "crystal"
mob_biotypes = MOB_BEAST
gender = NEUTER
mob_biotypes = MOB_INORGANIC
speak_chance = 0
turns_per_move = 10
response_help = "touches"
@@ -29,6 +30,7 @@
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
maxbodytemp = 3500
blood_volume = 0 //It's a fucking rock
faction = list("carp")
movement_type = FLYING
pressure_resistance = 500
@@ -211,13 +211,7 @@
return
if(href_list["shrink_belly"])
var/obj/item/organ/genital/belly/E = usr.getorganslot("belly")
if(E.size > 0)
to_chat(usr, "<span class='userlove'>You feel your belly diminish.</span>")
E.size -= 1
H.update_genitals()
else
to_chat(usr, "<span class='warning'>Your belly is already at the minimum size! </span>")
H.shrink_belly(1)
if(href_list["removecondom"])
H.menuremovecondom()
@@ -0,0 +1,35 @@
/mob/living/carbon/proc/expand_belly(expansion = 1)
var/obj/item/organ/genital/belly/_belly = getorganslot("belly")
if(!expansion || !_belly || !_belly.inflatable)
return
var/original_size = _belly.size
_belly.size = clamp(_belly.size + expansion, BELLY_MIN_SIZE, BELLY_MAX_SIZE)
if(_belly.size == original_size)
return
var/_verb = "expand"
switch(_belly.size)
if(BELLY_MAX_SIZE to INFINITY)
_verb = "stretch to its limit"
if(BELLY_STRETCH_SIZE to BELLY_MAX_SIZE)
_verb = "stretch"
if(BELLY_STRAIN_SIZE to BELLY_STRETCH_SIZE)
_verb = "strain"
to_chat(src, "<span class='userlove'>You feel your belly [_verb].</span>")
_belly.update()
/mob/living/carbon/proc/shrink_belly(shrinkage = 1)
var/obj/item/organ/genital/belly/_belly = getorganslot("belly")
if(!shrinkage ||!_belly || !_belly.inflatable)
return
var/original_size = _belly.size
_belly.size = clamp(_belly.size - shrinkage, BELLY_MIN_SIZE, BELLY_MAX_SIZE)
if(_belly.size == original_size)
return
var/_verb = "diminish"
var/_class = "userlove"
if(_belly.size == BELLY_MIN_SIZE)
_verb = "can't shrink anymore"
_class = "warning"
to_chat(src, "<span class='[_class]'>You feel your belly [_verb].</span>")
_belly.update()
@@ -0,0 +1,11 @@
/datum/gear/syntech/ring
name = "Normalizer Ring"
category = SLOT_GLOVES
path = /obj/item/clothing/gloves/ring/syntech
cost = 6
/datum/gear/syntech/band
name = "Normalizer Band"
category = SLOT_GLOVES
path = /obj/item/clothing/gloves/ring/syntech/band
cost = 6
@@ -0,0 +1,5 @@
/datum/gear/gasmask
name = "gas mask"
category = SLOT_WEAR_MASK
path = /obj/item/clothing/mask/gas
cost = 3
@@ -0,0 +1,17 @@
/datum/gear/syntech/pendant
name = "Normalizer Pendant"
category = SLOT_NECK
path = /obj/item/clothing/neck/syntech
cost = 6
/datum/gear/syntech/choker
name = "Normalizer Choker"
category = SLOT_NECK
path = /obj/item/clothing/neck/syntech/choker
cost = 6
/datum/gear/syntech/collar
name = "Normalizer Collar"
category = SLOT_NECK
path = /obj/item/clothing/neck/syntech/collar
cost = 6
@@ -0,0 +1,115 @@
//Clothing vars and procs
/obj/item/clothing
var/normalize_size = RESIZE_NORMAL //This number is used as the "normal" height people will be given when wearing one of these accessories
var/natural_size = null //The value of the wearer's body_size var in prefs. Unused for now.
var/recorded_size = null //the user's height prior to equipping
//For applying a normalization
/obj/item/clothing/proc/normalize_mob_size(mob/living/carbon/human/H)
if(H.normalized) //First we make a check to see if they're already normalized, from wearing another article of SynTech jewelry
to_chat(H, "<span class='warning'>This accessory buzzes, being overwritten by another.</span>")
playsound(H, 'sound/machines/buzz-sigh.ogg', 50, 1)
return
recorded_size = H.get_effective_size() //If not, grab their current size
playsound(H, 'sound/effects/magic.ogg', 50, 1)
flash_lighting_fx(3, 3, LIGHT_COLOR_PURPLE)
H.visible_message("<span class='warning'>A flash of purple light engulfs [H], before they change to normal!</span>","<span class='notice'>You feel warm for a moment, before everything scales to your size...</span>")
H.resize(normalize_size) //Then apply the size
H.normalized = TRUE //And set normalization
//For removing a normalization, and reverting back to normal
/obj/item/clothing/proc/denormalize_mob_size(mob/living/carbon/human/H)
if(H.normalized) //sanity check
playsound(H,'sound/weapons/emitter2.ogg', 50, 1)
flash_lighting_fx(3, 3, LIGHT_COLOR_YELLOW)
H.visible_message("<span class='warning'>Golden light engulfs [H], and they shoot back to their default height!</span>","<span class='notice'>Energy rushes through your body, and you return to normal.</span>")
H.resize(recorded_size)
H.normalized = FALSE
//For storing normalization on mobs
/mob/living
var/normalized = FALSE
//normalized is a check for instances where more than one accessory of jewelry is worn. For all intensive purposes, only the first worn accessory stores the user's size.
//Anything else is just extra.
//Clothing below. Code could be compressed more, but until I make jewelry slots, this will do. -Dahl
//GLOVE SLOT ITEMS...
//SynTech ring
/obj/item/clothing/gloves/ring/syntech
name = "normalizer ring"
desc = "An expensive, shimmering SynTech ring gilded with golden Kinaris markings. It will 'normalize' the size of the user to a specified height approved for work-conditions, as long as it is equipped. The artificial violet gem inside twinkles ominously."
icon = 'hyperstation/icons/obj/clothing/sizeaccessories.dmi'
icon_state = "ring"
item_state = "sring" //No use in a unique sprite since it's just one pixel
w_class = WEIGHT_CLASS_TINY
body_parts_covered = 0
transfer_prints = TRUE
strip_delay = 40
//These are already defined under the parent ring, but I wanna leave em here for reference purposes
//For glove slots
/obj/item/clothing/gloves/ring/syntech/equipped(mob/living/user, slot)
if(ishuman(user))
var/mob/living/carbon/human/human_target = user
if(slot == SLOT_GLOVES)
if(human_target.custom_body_size)
normalize_mob_size(human_target)
/obj/item/clothing/gloves/ring/syntech/dropped(mob/living/user, slot)
if(ishuman(user))
var/mob/living/carbon/human/human_target = user
if(human_target.normalized)
denormalize_mob_size(human_target)
//SynTech Wristband
/obj/item/clothing/gloves/ring/syntech/band
name = "normalizer wristband"
desc = "An expensive technological wristband cast in SynTech purples with shimmering Kinaris golds. It will 'normalize' the size of the user to a specified height for approved work-conditions, as long as it is equipped. There is a small screen buzzing with information."
icon_state = "wristband"
item_state = "syntechband"
//NECK SLOT ITEMS...
//Syntech Pendant
/obj/item/clothing/neck/syntech
name = "normalizer pendant"
desc = "A vibrant violet jewel cast in silvery-gold metals, sporting the elegance of Kinaris with SynTech prowess. It will 'normalize' the size of the user to a specified height for approved work-conditions, as long as it is equipped. The artificial violet gem inside twinkles ominously."
icon = 'hyperstation/icons/obj/clothing/sizeaccessories.dmi'
icon_state = "pendant"
item_state = "pendant"
//For neck items
/obj/item/clothing/neck/syntech/equipped(mob/living/user, slot)
if(ishuman(user))
var/mob/living/carbon/human/human_target = user
if(slot == SLOT_NECK)
if(human_target.custom_body_size)
normalize_mob_size(human_target)
/obj/item/clothing/neck/syntech/dropped(mob/living/user, slot)
if(ishuman(user))
var/mob/living/carbon/human/human_target = user
if(human_target.normalized)
denormalize_mob_size(human_target)
//Syntech Choker
/obj/item/clothing/neck/syntech/choker
name = "normalizer choker"
desc = "A sleek, tight-fitting choker embezzled with silver to gold, adorned with vibrant purple studs; combined technology of Kinaris and SynTech. It will 'normalize' the size of the user to a specified height for approved work-conditions, as long as it is equipped. There is a small screen buzzing with information."
icon_state = "choker"
item_state = "collar"
//Syntech Collar
/obj/item/clothing/neck/syntech/collar
name = "normalizer collar"
desc = "A cute pet collar, technologically designed with vibrant purples and smooth silvers. There is a small gem bordered by gold at the front, reading 'SYNTECH' engraved within the metal. It will 'normalize' the size of the user to a specified height for approved work-conditions, as long as it is equipped. The artificial violet gem inside twinkles ominously."
icon_state = "collar"
item_state = "collar"
@@ -3,3 +3,9 @@
id = /datum/reagent/consumable/pilk
results = list(/datum/reagent/consumable/pilk = 2)
required_reagents = list(/datum/reagent/consumable/milk = 1, /datum/reagent/consumable/space_cola = 1)
/datum/chemical_reaction/javelin
name = "Javelin"
id = /datum/reagent/consumable/ethanol/javelin
results = list(/datum/reagent/consumable/ethanol/javelin = 5)
required_reagents = list(/datum/reagent/consumable/kalynajuice = 1, /datum/reagent/consumable/ethanol/whiskey = 2, /datum/reagent/consumable/ethanol/vodka = 2)
@@ -0,0 +1,40 @@
// Kalyna Berries
/obj/item/seeds/kalyna
name = "pack of kalyna berry seeds"
desc = "Seeds that grow into Kalyna plants. Take that Red Kalyna and rise it up."
icon = 'hyperstation/icons/obj/hydroponics/seeds.dmi'
icon_state = "seed-kalyna"
species = "kalyna"
plantname = "Kalyna Shrub Tree"
product = /obj/item/reagent_containers/food/snacks/grown/kalyna
lifespan = 20
maturation = 5
production = 5
growthstages = 5
yield = 4
growing_icon = 'hyperstation/icons/obj/hydroponics/growing_fruits.dmi'
icon_grow = "kalyna-grow"
icon_dead = "kalyna-dead"
genes = list(/datum/plant_gene/trait/repeated_harvest)
reagents_add = list(/datum/reagent/consumable/nutriment/vitamin = 0.04, /datum/reagent/consumable/nutriment = 0.1)
/obj/item/reagent_containers/food/snacks/grown/kalyna
seed = /obj/item/seeds/kalyna
name = "branch of kalyna"
desc = "Red berries, attached to a branch. Just looking at it makes you feel an aura of unity."
icon = 'hyperstation/icons/obj/hydroponics/harvest.dmi'
icon_state = "kalynaberries"
gender = PLURAL
filling_color = "#FF0000"
bitesize_mod = 2
foodtype = FRUIT
juice_results = list(/datum/reagent/consumable/kalynajuice = 1)
tastes = list("sweet cranberries" = 1)
distill_reagent = /datum/reagent/consumable/ethanol/gin
//For those of you wondering, yes, this is very much an addition in support of Ukraine. I decided to make these after a distant Ukranian relative of mine sent me Go_A's 'Kalyna' song.
//Our future as a free world could very well depend on the heroism of the people of glorious Ukraine. We owe our freedom to them.
//I know that this game should be for escapism, but there's only so much we should escape from. When people's lives are being upturned-- Or taken by a brutal invasive reigime, perhaps then it's when we should take a stand.
//And for those that oppose the freedom of the people of Ukraine, Russia, and Belarus; Prykhyl'nyk Putina, idy na khuy. And show some basic empathy for once, it's not that hard.
//Glory to Ukraine, Glory to the Heroes!
// - Arctaisia, Hyperstation developer and spriter, 23/04/2022 #StandWithUkraine
@@ -67,6 +67,35 @@ SNOUTS
icon = 'hyperstation/icons/mob/char_snouts.dmi'
recommended_species = list("insect")
/datum/sprite_accessory/mam_snouts/easterndragon
name = "Eastern Dragon (Hyper)"
icon_state = "easterndw"
icon = 'hyperstation/icons/mob/char_snouts.dmi'
/datum/sprite_accessory/mam_snouts/feasterndragon
name = "Eastern Dragon (Top) (Hyper)"
icon_state = "feasterndw"
icon = 'hyperstation/icons/mob/char_snouts.dmi'
/datum/sprite_accessory/mam_snouts/easterndragonnowhiskers
name = "Eastern Dragon - No Whiskers (Hyper)"
icon_state = "easterndnw"
icon = 'hyperstation/icons/mob/char_snouts.dmi'
/datum/sprite_accessory/mam_snouts/feasterndragonnowhiskers
name = "Eastern Dragon - No Whiskers (Top) (Hyper)"
icon_state = "feasterndnw"
icon = 'hyperstation/icons/mob/char_snouts.dmi'
/datum/sprite_accessory/mam_snouts/fchemlight
name = "RadDog (Top) (Hyper)"
icon_state = "fchemlight"
icon = 'hyperstation/icons/mob/char_snouts.dmi'
/datum/sprite_accessory/mam_snouts/chemlight
name = "RadDog (Hyper)"
icon_state = "chemlight"
icon = 'hyperstation/icons/mob/char_snouts.dmi'
/*
EARS
@@ -109,6 +138,15 @@ EARS
icon = 'hyperstation/icons/mob/char_ears.dmi'
recommended_species = list("insect")
/datum/sprite_accessory/mam_ears/easterndragon
name = "Eastern Dragon (Hyper)"
icon_state = "easternd"
icon = 'hyperstation/icons/mob/char_ears.dmi'
/datum/sprite_accessory/mam_ears/chemlight
name = "RadDog (Hyper)"
icon_state = "chemlight"
icon = 'hyperstation/icons/mob/char_ears.dmi'
/*
WINGS
@@ -276,6 +314,26 @@ TAILS + ANIMATED TAILS
icon_state = "swallowstriped"
icon = 'hyperstation/icons/mob/char_tails.dmi'
/datum/sprite_accessory/mam_tails/easterndragon //Pulled base from Virgo, seriously love the server and love you guys, stay lovely.
name = "Eastern Dragon (Hyper)"
icon_state = "easternd"
icon = 'hyperstation/icons/mob/char_tails.dmi'
/datum/sprite_accessory/mam_tails_animated/easterndragon
name = "Eastern Dragon (Hyper)"
icon_state = "easternd"
icon = 'hyperstation/icons/mob/char_tails.dmi'
/datum/sprite_accessory/mam_tails/chemlight
name = "RadDog (Hyper)"
icon_state = "chemlight"
icon = 'hyperstation/icons/mob/char_tails.dmi'
/datum/sprite_accessory/mam_tails_animated/chemlight
name = "RadDog (Hyper)"
icon_state = "chemlight"
icon = 'hyperstation/icons/mob/char_tails.dmi'
/*
BODY MARKINGS
@@ -335,6 +393,22 @@ from modular_citadel/code/modules/mob/dead/new_player/sprite_accessories.dm:
icon = 'hyperstation/icons/mob/char_markings.dmi'
recommended_species = list("avian")
/datum/sprite_accessory/mam_body_markings/easterndragon
name = "Eastern Dragon (Hyper)"
icon_state = "easternd"
icon = 'hyperstation/icons/mob/char_markings.dmi'
//doged was here
/datum/sprite_accessory/mam_body_markings/chemlight
name = "RadDog (Hyper)"
icon_state = "chemlight"
icon = 'hyperstation/icons/mob/char_markings.dmi'
//racc do a code maybe it won't explode
/datum/sprite_accessory/mam_body_markings/raccalt
name = "RaccAlt (Hyper)"
icon_state = "raccalt"
icon = 'hyperstation/icons/mob/char_markings.dmi'
/*
TAUR BODIES
@@ -355,7 +429,17 @@ from modular_citadel/code/modules/mob/dead/new_player/sprite_accessories.dm:
color_src = MATRIXED
recommended_species = list("human", "lizard", "insect", "mammal", "xeno", "jelly", "slimeperson", "podweak", "avian", "aquatic")
*/
/datum/sprite_accessory/taur/chemnaga //Chemlight experimental sprites for future spriting
name = "RadDog Naga (Hyper)"
icon_state = "chemnaga"
taur_mode = SNEK_TAURIC
ckeys_allowed = list("chemlight")
/datum/sprite_accessory/taur/chemlight
name = "RadDog Taur (Hyper)"
icon_state = "chemlight"
taur_mode = PAW_TAURIC
ckeys_allowed = list("chemlight")
/*
HAIRSTYLES
@@ -97,7 +97,7 @@
stuttering += 3 //stutter words
//if they are asleep, this wont trigger.
if (total_pain > 110 && stat == 0) //taking 77 all damage at once from full health, will put you into shock and kill you. This cant be achived with chip damage (or fist fights), because youll die before you reach this pain level.
if (total_pain > 120 && stat == 0) //taking 130 all damage at once from full health, will put you into shock and kill you. This cant be achived with chip damage (or fist fights), because youll die before you reach this pain level.
if(prob(50))
emote("scream")//scream
to_chat(src, "<span class='big warning'>You give into the pain...</span>")
@@ -0,0 +1,246 @@
/mob/living/simple_animal/
var/happiness = 50 //how happy they are.
/////////////
//////////////// CHICKEN /////////////////
/////////////
/mob/living/simple_animal/chick
icon = 'hyperstation/icons/mob/chickens.dmi'
name = "\improper chick"
desc = "Adorable! They make such a racket though."
icon_state = "chick"
icon_living = "chick"
icon_dead = "chick_dead"
icon_gib = "chick_gib"
gender = FEMALE
mob_biotypes = MOB_ORGANIC|MOB_BEAST
speak = list("Cherp.","Cherp?","Chirrup.","Cheep!")
speak_emote = list("cheeps")
emote_hear = list("cheeps.")
emote_see = list("pecks at the ground.","flaps its tiny wings.")
density = FALSE
speak_chance = 2
turns_per_move = 2
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/chicken = 1)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "kicks"
attacktext = "kicks"
health = 3
maxHealth = 3
ventcrawler = VENTCRAWLER_ALWAYS
var/amount_grown = 0
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
mob_size = MOB_SIZE_TINY
gold_core_spawnable = FRIENDLY_SPAWN
do_footstep = TRUE
/mob/living/simple_animal/chick/Initialize()
. = ..()
pixel_x = rand(-6, 6)
pixel_y = rand(0, 10)
/mob/living/simple_animal/chick/Life()
. =..()
if(!.)
return
if(!stat && !ckey)
amount_grown += rand(1,2)
if(amount_grown >= 100)
new /mob/living/simple_animal/chicken(src.loc)
qdel(src)
/mob/living/simple_animal/chick/holo/Life()
..()
amount_grown = 0
/mob/living/simple_animal/chicken
icon = 'hyperstation/icons/mob/chickens.dmi'
name = "\improper chicken"
desc = "Hopefully the eggs are good this season."
gender = FEMALE
mob_biotypes = MOB_ORGANIC|MOB_BEAST
icon_state = "chicken_brown"
icon_living = "chicken_brown"
icon_dead = "chicken_brown_dead"
speak = list("Cluck!","BWAAAAARK BWAK BWAK BWAK!","Bwaak bwak.")
speak_emote = list("clucks","croons")
emote_hear = list("clucks.")
emote_see = list("pecks at the ground.","flaps its wings viciously.")
density = FALSE
speak_chance = 2
turns_per_move = 3
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/chicken = 2)
var/egg_type = /obj/item/reagent_containers/food/snacks/egg
var/food_type = /obj/item/reagent_containers/food/snacks/grown/wheat
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "kicks"
attacktext = "kicks"
health = 15
maxHealth = 15
ventcrawler = VENTCRAWLER_ALWAYS
var/eggsleft = 0
var/eggsFertile = FALSE
var/body_color
var/icon_prefix = "chicken"
pass_flags = PASSTABLE | PASSMOB
mob_size = MOB_SIZE_SMALL
var/list/feedMessages = list("It clucks happily.","It clucks happily.")
var/list/layMessage = EGG_LAYING_MESSAGES
var/list/validColors = list("brown","black","white")
gold_core_spawnable = FRIENDLY_SPAWN
var/static/chicken_count = 0
var/partner //for the sex.
var/egglay_timer = 0
var/obj/structure/nestbox/nest_target
var/last_egg
var/force_gender //for map loading
do_footstep = TRUE
/mob/living/simple_animal/chicken/Initialize()
. = ..()
if((prob(30) && !force_gender) || force_gender == "male") //30% of a male. or setup if already male.
gender = MALE
name = "rooster"
if(!body_color)
body_color = pick(validColors)
icon_state = "[icon_prefix]_[body_color]"
icon_living = "[icon_prefix]_[body_color]"
icon_dead = "[icon_prefix]_[body_color]_dead"
pixel_x = rand(-6, 6)
pixel_y = rand(0, 10)
++chicken_count
/mob/living/simple_animal/chicken/Destroy()
--chicken_count
return ..()
/mob/living/simple_animal/chicken/attackby(obj/item/O, mob/user, params)
if(istype(O, food_type)) //feedin' dem chickens
if(!stat && eggsleft < 2)
var/feedmsg = "[user] feeds [O] to [name]! [pick(feedMessages)]"
user.visible_message(feedmsg)
qdel(O)
eggsleft += 1
egglay_timer = 0
else
to_chat(user, "<span class='warning'>[name] doesn't seem hungry!</span>")
else
..()
/mob/living/simple_animal/chicken/Life()
. = ..()
if(!.)
return
if (istype(get_turf(src), /turf/open/floor))
var/turf/open/floor/turfon = get_turf(src)
if (turfon.farm_quality > happiness)
happiness ++
if (prob(5))
visible_message("[src] pecks happily at the ground.") //CLUCK CLUCK CLUCK
else
happiness --
else
happiness --
happiness = clamp(happiness,0,100) //clamp
if (!(gender == FEMALE)) //only females lay eggs and do the rest of the code.
return
//Breeding.
if (gender == FEMALE && eggsFertile == 0 && eggsleft > 0)
for(var/mob/living/simple_animal/chicken/C in view(2,src)) //look for a male near them, or on them.
if(C)
if(C.gender == MALE) //rooster
eggsFertile = 1 //they had sex, just go with it.
partner = C //you know who the partner is.
//EEGGGG TIME
//after 10mins, lay a egg regardless.
if(world.time > (last_egg+600 SECONDS) && !eggsleft)
if(prob(15)) //just to offset
eggsleft ++
last_egg = world.time
if((!stat && eggsleft > 0) && egg_type)
egglay_timer ++
else
egglay_timer = 0
//chance to lay egg on their own.
//look for nest!
//We have found a nest, override movement
if(nest_target) //if alive and we have a target.
stop_automated_movement = 1
walk_to(src,nest_target,0,8)
else
stop_automated_movement = 0
walk_to(src,0) //reset walk_to
if (egglay_timer > 10 && !stat) //time to lay a egg and not dead.
if((!stat && eggsleft > 0) && egg_type)
if (!nest_target)
for(var/obj/structure/nestbox/N in view(3,src)) // look for a eggbox if you dont have one already
nest_target = N
break
//We are at the nest we have chosen.
if (nest_target)
for(var/obj/structure/nestbox/B in get_turf(src))
if((prob(25) && eggsleft > 0) && egg_type)
visible_message("<span class='alertalien'>[src] [pick(layMessage)]</span>")
eggsleft--
var/obj/item/E = new egg_type(get_turf(src))
E.pixel_x = rand(-6,6)
E.pixel_y = rand(-6,6)
egglay_timer = 0 //set timer
nest_target = null //layed the egg, time to move on
if(eggsFertile && partner)
if(chicken_count < MAX_CHICKENS && prob(happiness))
START_PROCESSING(SSobj, E)
eggsFertile = 0 //youve layed your fertile egg.
E.name = "fertile egg"
partner = null
last_egg = world.time
break
/obj/item/reagent_containers/food/snacks/egg/var/amount_grown = 0
/obj/item/reagent_containers/food/snacks/egg/process()
if(isturf(loc))
for(var/obj/structure/nestbox/B in get_turf(src)) //can only hatch in a nestbox or incubator
amount_grown += rand(1,2)
if(amount_grown >= 100)
visible_message("[src] hatches with a quiet cracking sound.")
new /mob/living/simple_animal/chick(get_turf(src))
STOP_PROCESSING(SSobj, src)
qdel(src)
break
else
STOP_PROCESSING(SSobj, src)
/mob/living/simple_animal/chicken/examine()
. = ..()
. += "this one is [gender]."
if(happiness<20)
. += "<span class='warning'>It looks stressed.</span>"
@@ -0,0 +1,23 @@
/*
This is a pre-destroyed nuclear reactor for the sake of mapping special fluff stuff.
Not actually a reactor, just uses the icon and irradiates the surrounding area a bit.
Nowhere else to really put this.
*/
/obj/structure/fluff/destroyed_nuclear_reactor
name = "Destroyed Nuclear Reactor"
desc = "What in the hell happened here?"
icon = 'hyperstation/icons/obj/machinery/rbmk.dmi'
icon_state = "reactor_slagged"
pixel_x = -32
pixel_y = -32
density = FALSE
anchored = TRUE
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF
light_color = LIGHT_COLOR_CYAN
dir = 8 //Less headache inducing :))
/obj/structure/fluff/destroyed_nuclear_reactor/Initialize()
. = ..()
set_light(3)
AddComponent(/datum/component/radioactive, 15000 , src)
@@ -0,0 +1,11 @@
//Hope you're not a Russian T-90
/datum/reagent/consumable/ethanol/javelin
name = "Javelin Cocktail"
boozepwr = 80
color = "#F54F10"
quality = DRINK_FANTASTIC
taste_description = "explosive fireballs"
glass_icon_state = "javelin"
shot_glass_icon_state = "javelin_warhead"
glass_name = "Javelin Cocktail"
glass_desc = "A man-portable, delicious glass of justice."
@@ -21,3 +21,13 @@
if(holder.has_reagent(/datum/reagent/consumable/capsaicin))
holder.remove_reagent(/datum/reagent/consumable/capsaicin, 1)
..()
/datum/reagent/consumable/kalynajuice
name = "Red Kalyna Juice"
description = "Juice from Kalyna plants."
color = "#E90501" // rgb: 233, 5, 1
taste_description = "sweet cranberries"
glass_icon_state = "kalyna"
glass_name = "glass of red kalyna juice"
glass_desc = "A vibrantly red juice!"
hydration = 4
@@ -12,6 +12,7 @@ var/const/RESIZE_MICRO = 0.25
/mob/living
var/size_multiplier = 1 //multiplier for the mob's icon size atm
var/previous_size = 1
var/small_speech = FALSE
//Cyanosis - Action that resizes the sprite for the client but nobody else. Say goodbye to attacking yourself when someone's above you lmao
var/datum/action/sizecode_resize/small_sprite
@@ -237,8 +238,14 @@ mob/living/get_effective_size()
//Proc for changing mob_size to be grabbed for item weight classes
/mob/living/proc/update_mobsize(var/mob/living/tmob)
if(small_speech == TRUE) //if they have small speech reset it.
small_speech = FALSE
UnregisterSignal(src, COMSIG_MOB_SAY)
if(size_multiplier <= 0.50)
mob_size = 0
RegisterSignal(src, COMSIG_MOB_SAY, .proc/handle_small_speech)
small_speech = TRUE
if(size_multiplier < 1)
mob_size = 1
if(size_multiplier == 1)
@@ -246,6 +253,9 @@ mob/living/get_effective_size()
if(size_multiplier > 1)
mob_size = 3
/mob/living/proc/handle_small_speech(owner, list/speech_args) //for making peoples text small
speech_args[SPEECH_SPANS] |= SPAN_SMALL
//Proc for instantly grabbing valid size difference. Code optimizations soon(TM)
/*
/mob/living/proc/sizeinteractioncheck(var/mob/living/tmob)
+30
View File
@@ -0,0 +1,30 @@
/obj/item/reagent_containers/food/snacks/grown/wheat/
var stacktype = /obj/item/stack/tile/hay
var/tile_coefficient = 0.02 // same as grass
/obj/item/reagent_containers/food/snacks/grown/wheat/attack_self(mob/user)
to_chat(user, "<span class='notice'>You prepare the hay bedding.</span>")
var/grassAmt = 1 + round(seed.potency * tile_coefficient) // The grass we're holding
for(var/obj/item/reagent_containers/food/snacks/grown/wheat/G in user.loc) // The grass on the floor
if(G.type != type)
continue
grassAmt += 1 + round(G.seed.potency * tile_coefficient)
qdel(G)
new stacktype(user.drop_location(), grassAmt)
qdel(src)
/obj/structure/nestbox
name = "nest box"
icon = 'hyperstation/icons/obj/hydroponics/farming.dmi'
icon_state = "nestbox"
desc = "A little nest box, for collecting eggs"
density = FALSE
anchored = TRUE
/obj/structure/nestbox/wrench_act(mob/living/user, obj/item/I)
user.visible_message("<span class='warning'>[user] disassembles [src].</span>",
"<span class='notice'>You start to disassemble [src]...</span>", "You hear clanking and banging noises.")
if(I.use_tool(src, user, 20, volume=50))
new /obj/item/stack/sheet/mineral/wood (loc, 4)
qdel(src)
+44
View File
@@ -0,0 +1,44 @@
/obj/structure/jacuzzi
name = "jacuzzi"
icon = 'hyperstation/icons/obj/jacuzzi.dmi'
icon_state = "tub"
desc = "A luxurious pool, but with bubbles!"
var/filled = TRUE
density = FALSE
var/mutable_appearance/waterlower
var/mutable_appearance/water
var/mutable_appearance/top
var/mutable_appearance/mist
anchored = TRUE
//Dont move, it goes in walls and is shit.
///obj/structure/jacuzzi/attackby(obj/item/W, mob/user, params)
// if(istype(W, /obj/item/wrench))
// W.play_tool_sound(src)
// anchored = !anchored
/obj/structure/jacuzzi/Initialize()
. = ..()
top = mutable_appearance('hyperstation/icons/obj/jacuzzi.dmi', "tub_top")
top.layer = 5
add_overlay(top)
/obj/structure/jacuzzi/attack_hand(mob/user)
. = ..()
filled = !filled
if(!filled)
cut_overlay(waterlower)
cut_overlay(water)
cut_overlay(mist)
else
waterlower = mutable_appearance('hyperstation/icons/obj/jacuzzi.dmi', "water")
water = mutable_appearance('hyperstation/icons/obj/jacuzzi.dmi', "over_water")
mist = mutable_appearance('hyperstation/icons/obj/jacuzzi.dmi', "mist")
waterlower.layer = 3
water.layer = 10
mist.layer = 11
mist.pixel_y = 5
add_overlay(waterlower)
add_overlay(water)
add_overlay(mist)
+69
View File
@@ -129,3 +129,72 @@ obj/item/clothing/neck/stole/black
max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT
heat_protection = CHEST|GROIN|ARMS
armor = list("melee" = 60, "bullet" = 80, "laser" = 80, "energy" = 90, "bomb" = 50, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 50)
/obj/item/clothing/under/raccveralls
name = "form fitting overalls"
desc = "A tight form fitting pair of overalls."
icon = 'hyperstation/icons/obj/clothing/uniforms.dmi'
icon_state = "raccveralls"
alternate_worn_icon = 'hyperstation/icons/mobs/uniforms.dmi'
item_state = "raccveralls"
can_adjust = FALSE
/obj/item/clothing/under/officesexy
name = "Revealing office uniform"
desc = "A sexy office uniform, that has a low cropped front to show off some chest, or bra. And a tall dress that covers the stomach, complete with a set of buttons."
icon = 'hyperstation/icons/obj/clothing/uniforms.dmi'
icon_state = "office_revealing"
alternate_worn_icon = 'hyperstation/icons/mobs/uniforms.dmi'
item_state = "office_revealing"
can_adjust = FALSE
mutantrace_variation = NO_MUTANTRACE_VARIATION
/obj/item/clothing/under/vaultsuit
name = "vault suit"
desc = "A tight form fitting Vault-Tec standard issue Vault Jumpsuit! Snazzy!"
icon = 'hyperstation/icons/obj/clothing/uniforms.dmi'
icon_state = "vaultsuit"
alternate_worn_icon = 'hyperstation/icons/mobs/uniforms.dmi'
item_state = "b_suit"
can_adjust = FALSE
var/firstpickup = TRUE
var/pickupsound = TRUE
/obj/item/clothing/under/vaultsuit/no_sound
pickupsound = FALSE
/obj/item/clothing/under/vaultsuit/equipped(mob/user, slot)
. = ..()
if(!pickupsound)
return
if(!ishuman(user))
return
if(slot == SLOT_W_UNIFORM)
if(!firstpickup)
SEND_SOUND(user, sound('hyperstation/sound/effects/vaultsuit/FalloutEXPUp.ogg', volume = 50))
else
firstpickup = FALSE
SEND_SOUND(user, sound('hyperstation/sound/effects/vaultsuit/FalloutLevelUp.ogg', volume = 50))
SEND_SOUND(user, sound('hyperstation/sound/effects/vaultsuit/InkSpotsSting.ogg', volume = 60))
return
/obj/item/clothing/suit/tunnelfox
name = "tunnel fox jacket"
desc = "Tunnel Foxes Rule!"
icon = 'hyperstation/icons/obj/clothing/suits.dmi'
icon_state = "tunnelfox"
alternate_worn_icon = 'hyperstation/icons/mobs/suits.dmi'
item_state = "tunnelfox"
body_parts_covered = CHEST|LEGS|ARMS
min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
/obj/item/clothing/suit/tunnelfox_t
name = "opened tunnel fox jacket"
desc = "Tunnel Foxes Rule!"
icon = 'hyperstation/icons/obj/clothing/suits.dmi'
icon_state = "tunnelfox_t"
alternate_worn_icon = 'hyperstation/icons/mobs/suits.dmi'
item_state = "tunnelfox_t"
body_parts_covered = CHEST|LEGS|ARMS
min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
Binary file not shown.

Before

Width:  |  Height:  |  Size: 578 B

After

Width:  |  Height:  |  Size: 974 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 610 B

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 887 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 393 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 835 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 KiB

After

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 260 KiB

After

Width:  |  Height:  |  Size: 271 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 21 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

@@ -70,6 +70,7 @@
/obj/item/electropack/vibrator = 2,
/obj/item/fleshlight = 2,
/obj/item/storage/box/portallight = 1,
/obj/item/storage/pill_bottle/lovedice = 5,
)
contraband = list(
/obj/item/clothing/under/gear_harness = 3,
@@ -437,17 +437,9 @@
if(!remote && !in_range(src, L))
return
if(do_after(src, mb_time, target = src))
if(!spillage) //hyper inflation
var/obj/item/organ/genital/belly/B = L.getorganslot("belly")
if(B)
if(B.inflatable && total_fluids > 80) //requires a big cumshot to expand.
if(B.size < 3)
B.size += 1
to_chat(L, "<span class='userlove'>You feel your belly expand.</span>")
else
to_chat(L, "<span class='userlove'>You feel your belly strain.</span>")
var/mob/living/carbon/H = L
if(!spillage && total_fluids > 80) //hyper inflation; requires a big cumshot to expand
H.expand_belly(1)
var/obj/item/organ/genital/penis/P = G
if (P.condom)//condomed.
src.condomclimax()
@@ -673,8 +665,6 @@
var/mob/living/carbon/C = check_target
if(C.exposed_genitals.len || C.is_groin_exposed() || C.is_chest_exposed()) //Are they naked enough?
partner = C
else //A cat is fine too
partner = check_target
if(partner) //Did they pass the clothing checks?
mob_climax_partner(G, partner, mb_time = 0) //Instant climax due to forced
continue //You've climaxed once with this organ, continue on
@@ -229,7 +229,7 @@
if(!getorganslot("belly"))
var/obj/item/organ/genital/belly/B = new
if(dna.features["belly_size"])
B.size = dna.features["belly_size"]-1
B.size = dna.features["belly_size"]
B.Insert(src)
if(B)
if(dna.species.use_skintones && dna.features["genitals_use_skintone"])
@@ -478,32 +478,39 @@
genital_overlay.icon_state = "[G.slot]_[S.icon_state]_[size]_[aroused_state]_[layertext]"
colourcode = S.color_src
if(G.slot == "belly") //we have a different size system
if(G.slot == "belly")
size = round(size)
genital_overlay.icon = 'hyperstation/icons/obj/genitals/belly.dmi'
genital_overlay.icon_state = "belly_[size]"
genital_overlay.icon_state = "belly_[size]_OTHER"
colourcode = "belly_color"
//sizecheck added to prevent rendering blank icons
if(G.slot == "anus" && G.size > 0) //we have a different size system
//creates directional layering by rendering twice.
genital_overlay_directional.icon = 'hyperstation/icons/obj/genitals/belly.dmi' //Added directionals for larger bellies!
genital_overlay_directional.icon_state = "belly_[size]_NORTH"
genital_overlay_directional.layer = -GENITALS_BEHIND_LAYER
if(G.slot == "anus")
size = round(size)
genital_overlay.icon = 'hyperstation/icons/obj/genitals/butt.dmi'
genital_overlay.icon_state = "butt_[round(size)]_OTHER"
genital_overlay.icon_state = "butt_[size]_OTHER"
genital_overlay.layer = -ID_LAYER //in front of suit, behind bellies.
//creates directional layering by rendering twice. North has higher layer priority to occlude hands.
genital_overlay_directional.icon = 'hyperstation/icons/obj/genitals/butt.dmi'
genital_overlay_directional.icon_state = "butt_[round(size)]_NORTH"
genital_overlay_directional.icon_state = "butt_[size]_NORTH"
genital_overlay_directional.layer = -NECK_LAYER
colourcode = "butt_color"
if(use_skintones) //butts are forced a colour, either skin tones, or main colour. how ever, mutants use a darker version, because of their body tone.
if(use_skintones && H.dna.features["genitals_use_skintone"])
//butts are forced a colour, either skin tones, or main colour.
//how ever, mutants use a darker version, because of their body tone.
genital_overlay.color = "#[skintone2hex(H.skin_tone)]"
genital_overlay.icon_state = "butt_[round(size)]_OTHER"
genital_overlay_directional.icon_state = "butt_[round(size)]_NORTH"
genital_overlay.icon_state = "butt_[size]_OTHER"
genital_overlay_directional.icon_state = "butt_[size]_NORTH"
else
genital_overlay.color = "#[H.dna.features["mcolor"]]"
genital_overlay.icon_state = "butt_[round(size)]_OTHER_m"
genital_overlay_directional.icon_state = "butt_[round(size)]_NORTH_m"
genital_overlay.icon_state = "butt_[size]_OTHER_m"
genital_overlay_directional.icon_state = "butt_[size]_NORTH_m"
if(S.center)
@@ -514,21 +521,10 @@
if (colourtint)
genital_overlay.color = "#[colourtint]"
else
switch(colourcode)
if("cock_color")
genital_overlay.color = "#[H.dna.features["cock_color"]]"
if (colourtint)
genital_overlay.color = "#[colourtint]"
if("balls_color")
genital_overlay.color = "#[H.dna.features["balls_color"]]"
if("breasts_color")
genital_overlay.color = "#[H.dna.features["breasts_color"]]"
if("vag_color")
genital_overlay.color = "#[H.dna.features["vag_color"]]"
if("belly_color")
genital_overlay.color = "#[H.dna.features["belly_color"]]"
if("butt_color")
genital_overlay.color = "#[H.dna.features["butt_color"]]"
if(colourcode != MUTCOLORS)
genital_overlay.color = "#[H.dna.features[colourcode]]"
if(colourcode == "cock_color" && colourtint)
genital_overlay.color = "#[colourtint]"
standing += genital_overlay
@@ -542,7 +538,7 @@
if (colourtint)
genital_overlay_directional.color = "#[colourtint]"
else
genital_overlay_directional.color = "#[H.dna.features["butt_color"]]"
genital_overlay_directional.color = "#[H.dna.features[colourcode]]"
standing += genital_overlay_directional
@@ -523,4 +523,22 @@
name = "Tunic"
category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/tunic
cost = 1
/datum/gear/overalls
name = "form fitting overalls"
category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/raccveralls
cost = 1
/datum/gear/sexyoffice
name = "Revealing office uniform"
category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/officesexy
cost = 1
/datum/gear/vaultsuit
name = "vault jumpsuit"
category = SLOT_W_UNIFORM
path = /obj/item/clothing/under/vaultsuit
cost = 1
@@ -1655,6 +1655,7 @@ datum/sprite_accessory/ears/human/gret
name = "Dog"
icon_state = "dog"
/datum/sprite_accessory/mam_body_markings/eevee
name = "Eevee"
icon_state = "eevee"
@@ -2302,44 +2303,6 @@ datum/sprite_accessory/ears/human/gret
icon_state = "sabresune"
ckeys_allowed = list("poojawa")
//doged was here
/datum/sprite_accessory/mam_body_markings/chemlight
name = "RadDog"
icon_state = "chemlight"
/datum/sprite_accessory/mam_tails/chemlight
name = "RadDog"
icon_state = "chemlight"
/datum/sprite_accessory/mam_tails_animated/chemlight
name = "RadDog"
icon_state = "chemlight"
/datum/sprite_accessory/mam_ears/chemlight
name = "RadDog"
icon_state = "chemlight"
/datum/sprite_accessory/mam_snouts/fchemlight
name = "RadDog (Top)"
icon_state = "fchemlight"
/datum/sprite_accessory/mam_snouts/chemlight
name = "RadDog"
icon_state = "chemlight"
/datum/sprite_accessory/taur/chemnaga
name = "Naga Chemlight"
icon_state = "chemnaga"
taur_mode = SNEK_TAURIC
ckeys_allowed = list("chemlight")
/datum/sprite_accessory/taur/chemlight
name = "Chem taur"
icon_state = "chemlight"
taur_mode = PAW_TAURIC
ckeys_allowed = list("chemlight")
//Lunasune
/datum/sprite_accessory/mam_ears/lunasune
name = "lunasune"
@@ -412,7 +412,7 @@
B = nB
//If they have & opt in, increase size.
if(H.client?.prefs.cit_toggles & ASS_ENLARGEMENT)
if(B.size < 5) //just make sure you dont break sprites
if(B.size < BUTT_MAX_SIZE) //just make sure you dont break sprites
B.size = B.size + 0.05
B.update()
..()
Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

After

Width:  |  Height:  |  Size: 103 KiB

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