Merge branch 'master' into tinytweaks-2-9-20
@@ -735,7 +735,7 @@
|
||||
/obj/machinery/atmospherics/components/unary/outlet_injector{
|
||||
dir = 1
|
||||
},
|
||||
/turf/open/space/basic,
|
||||
/turf/open/floor/plating/airless,
|
||||
/area/engine/engineering)
|
||||
"Si" = (
|
||||
/obj/structure/cable/yellow{
|
||||
|
||||
@@ -240,7 +240,7 @@
|
||||
/obj/machinery/atmospherics/components/unary/outlet_injector{
|
||||
dir = 1
|
||||
},
|
||||
/turf/open/space/basic,
|
||||
/turf/open/floor/plating/airless,
|
||||
/area/engine/engineering)
|
||||
"nR" = (
|
||||
/obj/structure/cable{
|
||||
@@ -905,14 +905,6 @@
|
||||
},
|
||||
/turf/open/space/basic,
|
||||
/area/space/nearstation)
|
||||
"VR" = (
|
||||
/obj/structure/lattice/catwalk,
|
||||
/obj/machinery/camera/emp_proof{
|
||||
c_tag = "Tesla Engine Northeast";
|
||||
network = list("ss13","engine")
|
||||
},
|
||||
/turf/open/space/basic,
|
||||
/area/space/nearstation)
|
||||
"Wf" = (
|
||||
/obj/effect/turf_decal/stripes/line{
|
||||
dir = 9
|
||||
@@ -1728,7 +1720,7 @@ dz
|
||||
dz
|
||||
FP
|
||||
FP
|
||||
VR
|
||||
FP
|
||||
dz
|
||||
dz
|
||||
Yl
|
||||
|
||||
@@ -81645,6 +81645,19 @@
|
||||
/obj/machinery/door/firedoor,
|
||||
/turf/open/floor/plating,
|
||||
/area/crew_quarters/cryopod)
|
||||
"eQf" = (
|
||||
/obj/machinery/computer/shuttle/mining/common{
|
||||
dir = 1
|
||||
},
|
||||
/obj/structure/window/reinforced,
|
||||
/obj/structure/window/reinforced{
|
||||
dir = 8
|
||||
},
|
||||
/obj/structure/window/reinforced{
|
||||
dir = 4
|
||||
},
|
||||
/turf/open/floor/plating,
|
||||
/area/hallway/primary/port)
|
||||
"eZe" = (
|
||||
/obj/structure/cable/yellow{
|
||||
icon_state = "1-2"
|
||||
@@ -98511,7 +98524,7 @@ bgA
|
||||
biz
|
||||
bkb
|
||||
blZ
|
||||
bnM
|
||||
eQf
|
||||
bqf
|
||||
bqf
|
||||
bqf
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define CAN_MASTURBATE_WITH (1<<5)
|
||||
#define MASTURBATE_LINKED_ORGAN (1<<6) //used to pass our mission to the linked organ
|
||||
#define CAN_CLIMAX_WITH (1<<7)
|
||||
#define GENITAL_CAN_AROUSE (1<<8)
|
||||
|
||||
#define COCK_SIZE_MIN 1
|
||||
#define COCK_SIZE_MAX 20
|
||||
|
||||
@@ -199,4 +199,6 @@
|
||||
#define LORENTZ_CUMULATIVE_DISTRIBUTION(x, y, s) ( (1/PI)*TORADIANS(arctan((x-y)/s)) + 1/2 )
|
||||
|
||||
#define RULE_OF_THREE(a, b, x) ((a*x)/b)
|
||||
// )
|
||||
// )
|
||||
|
||||
#define MANHATTAN_DISTANCE(a, b) (abs(a.x - b.x) + abs(a.y - b.y))
|
||||
@@ -57,14 +57,11 @@ GLOBAL_LIST_EMPTY(ipc_antennas_list)
|
||||
|
||||
//Genitals and Arousal Lists
|
||||
GLOBAL_LIST_EMPTY(genitals_list)
|
||||
GLOBAL_LIST_EMPTY(cock_shapes_list)//global_lists.dm for the list initializations //Now also _DATASTRUCTURES globals.dm
|
||||
GLOBAL_LIST_EMPTY(cock_shapes_icons) //Associated list for names->icon_states for cockshapes.
|
||||
GLOBAL_LIST_EMPTY(cock_shapes_list)
|
||||
GLOBAL_LIST_EMPTY(gentlemans_organ_names)
|
||||
GLOBAL_LIST_EMPTY(balls_shapes_list)
|
||||
GLOBAL_LIST_EMPTY(balls_shapes_icons)
|
||||
GLOBAL_LIST_EMPTY(breasts_size_list)
|
||||
GLOBAL_LIST_EMPTY(breasts_shapes_list)
|
||||
GLOBAL_LIST_EMPTY(breasts_shapes_icons)
|
||||
GLOBAL_LIST_EMPTY(vagina_shapes_list)
|
||||
GLOBAL_LIST_INIT(cum_into_containers_list, list(/obj/item/reagent_containers/food/snacks/pie)) //Yer fuggin snowflake name list jfc
|
||||
GLOBAL_LIST_INIT(dick_nouns, list("dick","cock","member","shaft"))
|
||||
|
||||
@@ -51,26 +51,15 @@
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/antenna, GLOB.ipc_antennas_list, roundstart = TRUE)
|
||||
//genitals
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/penis, GLOB.cock_shapes_list)
|
||||
for(var/K in GLOB.cock_shapes_list)
|
||||
var/datum/sprite_accessory/penis/value = GLOB.cock_shapes_list[K]
|
||||
GLOB.cock_shapes_icons[K] = value.icon_state
|
||||
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/vagina, GLOB.vagina_shapes_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/breasts, GLOB.breasts_shapes_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/testicles, GLOB.balls_shapes_list)
|
||||
GLOB.breasts_size_list = list ("a", "b", "c", "d", "e") //We need the list to choose from initialized, but it's no longer a sprite_accessory thing.
|
||||
GLOB.gentlemans_organ_names = list("phallus", "willy", "dick", "prick", "member", "tool", "gentleman's organ",
|
||||
"cock", "wang", "knob", "dong", "joystick", "pecker", "johnson", "weenie", "tadger", "schlong", "thirsty ferret",
|
||||
"baloney pony", "schlanger", "Mutton dagger", "old blind bob","Hanging Johnny", "fishing rod", "Tally whacker", "polly rocket",
|
||||
"One eyed trouser trout", "Ding dong", "ankle spanker", "Pork sword", "engine cranker", "Harry hot dog", "Davy Crockett",
|
||||
"Kidney cracker", "Heat seeking moisture missile", "Giggle stick", "love whistle", "Tube steak", "Uncle Dick", "Purple helmet warrior")
|
||||
for(var/K in GLOB.breasts_shapes_list)
|
||||
var/datum/sprite_accessory/breasts/value = GLOB.breasts_shapes_list[K]
|
||||
GLOB.breasts_shapes_icons[K] = value.icon_state
|
||||
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/testicles, GLOB.balls_shapes_list)
|
||||
for(var/K in GLOB.balls_shapes_list)
|
||||
var/datum/sprite_accessory/testicles/value = GLOB.balls_shapes_list[K]
|
||||
GLOB.balls_shapes_icons[K] = value.icon_state
|
||||
|
||||
for(var/gpath in subtypesof(/obj/item/organ/genital))
|
||||
var/obj/item/organ/genital/G = gpath
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
// Basic geometry things.
|
||||
|
||||
/datum/vector/
|
||||
var/x = 0
|
||||
var/y = 0
|
||||
|
||||
/datum/vector/New(var/x, var/y)
|
||||
src.x = x
|
||||
src.y = y
|
||||
|
||||
/datum/vector/proc/duplicate()
|
||||
return new /datum/vector(x, y)
|
||||
|
||||
/datum/vector/proc/euclidian_norm()
|
||||
return sqrt(x*x + y*y)
|
||||
|
||||
/datum/vector/proc/squared_norm()
|
||||
return x*x + y*y
|
||||
|
||||
/datum/vector/proc/normalize()
|
||||
var/norm = euclidian_norm()
|
||||
x = x/norm
|
||||
y = y/norm
|
||||
return src
|
||||
|
||||
/datum/vector/proc/chebyshev_norm()
|
||||
return max(abs(x), abs(y))
|
||||
|
||||
/datum/vector/proc/chebyshev_normalize()
|
||||
var/norm = chebyshev_norm()
|
||||
x = x/norm
|
||||
y = y/norm
|
||||
return src
|
||||
|
||||
/datum/vector/proc/is_integer()
|
||||
return ISINTEGER(x) && ISINTEGER(y)
|
||||
|
||||
/atom/movable/proc/vector_translate(var/datum/vector/V, var/delay)
|
||||
var/turf/T = get_turf(src)
|
||||
var/turf/destination = locate(T.x + V.x, T.y + V.y, z)
|
||||
var/datum/vector/V_norm = V.duplicate()
|
||||
V_norm.chebyshev_normalize()
|
||||
if (!V_norm.is_integer())
|
||||
return
|
||||
var/turf/destination_temp
|
||||
while (destination_temp != destination)
|
||||
destination_temp = locate(T.x + V_norm.x, T.y + V_norm.y, z)
|
||||
forceMove(destination_temp)
|
||||
T = get_turf(src)
|
||||
sleep(delay + world.tick_lag) // Shortest possible time to sleep
|
||||
|
||||
/atom/proc/get_translated_turf(var/datum/vector/V)
|
||||
var/turf/T = get_turf(src)
|
||||
return locate(T.x + V.x, T.y + V.y, z)
|
||||
|
||||
/proc/atoms2vector(var/atom/A, var/atom/B)
|
||||
return new /datum/vector((B.x - A.x), (B.y - A.y)) // Vector from A -> B
|
||||
@@ -488,7 +488,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
if("SCORE")
|
||||
SSvote.initiate_vote("map","server",hideresults=TRUE,votesystem = MAJORITY_JUDGEMENT_VOTING)
|
||||
// fallback
|
||||
SSvote.initiate_vote("map","server",hideresults=TRUE,votesystem = MAJORITY_JUDGEMENT_VOTING)
|
||||
SSvote.initiate_vote("map","server",hideresults=TRUE)
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/HasRoundStarted()
|
||||
return current_state >= GAME_STATE_PLAYING
|
||||
|
||||
@@ -820,3 +820,11 @@
|
||||
target.layer = old_layer
|
||||
target.plane = old_plane
|
||||
current_button.appearance_cache = target.appearance
|
||||
|
||||
/proc/get_action_of_type(mob/M, var/action_type)
|
||||
if(!M.actions || !ispath(action_type, /datum/action))
|
||||
return
|
||||
for(var/datum/action/A in M.actions)
|
||||
if(istype(A, action_type))
|
||||
return A
|
||||
return
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
/obj/item/geiger_counter/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
QDEL_NULL(soundloop)
|
||||
return ..()
|
||||
|
||||
/obj/item/geiger_counter/process()
|
||||
|
||||
@@ -116,7 +116,7 @@ This file contains the cult dagger and rune list code
|
||||
if(user.blood_volume)
|
||||
user.apply_damage(initial(rune_to_scribe.scribe_damage), BRUTE, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM))
|
||||
var/scribe_mod = initial(rune_to_scribe.scribe_delay)
|
||||
if(istype(get_turf(user), /turf/open/floor/engine/cult))
|
||||
if(istype(get_turf(user), /turf/open/floor/engine/cult) && !(ispath(rune_to_scribe, /obj/effect/rune/narsie)))
|
||||
scribe_mod *= 0.5
|
||||
if(!do_after(user, scribe_mod, target = get_turf(user)))
|
||||
for(var/V in shields)
|
||||
|
||||
@@ -251,6 +251,7 @@
|
||||
/obj/machinery/atmospherics/components/unary/cryo_cell/close_machine(mob/living/carbon/user)
|
||||
if((isnull(user) || istype(user)) && state_open && !panel_open)
|
||||
..(user)
|
||||
reagent_transfer = 0
|
||||
return occupant
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/cryo_cell/container_resist(mob/living/user)
|
||||
|
||||
@@ -105,6 +105,7 @@ datum/bounty/reagent/complex_drink/New()
|
||||
/datum/reagent/consumable/ethanol/hearty_punch,\
|
||||
/datum/reagent/consumable/ethanol/manhattan_proj,\
|
||||
/datum/reagent/consumable/ethanol/narsour,\
|
||||
/datum/reagent/consumable/ethanol/cogchamp,\
|
||||
/datum/reagent/consumable/ethanol/neurotoxin,\
|
||||
/datum/reagent/consumable/ethanol/patron,\
|
||||
/datum/reagent/consumable/ethanol/quadruple_sec,\
|
||||
|
||||
@@ -107,9 +107,9 @@
|
||||
smash(hit_atom, throwingdatum?.thrower, TRUE)
|
||||
|
||||
/obj/item/reagent_containers/food/drinks/proc/smash(atom/target, mob/thrower, ranged = FALSE)
|
||||
if(!isGlass)
|
||||
if(!isGlass && !istype(src, /obj/item/reagent_containers/food/drinks/bottle)) //I don't like this but I also don't want to rework drink container hierarchy
|
||||
return
|
||||
if(QDELING(src) || !target) //Invalid loc
|
||||
if(QDELING(src) || (ranged && !target))
|
||||
return
|
||||
if(bartender_check(target) && ranged)
|
||||
return
|
||||
@@ -126,12 +126,69 @@
|
||||
B.transform = M
|
||||
B.pixel_x = rand(-12, 12)
|
||||
B.pixel_y = rand(-12, 12)
|
||||
if(prob(33))
|
||||
new/obj/item/shard(drop_location())
|
||||
playsound(src, "shatter", 70, 1)
|
||||
if(isGlass)
|
||||
playsound(src, "shatter", 70, 1)
|
||||
if(prob(33))
|
||||
new/obj/item/shard(drop_location())
|
||||
else
|
||||
B.force = 0
|
||||
B.throwforce = 0
|
||||
B.desc = "A carton with the bottom half burst open. Might give you a papercut."
|
||||
transfer_fingerprints_to(B)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/reagent_containers/food/drinks/MouseDrop(atom/over, atom/src_location, atom/over_location, src_control, over_control, params)
|
||||
var/mob/user = usr
|
||||
. = ..()
|
||||
if (!istype(src_location) || !istype(over_location))
|
||||
return
|
||||
if (!user || user.incapacitated() || !user.Adjacent(src))
|
||||
return
|
||||
if (!(locate(/obj/structure/table) in src_location) || !(locate(/obj/structure/table) in over_location))
|
||||
return
|
||||
|
||||
//Are we an expert slider?
|
||||
var/datum/action/innate/D = get_action_of_type(user, /datum/action/innate/drink_fling)
|
||||
if(!D?.active)
|
||||
if (!src_location.Adjacent(over_location)) // Regular users can only do short slides.
|
||||
return
|
||||
if (prob(10))
|
||||
user.visible_message("<span class='warning'>\The [user] tries to slide \the [src] down the table, but fails miserably.</span>", "<span class='warning'>You <b>fail</b> to slide \the [src] down the table!</span>")
|
||||
smash(over_location, user, FALSE)
|
||||
return
|
||||
user.visible_message("<span class='notice'>\The [user] slides \the [src] down the table.</span>", "<span class='notice'>You slide \the [src] down the table!</span>")
|
||||
forceMove(over_location)
|
||||
return
|
||||
var/distance = MANHATTAN_DISTANCE(over_location, src)
|
||||
if (distance >= 8 || distance == 0) // More than a full screen to go, or trying to slide to the same tile
|
||||
return
|
||||
|
||||
// Geometrically checking if we're on a straight line.
|
||||
var/datum/vector/V = atoms2vector(src, over_location)
|
||||
var/datum/vector/V_norm = V.duplicate()
|
||||
V_norm.normalize()
|
||||
if (!V_norm.is_integer())
|
||||
return // Only a cardinal vector (north, south, east, west) can pass this test
|
||||
|
||||
// Checks if there's tables on the path.
|
||||
var/turf/dest = get_translated_turf(V)
|
||||
var/turf/temp_turf = src_location
|
||||
|
||||
do
|
||||
temp_turf = temp_turf.get_translated_turf(V_norm)
|
||||
if (!locate(/obj/structure/table) in temp_turf)
|
||||
var/datum/vector/V2 = atoms2vector(src, temp_turf)
|
||||
vector_translate(V2, 0.1 SECONDS)
|
||||
user.visible_message("<span class='warning'>\The [user] slides \the [src] down the table... and straight into the ground!</span>", "<span class='warning'>You slide \the [src] down the table, and straight into the ground!</span>")
|
||||
smash(over_location, user, FALSE)
|
||||
return
|
||||
while (temp_turf != dest)
|
||||
|
||||
vector_translate(V, 0.1 SECONDS)
|
||||
user.visible_message("<span class='notice'>\The [user] expertly slides \the [src] down the table.</span>", "<span class='notice'>You slide \the [src] down the table. What a pro.</span>")
|
||||
return
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Drinks. END
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -294,28 +351,6 @@
|
||||
icon_state = "juicebox"
|
||||
volume = 15 //I figure if you have to craft these it should at least be slightly better than something you can get for free from a watercooler
|
||||
|
||||
/obj/item/reagent_containers/food/drinks/sillycup/smallcarton/smash(atom/target, mob/thrower, ranged = FALSE)
|
||||
if(bartender_check(target) && ranged)
|
||||
return
|
||||
var/obj/item/broken_bottle/B = new (loc)
|
||||
B.icon_state = icon_state
|
||||
var/icon/I = new('icons/obj/drinks.dmi', src.icon_state)
|
||||
I.Blend(B.broken_outline, ICON_OVERLAY, rand(5), 1)
|
||||
I.SwapColor(rgb(255, 0, 220, 255), rgb(0, 0, 0, 0))
|
||||
B.icon = I
|
||||
B.name = "broken [name]"
|
||||
B.force = 0
|
||||
B.throwforce = 0
|
||||
B.desc = "A carton with the bottom half burst open. Might give you a papercut."
|
||||
if(ranged)
|
||||
var/matrix/M = matrix(B.transform)
|
||||
M.Turn(rand(-170, 170))
|
||||
B.transform = M
|
||||
B.pixel_x = rand(-12, 12)
|
||||
B.pixel_y = rand(-12, 12)
|
||||
transfer_fingerprints_to(B)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/reagent_containers/food/drinks/sillycup/smallcarton/on_reagent_change(changetype)
|
||||
if (reagents.reagent_list.len)
|
||||
switch(reagents.get_master_reagent_id())
|
||||
|
||||
@@ -16,40 +16,6 @@
|
||||
isGlass = TRUE
|
||||
foodtype = ALCOHOL
|
||||
|
||||
|
||||
/obj/item/reagent_containers/food/drinks/bottle/smash(mob/living/target, mob/thrower, ranged = FALSE)
|
||||
//Creates a shattering noise and replaces the bottle with a broken_bottle
|
||||
if(bartender_check(target) && ranged)
|
||||
return
|
||||
var/obj/item/broken_bottle/B = new (loc)
|
||||
if(!ranged)
|
||||
thrower.put_in_hands(B)
|
||||
else
|
||||
var/matrix/M = matrix(B.transform)
|
||||
M.Turn(rand(-170, 170))
|
||||
B.transform = M
|
||||
B.pixel_x = rand(-12, 12)
|
||||
B.pixel_y = rand(-12, 12)
|
||||
B.icon_state = icon_state
|
||||
|
||||
var/icon/I = new('icons/obj/drinks.dmi', src.icon_state)
|
||||
I.Blend(B.broken_outline, ICON_OVERLAY, rand(5), 1)
|
||||
I.SwapColor(rgb(255, 0, 220, 255), rgb(0, 0, 0, 0))
|
||||
B.icon = I
|
||||
|
||||
if(isGlass)
|
||||
if(prob(33))
|
||||
new/obj/item/shard(drop_location())
|
||||
playsound(src, "shatter", 70, 1)
|
||||
else
|
||||
B.force = 0
|
||||
B.throwforce = 0
|
||||
B.desc = "A carton with the bottom half burst open. Might give you a papercut."
|
||||
B.name = "broken [name]"
|
||||
transfer_fingerprints_to(B)
|
||||
|
||||
qdel(src)
|
||||
|
||||
/obj/item/reagent_containers/food/drinks/bottle/attack(mob/living/target, mob/living/user)
|
||||
|
||||
if(!target)
|
||||
@@ -109,7 +75,7 @@
|
||||
//Keeping this here for now, I'll ask if I should keep it here.
|
||||
/obj/item/broken_bottle
|
||||
name = "broken bottle"
|
||||
desc = "A bottle with a sharp broken bottom."
|
||||
desc = "A shattered glass container with sharp edges."
|
||||
icon = 'icons/obj/drinks.dmi'
|
||||
icon_state = "broken_bottle"
|
||||
force = 9
|
||||
|
||||
@@ -585,6 +585,14 @@
|
||||
mix_message = "The mixture develops a sinister glow."
|
||||
mix_sound = 'sound/effects/singlebeat.ogg'
|
||||
|
||||
/datum/chemical_reaction/cogchamp
|
||||
name = "CogChamp"
|
||||
id = /datum/reagent/consumable/ethanol/cogchamp
|
||||
results = list(/datum/reagent/consumable/ethanol/cogchamp = 3)
|
||||
required_reagents = list(/datum/reagent/consumable/ethanol/cognac = 1, /datum/reagent/fuel = 1, /datum/reagent/consumable/ethanol/screwdrivercocktail = 1)
|
||||
mix_message = "You hear faint sounds of gears turning as it mixes."
|
||||
mix_sound = 'sound/effects/clockcult_gateway_closing.ogg'
|
||||
|
||||
/datum/chemical_reaction/quadruplesec
|
||||
name = "Quadruple Sec"
|
||||
id = /datum/reagent/consumable/ethanol/quadruple_sec
|
||||
|
||||
@@ -28,3 +28,7 @@
|
||||
backpack_contents = list(/obj/item/storage/box/beanbag=1,/obj/item/book/granter/action/drink_fling=1)
|
||||
shoes = /obj/item/clothing/shoes/laceup
|
||||
|
||||
/datum/job/bartender/after_spawn(mob/living/H, mob/M, latejoin = FALSE)
|
||||
. = ..()
|
||||
var/datum/action/innate/drink_fling/D = new
|
||||
D.Grant(H)
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
req_access = list()
|
||||
circuit = /obj/item/circuitboard/computer/mining_shuttle/common
|
||||
shuttleId = "mining_common"
|
||||
possible_destinations = "whiteship_home;lavaland_common_away;landing_zone_dock;mining_public"
|
||||
possible_destinations = "lavaland_common_away;commonmining_home"
|
||||
|
||||
/**********************Mining car (Crate like thing, not the rail car)**************************/
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
from doing this unless you absolutely know what you are doing, and have defined a
|
||||
conversion in savefile.dm
|
||||
*/
|
||||
/proc/init_sprite_accessory_subtypes(prototype, list/L, list/male, list/female,var/roundstart = FALSE)//Roundstart argument builds a specific list for roundstart parts where some parts may be locked
|
||||
/proc/init_sprite_accessory_subtypes(prototype, list/L, list/male, list/female, roundstart = FALSE, skip_prototype = TRUE)//Roundstart argument builds a specific list for roundstart parts where some parts may be locked
|
||||
if(!istype(L))
|
||||
L = list()
|
||||
if(!istype(male))
|
||||
@@ -25,7 +25,7 @@
|
||||
female = list()
|
||||
|
||||
for(var/path in typesof(prototype))
|
||||
if(path == prototype)
|
||||
if(path == prototype && skip_prototype)
|
||||
continue
|
||||
if(roundstart)
|
||||
var/datum/sprite_accessory/P = path
|
||||
|
||||
@@ -581,6 +581,9 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
|
||||
if(cultslurring)
|
||||
cultslurring = max(cultslurring-1, 0)
|
||||
|
||||
if(clockcultslurring)
|
||||
clockcultslurring = max(clockcultslurring-1, 0)
|
||||
|
||||
if(silent)
|
||||
silent = max(silent-1, 0)
|
||||
|
||||
|
||||
@@ -89,6 +89,7 @@
|
||||
var/stuttering = 0
|
||||
var/slurring = 0
|
||||
var/cultslurring = 0
|
||||
var/clockcultslurring = 0
|
||||
var/derpspeech = 0
|
||||
|
||||
var/list/implants = null
|
||||
|
||||
@@ -354,6 +354,9 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
|
||||
if(cultslurring)
|
||||
message = cultslur(message)
|
||||
|
||||
if(clockcultslurring)
|
||||
message = CLOCK_CULT_SLUR(message)
|
||||
|
||||
message = capitalize(message)
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#define PAI_EMP_SILENCE_DURATION 3 MINUTES
|
||||
|
||||
/mob/living/silicon/pai/blob_act(obj/structure/blob/B)
|
||||
return FALSE
|
||||
@@ -8,7 +9,7 @@
|
||||
return
|
||||
take_holo_damage(50/severity)
|
||||
Knockdown(400/severity)
|
||||
silent = max((3 MINUTES)/severity, silent)
|
||||
silent = max(silent, (PAI_EMP_SILENCE_DURATION) / SSmobs.wait / severity)
|
||||
if(holoform)
|
||||
fold_in(force = TRUE)
|
||||
emitter_next_use = world.time + emitter_emp_cd
|
||||
|
||||
@@ -147,6 +147,10 @@
|
||||
. += newletter
|
||||
return sanitize(.)
|
||||
|
||||
//Ratvarian Slurring!
|
||||
|
||||
#define CLOCK_CULT_SLUR(phrase) sanitize(text2ratvar(phrase))
|
||||
|
||||
///Adds stuttering to the message passed in
|
||||
/proc/stutter(phrase)
|
||||
phrase = html_decode(phrase)
|
||||
@@ -420,13 +424,10 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
|
||||
return TRUE
|
||||
|
||||
/mob/proc/getImplant(type)
|
||||
if (!istype(src,/mob/living))
|
||||
return
|
||||
var/mob/living/L = src
|
||||
for (var/I in L.implants)
|
||||
if (istype(I,type))
|
||||
return I
|
||||
return null
|
||||
return
|
||||
|
||||
/mob/living/getImplant(type)
|
||||
return locate(type) in implants
|
||||
|
||||
/proc/canGhostWrite(var/mob/A, var/obj/target, var/desc="", var/allow_all=FALSE)
|
||||
if(allow_all & TRUE)
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
var/icon_update_needed = FALSE
|
||||
var/obj/machinery/computer/apc_control/remote_control = null
|
||||
var/mob/living/carbon/hijacker
|
||||
var/hijackerlast = FALSE
|
||||
var/hijackerlast = TRUE
|
||||
|
||||
/obj/machinery/power/apc/unlocked
|
||||
locked = FALSE
|
||||
@@ -399,14 +399,14 @@
|
||||
if (hijacker)
|
||||
var/obj/item/implant/hijack/H = hijacker.getImplant(/obj/item/implant/hijack)
|
||||
hijackerreturn = H && !H.stealthmode
|
||||
if(last_update_state == update_state && last_update_overlay == update_overlay && hijackerreturn ? hijackerlast : !hijackerlast)
|
||||
if(last_update_state == update_state && last_update_overlay == update_overlay && hijackerreturn == hijackerlast)
|
||||
return 0
|
||||
if(last_update_state != update_state)
|
||||
results += 1
|
||||
if(last_update_overlay != update_overlay || hijackerreturn ? !hijackerlast : hijackerlast)
|
||||
if(last_update_overlay != update_overlay || hijackerreturn != hijackerlast)
|
||||
results += 2
|
||||
if (hijackerreturn ? !hijackerlast : hijackerlast)
|
||||
hijackerlast = hijackerreturn ? TRUE : FALSE
|
||||
if (hijackerreturn != hijackerlast)
|
||||
hijackerlast = hijackerreturn
|
||||
return results
|
||||
|
||||
// Used in process so it doesn't update the icon too much
|
||||
|
||||
@@ -150,7 +150,7 @@
|
||||
if(istype(v, /obj/item/ammo_casing/energy)) //already set
|
||||
ammo_type[v] = isnull(user_can_select)? TRUE : user_can_select
|
||||
else
|
||||
C = new v //if you put non energycasing/type stuff in here you deserve the runtime
|
||||
C = new v(src) //if you put non energycasing/type stuff in here you deserve the runtime
|
||||
ammo_type[i] = C
|
||||
ammo_type[C] = isnull(user_can_select)? TRUE : user_can_select
|
||||
set_firemode_index(initial(current_firemode_index))
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
|
||||
/obj/item/projectile/bullet/pellet/shotgun_buckshot
|
||||
name = "buckshot pellet"
|
||||
damage = 10
|
||||
damage = 12.5
|
||||
|
||||
/obj/item/projectile/bullet/pellet/shotgun_rubbershot
|
||||
name = "rubbershot pellet"
|
||||
|
||||
@@ -1513,6 +1513,23 @@ All effects don't start immediately, but rather get worse over time; the rate is
|
||||
M.stuttering = min(M.stuttering + 3, 3)
|
||||
..()
|
||||
|
||||
/datum/reagent/consumable/ethanol/cogchamp
|
||||
name = "CogChamp"
|
||||
description = "Now you can fill yourself with the power of Ratvar!"
|
||||
color = rgb(255, 201, 49)
|
||||
boozepwr = 10
|
||||
quality = DRINK_FANTASTIC
|
||||
taste_description = "a brass taste with a hint of oil"
|
||||
glass_icon_state = "cogchamp"
|
||||
glass_name = "CogChamp"
|
||||
glass_desc = "Not even Ratvar's Four Generals could withstand this! Qevax Jryy!"
|
||||
value = 8.13
|
||||
|
||||
/datum/reagent/consumable/ethanol/cogchamp/on_mob_life(mob/living/carbon/M)
|
||||
M.clockcultslurring = min(M.clockcultslurring + 3, 3)
|
||||
M.stuttering = min(M.stuttering + 3, 3)
|
||||
..()
|
||||
|
||||
/datum/reagent/consumable/ethanol/triple_sec
|
||||
name = "Triple Sec"
|
||||
description = "A sweet and vibrant orange liqueur."
|
||||
|
||||
@@ -105,11 +105,11 @@
|
||||
/obj/item/reagent_containers/proc/bartender_check(atom/target)
|
||||
. = FALSE
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T || target.CanPass(src, T) || !thrownby || !thrownby.actions)
|
||||
if(!T || !target.CanPass(src, T) || !thrownby || !thrownby.actions)
|
||||
return
|
||||
for(var/datum/action/innate/drink_fling/D in thrownby.actions)
|
||||
if(D.active)
|
||||
return TRUE
|
||||
var/datum/action/innate/D = get_action_of_type(thrownby, /datum/action/innate/drink_fling)
|
||||
if(D?.active)
|
||||
return TRUE
|
||||
|
||||
/obj/item/reagent_containers/proc/ForceResetRotation()
|
||||
transform = initial(transform)
|
||||
@@ -131,13 +131,14 @@
|
||||
if(thrownby)
|
||||
log_combat(thrownby, M, "splashed", R)
|
||||
reagents.reaction(target, TOUCH)
|
||||
|
||||
|
||||
else if(bartender_check(target) && thrown)
|
||||
visible_message("<span class='notice'>[src] lands onto the [target.name] without spilling a single drop.</span>")
|
||||
transform = initial(transform)
|
||||
addtimer(CALLBACK(src, .proc/ForceResetRotation), 1)
|
||||
return
|
||||
|
||||
|
||||
else
|
||||
if(isturf(target) && reagents.reagent_list.len && thrownby)
|
||||
log_combat(thrownby, target, "splashed (thrown) [english_list(reagents.reagent_list)]", "in [AREACOORD(target)]")
|
||||
|
||||
@@ -423,9 +423,9 @@
|
||||
else
|
||||
unload_hypo(vial,user)
|
||||
|
||||
/obj/item/hypospray/mkii/AltClick(mob/living/user)
|
||||
/obj/item/hypospray/mkii/CtrlClick(mob/living/user)
|
||||
. = ..()
|
||||
if(user.canUseTopic(src, FALSE))
|
||||
if(user.canUseTopic(src, FALSE) && user.get_active_held_item(src))
|
||||
switch(mode)
|
||||
if(HYPO_SPRAY)
|
||||
mode = HYPO_INJECT
|
||||
@@ -437,7 +437,7 @@
|
||||
|
||||
/obj/item/hypospray/mkii/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'><b>Alt-Click</b> it to toggle its mode from spraying to injecting and vice versa.</span>"
|
||||
. += "<span class='notice'><b>Ctrl-Click</b> it to toggle its mode from spraying to injecting and vice versa.</span>"
|
||||
|
||||
#undef HYPO_SPRAY
|
||||
#undef HYPO_INJECT
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "ancientpower"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscadd: "Ported drink sliding from /vg/station."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "Ghommie"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Fixed a little inconvenience with the character setup preview dummy having extra unwarranted bits."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "Ghommie"
|
||||
delete-after: True
|
||||
changes:
|
||||
- imageadd: "Fixed dozen missing privates sprites."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "Hatterhat"
|
||||
delete-after: True
|
||||
changes:
|
||||
- balance: "Buckshot individual pellet damage up from 10 to 12.5. Still firing 6 pellets."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "DeltaFire15"
|
||||
delete-after: True
|
||||
changes:
|
||||
- balance: "Nar'Sie runes no longer benefit from runed floors."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "kevinz000"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Energy weapons now once again have their lens in contents."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "Arturlang"
|
||||
delete-after: True
|
||||
changes:
|
||||
- tweak: "Hyposprays now switch modes on CTRL click, instead of alt, as it was already reserved for dispension amount."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "keronshb"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscadd: "Adds the CogChamp drink and Sprite"
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "kevinz000"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "pais are no longer muted for literally a whole hour on emp."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "Zellular"
|
||||
delete-after: True
|
||||
changes:
|
||||
- imageadd: "Movement state for pupdozer and its decals"
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "Putnam3145"
|
||||
delete-after: True
|
||||
changes:
|
||||
- tweak: "default should be... default"
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "kevinz000"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Cryo now actually transfers reagents at tier 4 on enter rather than every 80 machine fire()-process()s regardless of if it was \"reset\" by open/close."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "Seris02"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "apc icons"
|
||||
@@ -10,12 +10,6 @@
|
||||
var/hidden_undershirt = FALSE
|
||||
var/hidden_socks = FALSE
|
||||
|
||||
//Species vars
|
||||
/datum/species
|
||||
var/list/cum_fluids = list("semen")
|
||||
var/list/milk_fluids = list("milk")
|
||||
var/list/femcum_fluids = list("femcum")
|
||||
|
||||
//Mob procs
|
||||
/mob/living/carbon/human/proc/underwear_toggle()
|
||||
set name = "Toggle undergarments"
|
||||
@@ -46,20 +40,12 @@
|
||||
var/list/obj/item/organ/genital/genit_list = list()
|
||||
if(!client?.prefs.arousable || (aphro && (client?.prefs.cit_toggles & NO_APHRO)) || (maso && !HAS_TRAIT(src, TRAIT_MASO)))
|
||||
return // no adjusting made here
|
||||
if(strength>0)
|
||||
for(var/obj/item/organ/genital/G in internal_organs)
|
||||
if(!G.aroused_state && prob(strength*G.sensitivity))
|
||||
G.set_aroused_state(TRUE)
|
||||
G.update_appearance()
|
||||
if(G.aroused_state)
|
||||
genit_list += G
|
||||
else
|
||||
for(var/obj/item/organ/genital/G in internal_organs)
|
||||
if(G.aroused_state && prob(strength*G.sensitivity))
|
||||
G.set_aroused_state(FALSE)
|
||||
G.update_appearance()
|
||||
if(G.aroused_state)
|
||||
genit_list += G
|
||||
for(var/obj/item/organ/genital/G in internal_organs)
|
||||
if(G.genital_flags & GENITAL_CAN_AROUSE && !G.aroused_state && prob(strength*G.sensitivity))
|
||||
G.set_aroused_state(strength > 0)
|
||||
G.update_appearance()
|
||||
if(G.aroused_state)
|
||||
genit_list += G
|
||||
return genit_list
|
||||
|
||||
/obj/item/organ/genital/proc/climaxable(mob/living/carbon/human/H, silent = FALSE) //returns the fluid source (ergo reagents holder) if found.
|
||||
|
||||
@@ -32,23 +32,20 @@
|
||||
else
|
||||
update()
|
||||
|
||||
/obj/item/organ/genital/Destroy()
|
||||
if(linked_organ)
|
||||
update_link(TRUE)//this should remove any other links it has
|
||||
return ..()
|
||||
|
||||
/obj/item/organ/genital/proc/set_aroused_state(new_state)
|
||||
if(!(genital_flags & GENITAL_CAN_AROUSE))
|
||||
return FALSE
|
||||
if(!((HAS_TRAIT(owner,TRAIT_PERMABONER) && !new_state) || HAS_TRAIT(owner,TRAIT_NEVERBONER) && new_state))
|
||||
aroused_state = new_state
|
||||
return aroused_state
|
||||
|
||||
/obj/item/organ/genital/proc/update(removing = FALSE)
|
||||
/obj/item/organ/genital/proc/update()
|
||||
if(QDELETED(src))
|
||||
return
|
||||
update_size()
|
||||
update_appearance()
|
||||
if(linked_organ_slot || (linked_organ && removing))
|
||||
update_link(removing)
|
||||
if(linked_organ_slot || (linked_organ && !owner))
|
||||
update_link()
|
||||
|
||||
//exposure and through-clothing code
|
||||
/mob/living/carbon
|
||||
@@ -113,17 +110,7 @@
|
||||
set desc = "Allows you to toggle which genitals are showing signs of arousal."
|
||||
var/list/genital_list = list()
|
||||
for(var/obj/item/organ/genital/G in internal_organs)
|
||||
var/datum/sprite_accessory/S
|
||||
switch(G.type)
|
||||
if(/obj/item/organ/genital/penis)
|
||||
S = GLOB.cock_shapes_list[G.shape]
|
||||
if(/obj/item/organ/genital/testicles)
|
||||
S = GLOB.balls_shapes_list[G.shape]
|
||||
if(/obj/item/organ/genital/vagina)
|
||||
S = GLOB.vagina_shapes_list[G.shape]
|
||||
if(/obj/item/organ/genital/breasts)
|
||||
S = GLOB.breasts_shapes_list[G.shape]
|
||||
if(S?.alt_aroused)
|
||||
if(G.genital_flags & GENITAL_CAN_AROUSE)
|
||||
genital_list += G
|
||||
if(!genital_list.len) //There's nothing that can show arousal
|
||||
return
|
||||
@@ -174,19 +161,18 @@
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/organ/genital/proc/update_link(removing = FALSE)
|
||||
if(!removing && owner)
|
||||
/obj/item/organ/genital/proc/update_link()
|
||||
if(owner)
|
||||
if(linked_organ)
|
||||
return
|
||||
return FALSE
|
||||
linked_organ = owner.getorganslot(linked_organ_slot)
|
||||
if(linked_organ)
|
||||
linked_organ.linked_organ = src
|
||||
linked_organ.upon_link()
|
||||
upon_link()
|
||||
return TRUE
|
||||
else
|
||||
if(linked_organ)
|
||||
linked_organ.linked_organ = null
|
||||
if(linked_organ)
|
||||
linked_organ.linked_organ = null
|
||||
linked_organ = null
|
||||
return FALSE
|
||||
|
||||
@@ -200,10 +186,13 @@
|
||||
update()
|
||||
RegisterSignal(owner, COMSIG_MOB_DEATH, .proc/update_appearance)
|
||||
|
||||
/obj/item/organ/genital/Remove(mob/living/carbon/M, special = FALSE, drop_if_replaced = TRUE)
|
||||
update(TRUE)
|
||||
if(!QDELETED(owner))
|
||||
UnregisterSignal(owner, COMSIG_MOB_DEATH)
|
||||
/obj/item/organ/genital/Remove(special = FALSE)
|
||||
. = ..()
|
||||
var/mob/living/carbon/human/H = .
|
||||
update()
|
||||
if(!QDELETED(H))
|
||||
UnregisterSignal(H, COMSIG_MOB_DEATH)
|
||||
H.update_genitals()
|
||||
|
||||
//proc to give a player their genitals and stuff when they log in
|
||||
/mob/living/carbon/human/proc/give_genitals(clean = FALSE)//clean will remove all pre-existing genitals. proc will then give them any genitals that are enabled in their DNA
|
||||
@@ -238,12 +227,6 @@
|
||||
/obj/item/organ/genital/proc/get_features(mob/living/carbon/human/H)
|
||||
return
|
||||
|
||||
/datum/species/proc/genitals_layertext(layer)
|
||||
switch(layer)
|
||||
if(GENITALS_BEHIND_LAYER)
|
||||
return "BEHIND"
|
||||
if(GENITALS_FRONT_LAYER)
|
||||
return "FRONT"
|
||||
|
||||
//procs to handle sprite overlays being applied to humans
|
||||
|
||||
@@ -262,8 +245,90 @@
|
||||
update_genitals()
|
||||
|
||||
/mob/living/carbon/human/proc/update_genitals()
|
||||
if(!QDELETED(src))
|
||||
dna.species.handle_genitals(src)
|
||||
if(QDELETED(src))
|
||||
return
|
||||
var/static/list/relevant_layers = list("[GENITALS_BEHIND_LAYER]" = "BEHIND", "[GENITALS_FRONT_LAYER]" = "FRONT")
|
||||
var/static/list/layers_num
|
||||
if(!layers_num)
|
||||
for(var/L in relevant_layers)
|
||||
LAZYSET(layers_num, L, text2num(L))
|
||||
for(var/L in relevant_layers) //Less hardcode
|
||||
remove_overlay(layers_num[L])
|
||||
remove_overlay(GENITALS_EXPOSED_LAYER)
|
||||
if(!LAZYLEN(internal_organs) || ((NOGENITALS in dna.species.species_traits) && !genital_override) || HAS_TRAIT(src, TRAIT_HUSK))
|
||||
return
|
||||
|
||||
//start scanning for genitals
|
||||
|
||||
var/list/gen_index[GENITAL_LAYER_INDEX_LENGTH]
|
||||
var/list/genitals_to_add
|
||||
var/list/fully_exposed
|
||||
for(var/obj/item/organ/genital/G in internal_organs)
|
||||
if(G.is_exposed()) //Checks appropriate clothing slot and if it's through_clothes
|
||||
LAZYADD(gen_index[G.layer_index], G)
|
||||
for(var/L in gen_index)
|
||||
if(L) //skip nulls
|
||||
LAZYADD(genitals_to_add, L)
|
||||
if(!genitals_to_add)
|
||||
return
|
||||
//Now we added all genitals that aren't internal and should be rendered
|
||||
//start applying overlays
|
||||
for(var/layer in relevant_layers)
|
||||
var/list/standing = list()
|
||||
var/layertext = relevant_layers[layer]
|
||||
for(var/A in genitals_to_add)
|
||||
var/obj/item/organ/genital/G = A
|
||||
var/datum/sprite_accessory/S
|
||||
var/size = G.size
|
||||
switch(G.type)
|
||||
if(/obj/item/organ/genital/penis)
|
||||
S = GLOB.cock_shapes_list[G.shape]
|
||||
if(/obj/item/organ/genital/testicles)
|
||||
S = GLOB.balls_shapes_list[G.shape]
|
||||
if(/obj/item/organ/genital/vagina)
|
||||
S = GLOB.vagina_shapes_list[G.shape]
|
||||
if(/obj/item/organ/genital/breasts)
|
||||
S = GLOB.breasts_shapes_list[G.shape]
|
||||
|
||||
if(!S || S.icon_state == "none")
|
||||
continue
|
||||
var/aroused_state = G.aroused_state && S.alt_aroused
|
||||
|
||||
var/mutable_appearance/genital_overlay = mutable_appearance(S.icon, layer = -layer)
|
||||
if(S.center)
|
||||
genital_overlay = center_image(genital_overlay, S.dimension_x, S.dimension_y)
|
||||
|
||||
if(dna.species.use_skintones && dna.features["genitals_use_skintone"])
|
||||
genital_overlay.color = "#[skintone2hex(skin_tone)]"
|
||||
else
|
||||
switch(S.color_src)
|
||||
if("cock_color")
|
||||
genital_overlay.color = "#[dna.features["cock_color"]]"
|
||||
if("balls_color")
|
||||
genital_overlay.color = "#[dna.features["balls_color"]]"
|
||||
if("breasts_color")
|
||||
genital_overlay.color = "#[dna.features["breasts_color"]]"
|
||||
if("vag_color")
|
||||
genital_overlay.color = "#[dna.features["vag_color"]]"
|
||||
|
||||
genital_overlay.icon_state = "[G.slot]_[S.icon_state]_[size][dna.species.use_skintones ? "_s" : ""]_[aroused_state]_[layertext]"
|
||||
|
||||
if(layer == GENITALS_FRONT_LAYER && CHECK_BITFIELD(G.genital_flags, GENITAL_THROUGH_CLOTHES))
|
||||
genital_overlay.layer = -GENITALS_EXPOSED_LAYER
|
||||
LAZYADD(fully_exposed, genital_overlay) // to be added to a layer with higher priority than clothes, hence the name of the bitflag.
|
||||
else
|
||||
standing += genital_overlay
|
||||
|
||||
if(LAZYLEN(standing))
|
||||
overlays_standing[layers_num[layer]] = standing
|
||||
|
||||
if(LAZYLEN(fully_exposed))
|
||||
overlays_standing[GENITALS_EXPOSED_LAYER] = fully_exposed
|
||||
apply_overlay(GENITALS_EXPOSED_LAYER)
|
||||
|
||||
for(var/L in relevant_layers)
|
||||
apply_overlay(layers_num[L])
|
||||
|
||||
|
||||
//Checks to see if organs are new on the mob, and changes their colours so that they don't get crazy colours.
|
||||
/mob/living/carbon/human/proc/emergent_genital_call()
|
||||
@@ -292,86 +357,3 @@
|
||||
else if (willyCheck == FALSE)
|
||||
dna.features["cock_color"] = dna.features["breasts_color"]
|
||||
return TRUE
|
||||
|
||||
/datum/species/proc/handle_genitals(mob/living/carbon/human/H)//more like handle sadness
|
||||
if(!H)//no args
|
||||
CRASH("H = null")
|
||||
if(!LAZYLEN(H.internal_organs) || ((NOGENITALS in species_traits) && !H.genital_override) || HAS_TRAIT(H, TRAIT_HUSK))
|
||||
return
|
||||
var/list/relevant_layers = list(GENITALS_BEHIND_LAYER, GENITALS_FRONT_LAYER)
|
||||
|
||||
for(var/L in relevant_layers) //Less hardcode
|
||||
H.remove_overlay(L)
|
||||
H.remove_overlay(GENITALS_EXPOSED_LAYER)
|
||||
//start scanning for genitals
|
||||
|
||||
var/list/gen_index[GENITAL_LAYER_INDEX_LENGTH]
|
||||
var/list/genitals_to_add
|
||||
var/list/fully_exposed
|
||||
for(var/obj/item/organ/genital/G in H.internal_organs)
|
||||
if(G.is_exposed()) //Checks appropriate clothing slot and if it's through_clothes
|
||||
LAZYADD(gen_index[G.layer_index], G)
|
||||
for(var/L in gen_index)
|
||||
if(L) //skip nulls
|
||||
LAZYADD(genitals_to_add, L)
|
||||
if(!genitals_to_add)
|
||||
return
|
||||
//Now we added all genitals that aren't internal and should be rendered
|
||||
//start applying overlays
|
||||
for(var/layer in relevant_layers)
|
||||
var/list/standing = list()
|
||||
var/layertext = genitals_layertext(layer)
|
||||
for(var/A in genitals_to_add)
|
||||
var/obj/item/organ/genital/G = A
|
||||
var/datum/sprite_accessory/S
|
||||
var/size = G.size
|
||||
var/aroused_state = G.aroused_state
|
||||
switch(G.type)
|
||||
if(/obj/item/organ/genital/penis)
|
||||
S = GLOB.cock_shapes_list[G.shape]
|
||||
if(/obj/item/organ/genital/testicles)
|
||||
S = GLOB.balls_shapes_list[G.shape]
|
||||
if(/obj/item/organ/genital/vagina)
|
||||
S = GLOB.vagina_shapes_list[G.shape]
|
||||
if(/obj/item/organ/genital/breasts)
|
||||
S = GLOB.breasts_shapes_list[G.shape]
|
||||
|
||||
if(!S || S.icon_state == "none")
|
||||
continue
|
||||
|
||||
var/mutable_appearance/genital_overlay = mutable_appearance(S.icon, layer = -layer)
|
||||
genital_overlay.icon_state = "[G.slot]_[S.icon_state]_[size]_[aroused_state]_[layertext]"
|
||||
|
||||
if(S.center)
|
||||
genital_overlay = center_image(genital_overlay, S.dimension_x, S.dimension_y)
|
||||
|
||||
if(use_skintones && H.dna.features["genitals_use_skintone"])
|
||||
genital_overlay.color = "#[skintone2hex(H.skin_tone)]"
|
||||
else
|
||||
switch(S.color_src)
|
||||
if("cock_color")
|
||||
genital_overlay.color = "#[H.dna.features["cock_color"]]"
|
||||
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"]]"
|
||||
|
||||
genital_overlay.icon_state = "[G.slot]_[S.icon_state]_[size]-s_[aroused_state]_[layertext]"
|
||||
|
||||
if(layer == GENITALS_FRONT_LAYER && CHECK_BITFIELD(G.genital_flags, GENITAL_THROUGH_CLOTHES))
|
||||
genital_overlay.layer = -GENITALS_EXPOSED_LAYER
|
||||
LAZYADD(fully_exposed, genital_overlay) // to be added to a layer with higher priority than clothes, hence the name of the bitflag.
|
||||
else
|
||||
standing += genital_overlay
|
||||
|
||||
if(LAZYLEN(standing))
|
||||
H.overlays_standing[layer] = standing
|
||||
|
||||
if(LAZYLEN(fully_exposed))
|
||||
H.overlays_standing[GENITALS_EXPOSED_LAYER] = fully_exposed
|
||||
H.apply_overlay(GENITALS_EXPOSED_LAYER)
|
||||
|
||||
for(var/L in relevant_layers)
|
||||
H.apply_overlay(L)
|
||||
|
||||
@@ -85,36 +85,36 @@
|
||||
//Vaginas
|
||||
/datum/sprite_accessory/vagina
|
||||
icon = 'modular_citadel/icons/obj/genitals/vagina_onmob.dmi'
|
||||
icon_state = null
|
||||
name = "vagina"
|
||||
color_src = "vag_color"
|
||||
alt_aroused = TRUE
|
||||
|
||||
/datum/sprite_accessory/vagina/human
|
||||
icon_state = "human"
|
||||
name = "Human"
|
||||
alt_aroused = TRUE
|
||||
|
||||
/datum/sprite_accessory/vagina/tentacles
|
||||
icon_state = "tentacle"
|
||||
name = "Tentacle"
|
||||
alt_aroused = TRUE
|
||||
|
||||
/datum/sprite_accessory/vagina/dentata
|
||||
icon_state = "dentata"
|
||||
name = "Dentata"
|
||||
alt_aroused = TRUE
|
||||
|
||||
/datum/sprite_accessory/vagina/hairy
|
||||
icon_state = "hairy"
|
||||
name = "Hairy"
|
||||
alt_aroused = FALSE
|
||||
|
||||
/datum/sprite_accessory/vagina/spade
|
||||
icon_state = "spade"
|
||||
name = "Spade"
|
||||
alt_aroused = FALSE
|
||||
|
||||
/datum/sprite_accessory/vagina/furred
|
||||
icon_state = "furred"
|
||||
name = "Furred"
|
||||
alt_aroused = FALSE
|
||||
|
||||
/datum/sprite_accessory/vagina/gaping
|
||||
icon_state = "gaping"
|
||||
@@ -125,7 +125,6 @@
|
||||
icon = 'modular_citadel/icons/obj/genitals/breasts_onmob.dmi'
|
||||
name = "breasts"
|
||||
color_src = "breasts_color"
|
||||
alt_aroused = TRUE
|
||||
|
||||
/datum/sprite_accessory/breasts/pair
|
||||
icon_state = "pair"
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#define BREASTS_ICON_MIN_SIZE 1
|
||||
#define BREASTS_ICON_MAX_SIZE 6
|
||||
|
||||
/obj/item/organ/genital/breasts
|
||||
name = "breasts"
|
||||
desc = "Female milk producing organs."
|
||||
@@ -9,7 +12,7 @@
|
||||
fluid_id = /datum/reagent/consumable/milk
|
||||
fluid_rate = MILK_RATE
|
||||
shape = "pair"
|
||||
genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH|GENITAL_FUID_PRODUCTION
|
||||
genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH|GENITAL_FUID_PRODUCTION|GENITAL_CAN_AROUSE
|
||||
masturbation_verb = "massage"
|
||||
arousal_verb = "Your breasts start feeling sensitive"
|
||||
unarousal_verb = "Your breasts no longer feel sensitive"
|
||||
@@ -49,21 +52,21 @@
|
||||
var/datum/reagent/R = GLOB.chemical_reagents_list[fluid_id]
|
||||
if(R)
|
||||
desc += " They're leaking [lowertext(R.name)]."
|
||||
var/string
|
||||
var/datum/sprite_accessory/S = GLOB.breasts_shapes_list[shape]
|
||||
var/icon_shape = S ? S.icon_state : "pair"
|
||||
var/icon_size = CLAMP(breast_values[size], BREASTS_ICON_MIN_SIZE, BREASTS_ICON_MAX_SIZE)
|
||||
icon_state = "breasts_[icon_shape]_[breast_values[icon_size]]"
|
||||
if(owner)
|
||||
if(owner.dna.species.use_skintones && owner.dna.features["genitals_use_skintone"])
|
||||
if(ishuman(owner)) // Check before recasting type, although someone fucked up if you're not human AND have use_skintones somehow...
|
||||
var/mob/living/carbon/human/H = owner // only human mobs have skin_tone, which we need.
|
||||
color = "#[skintone2hex(H.skin_tone)]"
|
||||
string = "breasts_[GLOB.breasts_shapes_icons[shape]]_[size]-s"
|
||||
icon_state += "_s"
|
||||
else
|
||||
color = "#[owner.dna.features["breasts_color"]]"
|
||||
string = "breasts_[GLOB.breasts_shapes_icons[shape]]_[size]"
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/H = owner
|
||||
icon_state = sanitize_text(string)
|
||||
H.update_genitals()
|
||||
icon_state = sanitize_text(string)
|
||||
|
||||
//Allows breasts to grow and change size, with sprite changes too.
|
||||
//maximum wah
|
||||
@@ -130,3 +133,6 @@
|
||||
cached_size = size
|
||||
size = breast_values[size]
|
||||
prev_size = cached_size
|
||||
|
||||
#undef BREASTS_ICON_MIN_SIZE
|
||||
#undef BREASTS_ICON_MAX_SIZE
|
||||
@@ -8,13 +8,13 @@
|
||||
masturbation_verb = "stroke"
|
||||
arousal_verb = "You pop a boner"
|
||||
unarousal_verb = "Your boner goes down"
|
||||
genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH
|
||||
genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH|GENITAL_CAN_AROUSE
|
||||
linked_organ_slot = ORGAN_SLOT_TESTICLES
|
||||
fluid_transfer_factor = 0.5
|
||||
size = 2 //arbitrary value derived from length and girth for sprites.
|
||||
layer_index = PENIS_LAYER_INDEX
|
||||
var/length = 6 //inches
|
||||
var/prev_length = 6 //really should be renamed to prev_length
|
||||
var/prev_length = 6
|
||||
var/girth = 4.38
|
||||
var/girth_ratio = COCK_GIRTH_RATIO_DEF //0.73; check citadel_defines.dm
|
||||
|
||||
@@ -73,22 +73,21 @@
|
||||
|
||||
/obj/item/organ/genital/penis/update_appearance()
|
||||
. = ..()
|
||||
var/string
|
||||
var/datum/sprite_accessory/S = GLOB.cock_shapes_list[shape]
|
||||
var/icon_shape = S ? S.icon_state : "human"
|
||||
icon_state = "penis_[icon_shape]_[size]"
|
||||
var/lowershape = lowertext(shape)
|
||||
desc = "You see [aroused_state ? "an erect" : "a flaccid"] [lowershape] [name]. You estimate it's about [round(length, 0.25)] inch[round(length, 0.25) != 1 ? "es" : ""] long and [round(girth, 0.25)] inch[round(girth, 0.25) != 1 ? "es" : ""] in girth."
|
||||
|
||||
if(owner)
|
||||
if(owner.dna.species.use_skintones && owner.dna.features["genitals_use_skintone"])
|
||||
if(ishuman(owner)) // Check before recasting type, although someone fucked up if you're not human AND have use_skintones somehow...
|
||||
var/mob/living/carbon/human/H = owner // only human mobs have skin_tone, which we need.
|
||||
color = "#[skintone2hex(H.skin_tone)]"
|
||||
string = "penis_[GLOB.cock_shapes_icons[shape]]_[size]-s"
|
||||
icon_state += "_s"
|
||||
else
|
||||
color = "#[owner.dna.features["cock_color"]]"
|
||||
string = "penis_[GLOB.cock_shapes_icons[shape]]_[size]"
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/H = owner
|
||||
icon_state = sanitize_text(string)
|
||||
H.update_genitals()
|
||||
|
||||
/obj/item/organ/genital/penis/get_features(mob/living/carbon/human/H)
|
||||
|
||||
@@ -43,19 +43,19 @@
|
||||
/obj/item/organ/genital/testicles/update_appearance()
|
||||
. = ..()
|
||||
desc = "You see an [size_name] pair of testicles."
|
||||
var/datum/sprite_accessory/S = GLOB.balls_shapes_list[shape]
|
||||
var/icon_shape = S ? S.icon_state : "single"
|
||||
icon_state = "testicles_[icon_shape]_[size]"
|
||||
if(owner)
|
||||
var/string
|
||||
if(owner.dna.species.use_skintones && owner.dna.features["genitals_use_skintone"])
|
||||
if(ishuman(owner)) // Check before recasting type, although someone fucked up if you're not human AND have use_skintones somehow...
|
||||
var/mob/living/carbon/human/H = owner // only human mobs have skin_tone, which we need.
|
||||
color = "#[skintone2hex(H.skin_tone)]"
|
||||
string = "testicles_[GLOB.balls_shapes_icons[shape]]_[size]-s"
|
||||
icon_state += "_s"
|
||||
else
|
||||
color = "#[owner.dna.features["balls_color"]]"
|
||||
string = "testicles_[GLOB.balls_shapes_icons[shape]]_[size]"
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/H = owner
|
||||
icon_state = sanitize_text(string)
|
||||
H.update_genitals()
|
||||
|
||||
/obj/item/organ/genital/testicles/get_features(mob/living/carbon/human/H)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
zone = BODY_ZONE_PRECISE_GROIN
|
||||
slot = "vagina"
|
||||
size = 1 //There is only 1 size right now
|
||||
genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH
|
||||
genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH|GENITAL_CAN_AROUSE
|
||||
masturbation_verb = "finger"
|
||||
arousal_verb = "You feel wetness on your crotch"
|
||||
unarousal_verb = "You no longer feel wet"
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
/obj/item/organ/genital/vagina/update_appearance()
|
||||
. = ..()
|
||||
var/string //Keeping this code here, so making multiple sprites for the different kinds is easier.
|
||||
icon_state = "vagina"
|
||||
var/lowershape = lowertext(shape)
|
||||
var/details
|
||||
|
||||
@@ -55,13 +55,11 @@
|
||||
if(ishuman(owner)) // Check before recasting type, although someone fucked up if you're not human AND have use_skintones somehow...
|
||||
var/mob/living/carbon/human/H = owner // only human mobs have skin_tone, which we need.
|
||||
color = "#[skintone2hex(H.skin_tone)]"
|
||||
string = "vagina-s"
|
||||
icon_state += "_s"
|
||||
else
|
||||
color = "#[owner.dna.features["vag_color"]]"
|
||||
string = "vagina"
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/H = owner
|
||||
icon_state = sanitize_text(string)
|
||||
H.update_genitals()
|
||||
|
||||
/obj/item/organ/genital/vagina/get_features(mob/living/carbon/human/H)
|
||||
|
||||
|
Before Width: | Height: | Size: 680 KiB After Width: | Height: | Size: 706 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 626 B After Width: | Height: | Size: 546 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -152,6 +152,7 @@
|
||||
#include "code\__HELPERS\type2type_vr.dm"
|
||||
#include "code\__HELPERS\typelists.dm"
|
||||
#include "code\__HELPERS\unsorted.dm"
|
||||
#include "code\__HELPERS\vector.dm"
|
||||
#include "code\__HELPERS\view.dm"
|
||||
#include "code\__HELPERS\sorts\__main.dm"
|
||||
#include "code\__HELPERS\sorts\InsertSort.dm"
|
||||
|
||||