mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2025-12-10 01:49:19 +00:00
Merge branch 'master' into research-table
This commit is contained in:
@@ -68,11 +68,8 @@
|
||||
/turf/closed/indestructible/hotelwall,
|
||||
/area/hilbertshotel)
|
||||
"fv" = (
|
||||
/obj/machinery/atmospherics/components/unary/outlet_injector/on{
|
||||
piping_layer = 3;
|
||||
pixel_y = 5
|
||||
},
|
||||
/obj/structure/lattice,
|
||||
/obj/machinery/atmospherics/components/unary/outlet_injector/on/layer3,
|
||||
/turf/open/space/bluespace,
|
||||
/area/hilbertshotel)
|
||||
"fF" = (
|
||||
@@ -88,9 +85,8 @@
|
||||
/turf/closed/indestructible/hotelwall,
|
||||
/area/hilbertshotel)
|
||||
"hk" = (
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
|
||||
dir = 8;
|
||||
piping_layer = 3
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer3{
|
||||
dir = 8
|
||||
},
|
||||
/turf/open/floor/carpet,
|
||||
/area/hilbertshotel)
|
||||
@@ -191,6 +187,21 @@
|
||||
"re" = (
|
||||
/obj/structure/table/reinforced,
|
||||
/obj/item/reagent_containers/food/drinks/drinkingglass,
|
||||
/obj/item/reagent_containers/food/drinks/drinkingglass{
|
||||
pixel_x = -2;
|
||||
pixel_y = 4
|
||||
},
|
||||
/obj/item/reagent_containers/food/drinks/drinkingglass{
|
||||
pixel_y = 7
|
||||
},
|
||||
/obj/item/reagent_containers/food/drinks/drinkingglass{
|
||||
pixel_x = 5;
|
||||
pixel_y = 4
|
||||
},
|
||||
/obj/item/reagent_containers/food/drinks/drinkingglass{
|
||||
pixel_x = -5;
|
||||
pixel_y = 5
|
||||
},
|
||||
/turf/open/floor/plasteel/cafeteria,
|
||||
/area/hilbertshotel)
|
||||
"su" = (
|
||||
@@ -249,9 +260,8 @@
|
||||
/turf/open/floor/plasteel/cafeteria,
|
||||
/area/hilbertshotel)
|
||||
"zr" = (
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
|
||||
dir = 4;
|
||||
piping_layer = 3
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer3{
|
||||
dir = 4
|
||||
},
|
||||
/turf/open/indestructible/hotelwood,
|
||||
/area/hilbertshotel)
|
||||
@@ -445,9 +455,8 @@
|
||||
/turf/open/indestructible/hotelwood,
|
||||
/area/hilbertshotel)
|
||||
"RP" = (
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
|
||||
dir = 1;
|
||||
piping_layer = 3
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer3{
|
||||
dir = 1
|
||||
},
|
||||
/turf/open/indestructible/hoteltile,
|
||||
/area/hilbertshotel)
|
||||
|
||||
308
_maps/splurt_maps/templates/hilbertshotelempty.dmm
Normal file
308
_maps/splurt_maps/templates/hilbertshotelempty.dmm
Normal file
@@ -0,0 +1,308 @@
|
||||
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
|
||||
"a" = (
|
||||
/turf/open/space/bluespace,
|
||||
/area/hilbertshotel)
|
||||
"b" = (
|
||||
/turf/closed/indestructible/hotelwall,
|
||||
/area/hilbertshotel)
|
||||
"c" = (
|
||||
/turf/open/indestructible/hotelwood,
|
||||
/area/hilbertshotel)
|
||||
"d" = (
|
||||
/turf/open/indestructible/hoteltile,
|
||||
/area/hilbertshotel)
|
||||
"e" = (
|
||||
/turf/closed/indestructible/hoteldoor,
|
||||
/area/hilbertshotel)
|
||||
"X" = (
|
||||
/turf/open/space/bluespace,
|
||||
/area/space)
|
||||
|
||||
(1,1,1) = {"
|
||||
X
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
"}
|
||||
(2,1,1) = {"
|
||||
X
|
||||
a
|
||||
b
|
||||
b
|
||||
b
|
||||
b
|
||||
b
|
||||
e
|
||||
b
|
||||
b
|
||||
b
|
||||
b
|
||||
b
|
||||
b
|
||||
b
|
||||
a
|
||||
"}
|
||||
(3,1,1) = {"
|
||||
X
|
||||
a
|
||||
b
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
b
|
||||
a
|
||||
"}
|
||||
(4,1,1) = {"
|
||||
X
|
||||
a
|
||||
b
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
b
|
||||
a
|
||||
"}
|
||||
(5,1,1) = {"
|
||||
X
|
||||
a
|
||||
b
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
b
|
||||
a
|
||||
"}
|
||||
(6,1,1) = {"
|
||||
X
|
||||
a
|
||||
b
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
b
|
||||
a
|
||||
"}
|
||||
(7,1,1) = {"
|
||||
X
|
||||
a
|
||||
b
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
b
|
||||
a
|
||||
"}
|
||||
(8,1,1) = {"
|
||||
X
|
||||
a
|
||||
b
|
||||
b
|
||||
b
|
||||
c
|
||||
b
|
||||
b
|
||||
b
|
||||
b
|
||||
b
|
||||
b
|
||||
b
|
||||
b
|
||||
b
|
||||
a
|
||||
"}
|
||||
(9,1,1) = {"
|
||||
X
|
||||
a
|
||||
b
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
d
|
||||
d
|
||||
d
|
||||
d
|
||||
d
|
||||
b
|
||||
a
|
||||
"}
|
||||
(10,1,1) = {"
|
||||
X
|
||||
a
|
||||
b
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
b
|
||||
d
|
||||
d
|
||||
d
|
||||
d
|
||||
d
|
||||
b
|
||||
a
|
||||
"}
|
||||
(11,1,1) = {"
|
||||
X
|
||||
a
|
||||
b
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
b
|
||||
d
|
||||
d
|
||||
d
|
||||
d
|
||||
d
|
||||
b
|
||||
a
|
||||
"}
|
||||
(12,1,1) = {"
|
||||
X
|
||||
a
|
||||
b
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
b
|
||||
d
|
||||
d
|
||||
d
|
||||
d
|
||||
d
|
||||
b
|
||||
a
|
||||
"}
|
||||
(13,1,1) = {"
|
||||
X
|
||||
a
|
||||
b
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
b
|
||||
d
|
||||
d
|
||||
d
|
||||
d
|
||||
d
|
||||
b
|
||||
a
|
||||
"}
|
||||
(14,1,1) = {"
|
||||
X
|
||||
a
|
||||
b
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
c
|
||||
b
|
||||
d
|
||||
d
|
||||
d
|
||||
d
|
||||
d
|
||||
b
|
||||
a
|
||||
"}
|
||||
(15,1,1) = {"
|
||||
X
|
||||
a
|
||||
b
|
||||
b
|
||||
b
|
||||
b
|
||||
b
|
||||
b
|
||||
b
|
||||
b
|
||||
b
|
||||
b
|
||||
b
|
||||
b
|
||||
b
|
||||
a
|
||||
"}
|
||||
(16,1,1) = {"
|
||||
X
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
a
|
||||
"}
|
||||
@@ -91,6 +91,7 @@
|
||||
target.clean_blood()
|
||||
SEND_SIGNAL(target, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_MEDIUM)
|
||||
target.wash_cream()
|
||||
target.wash_cum() //sandstorm edit
|
||||
return
|
||||
|
||||
|
||||
|
||||
@@ -549,6 +549,7 @@
|
||||
H.lip_style = null //Washes off lipstick
|
||||
H.lip_color = initial(H.lip_color)
|
||||
H.wash_cream()
|
||||
H.wash_cum() //sandstorm edit
|
||||
H.regenerate_icons()
|
||||
user.drowsyness = max(user.drowsyness - rand(2,3), 0) //Washing your face wakes you up if you're falling asleep
|
||||
else
|
||||
@@ -622,6 +623,7 @@
|
||||
busy = FALSE
|
||||
SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
|
||||
O.clean_blood()
|
||||
O.wash_cum() //sandstorm edit
|
||||
var/datum/component/acid/acid = O.GetComponent(/datum/component/acid)
|
||||
if(acid)
|
||||
acid.level = 0
|
||||
|
||||
@@ -134,7 +134,7 @@
|
||||
return
|
||||
to_chat(src,"<span class='userlove'>You used your [G.name] to fill [container].</span>")
|
||||
message_admins("[src] used their [G.name] to fill [container].")
|
||||
do_climax(fluid_source, container, G, FALSE)
|
||||
do_climax(fluid_source, container, G, FALSE, cover = TRUE)
|
||||
|
||||
/mob/living/carbon/human/proc/pick_climax_genitals(silent = FALSE)
|
||||
var/list/genitals_list
|
||||
@@ -276,7 +276,7 @@
|
||||
return
|
||||
|
||||
//Ok, now we check what they want to do.
|
||||
var/choice = input(src, "Select sexual activity", "Sexual activity:") as null|anything in list("Climax alone","Climax with partner", "Fill container")
|
||||
var/choice = input(src, "Select sexual activity", "Sexual activity:") as null|anything in list("Climax alone","Climax with partner", "Climax over partner", "Fill container")
|
||||
if(!choice)
|
||||
return
|
||||
|
||||
@@ -310,6 +310,14 @@
|
||||
var/obj/item/reagent_containers/fluid_container = pick_climax_container()
|
||||
if(fluid_container && available_rosie_palms(TRUE, /obj/item/reagent_containers))
|
||||
mob_fill_container(picked_organ, fluid_container)
|
||||
if("Climax over partner")
|
||||
//We need no hands, we can be restrained and so on, so let's pick an organ
|
||||
var/obj/item/organ/genital/picked_organ = pick_climax_genitals()
|
||||
if(picked_organ)
|
||||
var/mob/living/partner = pick_partner() //Get someone
|
||||
if(partner)
|
||||
mob_climax_over(picked_organ, partner, TRUE)
|
||||
|
||||
mb_cd_timer = world.time + mb_cd_length
|
||||
|
||||
/mob/living/carbon/human/verb/climax_verb()
|
||||
|
||||
@@ -1332,6 +1332,7 @@
|
||||
O.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
|
||||
SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
|
||||
O.clean_blood()
|
||||
O.wash_cum() //sandstorm edit
|
||||
|
||||
/datum/reagent/space_cleaner/reaction_turf(turf/T, reac_volume)
|
||||
..()
|
||||
@@ -1339,6 +1340,7 @@
|
||||
T.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
|
||||
SEND_SIGNAL(T, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
|
||||
T.clean_blood()
|
||||
T.wash_cum() //sandstorm edit
|
||||
for(var/obj/effect/decal/cleanable/C in T)
|
||||
qdel(C)
|
||||
|
||||
@@ -1381,6 +1383,7 @@
|
||||
if(H.shoes.clean_blood())
|
||||
H.update_inv_shoes()
|
||||
H.wash_cream()
|
||||
H.wash_cum() //sandstorm edit
|
||||
SEND_SIGNAL(M, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
|
||||
M.clean_blood()
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
reagents.add_reagent(r_id, amount * 0.3)
|
||||
M.adjust_fire_stacks(minus_plus * amount)
|
||||
M.wash_cream()
|
||||
M.wash_cum() //sandstorm edit
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -794,12 +794,6 @@
|
||||
<ul class="changes bgimages16">
|
||||
<li class="admin">Admins get messaged if dynamic midrounds fail to hijack</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">13 November 2021</h2>
|
||||
<h3 class="author">Putnam3145 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="balance">Chonker cubans pete now no longer have a reasonable chance to be unbeatable</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<b>GoonStation 13 Development Team</b>
|
||||
|
||||
7
html/changelogs/AutoChangeLog-pr-132.yml
Normal file
7
html/changelogs/AutoChangeLog-pr-132.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
author: BongaTheProto
|
||||
delete-after: true
|
||||
changes:
|
||||
- rscadd: Milking machines
|
||||
- rscadd: Pleasuremaws
|
||||
- rscadd: dogborg stuff cit erased
|
||||
- rscadd: cum over
|
||||
4
html/changelogs/AutoChangeLog-pr-133.yml
Normal file
4
html/changelogs/AutoChangeLog-pr-133.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
author: jbox144
|
||||
delete-after: true
|
||||
changes:
|
||||
- tweak: Added the ability to TK hug people!
|
||||
8
html/changelogs/AutoChangeLog-pr-134.yml
Normal file
8
html/changelogs/AutoChangeLog-pr-134.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
author: jbox144
|
||||
delete-after: true
|
||||
changes:
|
||||
- bugfix: Fixed the offset door bug on hilbert's hotel. Rather, the wall was actually
|
||||
the problematic part. So I guess the wall is fixed.
|
||||
- rscadd: Added 4 more glasses to the kitchen in hilbert's hotel.
|
||||
- tweak: Changed the scrubbers in hilbert's hotel to use layer 3, instead of being
|
||||
var edited to layer 3
|
||||
@@ -87,8 +87,32 @@
|
||||
subcategory = CAT_TOOL
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/*
|
||||
//Hyper stuff
|
||||
//Milking machines
|
||||
/datum/crafting_recipe/milking_machine
|
||||
name = "Milking Machine"
|
||||
result = /obj/item/milking_machine
|
||||
reqs = list(
|
||||
/obj/item/stack/cable_coil = 5,
|
||||
/obj/item/stack/rods = 2,
|
||||
/obj/item/stack/sheet/cardboard = 1,
|
||||
/obj/item/reagent_containers/glass/beaker = 2,
|
||||
/obj/item/stock_parts/manipulator = 1
|
||||
)
|
||||
tools = list(TOOL_WELDER, TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/milking_machine/penis
|
||||
name = "Cock Milker"
|
||||
result = /obj/item/milking_machine/penis
|
||||
reqs = list(
|
||||
/obj/item/stack/cable_coil = 5,
|
||||
/obj/item/stack/rods = 1,
|
||||
/obj/item/stack/sheet/cardboard = 1,
|
||||
/obj/item/reagent_containers/glass/beaker/large = 1,
|
||||
/obj/item/stock_parts/manipulator = 1
|
||||
)
|
||||
|
||||
//Bouquets
|
||||
/datum/crafting_recipe/mixedbouquet
|
||||
name = "Mixed bouquet"
|
||||
@@ -97,22 +121,25 @@
|
||||
/obj/item/grown/sunflower = 2,
|
||||
/obj/item/reagent_containers/food/snacks/grown/poppy/geranium = 2)
|
||||
category = CAT_MISCELLANEOUS
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/sunbouquet
|
||||
name = "Sunflower bouquet"
|
||||
result = /obj/item/bouquet/sunflower
|
||||
reqs = list(/obj/item/grown/sunflower = 6)
|
||||
category = CAT_MISCELLANEOUS
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/poppybouquet
|
||||
name = "Poppy bouquet"
|
||||
result = /obj/item/bouquet/poppy
|
||||
reqs = list (/obj/item/reagent_containers/food/snacks/grown/poppy = 6)
|
||||
category = CAT_MISCELLANEOUS
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/rosebouquet
|
||||
name = "Rose bouquet"
|
||||
result = /obj/item/bouquet/rose
|
||||
reqs = list(/obj/item/grown/rose = 6)
|
||||
category = CAT_MISCELLANEOUS
|
||||
*/
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
|
||||
2
modular_sand/code/game/atoms.dm
Normal file
2
modular_sand/code/game/atoms.dm
Normal file
@@ -0,0 +1,2 @@
|
||||
/atom
|
||||
var/icon/cum_splatter_icon
|
||||
115
modular_sand/code/game/objects/items/milking_machine.dm
Normal file
115
modular_sand/code/game/objects/items/milking_machine.dm
Normal file
@@ -0,0 +1,115 @@
|
||||
/obj/item/milking_machine
|
||||
icon = 'modular_sand/icons/obj/milking_machine.dmi'
|
||||
name = "milking machine"
|
||||
icon_state = "Off"
|
||||
item_state = "Off"
|
||||
desc = "A pocket sized pump and tubing assembly designed to collect and store products from mammary glands."
|
||||
|
||||
slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_POCKET
|
||||
|
||||
var/on = FALSE
|
||||
var/obj/item/reagent_containers/inserted_item = null
|
||||
|
||||
var/milking_speed = 50
|
||||
var/engine_sound = 'sound/vehicles/carrev.ogg'
|
||||
var/target_organ = ORGAN_SLOT_BREASTS // What organ we are transfering from
|
||||
var/inuse = 0
|
||||
|
||||
/obj/item/milking_machine/Initialize()
|
||||
. = ..()
|
||||
item_flags |= NOBLUDGEON //No more attack messages
|
||||
|
||||
/obj/item/milking_machine/examine(mob/user)
|
||||
. = ..()
|
||||
to_chat(user, "<span class='notice'>[src] is currently [on ? "on" : "off"].</span>")
|
||||
if (inserted_item)
|
||||
to_chat(user, "<span class='notice'>[inserted_item] contains [inserted_item.reagents.total_volume]/[inserted_item.reagents.maximum_volume] units</span>")
|
||||
|
||||
/obj/item/milking_machine/attackby(obj/item/W, mob/user, params)
|
||||
add_fingerprint(user)
|
||||
if(istype(W, /obj/item/reagent_containers/) && !inserted_item)
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
return ..()
|
||||
inserted_item = W
|
||||
UpdateIcon()
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/milking_machine/interact(mob/user)
|
||||
if(!isAI(user) && inserted_item)
|
||||
add_fingerprint(user)
|
||||
on = !on
|
||||
if (on)
|
||||
to_chat(user, "<span class='notice'>You turn [src] on.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You turn [src] off.</span>")
|
||||
UpdateIcon()
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/milking_machine/proc/UpdateIcon()
|
||||
icon_state = "[on ? "On" : "Off"][inserted_item ? "Beaker" : ""]"
|
||||
item_state = icon_state
|
||||
|
||||
|
||||
/obj/item/milking_machine/AltClick(mob/living/user)
|
||||
add_fingerprint(user)
|
||||
user.put_in_hands(inserted_item)
|
||||
inserted_item = null
|
||||
on = FALSE
|
||||
UpdateIcon()
|
||||
|
||||
/obj/item/milking_machine/penis
|
||||
name = "cock milker"
|
||||
icon_state = "PenisOff"
|
||||
item_state = "PenisOff"
|
||||
desc = "A pocket sized pump and tubing assembly designed to collect and store products from the penis."
|
||||
target_organ = ORGAN_SLOT_PENIS
|
||||
|
||||
/obj/item/milking_machine/penis/UpdateIcon()
|
||||
icon_state = "Penis[on ? "On" : "Off"][inserted_item ? "Beaker" : ""]"
|
||||
item_state = icon_state
|
||||
|
||||
/obj/item/milking_machine/afterattack(mob/living/carbon/human/H, mob/living/user)
|
||||
if (!on)
|
||||
to_chat(user, "<span class='notice'>You can't use the [src] while it's off.</span>")
|
||||
return
|
||||
|
||||
var/obj/item/organ/genital/G = FALSE
|
||||
// Checking if a valid organ is being passed
|
||||
if (target_organ == ORGAN_SLOT_BREASTS || target_organ == ORGAN_SLOT_PENIS || target_organ == ORGAN_SLOT_VAGINA)
|
||||
G = H.getorganslot(target_organ)
|
||||
else
|
||||
return
|
||||
|
||||
if(inuse == 1) //just to stop stacking and causing people to cum instantly
|
||||
return
|
||||
if(G && G.is_exposed())
|
||||
inuse = 1
|
||||
if(!(H == user)) //lewd flavour text
|
||||
H.visible_message("<span class='love'>[user] pumps [H]'s [G.name] using [p_their()] [src.name].</span>", \
|
||||
"<span class='userlove'>[user] pumps your [G.name] with [p_their()] [src.name].</span>", \
|
||||
"<span class='userlove'>Someone is pumping your [G.name].</span>")
|
||||
else
|
||||
user.visible_message("<span class='love'>[user] sets [src] to suck on [p_their()] [G.name].</span>", \
|
||||
"<span class='userlove'>You pump your [G.name] using [src].</span>", \
|
||||
"<span class='userlove'>You pump your [G.name] into the machine.</span>")
|
||||
playsound(src, engine_sound, 30, 1, -1)
|
||||
if(!do_mob(user, H, 3 SECONDS)) //3 second delay
|
||||
inuse = 0
|
||||
return
|
||||
playsound(src, 'modular_sand/sound/lewd/slaps.ogg', 20, 1, -1)
|
||||
inuse = 0
|
||||
|
||||
if(prob(30)) //30% chance to make them moan.
|
||||
H.emote("moan")
|
||||
|
||||
H.add_lust(20) //make the target more aroused. (same ammount as the fleshlight)
|
||||
if (H.get_lust() >= H.get_lust_tolerance()*3 && ishuman(H) && H.has_dna())
|
||||
H.mob_fill_container(G, inserted_item, milking_speed, src) //make them cum if they are over the edge.
|
||||
H.do_jitter_animation()
|
||||
return
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You don't see anywhere to use this on.</span>")
|
||||
inuse = 0
|
||||
..()
|
||||
9
modular_sand/code/game/objects/structures/watercloset.dm
Normal file
9
modular_sand/code/game/objects/structures/watercloset.dm
Normal file
@@ -0,0 +1,9 @@
|
||||
/obj/machinery/shower/wash_obj(obj/O)
|
||||
. = ..()
|
||||
if(!O)
|
||||
return
|
||||
. = O.wash_cum()
|
||||
|
||||
/obj/machinery/shower/wash_mob(mob/living/L)
|
||||
L.wash_cum()
|
||||
. = ..()
|
||||
@@ -43,7 +43,7 @@
|
||||
if(B)
|
||||
B.fluid_rate *= 2
|
||||
|
||||
/mob/living/carbon/human/do_climax(datum/reagents/R, atom/target, obj/item/organ/genital/G, spill)
|
||||
/mob/living/carbon/human/do_climax(datum/reagents/R, atom/target, obj/item/organ/genital/G, spill, cover = FALSE)
|
||||
if(!G)
|
||||
return
|
||||
|
||||
@@ -54,4 +54,52 @@
|
||||
to_chat(src, "<span class='userlove'>You feel your sounding rod being pushed out of your cockhole with the burst of jizz!</span>")
|
||||
bepis.equipment.Remove(GENITAL_EQUIPMENT_SOUNDING)
|
||||
new /obj/item/genital_equipment/sounding/used_sounding(loc)
|
||||
|
||||
if(cover)
|
||||
target.add_cum_overlay()
|
||||
. = ..()
|
||||
|
||||
/mob/living/carbon/human/mob_fill_container(obj/item/organ/genital/G, obj/item/reagent_containers/container, mb_time, obj/item/milking_machine/M)
|
||||
if(!M)
|
||||
return ..()
|
||||
|
||||
var/datum/reagents/fluid_source = G.climaxable(src)
|
||||
if(!fluid_source)
|
||||
return
|
||||
var/main_fluid = lowertext(fluid_source.get_master_reagent_name())
|
||||
if(mb_time)
|
||||
visible_message("<span class='love'>You hear a strong suction sound coming from the [M.name] on [src]'s [G.name].</span>", \
|
||||
"<span class='userlove'>The [M.name] pumps faster, trying to get you over the edge.</span>", \
|
||||
"<span class='userlove'>Something vacuums your [G.name] with a quiet but powerfull vrrrr.</span>")
|
||||
if(!do_after(src, mb_time, target = src) || !in_range(src, container) || !G.climaxable(src, TRUE))
|
||||
return
|
||||
visible_message("<span class='love'>[src] twitches as [p_their()] [main_fluid] trickles into [container].</span>", \
|
||||
"<span class='userlove'>[M] sucks out all the [main_fluid] you had been saving up into [container].</span>", \
|
||||
"<span class='userlove'>You feel a vacuum sucking on your [G.name] as you climax</span>")
|
||||
do_climax(fluid_source, container, G, FALSE, cover = TRUE)
|
||||
|
||||
/mob/living/carbon/human/proc/mob_climax_over(obj/item/organ/genital/G, mob/living/L, spillage = TRUE, mb_time = 30)
|
||||
var/datum/reagents/fluid_source = G.climaxable(src)
|
||||
if(!fluid_source)
|
||||
return
|
||||
if(mb_time) //Skip warning if this is an instant climax.
|
||||
to_chat(src,"<span class='userlove'>You're about to climax over [L]!</span>")
|
||||
to_chat(L,"<span class='userlove'>[src] is about to climax over you!</span>")
|
||||
if(!do_after(src, mb_time, target = src) || !in_range(src, L) || !G.climaxable(src, TRUE))
|
||||
return
|
||||
to_chat(src,"<span class='userlove'>You climax all over [L] using your [G.name]!</span>")
|
||||
to_chat(L, "<span class='userlove'>[src] climaxes all over you using [p_their()] [G.name]!</span>")
|
||||
do_climax(fluid_source, L, G, spillage, cover = TRUE)
|
||||
|
||||
/atom/proc/add_cum_overlay() //This can go in a better spot, for now its here.
|
||||
cum_splatter_icon = icon(initial(icon), initial(icon_state), dir = 1)
|
||||
cum_splatter_icon.Blend("#fff", ICON_ADD)
|
||||
cum_splatter_icon.Blend(icon('modular_sand/icons/effects/cumoverlay.dmi', "cum_obj"), ICON_MULTIPLY)
|
||||
add_overlay(cum_splatter_icon)
|
||||
|
||||
/atom/proc/wash_cum()
|
||||
cut_overlay(mutable_appearance('modular_sand/icons/effects/cumoverlay.dmi', "cum_normal"))
|
||||
cut_overlay(mutable_appearance('modular_sand/icons/effects/cumoverlay.dmi', "cum_large"))
|
||||
if(cum_splatter_icon)
|
||||
cut_overlay(cum_splatter_icon)
|
||||
return TRUE
|
||||
|
||||
@@ -0,0 +1,543 @@
|
||||
/*
|
||||
DOG BORG EQUIPMENT HERE
|
||||
SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
|
||||
*/
|
||||
|
||||
/obj/item/dogborg/jaws
|
||||
name = "Dogborg jaws"
|
||||
desc = "The jaws of the debug errors oh god."
|
||||
icon = 'modular_sand/icons/mob/dogborg.dmi'
|
||||
flags_1 = CONDUCT_1
|
||||
force = 1
|
||||
throwforce = 0
|
||||
w_class = 3
|
||||
hitsound = 'sound/weapons/bite.ogg'
|
||||
sharpness = SHARP_EDGED
|
||||
|
||||
/obj/item/dogborg/jaws/big
|
||||
name = "combat jaws"
|
||||
desc = "The jaws of the law. Very sharp."
|
||||
icon_state = "jaws_2"
|
||||
force = 10 //Lowered to match secborg. No reason it should be more than a secborg's baton.
|
||||
attack_verb = list("chomped", "bit", "ripped", "mauled", "enforced")
|
||||
|
||||
/obj/item/dogborg/jaws/small
|
||||
name = "puppy jaws"
|
||||
desc = "Rubberized teeth designed to protect accidental harm. Sharp enough for specialized tasks however."
|
||||
icon_state = "jaws_2"
|
||||
force = 6
|
||||
attack_verb = list("nibbled", "bit", "gnawed", "chomped", "nommed")
|
||||
var/status = 0
|
||||
|
||||
/obj/item/dogborg/jaws/attack(atom/A, mob/living/silicon/robot/user)
|
||||
..()
|
||||
user.do_attack_animation(A, ATTACK_EFFECT_BITE)
|
||||
|
||||
/obj/item/dogborg/jaws/small/attack_self(mob/user)
|
||||
var/mob/living/silicon/robot/R = user
|
||||
if(R.cell && R.cell.charge > 100)
|
||||
if(R.emagged && status == 0)
|
||||
name = "combat jaws"
|
||||
icon_state = "jaws"
|
||||
desc = "The jaws of the law."
|
||||
force = 12
|
||||
attack_verb = list("chomped", "bit", "ripped", "mauled", "enforced")
|
||||
status = 1
|
||||
to_chat(user, "<span class='notice'>Your jaws are now [status ? "Combat" : "Pup'd"].</span>")
|
||||
else
|
||||
name = "puppy jaws"
|
||||
icon_state = "smalljaws"
|
||||
desc = "The jaws of a small dog."
|
||||
force = 5
|
||||
attack_verb = list("nibbled", "bit", "gnawed", "chomped", "nommed")
|
||||
status = 0
|
||||
if(R.emagged)
|
||||
to_chat(user, "<span class='notice'>Your jaws are now [status ? "Combat" : "Pup'd"].</span>")
|
||||
update_icon()
|
||||
|
||||
//Boop
|
||||
|
||||
/obj/item/analyzer/nose
|
||||
name = "boop module"
|
||||
icon = 'modular_sand/icons/mob/dogborg.dmi'
|
||||
icon_state = "nose"
|
||||
desc = "The BOOP module"
|
||||
flags_1 = CONDUCT_1
|
||||
force = 0
|
||||
throwforce = 0
|
||||
attack_verb = list("nuzzles", "pushes", "boops")
|
||||
w_class = 1
|
||||
|
||||
/obj/item/analyzer/nose/attack_self(mob/user)
|
||||
user.visible_message("[user] sniffs around the air.", "<span class='warning'>You sniff the air for gas traces.</span>")
|
||||
|
||||
var/turf/location = user.loc
|
||||
if(!istype(location))
|
||||
return
|
||||
|
||||
var/datum/gas_mixture/environment = location.return_air()
|
||||
|
||||
var/pressure = environment.return_pressure()
|
||||
var/total_moles = environment.total_moles()
|
||||
|
||||
to_chat(user, "<span class='info'><B>Results:</B></span>")
|
||||
if(abs(pressure - ONE_ATMOSPHERE) < 10)
|
||||
to_chat(user, "<span class='info'>Pressure: [round(pressure,0.1)] kPa</span>")
|
||||
else
|
||||
to_chat(user, "<span class='alert'>Pressure: [round(pressure,0.1)] kPa</span>")
|
||||
if(total_moles)
|
||||
var/list/env_gases = environment.get_gases()
|
||||
|
||||
var/o2_concentration = env_gases[/datum/gas/oxygen]/total_moles
|
||||
var/n2_concentration = env_gases[/datum/gas/nitrogen]/total_moles
|
||||
var/co2_concentration = env_gases[/datum/gas/carbon_dioxide]/total_moles
|
||||
var/plasma_concentration = env_gases[/datum/gas/plasma]/total_moles
|
||||
GAS_GARBAGE_COLLECT(environment.get_gases())
|
||||
|
||||
if(abs(n2_concentration - N2STANDARD) < 20)
|
||||
to_chat(user, "<span class='info'>Nitrogen: [round(n2_concentration*100, 0.01)] %</span>")
|
||||
else
|
||||
to_chat(user, "<span class='alert'>Nitrogen: [round(n2_concentration*100, 0.01)] %</span>")
|
||||
|
||||
if(abs(o2_concentration - O2STANDARD) < 2)
|
||||
to_chat(user, "<span class='info'>Oxygen: [round(o2_concentration*100, 0.01)] %</span>")
|
||||
else
|
||||
to_chat(user, "<span class='alert'>Oxygen: [round(o2_concentration*100, 0.01)] %</span>")
|
||||
|
||||
if(co2_concentration > 0.01)
|
||||
to_chat(user, "<span class='alert'>CO2: [round(co2_concentration*100, 0.01)] %</span>")
|
||||
else
|
||||
to_chat(user, "<span class='info'>CO2: [round(co2_concentration*100, 0.01)] %</span>")
|
||||
|
||||
if(plasma_concentration > 0.005)
|
||||
to_chat(user, "<span class='alert'>Plasma: [round(plasma_concentration*100, 0.01)] %</span>")
|
||||
else
|
||||
to_chat(user, "<span class='info'>Plasma: [round(plasma_concentration*100, 0.01)] %</span>")
|
||||
|
||||
|
||||
for(var/id in env_gases)
|
||||
if(id in GLOB.hardcoded_gases)
|
||||
continue
|
||||
var/gas_concentration = env_gases[id]/total_moles
|
||||
to_chat(user, "<span class='alert'>[GLOB.gas_data.names[id]]: [round(gas_concentration*100, 0.01)] %</span>")
|
||||
to_chat(user, "<span class='info'>Temperature: [round(environment.return_temperature()-T0C)] °C</span>")
|
||||
|
||||
/obj/item/analyzer/nose/afterattack(atom/target, mob/user, proximity)
|
||||
. = ..()
|
||||
if(!proximity)
|
||||
return
|
||||
do_attack_animation(target, null, src)
|
||||
user.visible_message("<span class='notice'>[user] [pick(attack_verb)] \the [target.name] with their nose!</span>")
|
||||
|
||||
//Delivery
|
||||
/obj/item/storage/bag/borgdelivery
|
||||
name = "fetching storage"
|
||||
desc = "Fetch the thing!"
|
||||
icon = 'modular_sand/icons/mob/dogborg.dmi'
|
||||
icon_state = "dbag"
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
|
||||
/obj/item/storage/bag/borgdelivery/ComponentInitialize()
|
||||
. = ..()
|
||||
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
|
||||
STR.max_w_class = WEIGHT_CLASS_BULKY
|
||||
STR.max_combined_w_class = 5
|
||||
STR.max_items = 1
|
||||
STR.cant_hold = typecacheof(list(/obj/item/disk/nuclear, /obj/item/radio/intercom))
|
||||
|
||||
//Tongue stuff
|
||||
/obj/item/soap/tongue
|
||||
name = "synthetic tongue"
|
||||
desc = "Useful for slurping mess off the floor before affectionally licking the crew members in the face."
|
||||
icon = 'modular_sand/icons/mob/dogborg.dmi'
|
||||
icon_state = "synthtongue"
|
||||
hitsound = 'sound/effects/attackblob.ogg'
|
||||
cleanspeed = 80
|
||||
var/status = 0
|
||||
|
||||
/obj/item/soap/tongue/scrubpup
|
||||
cleanspeed = 25 //slightly faster than a mop.
|
||||
|
||||
/obj/item/soap/tongue/New()
|
||||
..()
|
||||
item_flags |= NOBLUDGEON //No more attack messages
|
||||
|
||||
/obj/item/soap/tongue/attack_self(mob/user)
|
||||
var/mob/living/silicon/robot/R = user
|
||||
if(R.cell && R.cell.charge > 100)
|
||||
if(R.emagged && status == 0)
|
||||
status = !status
|
||||
name = "energized tongue"
|
||||
desc = "Your tongue is energized for dangerously maximum efficency."
|
||||
icon_state = "syndietongue"
|
||||
to_chat(user, "<span class='notice'>Your tongue is now [status ? "Energized" : "Normal"].</span>")
|
||||
cleanspeed = 10 //(nerf'd)tator soap stat
|
||||
else
|
||||
status = 0
|
||||
name = "synthetic tongue"
|
||||
desc = "Useful for slurping mess off the floor before affectionally licking the crew members in the face."
|
||||
icon_state = "synthtongue"
|
||||
cleanspeed = initial(cleanspeed)
|
||||
if(R.emagged)
|
||||
to_chat(user, "<span class='notice'>Your tongue is now [status ? "Energized" : "Normal"].</span>")
|
||||
update_icon()
|
||||
|
||||
/obj/item/soap/tongue/afterattack(atom/target, mob/user, proximity)
|
||||
var/mob/living/silicon/robot/R = user
|
||||
if(!proximity || !check_allowed_items(target))
|
||||
return
|
||||
if(R.client && (target in R.client.screen))
|
||||
to_chat(R, "<span class='warning'>You need to take that [target.name] off before cleaning it!</span>")
|
||||
else if(is_cleanable(target))
|
||||
R.visible_message("[R] begins to lick off \the [target.name].", "<span class='warning'>You begin to lick off \the [target.name]...</span>")
|
||||
if(do_after(R, src.cleanspeed, target = target))
|
||||
if(!in_range(src, target)) //Proximity is probably old news by now, do a new check.
|
||||
return //If they moved away, you can't eat them.
|
||||
to_chat(R, "<span class='notice'>You finish licking off \the [target.name].</span>")
|
||||
qdel(target)
|
||||
R.cell.give(50)
|
||||
else if(isobj(target)) //hoo boy. danger zone man
|
||||
if(istype(target,/obj/item/trash))
|
||||
R.visible_message("[R] nibbles away at \the [target.name].", "<span class='warning'>You begin to nibble away at \the [target.name]...</span>")
|
||||
if(!do_after(R, src.cleanspeed, target = target))
|
||||
return //If they moved away, you can't eat them.
|
||||
to_chat(R, "<span class='notice'>You finish off \the [target.name].</span>")
|
||||
qdel(target)
|
||||
R.cell.give(250)
|
||||
return
|
||||
if(istype(target,/obj/item/stock_parts/cell))
|
||||
R.visible_message("[R] begins cramming \the [target.name] down its throat.", "<span class='warning'>You begin cramming \the [target.name] down your throat...</span>")
|
||||
if(!do_after(R, 50, target = target))
|
||||
return //If they moved away, you can't eat them.
|
||||
to_chat(R, "<span class='notice'>You finish off \the [target.name].</span>")
|
||||
var/obj/item/stock_parts/cell/C = target
|
||||
R.cell.charge = R.cell.charge + (C.charge / 3) //Instant full cell upgrades op idgaf
|
||||
qdel(target)
|
||||
return
|
||||
var/obj/item/I = target //HAHA FUCK IT, NOT LIKE WE ALREADY HAVE A SHITTON OF WAYS TO REMOVE SHIT
|
||||
if(!I.anchored && R.emagged)
|
||||
R.visible_message("[R] begins chewing up \the [target.name]. Looks like it's trying to loophole around its diet restriction!", "<span class='warning'>You begin chewing up \the [target.name]...</span>")
|
||||
if(!do_after(R, 100, target = I)) //Nerf dat time yo
|
||||
return //If they moved away, you can't eat them.
|
||||
visible_message("<span class='warning'>[R] chews up \the [target.name] and cleans off the debris!</span>")
|
||||
to_chat(R, "<span class='notice'>You finish off \the [target.name].</span>")
|
||||
qdel(I)
|
||||
R.cell.give(500)
|
||||
return
|
||||
R.visible_message("[R] begins to lick \the [target.name] clean...", "<span class='notice'>You begin to lick \the [target.name] clean...</span>")
|
||||
else if(ishuman(target))
|
||||
var/mob/living/L = target
|
||||
if(status == 0 && check_zone(R.zone_selected) == "head")
|
||||
R.visible_message("<span class='warning'>\the [R] affectionally licks \the [L]'s face!</span>", "<span class='notice'>You affectionally lick \the [L]'s face!</span>")
|
||||
playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1)
|
||||
if(istype(L) && L.fire_stacks > 0)
|
||||
L.adjust_fire_stacks(-10)
|
||||
return
|
||||
else if(status == 0)
|
||||
R.visible_message("<span class='warning'>\the [R] affectionally licks \the [L]!</span>", "<span class='notice'>You affectionally lick \the [L]!</span>")
|
||||
playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1)
|
||||
if(istype(L) && L.fire_stacks > 0)
|
||||
L.adjust_fire_stacks(-10)
|
||||
return
|
||||
else
|
||||
if(R.cell.charge <= 800)
|
||||
to_chat(R, "Insufficent Power!")
|
||||
return
|
||||
L.Stun(4) // normal stunbaton is force 7 gimme a break good sir!
|
||||
L.Knockdown(80)
|
||||
L.apply_effect(EFFECT_STUTTER, 4)
|
||||
L.visible_message("<span class='danger'>[R] has shocked [L] with its tongue!</span>", \
|
||||
"<span class='userdanger'>[R] has shocked you with its tongue!</span>")
|
||||
playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1)
|
||||
R.cell.use(666)
|
||||
log_combat(R, L, "tongue stunned")
|
||||
|
||||
else if(istype(target, /obj/structure/window))
|
||||
R.visible_message("[R] begins to lick \the [target.name] clean...", "<span class='notice'>You begin to lick \the [target.name] clean...</span>")
|
||||
if(do_after(user, src.cleanspeed, target = target))
|
||||
to_chat(user, "<span class='notice'>You clean \the [target.name].</span>")
|
||||
target.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
|
||||
target.set_opacity(initial(target.opacity))
|
||||
else
|
||||
R.visible_message("[R] begins to lick \the [target.name] clean...", "<span class='notice'>You begin to lick \the [target.name] clean...</span>")
|
||||
if(do_after(user, src.cleanspeed, target = target))
|
||||
to_chat(user, "<span class='notice'>You clean \the [target.name].</span>")
|
||||
var/obj/effect/decal/cleanable/C = locate() in target
|
||||
qdel(C)
|
||||
target.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
|
||||
SEND_SIGNAL(target, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_MEDIUM)
|
||||
target.wash_cream()
|
||||
target.wash_cum()
|
||||
return
|
||||
|
||||
//Dogfood
|
||||
|
||||
/obj/item/trash/rkibble
|
||||
name = "robo kibble"
|
||||
desc = "A novelty bowl of assorted mech fabricator byproducts. Mockingly feed this to the sec-dog to help it recharge."
|
||||
icon = 'modular_sand/icons/mob/dogborg.dmi'
|
||||
icon_state= "kibble"
|
||||
|
||||
//Defibs
|
||||
|
||||
/obj/item/twohanded/shockpaddles/cyborg/hound
|
||||
name = "Paws of Life"
|
||||
desc = "MediHound specific shock paws."
|
||||
icon = 'modular_sand/icons/mob/dogborg.dmi'
|
||||
icon_state = "defibpaddles0"
|
||||
item_state = "defibpaddles0"
|
||||
|
||||
// Pounce stuff for K-9
|
||||
|
||||
/obj/item/dogborg/pounce
|
||||
name = "pounce"
|
||||
icon = 'modular_sand/icons/mob/dogborg.dmi'
|
||||
icon_state = "pounce"
|
||||
desc = "Leap at your target to momentarily stun them."
|
||||
force = 0
|
||||
throwforce = 0
|
||||
|
||||
/obj/item/dogborg/pounce/New()
|
||||
..()
|
||||
item_flags |= NOBLUDGEON
|
||||
|
||||
/mob/living/silicon/robot
|
||||
var/leaping = 0
|
||||
var/pounce_cooldown = 0
|
||||
var/pounce_cooldown_time = 20 //Buffed to counter balance changes
|
||||
var/pounce_spoolup = 1
|
||||
var/leap_at
|
||||
|
||||
#define MAX_K9_LEAP_DIST 4 //because something's definitely borked the pounce functioning from a distance.
|
||||
|
||||
/obj/item/dogborg/pounce/afterattack(atom/A, mob/user)
|
||||
var/mob/living/silicon/robot/R = user
|
||||
if(R && !R.pounce_cooldown)
|
||||
R.pounce_cooldown = !R.pounce_cooldown
|
||||
to_chat(R, "<span class ='warning'>Your targeting systems lock on to [A]...</span>")
|
||||
addtimer(CALLBACK(R, /mob/living/silicon/robot.proc/leap_at, A), R.pounce_spoolup)
|
||||
spawn(R.pounce_cooldown_time)
|
||||
R.pounce_cooldown = !R.pounce_cooldown
|
||||
else if(R && R.pounce_cooldown)
|
||||
to_chat(R, "<span class='danger'>Your leg actuators are still recharging!</span>")
|
||||
|
||||
/mob/living/silicon/robot/proc/leap_at(atom/A)
|
||||
if(leaping || stat || buckled || lying)
|
||||
return
|
||||
|
||||
if(!has_gravity(src) || !has_gravity(A))
|
||||
to_chat(src,"<span class='danger'>It is unsafe to leap without gravity!</span>")
|
||||
//It's also extremely buggy visually, so it's balance+bugfix
|
||||
return
|
||||
|
||||
if(cell.charge <= 750)
|
||||
to_chat(src,"<span class='danger'>Insufficent reserves for jump actuators!</span>")
|
||||
return
|
||||
|
||||
else
|
||||
leaping = 1
|
||||
weather_immunities += "lava"
|
||||
pixel_y = 10
|
||||
update_icons()
|
||||
throw_at(A, MAX_K9_LEAP_DIST, 1, spin=0, diagonals_first = 1)
|
||||
cell.use(750) //Less than a stunbaton since stunbatons hit everytime.
|
||||
weather_immunities -= "lava"
|
||||
|
||||
/mob/living/silicon/robot/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
|
||||
if(!leaping)
|
||||
return ..()
|
||||
|
||||
if(hit_atom)
|
||||
if(isliving(hit_atom))
|
||||
var/mob/living/L = hit_atom
|
||||
var/list/block_return = list()
|
||||
//if(!L.check_shields(0, "the [name]", src, attack_type = LEAP_ATTACK))
|
||||
if(!(L.mob_run_block(src, 0, "the [name]", ATTACK_TYPE_TACKLE, 0, src, hit_atom, block_return) & BLOCK_SUCCESS))
|
||||
L.visible_message("<span class ='danger'>[src] pounces on [L]!</span>", "<span class ='userdanger'>[src] pounces on you!</span>")
|
||||
L.Knockdown(iscarbon(L) ? 225 : 45) // Temporary. If someone could rework how dogborg pounces work to accomodate for combat changes, that'd be nice.
|
||||
playsound(src, 'sound/weapons/Egloves.ogg', 50, 1)
|
||||
sleep(2)//Runtime prevention (infinite bump() calls on hulks)
|
||||
step_towards(src,L)
|
||||
log_combat(src, L, "borg pounced")
|
||||
else
|
||||
Knockdown(15, 1, 1)
|
||||
|
||||
pounce_cooldown = !pounce_cooldown
|
||||
spawn(pounce_cooldown_time) //3s by default
|
||||
pounce_cooldown = !pounce_cooldown
|
||||
else if(hit_atom.density && !hit_atom.CanPass(src))
|
||||
visible_message("<span class ='danger'>[src] smashes into [hit_atom]!</span>", "<span class ='userdanger'>You smash into [hit_atom]!</span>")
|
||||
playsound(src, 'sound/items/trayhit1.ogg', 50, 1)
|
||||
Knockdown(15, 1, 1)
|
||||
|
||||
if(leaping)
|
||||
leaping = 0
|
||||
pixel_y = initial(pixel_y)
|
||||
update_icons()
|
||||
update_mobility()
|
||||
|
||||
//pleasuremaw stuff
|
||||
/obj/item/milking_machine/pleasuremaw
|
||||
name = "pleasuremaw"
|
||||
desc = "A module that makes hound maws become slippery, warm, sticky, and soft, perfect place to slip your dick inside and relax, feed and help charge the borgs."
|
||||
icon = 'modular_sand/icons/mob/dogborg.dmi'
|
||||
icon_state = "pleasuremaw"
|
||||
on = TRUE
|
||||
var/toggle_process_regents = FALSE
|
||||
var/consumption_rate = 2
|
||||
var/mob/living/silicon/robot/borg_self = null
|
||||
|
||||
/obj/item/milking_machine/pleasuremaw/Initialize()
|
||||
. = ..()
|
||||
inserted_item = new /obj/item/reagent_containers/glass/beaker/large(src)
|
||||
inserted_item.name = "cyborg stomach"
|
||||
inserted_item.desc = "A cyborg stomach. It seems integrated into [src]'s machinery."
|
||||
|
||||
/obj/item/milking_machine/pleasuremaw/interact(mob/user)
|
||||
//start processing the regents in the container - and slowly use em up to create power
|
||||
toggle_process_regents = !toggle_process_regents
|
||||
if (toggle_process_regents)
|
||||
to_chat(user, "<span class='notice'>You start churning the sexual fluids from your [inserted_item.name] into energy.</span>")
|
||||
borg_self = user
|
||||
START_PROCESSING(SSobj, src)
|
||||
else
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
to_chat(user, "<span class='notice'>You stop processing the fluids from the [inserted_item.name].</span>")
|
||||
return
|
||||
|
||||
/obj/item/milking_machine/pleasuremaw/process()
|
||||
//TODO: Check if any of the regents are not erotic fluids - if they are - stop the process and spit out a message to the user.
|
||||
if (inserted_item.reagents.total_volume < consumption_rate)
|
||||
src.interact(borg_self)
|
||||
return
|
||||
inserted_item.reagents.remove_all(consumption_rate)
|
||||
borg_self.cell.charge = min(borg_self.cell.charge + borg_self.cell.maxcharge/50, borg_self.cell.maxcharge)
|
||||
|
||||
/obj/item/milking_machine/pleasuremaw/AltClick(mob/living/user)
|
||||
//function for when alt-clicked - do nothing for now - do not call parent
|
||||
return
|
||||
|
||||
/obj/item/milking_machine/pleasuremaw/afterattack(mob/living/carbon/C, mob/living/user, proximity)
|
||||
//use pleasuremaw on designated body part in different ways depending on the intent
|
||||
var/mob/living/silicon/robot/R = user
|
||||
if(!proximity || !check_allowed_items(C))
|
||||
return
|
||||
else if(istype(C, /obj/item/reagent_containers/))
|
||||
R.visible_message("<span class='warning'>You open your mouth and dispense the contents of your [src.name]'s storage into [C]</span>", \
|
||||
"<span class='notice'>[R] opens [p_their()] [src.name] and dispenses something sticky into [C]</span>")
|
||||
//TODO: check if internal beaker is too full - and if yes - spill rest onto floor
|
||||
inserted_item.reagents.trans_to(C, inserted_item.reagents.total_volume)
|
||||
else if(ishuman(C))
|
||||
var/mob/living/carbon/human/H = C
|
||||
//TODO: arms and legs?
|
||||
if(check_zone(R.zone_selected) == BODY_ZONE_HEAD)
|
||||
//mouth
|
||||
//TODO: on harm intent feed contents of cyborg stomach to person instead
|
||||
// make a check for if the mouth is covered
|
||||
if (R.zone_selected == BODY_ZONE_PRECISE_MOUTH)
|
||||
R.visible_message("<span class='warning'>[R] kisses [H]!</span>", \
|
||||
"<span class='notice'>You kiss [H]!</span>")
|
||||
playsound(src.loc, 'sound/effects/attackblob.ogg', 30, 1)
|
||||
H.add_lust(10)
|
||||
//ears
|
||||
else if (R.zone_selected == BODY_ZONE_HEAD)
|
||||
//make check for ear visibility? nah.
|
||||
R.visible_message("<span class='warning'>[R] licks [H]'s ears!</span>", \
|
||||
"<span class='notice'>You lick [H]'s ears!</span>")
|
||||
playsound(src.loc, 'sound/effects/attackblob.ogg', 30, 1)
|
||||
H.add_lust(5)
|
||||
else if(check_zone(R.zone_selected) == BODY_ZONE_CHEST)
|
||||
//breasts
|
||||
if (R.zone_selected == BODY_ZONE_CHEST)
|
||||
var/obj/item/organ/genital/breasts/G = H.getorganslot("breasts")
|
||||
target_organ = G.name
|
||||
if (G && G.is_exposed())
|
||||
R.visible_message("<span class='warning'>[R] sucks on [H]'s [G.name]!</span>", \
|
||||
"<span class='notice'>You suck on [H]'s [G.name]!</span>")
|
||||
playsound(src.loc, 'sound/effects/attackblob.ogg', 30, 1)
|
||||
H.add_lust(10)
|
||||
..()
|
||||
else
|
||||
to_chat(R, "<span class='info'>Lickable breasts not found!</span>")
|
||||
//penis,testies,vag,ass
|
||||
//TODO: add only the parts that the target actually has to the radial menu
|
||||
// add color to images and make them correspond with the type that the target user has
|
||||
// make it so that if a covered up part is chosen - it licks the outside (the clothes). (apply this to the mouth interaction)
|
||||
else if (R.zone_selected == BODY_ZONE_PRECISE_GROIN)
|
||||
var/static/list/possible_choices = sortList(list(
|
||||
"Penis" = image(icon = 'icons/obj/genitals/penis.dmi', icon_state = "penis"),
|
||||
"Testicles" = image(icon= 'icons/obj/genitals/testicles.dmi', icon_state = "testicles"),
|
||||
"Vagina" = image(icon= 'icons/obj/genitals/vagina.dmi', icon_state = "vagina"),
|
||||
"Butt" = image(icon= 'icons/obj/genitals/breasts.dmi', icon_state = "butt"),
|
||||
"Belly" = image(icon= 'modular_sand/icons/obj/genitals/belly_onmob.dmi', icon_state = "belly_pair_4_0_FRONT")
|
||||
))
|
||||
var/choice = show_radial_menu(R, src, possible_choices)
|
||||
if(!choice)
|
||||
return
|
||||
switch(choice)
|
||||
if("Penis")
|
||||
var/obj/item/organ/genital/penis/G = H.getorganslot(ORGAN_SLOT_PENIS)
|
||||
target_organ = G.name
|
||||
if (G && G.is_exposed())
|
||||
R.visible_message("<span class='warning'>[R] blows [H]'s [G.name]!</span>", \
|
||||
"<span class='notice'>You blow [H]'s [G.name]!</span>")
|
||||
playsound(src.loc, 'sound/effects/attackblob.ogg', 30, 1)
|
||||
H.add_lust(10)
|
||||
..()
|
||||
else
|
||||
to_chat(R, "<span class='info'>Lickable penis not found!</span>")
|
||||
if("Testicles")
|
||||
var/obj/item/organ/genital/testicles/G = H.getorganslot(ORGAN_SLOT_TESTICLES)
|
||||
target_organ = G.name
|
||||
if (G && G.is_exposed())
|
||||
R.visible_message("<span class='warning'>[R] laps [H]'s [G.name]!</span>", \
|
||||
"<span class='notice'>You lap [H]'s [G.name]!</span>")
|
||||
playsound(src.loc, 'sound/effects/attackblob.ogg', 30, 1)
|
||||
H.add_lust(10)
|
||||
..()
|
||||
else
|
||||
to_chat(R, "<span class='info'>Lickable testicles not found!</span>")
|
||||
if("Vagina")
|
||||
var/obj/item/organ/genital/vagina/G = H.getorganslot(ORGAN_SLOT_VAGINA)
|
||||
target_organ = G.name
|
||||
if (G && G.is_exposed())
|
||||
R.visible_message("<span class='warning'>[R] tongue fucks [H]'s [G.name]!</span>", \
|
||||
"<span class='notice'>You tongue fuck [H]'s [G.name]!</span>")
|
||||
playsound(src.loc, 'sound/effects/attackblob.ogg', 30, 1)
|
||||
H.add_lust(10)
|
||||
..()
|
||||
else
|
||||
to_chat(R, "<span class='info'>Lickable pussy not found!</span>")
|
||||
if("Butt")
|
||||
var/obj/item/organ/genital/butt/G = H.getorganslot(ORGAN_SLOT_BUTT)
|
||||
target_organ = G.name
|
||||
if (G && G.is_exposed())
|
||||
R.visible_message("<span class='warning'>[R]'s giving [H] a rimjob!</span>", \
|
||||
"<span class='notice'>You rim [H]'s [G.name]!</span>")
|
||||
playsound(src.loc, 'sound/effects/attackblob.ogg', 30, 1)
|
||||
H.add_lust(15)
|
||||
else
|
||||
to_chat(R, "<span class='info'>Lickable ass not found!</span>")
|
||||
if("Belly")
|
||||
var/obj/item/organ/genital/belly/G = H.getorganslot(ORGAN_SLOT_BELLY)
|
||||
target_organ = G.name
|
||||
if (G && G.is_exposed())
|
||||
R.visible_message("<span class='warning'>[R]'s lapping [H]'s [G.name]!</span>", \
|
||||
"<span class='notice'>You lick [H]'s [G.name]!</span>")
|
||||
playsound(src, 'sound/effects/attackblob.ogg', 30, 1)
|
||||
H.add_lust(5)
|
||||
else
|
||||
to_chat(R, "<span class='info'>Lickable belly not found!</span>")
|
||||
|
||||
//TODO: make check for if is in harm intent - if yes (spit regents from cyborg stomach) at target
|
||||
// if is nearby
|
||||
// if target has a mouth and target_bodypart is mouth
|
||||
// feed all of the regents to target
|
||||
// else
|
||||
// splash target with regents
|
||||
// else spit regents in direction of where it was clicked and get what was hit (target)
|
||||
// if target has a mouth and target_bodypart is mouth
|
||||
// feed 10u of the regents to target
|
||||
// splash target with remaining regents
|
||||
return
|
||||
@@ -73,6 +73,40 @@
|
||||
rebuild_modules()
|
||||
return I
|
||||
|
||||
/obj/item/robot_module/medical/Initialize()
|
||||
var/list/extra = list(
|
||||
/obj/item/dogborg/jaws/small,
|
||||
/obj/item/storage/bag/borgdelivery,
|
||||
/obj/item/analyzer/nose,
|
||||
/obj/item/soap/tongue,
|
||||
/obj/item/twohanded/shockpaddles/cyborg/hound
|
||||
)
|
||||
LAZYADD(basic_modules, extra)
|
||||
. = ..()
|
||||
|
||||
/obj/item/robot_module/peacekeeper/Initialize()
|
||||
var/list/extra = list(
|
||||
/obj/item/dogborg/jaws/small,
|
||||
/obj/item/storage/bag/borgdelivery,
|
||||
/obj/item/analyzer/nose,
|
||||
/obj/item/soap/tongue
|
||||
)
|
||||
LAZYADD(basic_modules, extra)
|
||||
. = ..()
|
||||
|
||||
/obj/item/robot_module/security/Initialize()
|
||||
var/list/extra = list(
|
||||
/obj/item/storage/bag/borgdelivery,
|
||||
/obj/item/dogborg/jaws/big,
|
||||
/obj/item/dogborg/pounce,
|
||||
/obj/item/soap/tongue,
|
||||
/obj/item/analyzer/nose,
|
||||
/obj/item/holosign_creator/security
|
||||
)
|
||||
LAZYADD(basic_modules, extra)
|
||||
. = ..()
|
||||
|
||||
|
||||
/obj/item/robot_module/engineering/Initialize()
|
||||
basic_modules += /obj/item/pen
|
||||
basic_modules += /obj/item/stack/sheet/plasmaglass/cyborg
|
||||
@@ -87,6 +121,12 @@
|
||||
basic_modules += /obj/item/reagent_containers/borghypo/borgshaker/juiceshaker
|
||||
basic_modules += /obj/item/reagent_containers/borghypo/borgshaker/sodashaker
|
||||
basic_modules += /obj/item/reagent_containers/borghypo/borgshaker/miscshaker
|
||||
var/list/extra = list(
|
||||
/obj/item/dogborg/jaws/small,
|
||||
/obj/item/analyzer/nose,
|
||||
/obj/item/soap/tongue/scrubpup
|
||||
)
|
||||
LAZYADD(basic_modules, extra)
|
||||
. = ..()
|
||||
|
||||
/obj/item/robot_module/miner/Initialize()
|
||||
@@ -220,4 +260,5 @@
|
||||
|
||||
/obj/item/robot_module/Initialize()
|
||||
basic_modules += /obj/item/dildo/custom
|
||||
basic_modules += /obj/item/milking_machine/pleasuremaw
|
||||
. = ..()
|
||||
|
||||
BIN
modular_sand/icons/effects/cumoverlay.dmi
Normal file
BIN
modular_sand/icons/effects/cumoverlay.dmi
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.9 KiB |
BIN
modular_sand/icons/mob/dogborg.dmi
Normal file
BIN
modular_sand/icons/mob/dogborg.dmi
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
BIN
modular_sand/icons/obj/milking_machine.dmi
Normal file
BIN
modular_sand/icons/obj/milking_machine.dmi
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 772 B |
BIN
modular_sand/sound/lewd/slaps.ogg
Normal file
BIN
modular_sand/sound/lewd/slaps.ogg
Normal file
Binary file not shown.
@@ -212,8 +212,8 @@
|
||||
|
||||
message = "<span class='lewd'>\The <b>[src]</b> [pick(hell)]"
|
||||
visible_message(message, ignored_mobs = get_unconsenting(unholy = TRUE))
|
||||
playlewdinteractionsound(loc, pick(GLOB.brap_noises), 50, 1, -1, ignored_mobs = get_unconsenting(unholy = TRUE))
|
||||
playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/bang1.ogg',
|
||||
playlewdinteractionsound(target.loc, pick(GLOB.brap_noises), 50, 1, -1, ignored_mobs = get_unconsenting(unholy = TRUE))
|
||||
playlewdinteractionsound(target.loc, pick('modular_sand/sound/interactions/bang1.ogg',
|
||||
'modular_sand/sound/interactions/bang2.ogg',
|
||||
'modular_sand/sound/interactions/bang3.ogg',
|
||||
'modular_sand/sound/interactions/bang4.ogg',
|
||||
@@ -301,8 +301,8 @@
|
||||
|
||||
message = "<span class='lewd'>\The <b>[src]</b> [pick(hell)]"
|
||||
visible_message(message, ignored_mobs = get_unconsenting(unholy = TRUE), ignored_mobs = get_unconsenting(unholy = TRUE))
|
||||
playlewdinteractionsound(loc, pick(GLOB.brap_noises), 70, 1, -1)
|
||||
playlewdinteractionsound(loc, pick('modular_sand/sound/interactions/bang1.ogg',
|
||||
playlewdinteractionsound(target.loc, pick(GLOB.brap_noises), 70, 1, -1)
|
||||
playlewdinteractionsound(target.loc, pick('modular_sand/sound/interactions/bang1.ogg',
|
||||
'modular_sand/sound/interactions/bang2.ogg',
|
||||
'modular_sand/sound/interactions/bang3.ogg',
|
||||
'modular_sand/sound/interactions/bang4.ogg',
|
||||
|
||||
5
modular_splurt/code/datums/mutations/telekenisis.dm
Normal file
5
modular_splurt/code/datums/mutations/telekenisis.dm
Normal file
@@ -0,0 +1,5 @@
|
||||
/mob/living/carbon/attack_tk(mob/living/carbon/owner)
|
||||
if(owner.CheckActionCooldown(CLICK_CD_MELEE) && owner.a_intent == INTENT_HELP)
|
||||
src.help_shake_act(owner)
|
||||
owner.DelayNextAction()
|
||||
. = ..()
|
||||
@@ -25,10 +25,10 @@
|
||||
else // Linked
|
||||
for(var/member in SSdiscord.notify_members) // If they are in the list, take them out
|
||||
if(member == "[stored_id]")
|
||||
SSdiscord.notify_members -= "[stored_id]" // The list uses strings because BYOND cannot handle a 17 digit integer
|
||||
SSdiscord.notify_members -= "<@[stored_id]>" // The list uses strings because BYOND cannot handle a 17 digit integer
|
||||
to_chat(src, span_notice("You will no longer be notified when the server restarts"))
|
||||
return // This is necassary so it doesnt get added again, as it relies on the for loop being unsuccessful to tell us if they are in the list or not
|
||||
|
||||
// If we got here, they arent in the list. Chuck 'em in!
|
||||
to_chat(src, span_notice("You will now be notified when the server restarts"))
|
||||
SSdiscord.notify_members += "[stored_id]" // The list uses strings because BYOND cannot handle a 17 digit integer
|
||||
SSdiscord.notify_members += "<@[stored_id]>" // The list uses strings because BYOND cannot handle a 17 digit integer
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
//Better SPLURT version of hilbert's
|
||||
// Better SPLURT version of hilbert's
|
||||
/datum/map_template/hilbertshotel
|
||||
mappath = '_maps/splurt_maps/templates/hilbertshotel.dmm'
|
||||
|
||||
// Empty room - different due to the dimensions of the updated map
|
||||
/datum/map_template/hilbertshotel/empty
|
||||
mappath = '_maps/splurt_maps/templates/hilbertshotelempty.dmm'
|
||||
|
||||
@@ -3870,6 +3870,7 @@
|
||||
#include "modular_sand\code\datums\traits\negative.dm"
|
||||
#include "modular_sand\code\datums\traits\neutral.dm"
|
||||
#include "modular_sand\code\datums\wires\firealarm.dm"
|
||||
#include "modular_sand\code\game\atoms.dm"
|
||||
#include "modular_sand\code\game\area\ship_area.dm"
|
||||
#include "modular_sand\code\game\area\areas\shuttles.dm"
|
||||
#include "modular_sand\code\game\area\areas\ruins\lavaland.dm"
|
||||
@@ -3897,6 +3898,7 @@
|
||||
#include "modular_sand\code\game\objects\items\cosmetics.dm"
|
||||
#include "modular_sand\code\game\objects\items\extinguisher.dm"
|
||||
#include "modular_sand\code\game\objects\items\fleshlight.dm"
|
||||
#include "modular_sand\code\game\objects\items\milking_machine.dm"
|
||||
#include "modular_sand\code\game\objects\items\miscellaneous.dm"
|
||||
#include "modular_sand\code\game\objects\items\weaponry.dm"
|
||||
#include "modular_sand\code\game\objects\items\circuitboards\computer_circuitboards.dm"
|
||||
@@ -3942,6 +3944,7 @@
|
||||
#include "modular_sand\code\game\objects\structures\ghost_role_spawners.dm"
|
||||
#include "modular_sand\code\game\objects\structures\ladders.dm"
|
||||
#include "modular_sand\code\game\objects\structures\tank_holder.dm"
|
||||
#include "modular_sand\code\game\objects\structures\watercloset.dm"
|
||||
#include "modular_sand\code\game\objects\structures\bed_chairs\bed.dm"
|
||||
#include "modular_sand\code\game\objects\structures\crates_lockers\closets\secure\cargo.dm"
|
||||
#include "modular_sand\code\game\objects\structures\crates_lockers\closets\secure\engineering.dm"
|
||||
@@ -4060,6 +4063,7 @@
|
||||
#include "modular_sand\code\modules\mob\living\carbon\human\species.dm"
|
||||
#include "modular_sand\code\modules\mob\living\silicon\silicon.dm"
|
||||
#include "modular_sand\code\modules\mob\living\silicon\ai\vox_sounds.dm"
|
||||
#include "modular_sand\code\modules\mob\living\silicon\robot\dogborg_equipment.dm"
|
||||
#include "modular_sand\code\modules\mob\living\silicon\robot\robot.dm"
|
||||
#include "modular_sand\code\modules\mob\living\silicon\robot\robot_modules.dm"
|
||||
#include "modular_sand\code\modules\mob\living\simple_animal\bot\hugbot.dm"
|
||||
@@ -4180,6 +4184,7 @@
|
||||
#include "modular_splurt\code\datums\interactions\lewd\lewd_datums.dm"
|
||||
#include "modular_splurt\code\datums\interactions\lewd\lewd_interactions.dm"
|
||||
#include "modular_splurt\code\datums\mood_events\generic_positive_events.dm"
|
||||
#include "modular_splurt\code\datums\mutations\telekenisis.dm"
|
||||
#include "modular_splurt\code\datums\ruins\lavaland.dm"
|
||||
#include "modular_splurt\code\datums\traits\defines.dm"
|
||||
#include "modular_splurt\code\datums\traits\good.dm"
|
||||
|
||||
Reference in New Issue
Block a user