mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-30 08:37:43 +01:00
Adds "Aphrodisiacal Bite" Quirk, moving "Venomous Bite" 's ERP options. (#4269)
## About The Pull Request Adds a new 0 Points quirk that injects people with ERP poisons, moving them from Venomous Bite to it. <img width="478" height="223" alt="image" src="https://github.com/user-attachments/assets/51a685bc-4674-43ec-b95d-53407f0c0411" /> <img width="469" height="241" alt="image" src="https://github.com/user-attachments/assets/f155d7a0-2ceb-4d1c-a13d-2c07da9c64a5" /> <img width="217" height="230" alt="image" src="https://github.com/user-attachments/assets/7f769484-eda3-4a66-8560-5bb52dc5a8bd" /> Links the Venom Milker over to this quirk. Links Aphro-Biting to the Aphrodisiac preference, and logs its usage. <img width="679" height="68" alt="image" src="https://github.com/user-attachments/assets/29b819be-398a-4bd8-8d75-3aa0c3eb9931" /> Frankly, I have no attachment over the sprite or name/descriptions, feel free to change to something more proper. First PR here! Tell me if I've majorly fucked something up. ## Why It's Good For The Game I've seen people mention it was weird a Mechanical Quirk had ERP options, especially for such a steep point cost, I agree. Separating them fixes it, giving each quirk its own niche and usage. ## Proof Of Testing See above, compiles. <details> <summary>Screenshots/Videos</summary> </details> ## Changelog 🆑 sunnyaries add: added a new quirk "Aphrodisiacal Bite", and moved ERP chems from "Venomous Bite" to it. /🆑 --------- Co-authored-by: Roxy <75404941+TealSeer@users.noreply.github.com>
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
/obj/item/reagent_containers/venom_milker/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
var/filter_immune_string = /datum/preference/choiced/venomous_bite_venom::filter_immune_string
|
||||
var/filter_immune_string = /datum/preference/choiced/aphrodisiacal_bite_venom::filter_immune_string
|
||||
if (length(filter_immune_string))
|
||||
desc += span_notice("\nThe following reagents cannot be filtered by the neutralizer: [filter_immune_string]")
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
* * silent = FALSE: If TRUE, will not give user any feedback.
|
||||
*/
|
||||
/obj/item/reagent_containers/venom_milker/proc/can_milk(mob/living/target, mob/living/user, silent = FALSE)
|
||||
var/datum/action/cooldown/mob_cooldown/venomous_bite/bite = locate() in target.actions
|
||||
var/datum/action/cooldown/mob_cooldown/aphrodisiacal_bite/bite = locate() in target.actions
|
||||
if (isnull(bite))
|
||||
if (!silent)
|
||||
user?.balloon_alert(user, "no fangs!")
|
||||
@@ -87,7 +87,7 @@
|
||||
/obj/item/reagent_containers/venom_milker/proc/siphon(mob/living/target, mob/living/user)
|
||||
if (!can_milk(target, user))
|
||||
return FALSE
|
||||
var/datum/action/cooldown/mob_cooldown/venomous_bite/bite = locate(/datum/action/cooldown/mob_cooldown/venomous_bite) in target.actions
|
||||
var/datum/action/cooldown/mob_cooldown/aphrodisiacal_bite/bite = locate() in target.actions
|
||||
if (isnull(bite))
|
||||
return FALSE
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* If a reagent milked from someone with the venom quirk is NOT in /datum/preference/choiced/venomous_bite_venom::milkable_venoms, it will be transformed into this
|
||||
* If a reagent milked from someone with the venom quirk is NOT in /datum/preference/choiced/aphrodisiacal_bite_venom::milkable_venoms, it will be transformed into this
|
||||
* generic chem that has no effects.
|
||||
*/
|
||||
/datum/reagent/generic_milked_venom
|
||||
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/datum/action/cooldown/mob_cooldown/aphrodisiacal_bite
|
||||
name = "Inject Aphrodisiac"
|
||||
desc = "Sink your fangs into another and inject them with your aphrodisiac."
|
||||
|
||||
button_icon = 'modular_zubbers/icons/mob/actions/quirks/aphrodisiacal_bite.dmi'
|
||||
button_icon_state = "aphrodisiac"
|
||||
|
||||
ranged_mousepointer = 'icons/effects/mouse_pointers/supplypod_pickturf.dmi'
|
||||
|
||||
check_flags = AB_CHECK_CONSCIOUS | AB_CHECK_INCAPACITATED // can use it if cuffed, enjoy
|
||||
|
||||
shared_cooldown = NONE
|
||||
|
||||
/// The reagent we will inject.
|
||||
var/datum/reagent/reagent_typepath
|
||||
/// How much of [reagent_typepath] we will inject.
|
||||
var/to_inject = 0
|
||||
|
||||
/datum/action/cooldown/mob_cooldown/aphrodisiacal_bite/New(Target, original, datum/reagent/our_reagent, quantity_override = null)
|
||||
. = ..()
|
||||
set_reagent(our_reagent, quantity_override)
|
||||
|
||||
/datum/action/cooldown/mob_cooldown/aphrodisiacal_bite/proc/set_reagent(datum/reagent/new_reagent, quantity_override = null, cooldown_override = null)
|
||||
reagent_typepath = new_reagent
|
||||
var/list/reagent_spec = /datum/preference/choiced/aphrodisiacal_bite_venom::aphrodisiacal_bite_choice_specs[new_reagent]
|
||||
to_inject = quantity_override || reagent_spec[1]
|
||||
cooldown_time = cooldown_override || reagent_spec[2]
|
||||
|
||||
/datum/action/cooldown/mob_cooldown/aphrodisiacal_bite/set_click_ability(mob/on_who)
|
||||
. = ..()
|
||||
if (!.)
|
||||
return
|
||||
owner.visible_message(span_warning("[owner] bares [owner.p_their()] fangs..."), span_notice("You bare your fangs..."))
|
||||
|
||||
/datum/action/cooldown/mob_cooldown/aphrodisiacal_bite/Activate(atom/target_atom)
|
||||
if (!isliving(target_atom))
|
||||
return FALSE
|
||||
|
||||
if (astype(owner, /mob/living/carbon)?.is_mouth_covered())
|
||||
owner.balloon_alert(owner, "mouth covered!")
|
||||
return FALSE
|
||||
|
||||
if (!owner.Adjacent(target_atom))
|
||||
owner.balloon_alert(owner, "too far!")
|
||||
return FALSE
|
||||
|
||||
if (target_atom == owner)
|
||||
owner.balloon_alert(owner, "can't bite yourself!")
|
||||
return FALSE
|
||||
|
||||
if(!iscarbon(target_atom))
|
||||
owner.balloon_alert(owner, "not carbon!")
|
||||
return FALSE
|
||||
|
||||
if(!astype(target_atom, /mob/living/carbon).client?.prefs.read_preference(/datum/preference/toggle/erp/aphro))
|
||||
owner.balloon_alert(owner, "not interested!")
|
||||
log_game("[key_name(owner)] tried to bite [key_name(astype(target_atom, /mob/living/carbon))] but [key_name(astype(target_atom, /mob/living/carbon))] had aphrodisiacs disabled")
|
||||
return FALSE
|
||||
|
||||
log_combat(owner, target_atom, "started to bite", null, "with venom: [reagent_typepath::name]")
|
||||
owner.visible_message(span_warning("[owner] starts to bite [target_atom]!"), span_warning("You start to bite [target_atom]!"), ignored_mobs = target_atom)
|
||||
to_chat(target_atom, span_userdanger("[owner] starts to bite you!"))
|
||||
owner.balloon_alert_to_viewers("biting...")
|
||||
if (!do_after(owner, 0.5 SECONDS, target_atom, IGNORE_HELD_ITEM))
|
||||
return FALSE
|
||||
|
||||
. = ..()
|
||||
|
||||
if (try_bite(target_atom))
|
||||
inject(target_atom)
|
||||
return TRUE
|
||||
|
||||
/// Does NOT inject reagents; represents the initial bite.
|
||||
/datum/action/cooldown/mob_cooldown/aphrodisiacal_bite/proc/try_bite(mob/living/target)
|
||||
PRIVATE_PROC(TRUE)
|
||||
var/target_zone = check_zone(owner.zone_selected)
|
||||
|
||||
var/text = "[owner] sinks [owner.p_their()] teeth into [target]'s [target.parse_zone_with_bodypart(target_zone)]!"
|
||||
var/self_message = "You sink your teeth into [target]'s [target.parse_zone_with_bodypart(target_zone)]!"
|
||||
var/victim_message = "[owner] sinks [owner.p_their()] teeth into your [target.parse_zone_with_bodypart(target_zone)]!"
|
||||
|
||||
owner.visible_message(span_warning(text), span_warning(self_message), ignored_mobs = list(target))
|
||||
to_chat(target, span_userdanger(victim_message))
|
||||
|
||||
owner.do_attack_animation(target, ATTACK_EFFECT_BITE)
|
||||
playsound(owner, 'sound/items/weapons/bite.ogg', 60, TRUE)
|
||||
log_combat(owner, target, "successfully bit", null, "with venom: [reagent_typepath::name]")
|
||||
return TRUE
|
||||
|
||||
/datum/action/cooldown/mob_cooldown/aphrodisiacal_bite/proc/inject(mob/living/target)
|
||||
if (!target.try_inject(owner, check_zone(owner.zone_selected)))
|
||||
return FALSE
|
||||
|
||||
add_reagents(target.reagents)
|
||||
return TRUE
|
||||
|
||||
/datum/action/cooldown/mob_cooldown/aphrodisiacal_bite/proc/add_reagents(datum/reagents/target, harvesting = FALSE)
|
||||
var/temp = astype(owner, /mob/living/carbon/human)?.coretemperature
|
||||
var/datum/reagent/local_typepath = reagent_typepath
|
||||
if (harvesting)
|
||||
var/list/spec = /datum/preference/choiced/aphrodisiacal_bite_venom::aphrodisiacal_bite_choice_specs[local_typepath]
|
||||
if (!spec[3])
|
||||
local_typepath = /datum/reagent/generic_milked_venom
|
||||
|
||||
target.add_reagent(local_typepath, to_inject, reagtemp = temp)
|
||||
return TRUE
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
/datum/quirk/aphrodisiacal_bite
|
||||
name = "Aphrodisiacal Bite"
|
||||
desc = "You have a aphrodisiacal gland, and can bite people to inject them with an aphrodisiac of your choosing."
|
||||
icon = FA_ICON_ICICLES
|
||||
value = 0
|
||||
gain_text = span_notice("You feel a aphrodisiacal gland in the back of your throat.")
|
||||
lose_text = span_warning("Your aphrodisiacal gland vanishes.")
|
||||
medical_record_text = "Patient possesses an aphrodisiacal gland."
|
||||
|
||||
/datum/quirk/aphrodisiacal_bite/add(client/client_source)
|
||||
var/datum/reagent/reagent = text2path(client_source?.prefs?.read_preference(/datum/preference/choiced/aphrodisiacal_bite_venom))
|
||||
|
||||
var/mob/living/carbon/human/human_holder = quirk_holder
|
||||
var/datum/action/cooldown/mob_cooldown/aphrodisiacal_bite/action = new /datum/action/cooldown/mob_cooldown/aphrodisiacal_bite(human_holder, our_reagent = reagent)
|
||||
action.Grant(human_holder)
|
||||
|
||||
/datum/quirk/aphrodisiacal_bite/remove()
|
||||
if(QDELETED(quirk_holder))
|
||||
return ..()
|
||||
var/datum/action/cooldown/mob_cooldown/aphrodisiacal_bite/action = locate(/datum/action/cooldown/mob_cooldown/aphrodisiacal_bite) in quirk_holder.actions
|
||||
action.Remove()
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/quirk_constant_data/aphrodisiacal_bite
|
||||
associated_typepath = /datum/quirk/aphrodisiacal_bite
|
||||
customization_options = list(/datum/preference/choiced/aphrodisiacal_bite_venom)
|
||||
|
||||
/datum/preference/choiced/aphrodisiacal_bite_venom
|
||||
category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
|
||||
savefile_key = "aphrodisiacal_bite_venom"
|
||||
savefile_identifier = PREFERENCE_CHARACTER
|
||||
/// Format: (reagent typepath -> list(amount to inject per bite, cooldown, can be milked (venom_milker.dm)))
|
||||
var/static/list/aphrodisiacal_bite_choice_specs = list(
|
||||
/datum/reagent/drug/aphrodisiac/crocin = list(5, 2 SECONDS, TRUE),
|
||||
/datum/reagent/drug/aphrodisiac/crocin/hexacrocin = list(5, 5 SECONDS, TRUE),
|
||||
/datum/reagent/drug/aphrodisiac/succubus_milk = list(5, 2 SECONDS, TRUE),
|
||||
/datum/reagent/drug/aphrodisiac/incubus_draft = list(5, 2 SECONDS, TRUE),
|
||||
)
|
||||
var/static/list/milkable_venoms = generate_milkable_venom_list()
|
||||
var/static/filter_immune_string = generate_filter_immune_string()
|
||||
|
||||
/**
|
||||
* Generates a static list of /datum/reagent that will not be transformed into [/datum/reagent/generic_milked_venom] upon being milked by a venom milker.
|
||||
*
|
||||
* Ran once, then never again.
|
||||
*/
|
||||
/proc/generate_milkable_venom_list()
|
||||
RETURN_TYPE(/list)
|
||||
|
||||
var/list/milkable = list()
|
||||
|
||||
for (var/datum/reagent/typepath as anything in /datum/preference/choiced/aphrodisiacal_bite_venom::aphrodisiacal_bite_choice_specs)
|
||||
var/list/spec = /datum/preference/choiced/aphrodisiacal_bite_venom::aphrodisiacal_bite_choice_specs[typepath]
|
||||
|
||||
if (spec[3])
|
||||
milkable += typepath
|
||||
|
||||
return milkable
|
||||
|
||||
/**
|
||||
* Generates a static string appended to the venom milker's description, detailing which reagents available to the venom quirk will not be transformed into [/datum/reagent/generic_milked_venom].
|
||||
*
|
||||
* Ran once, then never again.
|
||||
*/
|
||||
/proc/generate_filter_immune_string()
|
||||
var/filter_immune_string = ""
|
||||
for (var/datum/reagent/typepath as anything in /datum/preference/choiced/aphrodisiacal_bite_venom::milkable_venoms)
|
||||
if (length(filter_immune_string))
|
||||
filter_immune_string += ", "
|
||||
filter_immune_string += typepath::name
|
||||
return filter_immune_string
|
||||
|
||||
/datum/preference/choiced/aphrodisiacal_bite_venom/init_possible_values()
|
||||
var/list/choices = list()
|
||||
for (var/entry in aphrodisiacal_bite_choice_specs)
|
||||
choices += "[entry]"
|
||||
|
||||
return choices
|
||||
|
||||
/datum/preference/choiced/aphrodisiacal_bite_venom/create_default_value()
|
||||
return "/datum/reagent/drug/aphrodisiac/crocin"
|
||||
|
||||
/datum/preference/choiced/aphrodisiacal_bite_venom/compile_constant_data()
|
||||
var/list/data = ..()
|
||||
|
||||
var/list/titles = list()
|
||||
|
||||
for (var/datum/reagent/entry as anything in aphrodisiacal_bite_choice_specs)
|
||||
var/list/specs = aphrodisiacal_bite_choice_specs[entry]
|
||||
|
||||
var/inject = specs[1]
|
||||
var/cooldown = specs[2]
|
||||
|
||||
var/name = entry::name
|
||||
|
||||
titles["[entry]"] = "[name] ([inject]u, [cooldown / 10] second cooldown)"
|
||||
|
||||
data[CHOICED_PREFERENCE_DISPLAY_NAMES] = titles
|
||||
|
||||
return data
|
||||
|
||||
/datum/preference/choiced/aphrodisiacal_bite_venom/is_accessible(datum/preferences/preferences)
|
||||
. = ..()
|
||||
if (!.)
|
||||
return FALSE
|
||||
|
||||
return "Aphrodisiacal Bite" in preferences.all_quirks
|
||||
|
||||
/datum/preference/choiced/aphrodisiacal_bite_venom/apply_to_human(mob/living/carbon/human/target, value)
|
||||
return
|
||||
+1
-5
@@ -116,13 +116,9 @@
|
||||
add_reagents(target.reagents)
|
||||
return TRUE
|
||||
|
||||
/datum/action/cooldown/mob_cooldown/venomous_bite/proc/add_reagents(datum/reagents/target, harvesting = FALSE)
|
||||
/datum/action/cooldown/mob_cooldown/venomous_bite/proc/add_reagents(datum/reagents/target)
|
||||
var/temp = astype(owner, /mob/living/carbon/human)?.coretemperature
|
||||
var/datum/reagent/local_typepath = reagent_typepath
|
||||
if (harvesting)
|
||||
var/list/spec = /datum/preference/choiced/venomous_bite_venom::venomous_bite_choice_specs[local_typepath]
|
||||
if (!spec[3])
|
||||
local_typepath = /datum/reagent/generic_milked_venom
|
||||
|
||||
target.add_reagent(local_typepath, to_inject, reagtemp = temp)
|
||||
return TRUE
|
||||
+6
-44
@@ -30,53 +30,15 @@
|
||||
category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
|
||||
savefile_key = "venomous_bite_venom"
|
||||
savefile_identifier = PREFERENCE_CHARACTER
|
||||
/// Format: (reagent typepath -> list(amount to inject per bite, cooldown, can be milked (venom_milker.dm)))
|
||||
/// Format: (reagent typepath -> list(amount to inject per bite, cooldown))
|
||||
var/static/list/venomous_bite_choice_specs = list(
|
||||
/datum/reagent/toxin = list(5, 80 SECONDS, FALSE),
|
||||
/datum/reagent/toxin/venom = list(5, 180 SECONDS, FALSE),
|
||||
/datum/reagent/toxin/carpotoxin = list(5, 60 SECONDS, FALSE), // less powerful than toxin
|
||||
/datum/reagent/toxin = list(5, 80 SECONDS),
|
||||
/datum/reagent/toxin/venom = list(5, 180 SECONDS),
|
||||
/datum/reagent/toxin/carpotoxin = list(5, 60 SECONDS), // less powerful than toxin
|
||||
// drugs
|
||||
/datum/reagent/drug/space_drugs = list(5, 60 SECONDS, TRUE),
|
||||
/datum/reagent/toxin/mindbreaker = list(5, 60 SECONDS, FALSE),
|
||||
// erp stuff
|
||||
/datum/reagent/drug/aphrodisiac/crocin = list(5, 2 SECONDS, TRUE),
|
||||
/datum/reagent/drug/aphrodisiac/crocin/hexacrocin = list(5, 5 SECONDS, TRUE),
|
||||
/datum/reagent/drug/aphrodisiac/succubus_milk = list(5, 2 SECONDS, TRUE),
|
||||
/datum/reagent/drug/aphrodisiac/incubus_draft = list(5, 2 SECONDS, TRUE),
|
||||
/datum/reagent/drug/space_drugs = list(5, 60 SECONDS),
|
||||
/datum/reagent/toxin/mindbreaker = list(5, 60 SECONDS),
|
||||
)
|
||||
var/static/list/milkable_venoms = generate_milkable_venom_list()
|
||||
var/static/filter_immune_string = generate_filter_immune_string()
|
||||
|
||||
/**
|
||||
* Generates a static list of /datum/reagent that will not be transformed into [/datum/reagent/generic_milked_venom] upon being milked by a venom milker.
|
||||
*
|
||||
* Ran once, then never again.
|
||||
*/
|
||||
/proc/generate_milkable_venom_list()
|
||||
RETURN_TYPE(/list)
|
||||
|
||||
var/list/milkable = list()
|
||||
|
||||
for (var/datum/reagent/typepath as anything in /datum/preference/choiced/venomous_bite_venom::venomous_bite_choice_specs)
|
||||
var/list/spec = /datum/preference/choiced/venomous_bite_venom::venomous_bite_choice_specs[typepath]
|
||||
|
||||
if (spec[3])
|
||||
milkable += typepath
|
||||
|
||||
return milkable
|
||||
|
||||
/**
|
||||
* Generates a static string appended to the venom milker's description, detailing which reagents available to the venom quirk will not be transformed into [/datum/reagent/generic_milked_venom].
|
||||
*
|
||||
* Ran once, then never again.
|
||||
*/
|
||||
/proc/generate_filter_immune_string()
|
||||
var/filter_immune_string = ""
|
||||
for (var/datum/reagent/typepath as anything in /datum/preference/choiced/venomous_bite_venom::milkable_venoms)
|
||||
if (length(filter_immune_string))
|
||||
filter_immune_string += ", "
|
||||
filter_immune_string += typepath::name
|
||||
return filter_immune_string
|
||||
|
||||
/datum/preference/choiced/venomous_bite_venom/init_possible_values()
|
||||
var/list/choices = list()
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 324 B |
+4
-2
@@ -8943,6 +8943,8 @@
|
||||
#include "modular_zubbers\code\datums\quirks\neutral_quirks\seamless_clothes.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\neutral_quirks\unblinking.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\neutral_quirks\waddle.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\neutral_quirks\aphrodisiacal_bite\aphrodisiacal_bite.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\neutral_quirks\aphrodisiacal_bite\aphrodisiacal_bite_quirk.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\positive_quirks\apathetic_override.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\positive_quirks\bilingual_override.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\positive_quirks\chip_connector_override.dm"
|
||||
@@ -8960,8 +8962,8 @@
|
||||
#include "modular_zubbers\code\datums\quirks\positive_quirks\spacer_override.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\positive_quirks\strong_stomach_override.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\positive_quirks\tagger_override.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\positive_quirks\venemous_bite\venomous_bite.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\positive_quirks\venemous_bite\venomous_bite_quirk.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\positive_quirks\venomous_bite\venomous_bite.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\positive_quirks\venomous_bite\venomous_bite_quirk.dm"
|
||||
#include "modular_zubbers\code\datums\shuttle\arena.dm"
|
||||
#include "modular_zubbers\code\datums\shuttles\emergency.dm"
|
||||
#include "modular_zubbers\code\datums\station_traits\disabled_traits.dm"
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
import type { FeatureChoiced } from '../../base';
|
||||
import { FeatureDropdownInput } from '../../dropdowns';
|
||||
|
||||
export const aphrodisiacal_bite_venom: FeatureChoiced = {
|
||||
name: 'Aphrodisiac Type',
|
||||
component: FeatureDropdownInput,
|
||||
};
|
||||
Reference in New Issue
Block a user