From 693d2b6dee428993b6fcd915266ac4fe1d8ccd41 Mon Sep 17 00:00:00 2001 From: Alphas00 <154434082+Alphas00@users.noreply.github.com> Date: Tue, 30 Apr 2024 22:17:29 +0200 Subject: [PATCH 1/3] Web Weaver webs and Genital Nutriment Web Weaver quirk now also adds an action to spin sticky webs where you stand. Characters with the Web Weaver quirk can freely move through webs. Added nutriment as an option for fluid for genitals --- GainStation13/code/mechanics/web_weaving.dm | 30 ++++++++++++++++++--- code/__DEFINES/traits.dm | 1 + code/__HELPERS/global_lists.dm | 2 +- code/game/objects/effects/spiders.dm | 2 +- code/modules/client/preferences.dm | 8 ++++++ 5 files changed, 37 insertions(+), 6 deletions(-) diff --git a/GainStation13/code/mechanics/web_weaving.dm b/GainStation13/code/mechanics/web_weaving.dm index e6c6904a..ef2b768c 100644 --- a/GainStation13/code/mechanics/web_weaving.dm +++ b/GainStation13/code/mechanics/web_weaving.dm @@ -5,15 +5,20 @@ gain_text = "You find yourself able to weave webs." lose_text = "You are no longer able to weave webs." category = CATEGORY_SEXUAL + mob_trait = TRAIT_WEB_WEAVER ///What action is linked with this quirk? - var/datum/action/innate/wrap_target/linked_action + var/datum/action/innate/wrap_target/linked_action1 + var/datum/action/innate/make_web/linked_action2 /datum/quirk/web_weaving/post_add() - linked_action = new - linked_action.Grant(quirk_holder) + linked_action1 = new + linked_action1.Grant(quirk_holder) + linked_action2 = new + linked_action2.Grant(quirk_holder) /datum/quirk/web_weaving/remove() - linked_action.Remove(quirk_holder) + linked_action1.Remove(quirk_holder) + linked_action2.Remove(quirk_holder) return ..() /datum/action/innate/wrap_target @@ -83,3 +88,20 @@ /obj/structure/spider/cocoon/quirk max_integrity = 20 + +/datum/action/innate/make_web + name = "weave" + desc = "spins a sticky web." + icon_icon = 'icons/effects/effects.dmi' + button_icon_state = "stickyweb1" + background_icon_state = "bg_alien" + +/datum/action/innate/make_web/Activate() + var/turf/T = get_turf(owner) + owner.visible_message("[owner] begins spinning a web!", "You begin spinning a web.") + if(!do_after(owner, 10 SECONDS, 1, null, 1)) + owner.visible_message("[owner] fails to spin a web!", "You fail to spin web.") + return FALSE + T.ChangeTurf(/obj/structure/spider/stickyweb) + owner.visible_message("[owner] spin a sticky web!", "You spin a sticky web.") + return TRUE diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 2b3f5934..1778d470 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -203,6 +203,7 @@ #define TRAIT_LIPOLICIDE_TOLERANCE "lipolicide_tolerance" #define TRAIT_WEAKLEGS "weak_legs" #define TRAIT_STRONGLEGS "strong_legs" +#define TRAIT_WEB_WEAVER "web_weaving" //Hyper #define TRAIT_MACROPHILE "macrophile" //likes the big diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index b20cc07d..c94989ca 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -55,7 +55,7 @@ init_sprite_accessory_subtypes(/datum/sprite_accessory/vagina, GLOB.vagina_shapes_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/breasts, GLOB.breasts_shapes_list) GLOB.breasts_size_list = list ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o") //We need the list to choose from initialized, but it's no longer a sprite_accessory thing. - GLOB.genital_fluids_list = list ("Milk", "Water", "Semen", "Femcum", "Honey", "Strawberry Milk") + GLOB.genital_fluids_list = list ("Milk", "Water", "Semen", "Femcum", "Honey", "Strawberry Milk", "Nutriment") 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") for(var/K in GLOB.breasts_shapes_list) var/datum/sprite_accessory/breasts/value = GLOB.breasts_shapes_list[K] diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm index d53e7250..737247ac 100644 --- a/code/game/objects/effects/spiders.dm +++ b/code/game/objects/effects/spiders.dm @@ -36,7 +36,7 @@ . = ..() /obj/structure/spider/stickyweb/CanPass(atom/movable/mover, turf/target) - if(istype(mover, /mob/living/simple_animal/hostile/poison/giant_spider)) + if(istype(mover, /mob/living/simple_animal/hostile/poison/giant_spider) || HAS_TRAIT(mover, TRAIT_WEB_WEAVER)) return TRUE else if(isliving(mover)) if(istype(mover.pulledby, /mob/living/simple_animal/hostile/poison/giant_spider)) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 8a06e02b..8702b594 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -893,6 +893,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "Femcum" if(/datum/reagent/consumable/alienhoney) dat += "Honey" + if(/datum/reagent/consumable/nutriment) + dat += "Nutriment" else dat += "Nothing?" //This else is a safeguard for errors, and if it happened, they wouldn't be able to change this pref, @@ -940,6 +942,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "Honey" if(/datum/reagent/consumable/pinkmilk) dat += "Strawberry Milk" + if(/datum/reagent/consumable/nutriment) + dat += "Nutriment" else dat += "Nothing?" //This else is a safeguard for errors, and if it happened, they wouldn't be able to change this pref, @@ -2381,6 +2385,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) features["balls_fluid"] = /datum/reagent/consumable/alienhoney if("Strawberry Milk") features["balls_fluid"] = /datum/reagent/consumable/pinkmilk + if("Nutriment") + features["balls_fluid"] = /datum/reagent/consumable/nutriment if("egg_size") var/new_size @@ -2426,6 +2432,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) features["breasts_fluid"] = /datum/reagent/consumable/alienhoney if("Strawberry Milk") features["breasts_fluid"] = /datum/reagent/consumable/pinkmilk + if("Nutriment") + features["breasts_fluid"] = /datum/reagent/consumable/nutriment if("breasts_color") var/new_breasts_color = input(user, "Breast Color:", "Character Preference", "#"+features["breasts_color"]) as color|null From 6d72a17e1dc330772a6bde178b384e7aa1d6e9a1 Mon Sep 17 00:00:00 2001 From: Alphas00 <154434082+Alphas00@users.noreply.github.com> Date: Tue, 30 Apr 2024 23:27:45 +0200 Subject: [PATCH 2/3] Genital feeding Adds an option to feed a character pulled by the user with the reagents of a chosen genital --- .../code/modules/arousal/arousalhud.dm | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/hyperstation/code/modules/arousal/arousalhud.dm b/hyperstation/code/modules/arousal/arousalhud.dm index 6d0c0131..801d7c9d 100644 --- a/hyperstation/code/modules/arousal/arousalhud.dm +++ b/hyperstation/code/modules/arousal/arousalhud.dm @@ -34,9 +34,13 @@ if(user.pulling) dat += "Kiss [user.pulling]" dat += "(Kiss a partner, or object.)
" + dat += "Feed [user.pulling]" + dat += "(Feed a partner.)
" else dat += "Kiss" dat += "(Requires a partner)
" + dat += "Feed" + dat += "(Requires a partner)
" var/obj/item/organ/genital/belly/Belly = user.getorganslot("belly") if(Belly) @@ -202,6 +206,13 @@ to_chat(usr, "You cannot do this alone!") return + if(href_list["feed"]) + if(usr.pulling) + feed() + else + to_chat(usr, "You cannot do this alone!") + return + if(href_list["shrink_belly"]) var/obj/item/organ/genital/belly/E = usr.getorganslot("belly") if(E.size > 0) @@ -282,6 +293,14 @@ obj/screen/arousal/proc/kiss() if (H) H.kisstarget(H.pulling) +obj/screen/arousal/proc/feed() + if(usr.restrained(TRUE)) + to_chat(usr, "You can't do that while restrained!") + return + var/mob/living/carbon/human/H = usr + if (H) + H.genitalfeed(H.pulling) + /mob/living/carbon/human/proc/menuremovecondom() @@ -517,3 +536,44 @@ obj/screen/arousal/proc/kiss() if(cum_splatter_icon) cut_overlay(cum_splatter_icon) return TRUE + +/mob/living/carbon/human/proc/genitalfeed(mob/living/L, mb_time = 30) + if(isliving(L)) //is your target living? Living people can resist your advances if they want to via moving. + if(iscarbon(L)) + var/obj/item/organ/genital/picked_organ + var/total_fluids = 0 + var/datum/reagents/fluid_source = null + src << browse(null, "window=arousal") + picked_organ = pick_climax_genitals() //Gotta be climaxable, not just masturbation, to fill with fluids. + if(picked_organ) + //Good, got an organ, time to pick a container + if(picked_organ.name == "penis")//if the select organ is a penis + var/obj/item/organ/genital/penis/P = src.getorganslot("penis") + if(P.condom) //if the penis is condomed + to_chat(src, "You cannot fill containers when there is a condom over your [picked_organ.name].") + return + if(P.sounding) //if the penis is sounded + to_chat(src, "You cannot fill containers when there is a rod inside your [picked_organ.name].") + return + if(picked_organ.producing) //Can it produce its own fluids, such as breasts? + fluid_source = picked_organ.reagents + else + if(!picked_organ.linked_organ) + to_chat(src, "Your [picked_organ.name] is unable to produce it's own fluids, it's missing the organs for it.") + return + fluid_source = picked_organ.linked_organ.reagents + total_fluids = fluid_source.total_volume + + src.visible_message("[src] starts to feed [L.name] with their [picked_organ.name].", \ + "You feed [L.name] with your [picked_organ.name].") + if(do_after(src, mb_time, target = src) && in_range(src, L)) + fluid_source.trans_to(L, total_fluids) + src.visible_message("[src] uses [p_their()] [picked_organ.name] to feed [L.name]!", \ + "You used your [picked_organ.name] to feed [L.name] a total of [total_fluids]u's.") + SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) + if(picked_organ.can_climax) + setArousalLoss(min_arousal) + + else //They either lack organs that can climax, or they didn't pick one. + to_chat(src, "You cannot fill anything without choosing exposed genitals.") + return From 0f61e09deb16e430b8b8165041e50b42f293359e Mon Sep 17 00:00:00 2001 From: Alphas00 <154434082+Alphas00@users.noreply.github.com> Date: Wed, 1 May 2024 11:56:05 +0200 Subject: [PATCH 3/3] Arousal menu options, Nibble buff, milk nutriment Added options in the arousal menu to feed yourself using your own organs or that of others you are pulling The Nibble now pumps venom over time if used against character you are pulling Milk now has a nutriment factor --- .../code/datums/mutations/fatfang.dm | 18 ++- .../chemistry/reagents/drink_reagents.dm | 1 + .../code/modules/arousal/arousalhud.dm | 131 +++++++++++++++++- 3 files changed, 143 insertions(+), 7 deletions(-) diff --git a/GainStation13/code/datums/mutations/fatfang.dm b/GainStation13/code/datums/mutations/fatfang.dm index 16eba2b3..0303b090 100644 --- a/GainStation13/code/datums/mutations/fatfang.dm +++ b/GainStation13/code/datums/mutations/fatfang.dm @@ -8,6 +8,7 @@ power = /obj/effect/proc_holder/spell/targeted/touch/fatfang instability = 10 energy_coeff = 1 + power_coeff = 1 /obj/effect/proc_holder/spell/targeted/touch/fatfang name = "The Nibble" @@ -28,7 +29,8 @@ icon_state = "power_feed" ///How much weight is added? var/chem_to_add = 5 - ///What verb is used for the spell? + + var/starttime = 0 /obj/item/melee/touch_attack/fatfang/afterattack(atom/target, mob/living/carbon/user, proximity) if(!proximity || !iscarbon(target) || target == user) @@ -36,10 +38,18 @@ if(!target || !chem_to_add) return FALSE - - target.reagents.add_reagent(/datum/reagent/consumable/lipoifier, chem_to_add) - target.visible_message("[user] nibbles [target]!","[user] nibbles you!") + if(target == user.pulling && ishuman(user.pulling)) + starttime = world.time + user.dna.get_mutation(FATFANG).power.charge_max = 600 * GET_MUTATION_ENERGY(user.dna.get_mutation(FATFANG)) + while(starttime + 300 > world.time && in_range(user, target)) + if(do_mob(user, target, 10, 0, 1)) + target.reagents.add_reagent(/datum/reagent/consumable/lipoifier, (chem_to_add * GET_MUTATION_POWER(user.dna.get_mutation(FATFANG))/2)) + target.visible_message("[user] pumps some venom in [target]!","[user] pumps some venom in you!") + else + user.dna.get_mutation(FATFANG).power.charge_max = 50 * GET_MUTATION_ENERGY(user.dna.get_mutation(FATFANG)) + target.reagents.add_reagent(/datum/reagent/consumable/lipoifier, chem_to_add * GET_MUTATION_POWER(user.dna.get_mutation(FATFANG))) + return ..() /obj/item/dnainjector/antifang diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm index de4a4b68..3c506574 100644 --- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm @@ -222,6 +222,7 @@ glass_desc = "White and nutritious goodness!" pH = 6.5 hydration = 3 + nutriment_factor = 15 * REAGENTS_METABOLISM /datum/reagent/consumable/milk/on_mob_life(mob/living/carbon/M) if(HAS_TRAIT(M, TRAIT_CALCIUM_HEALER)) diff --git a/hyperstation/code/modules/arousal/arousalhud.dm b/hyperstation/code/modules/arousal/arousalhud.dm index 801d7c9d..5f43568b 100644 --- a/hyperstation/code/modules/arousal/arousalhud.dm +++ b/hyperstation/code/modules/arousal/arousalhud.dm @@ -36,11 +36,17 @@ dat += "(Kiss a partner, or object.)
" dat += "Feed [user.pulling]" dat += "(Feed a partner.)
" + dat += "Feed from [user.pulling]" + dat += "(Feed a partner.)
" else dat += "Kiss" dat += "(Requires a partner)
" - dat += "Feed" + dat += "Feed others" dat += "(Requires a partner)
" + dat += "Feed from others" + dat += "(Requires a partner)
" + dat += "Feed yourself" + dat += "(Feed yourself with your own genitals)
" var/obj/item/organ/genital/belly/Belly = user.getorganslot("belly") if(Belly) @@ -213,6 +219,17 @@ to_chat(usr, "You cannot do this alone!") return + if(href_list["feedfrom"]) + if(usr.pulling) + feedfrom() + else + to_chat(usr, "You cannot do this alone!") + return + + if(href_list["feedyourself"]) + feedyourself() + return + if(href_list["shrink_belly"]) var/obj/item/organ/genital/belly/E = usr.getorganslot("belly") if(E.size > 0) @@ -301,6 +318,22 @@ obj/screen/arousal/proc/feed() if (H) H.genitalfeed(H.pulling) +obj/screen/arousal/proc/feedfrom() + if(usr.restrained(TRUE)) + to_chat(usr, "You can't do that while restrained!") + return + var/mob/living/carbon/human/H = usr + if (H) + H.genitalfeedfrom(H.pulling) + +obj/screen/arousal/proc/feedyourself() + if(usr.restrained(TRUE)) + to_chat(usr, "You can't do that while restrained!") + return + var/mob/living/carbon/human/H = usr + if (H) + H.genitalfeedyourself() + /mob/living/carbon/human/proc/menuremovecondom() @@ -550,10 +583,10 @@ obj/screen/arousal/proc/feed() if(picked_organ.name == "penis")//if the select organ is a penis var/obj/item/organ/genital/penis/P = src.getorganslot("penis") if(P.condom) //if the penis is condomed - to_chat(src, "You cannot fill containers when there is a condom over your [picked_organ.name].") + to_chat(src, "You cannot feed someone when there is a condom over your [picked_organ.name].") return if(P.sounding) //if the penis is sounded - to_chat(src, "You cannot fill containers when there is a rod inside your [picked_organ.name].") + to_chat(src, "You cannot feed someone when there is a rod inside your [picked_organ.name].") return if(picked_organ.producing) //Can it produce its own fluids, such as breasts? fluid_source = picked_organ.reagents @@ -577,3 +610,95 @@ obj/screen/arousal/proc/feed() else //They either lack organs that can climax, or they didn't pick one. to_chat(src, "You cannot fill anything without choosing exposed genitals.") return + +/mob/living/carbon/human/proc/genitalfeedfrom(mob/living/target, mb_time = 30) + var/mob/living/carbon/human/L = target + var/obj/item/organ/genital/picked_organ + var/total_fluids = 0 + var/datum/reagents/fluid_source = null + src << browse(null, "window=arousal") + + var/list/genitals_list = list() + var/list/worn_stuff = L.get_equipped_items() + + for(var/obj/item/organ/genital/G in L.internal_organs) + if(G.can_climax) //filter out what you can't masturbate with + if(G.is_exposed(worn_stuff)) //Nude or through_clothing + if(!G.dontlist) + genitals_list += G + if(genitals_list.len) + picked_organ = input(src, "with what?", "Climax", null) as null|obj in genitals_list + else + return + + if(picked_organ) + //Good, got an organ, time to pick a container + if(picked_organ.name == "penis")//if the select organ is a penis + var/obj/item/organ/genital/penis/P = L.getorganslot("penis") + if(P.condom) //if the penis is condomed + to_chat(src, "You cannot feed from [picked_organ.name] when there is a condom over it.") + return + if(P.sounding) //if the penis is sounded + to_chat(src, "You cannot feed from [picked_organ.name] when there is a rod inside it.") + return + if(picked_organ.producing) //Can it produce its own fluids, such as breasts? + fluid_source = picked_organ.reagents + else + if(!picked_organ.linked_organ) + to_chat(src, "The [picked_organ.name] is unable to produce it's own fluids, it's missing the organs for it.") + return + fluid_source = picked_organ.linked_organ.reagents + total_fluids = fluid_source.total_volume + + src.visible_message("[src] starts to feed from [L.name]'s [picked_organ.name].", \ + "You feed from [L.name]'s '[picked_organ.name].") + if(do_after(src, mb_time, target = src) && in_range(src, L)) + fluid_source.trans_to(src, total_fluids) + src.visible_message("[src] feeds from [L.name]'s [picked_organ.name]!", \ + "You used [L.name]'s [picked_organ.name] to feed with a total of [total_fluids]u's.") + SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) + if(picked_organ.can_climax) + L.setArousalLoss(min_arousal) + + else //They either lack organs that can climax, or they didn't pick one. + to_chat(src, "You cannot fill anything without choosing exposed genitals.") + return + +/mob/living/carbon/human/proc/genitalfeedyourself(mb_time = 30) + var/obj/item/organ/genital/picked_organ + var/total_fluids = 0 + var/datum/reagents/fluid_source = null + src << browse(null, "window=arousal") + picked_organ = pick_climax_genitals() //Gotta be climaxable, not just masturbation, to fill with fluids. + if(picked_organ) + //Good, got an organ, time to pick a container + if(picked_organ.name == "penis")//if the select organ is a penis + var/obj/item/organ/genital/penis/P = src.getorganslot("penis") + if(P.condom) //if the penis is condomed + to_chat(src, "You cannot feed yourself when there is a condom over your [picked_organ.name].") + return + if(P.sounding) //if the penis is sounded + to_chat(src, "You cannot feed yourself when there is a rod inside your [picked_organ.name].") + return + if(picked_organ.producing) //Can it produce its own fluids, such as breasts? + fluid_source = picked_organ.reagents + else + if(!picked_organ.linked_organ) + to_chat(src, "Your [picked_organ.name] is unable to produce it's own fluids, it's missing the organs for it.") + return + fluid_source = picked_organ.linked_organ.reagents + total_fluids = fluid_source.total_volume + + src.visible_message("[src] starts to feed themselves with their [picked_organ.name].", \ + "You feed yourself with your [picked_organ.name].") + if(do_after(src, mb_time)) + fluid_source.trans_to(src, total_fluids) + src.visible_message("[src] uses [p_their()] [picked_organ.name] to feed themselves!", \ + "You used your [picked_organ.name] to feed yourself a total of [total_fluids]u's.") + SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) + if(picked_organ.can_climax) + setArousalLoss(min_arousal) + + else //They either lack organs that can climax, or they didn't pick one. + to_chat(src, "You cannot fill anything without choosing exposed genitals.") + return