mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-22 20:48:56 +01:00
Merge branch 'master' into upstream-25-02a
This commit is contained in:
@@ -4,3 +4,4 @@
|
||||
#define span_velvet(str) ("<span class='velvet>" + str + "</span>")
|
||||
#define span_velvet_notice(str) ("<span class='velvet_notice'>" + str + "</span>")
|
||||
#define vote_font(str) ("<span class='vote'>" + str + "</span>")
|
||||
#define span_yellow_flashy(str) ("<span class='glossy'>" + str + "</span>")
|
||||
|
||||
@@ -46,6 +46,7 @@ GLOBAL_LIST_INIT_TYPED(quirk_blacklist, /list/datum/quirk, list(
|
||||
list(/datum/quirk/featherweight, /datum/quirk/oversized),
|
||||
list(/datum/quirk/overweight, /datum/quirk/obese),
|
||||
list(/datum/quirk/dominant_aura, /datum/quirk/well_trained),
|
||||
list(/datum/quirk/equipping/entombed, /datum/quirk/equipping/seamless_clothes),
|
||||
list(/datum/quirk/equipping/entombed, /datum/quirk/badback),
|
||||
//BUBBER EDIT ADDITION END
|
||||
))
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "Alecksohs"
|
||||
delete-after: True
|
||||
changes:
|
||||
- code_imp: "Vendors are now aware of sprite refits and will inform you if any are available."
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "TealSeer"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "fixed the SAD deleting wounds"
|
||||
@@ -369,3 +369,21 @@
|
||||
- rscadd: Nurse costume suit now in loadout and medical vendor
|
||||
SpooksAnno:
|
||||
- rscadd: The ability to grab parts and cells as a borg.
|
||||
2025-02-25:
|
||||
ABoxFaux:
|
||||
- code_imp: Teshari and Vox primalis can now use size collars in dorms/interlink
|
||||
areas.
|
||||
Alecksohs:
|
||||
- code_imp: Vendors are now aware of sprite refits and will inform you if any are
|
||||
available.
|
||||
StrangeWeirdKitten:
|
||||
- rscadd: Seamless heels quirk
|
||||
- rscadd: Nameless Quirk
|
||||
xPokee:
|
||||
- rscadd: added the intern ghoul plushie to both in game and the loadouts
|
||||
2025-02-26:
|
||||
StrangeWeirdKitten:
|
||||
- rscadd: Hypnotic Quirk
|
||||
nikothedude:
|
||||
- rscadd: Quirk; venemous bite. Allows you to bite people and inject them with a
|
||||
venom, or medicine, of your choosing.
|
||||
|
||||
@@ -76,6 +76,9 @@
|
||||
/// What brain traumas does the owner currently have?
|
||||
var/list/trauma_list = list()
|
||||
|
||||
/// What wounds does the owner currently have?
|
||||
var/list/wound_list = list()
|
||||
|
||||
/datum/component/damage_tracker/human/update_damage_values()
|
||||
. = ..()
|
||||
var/mob/living/carbon/human/human_parent = parent
|
||||
@@ -86,7 +89,13 @@
|
||||
if(length(current_trauma_list))
|
||||
trauma_list = current_trauma_list.Copy()
|
||||
|
||||
heart_damage = human_parent.check_organ_damage(/obj/item/organ/heart)
|
||||
for(var/obj/item/bodypart/limb as anything in human_parent.get_wounded_bodyparts())
|
||||
for(var/datum/wound/limb_wound as anything in limb.wounds)
|
||||
if(!islist(wound_list[limb.type]))
|
||||
wound_list[limb.type] = list()
|
||||
wound_list[limb.type] |= limb_wound.type
|
||||
|
||||
heart_damage = human_parent.check_organ_damage(/obj/item/organ/heart)
|
||||
liver_damage = human_parent.check_organ_damage(/obj/item/organ/liver)
|
||||
lung_damage = human_parent.check_organ_damage(/obj/item/organ/lungs)
|
||||
stomach_damage = human_parent.check_organ_damage(/obj/item/organ/stomach)
|
||||
@@ -121,6 +130,14 @@
|
||||
|
||||
human_brain.gain_trauma(trauma_to_add)
|
||||
|
||||
for(var/obj/item/bodypart/limb_type as anything in wound_list)
|
||||
var/obj/item/bodypart/limb_instance = locate(limb_type) in human_parent.bodyparts
|
||||
if(!limb_instance)
|
||||
continue
|
||||
for(var/datum/wound/wound_type as anything in wound_list[limb_type])
|
||||
var/datum/wound/new_wound = new wound_type()
|
||||
new_wound.apply_wound(limb_instance, TRUE)
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/component/damage_tracker/human/Initialize(...)
|
||||
|
||||
@@ -116,13 +116,20 @@
|
||||
if(!human_parent || !size_to_apply || (human_parent.dna.features["body_size"] == size_to_apply))
|
||||
return FALSE
|
||||
|
||||
if(isteshari(human_parent) || isvoxprimalis(human_parent)) // We check if the human_parent is a Vox Primalis or Teshari & temporarily disable the bodysize restriction
|
||||
human_parent.dna.species.body_size_restricted = FALSE
|
||||
|
||||
human_parent.dna.features["body_size"] = size_to_apply
|
||||
human_parent.maptext_height = 32 * human_parent.dna.features["body_size"]
|
||||
human_parent.dna.update_body_size()
|
||||
return TRUE
|
||||
|
||||
/datum/component/temporary_size/Destroy(force, silent)
|
||||
var/mob/living/carbon/human/human_parent = parent
|
||||
apply_size(original_size)
|
||||
|
||||
if(isteshari(human_parent) || isvoxprimalis(human_parent)) // We reapply it on destroy if they were
|
||||
human_parent.dna.species.body_size_restricted = TRUE
|
||||
UnregisterSignal(parent, COMSIG_ENTER_AREA)
|
||||
|
||||
return ..()
|
||||
|
||||
@@ -175,7 +175,8 @@
|
||||
return "Civilian"
|
||||
|
||||
/datum/preference/choiced/entombed_skin/is_accessible(datum/preferences/preferences)
|
||||
if (!..())
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
|
||||
return "Entombed" in preferences.all_quirks
|
||||
@@ -191,7 +192,8 @@
|
||||
maximum_value_length = 48
|
||||
|
||||
/datum/preference/text/entombed_mod_name/is_accessible(datum/preferences/preferences)
|
||||
if (!..())
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
|
||||
return "Entombed" in preferences.all_quirks
|
||||
@@ -216,7 +218,8 @@
|
||||
can_randomize = FALSE
|
||||
|
||||
/datum/preference/text/entombed_mod_desc/is_accessible(datum/preferences/preferences)
|
||||
if (!..())
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
|
||||
return "Entombed" in preferences.all_quirks
|
||||
@@ -242,7 +245,8 @@
|
||||
maximum_value_length = 16
|
||||
|
||||
/datum/preference/text/entombed_mod_prefix/is_accessible(datum/preferences/preferences)
|
||||
if (!..())
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
|
||||
return "Entombed" in preferences.all_quirks
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/datum/quirk/hypnotic
|
||||
name = "Hypnotic"
|
||||
desc = "You are extremely captivating to people who might be suspectable to fall into a stupor"
|
||||
icon = FA_ICON_FACE_GRIN_HEARTS
|
||||
value = 0
|
||||
quirk_flags = QUIRK_HUMAN_ONLY | QUIRK_HIDE_FROM_SCAN
|
||||
gain_text = "Your presence grows richer."
|
||||
lose_text = "Your potent presence dulls."
|
||||
medical_record_text = "Patient shows signs of a far richer presence then normal."
|
||||
erp_quirk = TRUE
|
||||
var/hypnotic_text
|
||||
var/hypnotic_color
|
||||
|
||||
/datum/quirk/hypnotic/add(client/client_source)
|
||||
RegisterSignal(quirk_holder, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine))
|
||||
|
||||
/datum/quirk/hypnotic/post_add()
|
||||
hypnotic_text = quirk_holder.client.prefs.read_preference(/datum/preference/text/hypnotic_text)
|
||||
hypnotic_color = quirk_holder.client.prefs.read_preference(/datum/preference/choiced/hypnotic_span)
|
||||
|
||||
/datum/quirk/hypnotic/remove()
|
||||
UnregisterSignal(quirk_holder, COMSIG_ATOM_EXAMINE)
|
||||
|
||||
/datum/quirk/hypnotic/proc/on_examine(atom/source, mob/user, list/examine_list)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/mob/living/examinee = source
|
||||
if(!istype(user))
|
||||
return
|
||||
if(!(examinee.client.prefs.read_preference(/datum/preference/toggle/erp/hypnosis)))
|
||||
return
|
||||
if(user.stat == DEAD)
|
||||
return
|
||||
if(isnull(hypnotic_color))
|
||||
return
|
||||
examine_list += pick_color()
|
||||
|
||||
/datum/quirk/hypnotic/proc/pick_color()
|
||||
var/choice
|
||||
switch(hypnotic_color)
|
||||
if("Hypnophrase")
|
||||
choice = "hypnophrase"
|
||||
if("Velvet")
|
||||
choice = "velvet"
|
||||
if("Yellow Flashy")
|
||||
choice = "glossy"
|
||||
if("Pink")
|
||||
choice = "pink"
|
||||
if("Cult")
|
||||
choice = "cult"
|
||||
|
||||
return "<span class='[choice]'>[isnull(hypnotic_text) ? "Their eyes are enticing to stare at." : hypnotic_text]</span>"
|
||||
|
||||
/datum/quirk_constant_data/hypnotic
|
||||
associated_typepath = /datum/quirk/hypnotic
|
||||
customization_options = list(
|
||||
/datum/preference/text/hypnotic_text,
|
||||
/datum/preference/choiced/hypnotic_span,
|
||||
)
|
||||
|
||||
/datum/preference/text/hypnotic_text
|
||||
category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
|
||||
savefile_key = "hypnotic_quirk_text"
|
||||
savefile_identifier = PREFERENCE_CHARACTER
|
||||
can_randomize = FALSE
|
||||
maximum_value_length = 100
|
||||
|
||||
/datum/preference/text/hypnotic_text/serialize(input)
|
||||
return htmlrendertext(input)
|
||||
|
||||
/datum/preference/text/hypnotic_text/deserialize(input, datum/preferences/preferences)
|
||||
return htmlrendertext(input)
|
||||
|
||||
/datum/preference/choiced/hypnotic_span
|
||||
category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
|
||||
savefile_key = "flashy_text"
|
||||
savefile_identifier = PREFERENCE_CHARACTER
|
||||
can_randomize = FALSE
|
||||
|
||||
/datum/preference/choiced/hypnotic_span/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/preferences)
|
||||
return
|
||||
|
||||
/datum/preference/text/hypnotic_text/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/preferences)
|
||||
return
|
||||
|
||||
/datum/preference/text/hypnotic_text/create_default_value()
|
||||
return "Their eyes are inciticing to stare at."
|
||||
|
||||
/datum/preference/choiced/hypnotic_span/create_default_value()
|
||||
return "Hypnophrase"
|
||||
|
||||
/datum/preference/choiced/hypnotic_span/init_possible_values()
|
||||
return list(
|
||||
"Hypnophrase",
|
||||
"Velvet",
|
||||
"Yellow Flashy",
|
||||
"Pink",
|
||||
"Cult",
|
||||
)
|
||||
@@ -0,0 +1,63 @@
|
||||
/datum/quirk/nameless
|
||||
name = "Nameless"
|
||||
desc = "You don't have a name. You are known only as a number."
|
||||
medical_record_text = "Subject lacks a name in records."
|
||||
value = 0
|
||||
icon = FA_ICON_USER_NINJA
|
||||
gain_text = span_notice("You feel your name slip away.")
|
||||
lose_text = span_notice("You spontaniously remember your full name!")
|
||||
quirk_flags = QUIRK_HIDE_FROM_SCAN
|
||||
var/character_name
|
||||
var/new_name
|
||||
|
||||
/datum/preference/text/nameless_quirk_option
|
||||
category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
|
||||
savefile_key = "nameless_quirk_name"
|
||||
savefile_identifier = PREFERENCE_CHARACTER
|
||||
can_randomize = FALSE
|
||||
maximum_value_length = 20
|
||||
|
||||
/// Some sanity to ensure you can't have " #1000" as your name.
|
||||
/datum/preference/text/nameless_quirk_option/is_valid(value)
|
||||
if(isnull(value))
|
||||
return TRUE
|
||||
return !isnull(permissive_sanitize_name(value))
|
||||
|
||||
/datum/preference/text/nameless_quirk_option/serialize(input)
|
||||
return htmlrendertext(input)
|
||||
|
||||
/datum/preference/text/nameless_quirk_option/deserialize(input, datum/preferences/preferences)
|
||||
return htmlrendertext(input)
|
||||
|
||||
/datum/preference/text/nameless_quirk_option/apply_to_human(mob/living/carbon/human/target, value)
|
||||
return
|
||||
|
||||
/datum/quirk_constant_data/nameless
|
||||
associated_typepath = /datum/quirk/nameless
|
||||
customization_options = list(
|
||||
/datum/preference/text/nameless_quirk_option
|
||||
)
|
||||
|
||||
/datum/quirk/nameless/add(client/client_source)
|
||||
character_name = client_source?.prefs.read_preference(/datum/preference/name/real_name)
|
||||
new_name = generate_name()
|
||||
quirk_holder.fully_replace_character_name(character_name, new_name)
|
||||
|
||||
/datum/quirk/nameless/remove()
|
||||
quirk_holder.fully_replace_character_name(new_name, character_name)
|
||||
|
||||
/datum/quirk/nameless/proc/generate_name()
|
||||
|
||||
var/prefix = quirk_holder.client?.prefs.read_preference(/datum/preference/text/nameless_quirk_option)
|
||||
var/job
|
||||
var/number = pick(rand(1000, 9999))
|
||||
|
||||
if(prefix)
|
||||
job = prefix
|
||||
else
|
||||
job = isnull(quirk_holder.job) ? pick("Alpha", "Beta", "Delta", "Echo", "Zulu", "Omega") : quirk_holder.job
|
||||
|
||||
return "[job] #[number]"
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/datum/quirk/equipping/seamless_clothes
|
||||
name = "Seamless Heels"
|
||||
desc = "You come with heels stuck on you. Whether it be a freak accident or part of your design, you can't take them off."
|
||||
medical_record_text = "Subject appears to have clothing attire fused to their body."
|
||||
value = 0
|
||||
icon = FA_ICON_TSHIRT
|
||||
gain_text = span_notice("You feel things stick to your body.")
|
||||
lose_text = span_notice("You feel things loose their grip on your body.")
|
||||
quirk_flags = QUIRK_HIDE_FROM_SCAN
|
||||
forced_items = list(/obj/item/clothing/shoes/fancy_heels = list(ITEM_SLOT_FEET))
|
||||
var/prefix = "seamless"
|
||||
var/obj/item/clothing/shoes/shoes
|
||||
|
||||
/datum/quirk/equipping/seamless_clothes/on_equip_item(obj/item/equipped, success)
|
||||
shoes = equipped
|
||||
|
||||
/datum/quirk/equipping/seamless_clothes/post_add() // Quirks init on round start ready up before client does.
|
||||
if(!istype(shoes, /obj/item/clothing/shoes/fancy_heels))
|
||||
CRASH("Type mismatch on [src] during on_equip_item. Tried to equip [shoes]")
|
||||
shoes.name = "[prefix] [initial(shoes.name)]"
|
||||
shoes.desc = "A pair of heels which refuse to come off your feet."
|
||||
shoes.greyscale_colors = quirk_holder.client.prefs.read_preference(/datum/preference/color/seamless_shoe_color)
|
||||
shoes.resistance_flags = ACID_PROOF | FIRE_PROOF
|
||||
shoes.update_greyscale()
|
||||
ADD_TRAIT(shoes, TRAIT_NODROP, CLOTHING_TRAIT)
|
||||
RegisterSignal(shoes, COMSIG_ITEM_DROPPED, PROC_REF(remove_quirk))
|
||||
|
||||
/datum/quirk/equipping/seamless_clothes/remove()
|
||||
if(isnull(shoes))
|
||||
return
|
||||
UnregisterSignal(shoes, COMSIG_ITEM_DROPPED)
|
||||
QDEL_NULL(shoes)
|
||||
|
||||
/datum/quirk/equipping/seamless_clothes/proc/remove_quirk()
|
||||
SIGNAL_HANDLER
|
||||
qdel(src)
|
||||
|
||||
/datum/quirk_constant_data/seamless_clothes
|
||||
associated_typepath = /datum/quirk/equipping/seamless_clothes
|
||||
customization_options = list(
|
||||
/datum/preference/color/seamless_shoe_color
|
||||
)
|
||||
|
||||
/datum/preference/color/seamless_shoe_color
|
||||
savefile_key = "seamless_shoe_color"
|
||||
savefile_identifier = PREFERENCE_CHARACTER
|
||||
category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
|
||||
|
||||
/datum/preference/color/seamless_shoe_color/create_default_value()
|
||||
return "#e7e7e7"
|
||||
|
||||
/datum/preference/color/seamless_shoe_color/apply_to_human(mob/living/carbon/human/target, value)
|
||||
return
|
||||
@@ -0,0 +1,145 @@
|
||||
#define VENOMOUS_BITE_DAMAGE 5
|
||||
#define VENOMOUS_BITE_WOUND_CHANCE 20
|
||||
#define VENOMOUS_BITE_WOUND_BONUS 40
|
||||
|
||||
/datum/action/cooldown/mob_cooldown/venomous_bite
|
||||
name = "Inject Venom"
|
||||
desc = "Sink your fangs into another and inject them with your venom. Ineffective against those wearing armor."
|
||||
|
||||
button_icon = 'modular_zubbers/icons/mob/actions/quirks/venomous_bite.dmi'
|
||||
button_icon_state = "venom"
|
||||
|
||||
ranged_mousepointer = 'icons/effects/mouse_pointers/supplypod_pickturf.dmi'
|
||||
|
||||
check_flags = AB_CHECK_CONSCIOUS | AB_CHECK_INCAPACITATED | AB_CHECK_HANDS_BLOCKED // cant use it if cuffed
|
||||
|
||||
/// 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/venomous_bite/New(Target, original, datum/reagent/our_reagent, quantity_override = null)
|
||||
. = ..()
|
||||
|
||||
set_reagent(our_reagent, quantity_override)
|
||||
|
||||
/datum/action/cooldown/mob_cooldown/venomous_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/venomous_bite_venom::venomous_bite_choice_specs[new_reagent]
|
||||
if (isnum(quantity_override))
|
||||
to_inject = quantity_override
|
||||
else
|
||||
to_inject = reagent_spec[1]
|
||||
|
||||
if (isnum(cooldown_override))
|
||||
cooldown_time = cooldown_override
|
||||
else
|
||||
cooldown_time = reagent_spec[2]
|
||||
|
||||
/datum/action/cooldown/mob_cooldown/venomous_bite/set_click_ability(mob/on_who)
|
||||
. = ..()
|
||||
if (!.)
|
||||
return
|
||||
|
||||
owner.visible_message("[owner] bares [owner.p_their()] fangs...", span_warning("You bare your fangs..."))
|
||||
|
||||
/datum/action/cooldown/mob_cooldown/venomous_bite/Activate(atom/target_atom)
|
||||
if (!isliving(target_atom))
|
||||
return FALSE
|
||||
if (iscarbon(owner))
|
||||
var/mob/living/carbon/carbon_holder = owner
|
||||
if (carbon_holder.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
|
||||
|
||||
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...")
|
||||
var/result = do_after(owner, 0.5 SECONDS, target_atom, IGNORE_HELD_ITEM)
|
||||
if (!result)
|
||||
return FALSE
|
||||
|
||||
. = ..()
|
||||
|
||||
var/penetrated = try_bite(target_atom)
|
||||
if (penetrated)
|
||||
inject(target_atom)
|
||||
return TRUE
|
||||
|
||||
/// Does NOT inject reagents; represents the initial bite. Can end in your teeth being broken by armor. Dumbass.
|
||||
/datum/action/cooldown/mob_cooldown/venomous_bite/proc/try_bite(mob/living/target)
|
||||
var/target_zone = check_zone(owner.zone_selected)
|
||||
var/armor = target.run_armor_check(target_zone, MELEE)
|
||||
var/obj/item/bodypart/part = target.get_bodypart(target_zone)
|
||||
|
||||
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)]!"
|
||||
|
||||
var/covered = FALSE
|
||||
if (ishuman(target))
|
||||
var/mob/living/carbon/human/human_target = target
|
||||
for (var/obj/item/clothing/iter_clothing as anything in human_target.get_clothing_on_part(part))
|
||||
if (iter_clothing.clothing_flags & THICKMATERIAL)
|
||||
covered = TRUE
|
||||
|
||||
text = "[owner] tries to bite [target], but breaks [owner.p_their()] teeth on [target]'s clothing! Ouch!"
|
||||
self_message = "You try to bite [target], but you break your teeth on [target.p_their()] clothing! Ouch!"
|
||||
victim_message = "[owner] tries to bite you, but breaks [owner.p_their()] teeth on your clothing! Ouch!"
|
||||
|
||||
owner.emote("scream")
|
||||
if (isliving(owner))
|
||||
var/mob/living/living_owner = owner
|
||||
living_owner.apply_damage(1, BRUTE, BODY_ZONE_HEAD)
|
||||
|
||||
break
|
||||
|
||||
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)
|
||||
if (covered)
|
||||
return FALSE
|
||||
var/wound_bonus = 0
|
||||
if (prob(VENOMOUS_BITE_WOUND_CHANCE))
|
||||
wound_bonus = VENOMOUS_BITE_WOUND_BONUS
|
||||
target.apply_damage(VENOMOUS_BITE_DAMAGE, BRUTE, target_zone, armor, wound_bonus = wound_bonus, sharpness = SHARP_POINTY)
|
||||
if (iscarbon(owner))
|
||||
var/mob/living/carbon/carbon_owner = owner
|
||||
for (var/datum/disease/our_disease as anything in carbon_owner.diseases)
|
||||
if (our_disease.spread_flags & DISEASE_SPREAD_CONTACT_FLUIDS || our_disease.spread_flags & DISEASE_SPREAD_CONTACT_SKIN)
|
||||
target.ContactContractDisease(our_disease, target_zone)
|
||||
|
||||
if (iscarbon(target))
|
||||
var/mob/living/carbon/carbon_target = target
|
||||
for (var/datum/disease/their_disease as anything in carbon_target.diseases)
|
||||
if (their_disease.spread_flags & DISEASE_SPREAD_CONTACT_FLUIDS || their_disease.spread_flags & DISEASE_SPREAD_CONTACT_SKIN)
|
||||
carbon_owner.ContactContractDisease(their_disease, target_zone)
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/action/cooldown/mob_cooldown/venomous_bite/proc/inject(mob/living/target)
|
||||
var/target_zone = check_zone(owner.zone_selected)
|
||||
if (!target.try_inject(owner, target_zone))
|
||||
return FALSE
|
||||
var/temp
|
||||
if (ishuman(owner))
|
||||
var/mob/living/carbon/human/human_holder = owner
|
||||
temp = human_holder.coretemperature
|
||||
target.reagents.add_reagent(reagent_typepath, to_inject, reagtemp = temp)
|
||||
|
||||
return TRUE
|
||||
|
||||
#undef VENOMOUS_BITE_DAMAGE
|
||||
#undef VENOMOUS_BITE_WOUND_BONUS
|
||||
#undef VENOMOUS_BITE_WOUND_CHANCE
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/datum/quirk/venomous_bite
|
||||
name = "Venomous Bite"
|
||||
desc = "You have a venom gland, and can bite people to inject them with a toxin of your choosing."
|
||||
icon = FA_ICON_TEETH_OPEN
|
||||
value = 8
|
||||
gain_text = span_notice("You feel a venom gland in the back of your throat.")
|
||||
lose_text = span_warning("Your venom gland vanishes.")
|
||||
medical_record_text = "Patient possesses a venom gland."
|
||||
|
||||
/datum/quirk/venomous_bite/add(client/client_source)
|
||||
var/datum/reagent/reagent = text2path(client_source?.prefs?.read_preference(/datum/preference/choiced/venomous_bite_venom))
|
||||
|
||||
var/mob/living/carbon/human/human_holder = quirk_holder
|
||||
var/datum/action/cooldown/mob_cooldown/venomous_bite/action = new /datum/action/cooldown/mob_cooldown/venomous_bite(human_holder, our_reagent = reagent)
|
||||
action.Grant(human_holder)
|
||||
|
||||
/datum/quirk/venomous_bite/remove()
|
||||
var/datum/action/cooldown/mob_cooldown/venomous_bite/action = locate(/datum/action/cooldown/mob_cooldown/venomous_bite) in quirk_holder.actions
|
||||
action.Remove()
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/quirk_constant_data/venomous_bite
|
||||
associated_typepath = /datum/quirk/venomous_bite
|
||||
customization_options = list(/datum/preference/choiced/venomous_bite_venom)
|
||||
|
||||
/datum/preference/choiced/venomous_bite_venom
|
||||
category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
|
||||
savefile_key = "venomous_bite_venom"
|
||||
savefile_identifier = PREFERENCE_CHARACTER
|
||||
/// 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),
|
||||
/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),
|
||||
/datum/reagent/toxin/mindbreaker = list(5, 60 SECONDS),
|
||||
// erp stuff
|
||||
/datum/reagent/drug/aphrodisiac/crocin = list(5, 2 SECONDS),
|
||||
/datum/reagent/drug/aphrodisiac/crocin/hexacrocin = list(5, 5 SECONDS),
|
||||
/datum/reagent/drug/aphrodisiac/succubus_milk = list(5, 2 SECONDS),
|
||||
/datum/reagent/drug/aphrodisiac/incubus_draft = list(5, 2 SECONDS),
|
||||
)
|
||||
|
||||
|
||||
/datum/preference/choiced/venomous_bite_venom/init_possible_values()
|
||||
var/list/choices = list()
|
||||
for (var/entry in venomous_bite_choice_specs)
|
||||
choices += "[entry]"
|
||||
|
||||
return choices
|
||||
|
||||
/datum/preference/choiced/venomous_bite_venom/create_default_value()
|
||||
return "/datum/reagent/toxin"
|
||||
|
||||
/datum/preference/choiced/venomous_bite_venom/compile_constant_data()
|
||||
var/list/data = ..()
|
||||
|
||||
var/list/titles = list()
|
||||
|
||||
for (var/datum/reagent/entry as anything in venomous_bite_choice_specs)
|
||||
var/list/specs = venomous_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/venomous_bite_venom/is_accessible(datum/preferences/preferences)
|
||||
. = ..()
|
||||
if (!.)
|
||||
return FALSE
|
||||
|
||||
return "Venomous Bite" in preferences.all_quirks
|
||||
|
||||
/datum/preference/choiced/venomous_bite_venom/apply_to_human(mob/living/carbon/human/target, value)
|
||||
return
|
||||
@@ -244,3 +244,12 @@
|
||||
gender = FEMALE
|
||||
squeak_override = list('modular_zubbers/sound/emotes/arf.ogg' = 1)
|
||||
|
||||
// xPokee's plush
|
||||
/obj/item/toy/plush/ghoul
|
||||
name = "intern ghoul plushie"
|
||||
desc = "Even the marketable plushie of this thing is utterly terrifying. At least it's cuddly..."
|
||||
icon = 'modular_zubbers/icons/obj/toys/plushes.dmi'
|
||||
icon_state = "johnghoul"
|
||||
attack_verb_continuous = list("ghouls")
|
||||
attack_verb_simple = list("ghoul")
|
||||
squeak_override = list('modular_zubbers/code/modules/blooper/voice/bloopers/kazooie/ehh.ogg' = 1)
|
||||
|
||||
@@ -86,3 +86,7 @@
|
||||
/datum/loadout_item/toys/androiddog
|
||||
name = "Android Dog Plushie"
|
||||
item_path = /obj/item/toy/plush/androiddog
|
||||
|
||||
/datum/loadout_item/toys/ghoul
|
||||
name = "Intern Ghoul Plushie"
|
||||
item_path = /obj/item/toy/plush/ghoul
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 270 B |
Binary file not shown.
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 53 KiB |
@@ -8832,15 +8832,20 @@
|
||||
#include "modular_zubbers\code\datums\quirks\neutral_quirks\food.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\neutral_quirks\hungry.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\neutral_quirks\hydrophilic.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\neutral_quirks\hypnotic.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\neutral_quirks\lungs.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\neutral_quirks\nameless.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\neutral_quirks\oversized_quirk.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\neutral_quirks\pet_owner.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\neutral_quirks\seamless_clothes.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\neutral_quirks\waddle.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\positive_quirks\dominant_aura.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\positive_quirks\empath_override.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\positive_quirks\featherweight.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\positive_quirks\life_savings.dm"
|
||||
#include "modular_zubbers\code\datums\quirks\positive_quirks\masquerade_food.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\shuttle\arena.dm"
|
||||
#include "modular_zubbers\code\datums\shuttles\emergency.dm"
|
||||
#include "modular_zubbers\code\datums\station_traits\disabled_traits.dm"
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
import { Feature, FeatureChoiced, FeatureShortTextInput } from '../../base';
|
||||
import { FeatureDropdownInput } from '../../dropdowns';
|
||||
|
||||
export const hypnotic_quirk_text: Feature<string> = {
|
||||
name: 'Hypnotic Text Examine',
|
||||
description:
|
||||
'The examine text portrayed from your character. Use third person (Their, He, She, etc)',
|
||||
component: FeatureShortTextInput,
|
||||
};
|
||||
|
||||
export const flashy_text: FeatureChoiced = {
|
||||
name: 'Text Color Selection',
|
||||
component: FeatureDropdownInput,
|
||||
};
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import { Feature, FeatureShortTextInput } from '../../base';
|
||||
|
||||
export const nameless_quirk_name: Feature<string> = {
|
||||
name: 'Prefix Name',
|
||||
description:
|
||||
'Example: (Prefix) #1334. Leave blank to default to job title. Minimum 3 characters.',
|
||||
component: FeatureShortTextInput,
|
||||
};
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
import { Feature, FeatureColorInput } from '../../base';
|
||||
|
||||
export const seamless_shoe_color: Feature<string> = {
|
||||
name: 'Shoe Color',
|
||||
component: FeatureColorInput,
|
||||
};
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
import { FeatureChoiced } from '../../base';
|
||||
import { FeatureDropdownInput } from '../../dropdowns';
|
||||
|
||||
export const venomous_bite_venom: FeatureChoiced = {
|
||||
name: 'Venom Type',
|
||||
component: FeatureDropdownInput,
|
||||
};
|
||||
Reference in New Issue
Block a user