mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-26 14:39:58 +01:00
Merge remote-tracking branch 'origin/master' into upstream-feb12-2026
# Conflicts: # _maps/map_files/moonstation/moonstation.dmm # tgstation.dme
This commit is contained in:
File diff suppressed because it is too large
Load Diff
+3248
-2982
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
||||
GLOBAL_LIST_EMPTY(blooper_list)
|
||||
GLOBAL_LIST_EMPTY(blooper_random_list)
|
||||
@@ -1,4 +1,3 @@
|
||||
//BLOOPER defines
|
||||
#define BLOOPER_DEFAULT_MINPITCH 0.4
|
||||
#define BLOOPER_DEFAULT_MAXPITCH 2
|
||||
#define BLOOPER_DEFAULT_MINVARY 0.1
|
||||
@@ -8,12 +7,10 @@
|
||||
|
||||
#define BLOOPER_SPEED_BASELINE 4 //Used to calculate delay between BLOOPERs, any BLOOPER speeds below this feature higher BLOOPER density, any speeds above feature lower BLOOPER density. Keeps BLOOPERing length consistent
|
||||
|
||||
#define BLOOPER_TRANSMIT_VOLUME 55
|
||||
#define BLOOPER_MAX_BLOOPERS 24
|
||||
#define BLOOPER_MAX_TIME (1.5 SECONDS) // More or less the amount of time the above takes to process through with a BLOOPER speed of 2.
|
||||
|
||||
#define BLOOPER_PITCH_RAND(gend) ((gend == MALE ? rand(60, 120) : (gend == FEMALE ? rand(80, 140) : rand(60,140))) / 100) //Macro for determining random pitch based off gender
|
||||
#define BLOOPER_VARIANCE_RAND (rand(BLOOPER_DEFAULT_MINVARY * 100, BLOOPER_DEFAULT_MAXVARY * 100) / 100) //Macro for randomizing BLOOPER variance to reduce the amount of copy-pasta necessary for that
|
||||
|
||||
#define BLOOPER_DO_VARY(pitch, variance) (rand(((pitch * 100) - (variance*50)), ((pitch*100) + (variance*50))) / 100)
|
||||
|
||||
#define BLOOPER_SOUND_FALLOFF_EXPONENT 0.5 //At lower ranges, we want the exponent to be below 1 so that whispers don't sound too awkward. At higher ranges, we want the exponent fairly high to make yelling less obnoxious
|
||||
@@ -1,3 +1,4 @@
|
||||
// boolean - weather types that occur on the level
|
||||
|
||||
#define ZTRAIT_SANDSTORM_MOON "Weather_Sandstorm_Moon"
|
||||
#define AWAYSTART_MAINTSROOM "AWAYSTART_MAINTSROOM"
|
||||
|
||||
@@ -93,6 +93,7 @@ GLOBAL_LIST_INIT(organ_choice, list(
|
||||
"Lungs" = ORGAN_SLOT_LUNGS,
|
||||
"Liver" = ORGAN_SLOT_LIVER,
|
||||
"Stomach" = ORGAN_SLOT_STOMACH,
|
||||
"Brain" = ORGAN_SLOT_BRAIN, //BUBBER EDIT - Added line
|
||||
))
|
||||
|
||||
///Paraplegic Quirk
|
||||
|
||||
@@ -10,13 +10,16 @@
|
||||
|
||||
/// whether the removal needs to be surgical for it to explode. If you're adding more modes, just pass the signal directly instead
|
||||
var/surgical
|
||||
/// whether the removal causes the organ to qdel
|
||||
var/annihilate
|
||||
|
||||
/datum/element/dangerous_organ_removal/Attach(datum/target, surgical = FALSE)
|
||||
/datum/element/dangerous_organ_removal/Attach(datum/target, surgical = FALSE, annihilate = TRUE) //BUBBER EDIT - Adds new variable to make organ not qdel
|
||||
. = ..()
|
||||
if(!isorgan(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
|
||||
src.surgical = surgical
|
||||
src.annihilate = annihilate
|
||||
|
||||
if(surgical)
|
||||
RegisterSignal(target, COMSIG_ORGAN_SURGICALLY_REMOVED, PROC_REF(on_removal))
|
||||
@@ -40,4 +43,10 @@
|
||||
source.audible_message("[source] explodes into tiny pieces!")
|
||||
|
||||
explosion(source, light_impact_range = 1, explosion_cause = source)
|
||||
qdel(source)
|
||||
//BUBBER EDIT - if it doesn't qdel, set it to take all its health in damage
|
||||
//qdel(source)
|
||||
if(annihilate)
|
||||
qdel(source)
|
||||
else
|
||||
source.set_organ_damage(source.maxHealth)
|
||||
//EDIT END
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/datum/quirk/prosthetic_organ
|
||||
// BUBBER EDIT: moved to modular_zubbers\code\datums\quirks\negative_quirks\prosthetic_organ_bubber.dm
|
||||
/* /datum/quirk/prosthetic_organ
|
||||
name = "Prosthetic Organ"
|
||||
desc = "An accident caused you to lose one of your organs. Because of this, you now have a surplus prosthetic!"
|
||||
icon = FA_ICON_LUNGS
|
||||
@@ -72,3 +73,4 @@
|
||||
if(old_organ)
|
||||
old_organ.Insert(quirk_holder, special = TRUE)
|
||||
old_organ = null
|
||||
*/
|
||||
|
||||
@@ -515,12 +515,6 @@
|
||||
if(NAMEOF(src, glide_size))
|
||||
set_glide_size(var_value)
|
||||
. = TRUE
|
||||
// THE BUBBER EDIT ADDITION BEGIN - BLOOPER
|
||||
if(NAMEOF(src, blooper)) // Sorry, Vishenka.
|
||||
if(isfile(var_value))
|
||||
blooper = sound(var_value) //bark() expects vocal_bark to already be a sound datum, for performance reasons. adminbus QoL!
|
||||
. = TRUE
|
||||
// THE BUBBER EDIT ADDITION END
|
||||
if(!isnull(.))
|
||||
datum_flags |= DF_VAR_EDITED
|
||||
return
|
||||
|
||||
@@ -22,12 +22,6 @@
|
||||
// Snowflake for Ethereals
|
||||
human.updatehealth()
|
||||
human.updateappearance(mutcolor_update = TRUE)
|
||||
// BUBBER EDIT ADDITION BEGIN - Bloopers
|
||||
human.set_blooper(pick(GLOB.blooper_list))
|
||||
human.blooper_pitch = BLOOPER_PITCH_RAND(human.gender)
|
||||
human.blooper_pitch_range = BLOOPER_VARIANCE_RAND
|
||||
human.blooper_speed = rand(BLOOPER_DEFAULT_MINSPEED, BLOOPER_DEFAULT_MAXSPEED)
|
||||
// BUBBER EDIT ADDITION END - Bloopers
|
||||
|
||||
/**
|
||||
* Randomizes a human, but produces someone who looks exceedingly average (by most standards).
|
||||
|
||||
@@ -575,6 +575,10 @@
|
||||
new_profile.undershirt_color = target.undershirt_color
|
||||
new_profile.socks_color = target.socks_color
|
||||
new_profile.bra_color = target.bra_color
|
||||
new_profile.blooper = target.blooper
|
||||
new_profile.blooper_speed = target.blooper_speed
|
||||
new_profile.blooper_pitch = target.blooper_pitch
|
||||
new_profile.blooper_pitch_range = target.blooper_pitch_range
|
||||
new_profile.eye_color_left = target.eye_color_left
|
||||
new_profile.eye_color_right = target.eye_color_right
|
||||
new_profile.emissive_eyes = target.emissive_eyes
|
||||
@@ -584,12 +588,6 @@
|
||||
new_profile.target_size = target.mob_size
|
||||
//SKYRAT EDIT ADDITION END
|
||||
// Hair and facial hair gradients, alongside their colours.
|
||||
//THE BUBBER EDIT ADDITION BEGIN - Voice Bark
|
||||
new_profile.blooper_id = target.blooper_id
|
||||
new_profile.blooper_pitch = target.blooper_pitch
|
||||
new_profile.blooper_speed = target.blooper_speed
|
||||
new_profile.blooper_pitch_range = target.blooper_pitch_range
|
||||
//THE BUBBER EDIT END
|
||||
// Grab skillchips they have
|
||||
new_profile.skillchips = target.clone_skillchip_list(TRUE)
|
||||
|
||||
@@ -829,6 +827,10 @@
|
||||
user.undershirt_color = chosen_profile.undershirt_color
|
||||
user.socks_color = chosen_profile.socks_color
|
||||
user.bra_color = chosen_profile.bra_color
|
||||
user.blooper = chosen_profile.blooper
|
||||
user.blooper_speed = chosen_profile.blooper_speed
|
||||
user.blooper_pitch = chosen_profile.blooper_pitch
|
||||
user.blooper_pitch_range = chosen_profile.blooper_pitch_range
|
||||
user.emissive_eyes = chosen_profile.emissive_eyes
|
||||
user.dna.mutant_bodyparts = chosen_dna.mutant_bodyparts.Copy()
|
||||
user.dna.body_markings = chosen_dna.body_markings.Copy()
|
||||
@@ -970,13 +972,6 @@
|
||||
//this has to be at the end of the proc or it breaks everything below it, womp womp
|
||||
user.set_mob_height(chosen_profile.target_body_scaling)
|
||||
// SKYRAT EDIT END
|
||||
//THE BUBBER EDIT ADDITION BEGIN - Voice Bark
|
||||
user.blooper = null
|
||||
user.blooper_id = chosen_profile.blooper_id
|
||||
user.blooper_pitch = chosen_profile.blooper_pitch
|
||||
user.blooper_speed = chosen_profile.blooper_speed
|
||||
user.blooper_pitch_range = chosen_profile.blooper_pitch_range
|
||||
//THE BUBBER EDIT END
|
||||
// Changeling profile themselves. Store a data to store what every DNA instance looked like.
|
||||
/datum/changeling_profile
|
||||
/// The name of the profile / the name of whoever this profile source.
|
||||
@@ -1075,6 +1070,10 @@
|
||||
new_profile.socks_color = socks_color
|
||||
new_profile.bra = bra
|
||||
new_profile.bra_color = bra_color
|
||||
new_profile.blooper = blooper
|
||||
new_profile.blooper_speed = blooper_speed
|
||||
new_profile.blooper_pitch = blooper_pitch
|
||||
new_profile.blooper_pitch_range = blooper_pitch_range
|
||||
new_profile.eye_color_left = eye_color_left
|
||||
new_profile.eye_color_right = eye_color_right
|
||||
new_profile.emissive_eyes = emissive_eyes
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
name = "cybernetic brain"
|
||||
desc = "A mechanical brain found inside of androids. Not to be confused with a positronic brain."
|
||||
icon_state = "brain-c"
|
||||
organ_flags = ORGAN_ROBOTIC | ORGAN_VITAL
|
||||
organ_flags = ORGAN_ROBOTIC | ORGAN_VITAL | ORGAN_PROMINENT //BUBBER EDIT - Added ORGAN_PROMINENT
|
||||
failing_desc = "seems to be broken, and will not work without repairs."
|
||||
shade_color = null
|
||||
var/emp_dmg_mult = 1 //BUBBER EDIT - Variable multiplier for damage from EMPs. Note the base damage is 20.
|
||||
var/emp_dmg_max = 999 ///BUBBER EDIT - Threshold before the organ simply stops taking damage from EMPs. Defaults to kill
|
||||
|
||||
|
||||
/* BUBBER EDIT - Reformatted this to change text based on flags
|
||||
/obj/item/organ/brain/cybernetic/brain_damage_examine()
|
||||
if(suicided)
|
||||
return span_info("Its circuitry is smoking slightly. They must not have been able to handle the stress of it all.")
|
||||
@@ -21,9 +21,57 @@
|
||||
return span_info("You can feel the small spark of life still left in this one.")
|
||||
else
|
||||
return span_info("This one is completely devoid of life.")
|
||||
*/
|
||||
//BUBBER EDIT - See above
|
||||
/obj/item/organ/brain/cybernetic/brain_damage_examine()
|
||||
|
||||
var/is_organic = (organ_flags & ORGAN_ORGANIC) //this determines if it'll print the organic or cybernetic texts
|
||||
|
||||
if(suicided)
|
||||
return span_info("Its circuitry is smoking slightly. They must not have been able to handle the stress of it all.")
|
||||
if(brainmob && (decoy_override || brainmob.client || brainmob.get_ghost()))
|
||||
if(organ_flags & ORGAN_FAILING)
|
||||
return span_info("It seems to still have a bit of energy within it, but it's rather damaged... You may be able to repair it with [is_organic ? "some <b>mannitol</b> or " : ""]a <b>multitool</b>.")
|
||||
else if(damage >= BRAIN_DAMAGE_DEATH*0.5)
|
||||
return span_info("You can feel the small spark of life still left in this one, but it's got some dents. You may be able to restore it with [is_organic ? "some <b>mannitol</b> or " : ""]a <b>multitool</b>.")
|
||||
else
|
||||
return span_info("You can feel the small spark of life still left in this one.")
|
||||
else
|
||||
return span_info("This one is completely devoid of life.")
|
||||
// EDIT END
|
||||
|
||||
/* BUBBER EDIT - Expands this proc for hybrid brain_size.
|
||||
ORIGINAL:
|
||||
/obj/item/organ/brain/cybernetic/check_for_repair(obj/item/item, mob/user)
|
||||
if (item.tool_behaviour == TOOL_MULTITOOL) //attempt to repair the brain
|
||||
if (brainmob?.health <= HEALTH_THRESHOLD_DEAD) //if the brain is fucked anyway, do nothing
|
||||
to_chat(user, span_warning("[src] is far too damaged, there's nothing else we can do for it!"))
|
||||
return TRUE
|
||||
if (DOING_INTERACTION(user, src))
|
||||
to_chat(user, span_warning("you're already repairing [src]!"))
|
||||
return TRUE
|
||||
user.visible_message(span_notice("[user] slowly starts to repair [src] with [item]."), span_notice("You slowly start to repair [src] with [item]."))
|
||||
var/did_repair = FALSE
|
||||
while(damage > 0)
|
||||
if(item.use_tool(src, user, 3 SECONDS, volume = 50))
|
||||
did_repair = TRUE
|
||||
set_organ_damage(max(0, damage - 20))
|
||||
else
|
||||
break
|
||||
if (did_repair)
|
||||
if (damage > 0)
|
||||
user.visible_message(span_notice("[user] partially repairs [src] with [item]."), span_notice("You partially repair [src] with [item]."))
|
||||
else
|
||||
user.visible_message(span_notice("[user] fully repairs [src] with [item], causing its warning light to stop flashing."), span_notice("You fully repair [src] with [item], causing its warning light to stop flashing."))
|
||||
else
|
||||
to_chat(user, span_warning("You failed to repair [src] with [item]!"))
|
||||
return TRUE
|
||||
return FALSE
|
||||
EDIT END */
|
||||
|
||||
// EDITED:
|
||||
/obj/item/organ/brain/cybernetic/check_for_repair(obj/item/item, mob/user)
|
||||
if (item.tool_behaviour == TOOL_MULTITOOL && (organ_flags & ORGAN_ROBOTIC)) //robotic repair option
|
||||
if (brainmob?.health <= HEALTH_THRESHOLD_DEAD) //if the brain is fucked anyway, do nothing
|
||||
to_chat(user, span_warning("[src] is far too damaged, there's nothing else we can do for it!"))
|
||||
return TRUE
|
||||
@@ -50,6 +98,23 @@
|
||||
to_chat(user, span_warning("You failed to repair [src] with [item]!"))
|
||||
|
||||
return TRUE
|
||||
else if(damage && item.is_drainable() && item.reagents.has_reagent(/datum/reagent/medicine/mannitol) && (organ_flags & ORGAN_ORGANIC)) //ganic repair option (this is for the cortical children)
|
||||
if(brainmob?.health <= HEALTH_THRESHOLD_DEAD) //if the brain is fucked anyway, do nothing
|
||||
to_chat(user, span_warning("[src] is far too damaged, there's nothing else we can do for it!"))
|
||||
return TRUE
|
||||
|
||||
user.visible_message(span_notice("[user] starts to slowly pour the contents of [item] onto [src]."), span_notice("You start to slowly pour the contents of [item] onto [src]."))
|
||||
if(!do_after(user, 3 SECONDS, src))
|
||||
to_chat(user, span_warning("You failed to pour the contents of [item] onto [src]!"))
|
||||
return TRUE
|
||||
var/and_bright_shade = !shade_color ? "" : " and turn a slightly brighter shade of [shade_color]"
|
||||
user.visible_message(span_notice("[user] pours the contents of [item] onto [src], causing it to reform its original shape[and_bright_shade]."), span_notice("You pour the contents of [item] onto [src], causing it to reform its original shape[and_bright_shade]."))
|
||||
var/amount = item.reagents.get_reagent_amount(/datum/reagent/medicine/mannitol)
|
||||
var/healto = max(0, damage - amount * 2)
|
||||
item.reagents.remove_all(ROUND_UP(item.reagents.total_volume / amount * (damage - healto) * 0.5)) //only removes however much solution is needed while also taking into account how much of the solution is mannitol
|
||||
set_organ_damage(healto) //heals 2 damage per unit of mannitol, and by using "set_organ_damage", we clear the failing variable if that was up
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
|
||||
/obj/item/organ/brain/cybernetic/emp_act(severity)
|
||||
|
||||
@@ -1895,6 +1895,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
|
||||
|
||||
to_add += create_pref_liver_perks()
|
||||
to_add += create_pref_lung_perks()
|
||||
to_add += create_pref_brain_perks() //BUBBER EDIT - We got brain stuff
|
||||
|
||||
return to_add
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,17 @@
|
||||
# Vocal Bloopers
|
||||
|
||||
By default, no vocal bloopers are included in the repository, a sample config file is provided to demonstrate the format used.
|
||||
To set things up, copy `blooper_config.json.example` and rename it to `blooper_config.json`, then add an entry for each blooper.
|
||||
|
||||
## Config Format
|
||||
|
||||
- name: Required, the user-friendly name of the voice, will be shown in the config menu
|
||||
- id: Required, an internal ID for the voice, must be unique
|
||||
- files: Required, a JSON array of audio file names, relative to the bloopers directory.
|
||||
If there's more than one entry, a file is randomly chosen each time the user speaks
|
||||
- min_speed: Optional, the minimum value the user can set for the voice speed
|
||||
- max_speed: Optional, the maximum value the user can set for the voice speed
|
||||
- min_pitch: Optional, the minimum value the user can set for the voice pitch
|
||||
- max_pitch: Optional, the maximum value the user can set for the voice pitch
|
||||
- min_vary: Optional, the minimum value the user can set for the voice pitch variance
|
||||
- max_vary: Optional, the maximum value the user can set for the voice pitch variance
|
||||
@@ -0,0 +1,13 @@
|
||||
[
|
||||
{
|
||||
"name": "Example Blooper",
|
||||
"id": "example",
|
||||
"files": ["example.ogg"],
|
||||
"min_speed": 2,
|
||||
"max_speed": 16,
|
||||
"min_pitch": 0.4,
|
||||
"max_pitch": 2,
|
||||
"min_vary": 0.1,
|
||||
"max_vary": 0.8
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,12 @@
|
||||
author: "aKromatopzia"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscadd: "Previously-unobtainable surplus-cybernetic brain added to Prosthetic Organ quirk"
|
||||
- rscadd: "Cybernetic brains given the ORGAN_PROMINENT trait, following normal brains."
|
||||
- rscadd: "Vox Primalis unique cybernetic brain has been finally added to their species descriptions. (Bet you didn't know they had one)"
|
||||
- balance: "(Roundstart) Cortical brains given ORGAN_ORGANIC, so they can be fixed with both mannitol and a multitool. Vox brains are excluded"
|
||||
- balance: "Brain options in character prefs have been given a 1 quirkiness-point cost."
|
||||
- bugfix: "Cybernetic/Cortical brains have their repair hints updated to reflect what they can actually be repaired by"
|
||||
- code_imp: "Prosthetic Organ quirk moved to modular_zubbers"
|
||||
- code_imp: "'Vox Primalis' now considered a collective noun"
|
||||
- code_imp: "dangerous_organ_removal has a new variable to toggle between organ qdel or having its damage set to max health."
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "BingusTheClown"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "IPC's no longer have an error when customizing their look with a screen."
|
||||
@@ -24,3 +24,28 @@
|
||||
shayoki:
|
||||
- qol: Non-evolved dense organ tissues in Medical Cytology require Saline-Glucose
|
||||
Solution instead of Organ Tissue.
|
||||
2026-03-07:
|
||||
BingusTheClown:
|
||||
- bugfix: IPC's no longer have an error when customizing their look with a screen.
|
||||
MrGloopy:
|
||||
- rscadd: Recolouring for moth eyes. You will have to set new colours in character
|
||||
preferences.
|
||||
- bugfix: HUD implants not displaying on moth eyes
|
||||
- bugfix: De-spookified moths that have had their eyes replaced. (Fixed moth eyes
|
||||
disappearing when replaced with anything else, rendering your sprite eyeless
|
||||
until your original eyes were put back in).
|
||||
Yobrocharlie:
|
||||
- rscadd: Added a new gateway for admins to fuck around with.
|
||||
2026-03-08:
|
||||
xPokee:
|
||||
- rscadd: Added new zombie markings.
|
||||
xPokee, LT3, TealSeer:
|
||||
- refactor: Refactored vocal bloopers to be a config based subsystem.
|
||||
- config: Added all the previous vocal bloopers to the new config, as well as some
|
||||
new ones, look for them!
|
||||
2026-03-09:
|
||||
BurgerBB:
|
||||
- map: Makes Moon Station Botany better.
|
||||
ibexgoetia:
|
||||
- rscadd: Nanotrasen Consultants and Heads of Personnel may rejoice the presence
|
||||
of a Paperwork Implant autosurgeon in their lockers.
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/proc/make_skyrat_datum_references()
|
||||
init_prefs_emotes()
|
||||
make_bloopers()
|
||||
make_default_mutant_bodypart_references()
|
||||
make_body_marking_references()
|
||||
make_body_marking_set_references()
|
||||
@@ -181,12 +180,3 @@
|
||||
continue
|
||||
|
||||
SSaccessories.bra_m -= sprite_name
|
||||
|
||||
// Text bloopers
|
||||
/proc/make_bloopers()
|
||||
GLOB.blooper_list = list()
|
||||
for(var/sound_blooper_path in subtypesof(/datum/blooper))
|
||||
var/datum/blooper/bloop = new sound_blooper_path()
|
||||
GLOB.blooper_list[bloop.id] = sound_blooper_path
|
||||
if(bloop.allow_random)
|
||||
GLOB.blooper_random_list[bloop.id] = sound_blooper_path
|
||||
|
||||
@@ -36,11 +36,14 @@
|
||||
//BRAINS
|
||||
/datum/augment_item/organ/brain
|
||||
slot = AUGMENT_SLOT_BRAIN
|
||||
cost = 1 // while a sidegrade, there are genuine applications for having a vanilla brain
|
||||
|
||||
/datum/augment_item/organ/brain/cortical
|
||||
name = "Cortically-Augmented Brain"
|
||||
slot = AUGMENT_SLOT_BRAIN
|
||||
path = /obj/item/organ/brain/cybernetic/cortical
|
||||
cost = 1 // technically a downgrade in most applications, but has uses.
|
||||
|
||||
//EDIT END
|
||||
|
||||
//HEARTS
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/datum/species/vox
|
||||
// Bird-like humanoids
|
||||
name = "Vox Primalis"
|
||||
plural_form = "Vox Primalis"
|
||||
id = SPECIES_VOX
|
||||
can_augment = FALSE
|
||||
inherent_traits = list(
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
//The accessible cybernetic brain
|
||||
/obj/item/organ/brain/cybernetic/cortical
|
||||
name = "cortically-augmented brain"
|
||||
desc = "A brain which has been in some part mechanized."
|
||||
desc = "A brain which has been, in some part, mechanized."
|
||||
icon = 'modular_skyrat/master_files/icons/obj/medical/organs/organs.dmi'
|
||||
icon_state = "brain-c"
|
||||
organ_flags = ORGAN_ORGANIC | ORGAN_ROBOTIC | ORGAN_VITAL | ORGAN_PROMINENT //it's a bit weird to be both organic and robotic, but yk
|
||||
emp_dmg_mult = 1.5 //Note that the base damage is 20/10
|
||||
emp_dmg_max = 150
|
||||
|
||||
@@ -26,30 +27,23 @@
|
||||
owner.adjust_stutter(15 SECONDS)
|
||||
owner.adjust_confusion(3 SECONDS)
|
||||
|
||||
|
||||
// It's still organic
|
||||
/obj/item/organ/brain/cybernetic/cortical/brain_damage_examine()
|
||||
if(suicided)
|
||||
return span_info("Its circuitry is smoking slightly. They must not have been able to handle the stress of it all.")
|
||||
if(brainmob && (decoy_override || brainmob.client || brainmob.get_ghost()))
|
||||
if(organ_flags & ORGAN_FAILING)
|
||||
return span_info("It seems to still have a bit of energy within it, but it's rather damaged... You may be able to restore it with some <b>mannitol</b>.")
|
||||
else if(damage >= BRAIN_DAMAGE_DEATH*0.5)
|
||||
return span_info("You can feel the small spark of life still left in this one, but it's got some bruises. You may be able to restore it with some <b>mannitol</b>.")
|
||||
else
|
||||
return span_info("You can feel the small spark of life still left in this one.")
|
||||
else
|
||||
return span_info("This one is completely devoid of life.")
|
||||
|
||||
//New vox Brain
|
||||
/obj/item/organ/brain/cybernetic/cortical/vox
|
||||
name = "vox-augmented brain"
|
||||
desc = "A brain which has been in some part mechanized. The components are seamlessly integrated into the flesh."
|
||||
emp_dmg_mult = 1 //Nobody notices the brain damage anyways wink wink
|
||||
desc = "A brain which has been in some part mechanized. The components are seamlessly integrated into the flesh, which protect that grey matter from biological processes."
|
||||
organ_flags = ORGAN_ROBOTIC | ORGAN_VITAL | ORGAN_PROMINENT //Vox brains weren't organic originally. See no reason to change it
|
||||
emp_dmg_mult = 1 //20/10 is the voxs' original damage factor
|
||||
|
||||
//surplus; TBI to prosthetic organ quirk
|
||||
/obj/item/organ/brain/cybernetic/cortical/surplus
|
||||
//surplus; Used in prosthetic organ quirk
|
||||
//note that this is a direct child of the android brain, and is thus not organic
|
||||
/obj/item/organ/brain/cybernetic/surplus
|
||||
name = "surplus augmented brain"
|
||||
desc = "A brain which has been in some part mechanized. It looks a bit cheap."
|
||||
maxHealth = BRAIN_DAMAGE_DEATH*0.5 //200 -> 100, at time of creation
|
||||
desc = "A mostly-mechanized brain. Not much of the flesh remains. Does this make them an IPC? "
|
||||
maxHealth = BRAIN_DAMAGE_DEATH*0.75 //200 -> 150, per original intention
|
||||
emp_dmg_mult = 1.5 //Note that the base damage is 20/10
|
||||
emp_dmg_max = 999
|
||||
|
||||
/obj/item/organ/brain/cybernetic/surplus/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/dangerous_organ_removal, /*surgical = */ TRUE, /*annihilate = */ FALSE) //annihilate just means it wont qdel when removed
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
#define BLOOPER_CONFIG_PATH "[global.config.directory]/bloopers"
|
||||
|
||||
SUBSYSTEM_DEF(blooper)
|
||||
name = "Blooper"
|
||||
flags = SS_NO_FIRE | SS_NO_INIT
|
||||
|
||||
var/list/blooper_list
|
||||
|
||||
/datum/controller/subsystem/blooper/OnConfigLoad()
|
||||
blooper_list = initialize_blooper_datums()
|
||||
|
||||
/datum/controller/subsystem/blooper/proc/initialize_blooper_datums()
|
||||
var/list/blooper_datums = list()
|
||||
if(!rustg_file_exists("[BLOOPER_CONFIG_PATH]/blooper_config.json"))
|
||||
logger.Log(LOG_CATEGORY_DEBUG, "blooper_config.json not found.")
|
||||
return blooper_datums
|
||||
var/list/blooper_entries = safe_json_decode(rustg_file_read("[BLOOPER_CONFIG_PATH]/blooper_config.json"))
|
||||
if(isnull(blooper_entries))
|
||||
stack_trace("Blooper config is malformed!")
|
||||
return blooper_datums
|
||||
for(var/entry in blooper_entries)
|
||||
// These fields are required
|
||||
if(isnull(entry["name"]) || isnull(entry["id"]) || isnull(entry["files"]) || !length(entry["files"]))
|
||||
stack_trace("Blooper config entry was missing required field!")
|
||||
continue
|
||||
var/datum/blooper/new_blooper = new()
|
||||
new_blooper.name = entry["name"]
|
||||
new_blooper.id = entry["id"]
|
||||
for(var/file in entry["files"])
|
||||
new_blooper.soundpath_list += sound("[BLOOPER_CONFIG_PATH]/[file]")
|
||||
new_blooper.min_pitch = entry["min_pitch"] || BLOOPER_DEFAULT_MINPITCH
|
||||
new_blooper.max_pitch = entry["max_pitch"] || BLOOPER_DEFAULT_MAXPITCH
|
||||
new_blooper.min_vary = entry["min_vary"] || BLOOPER_DEFAULT_MINVARY
|
||||
new_blooper.max_vary = entry["max_vary"] || BLOOPER_DEFAULT_MAXVARY
|
||||
new_blooper.min_speed = entry["min_speed"] || BLOOPER_DEFAULT_MINSPEED
|
||||
new_blooper.max_speed = entry["max_speed"] || BLOOPER_DEFAULT_MAXSPEED
|
||||
blooper_datums[new_blooper.id] = new_blooper
|
||||
return blooper_datums
|
||||
|
||||
#undef BLOOPER_CONFIG_PATH
|
||||
@@ -0,0 +1,63 @@
|
||||
/datum/blooper
|
||||
/// User friendly name of the blooper, displayed in preferences menu
|
||||
var/name = null
|
||||
/// Internal ID of blooper, must be unique
|
||||
var/id = null
|
||||
/// List of sounds, one is chosen randomly each time the blooper is played
|
||||
var/list/sound/soundpath_list = list()
|
||||
|
||||
var/min_pitch = BLOOPER_DEFAULT_MINPITCH
|
||||
var/max_pitch = BLOOPER_DEFAULT_MAXPITCH
|
||||
var/min_vary = BLOOPER_DEFAULT_MINVARY
|
||||
var/max_vary = BLOOPER_DEFAULT_MAXVARY
|
||||
|
||||
// Speed vars. Speed determines the number of characters required for each blooper, with lower speeds being faster with higher blooper density
|
||||
var/min_speed = BLOOPER_DEFAULT_MINSPEED
|
||||
var/max_speed = BLOOPER_DEFAULT_MAXSPEED
|
||||
|
||||
/**
|
||||
* Plays the vocal blooper for all listeners, duration is controlled by length of the message argument
|
||||
* * speaker - Origin source of the blooper, used for 3D audio calculations and to set the cooldown
|
||||
* * listeners - List of mobs that will hear the blooper
|
||||
* * message - Chat message being sent, used to determine how long bloopers play for (longer message, more sounds)
|
||||
* * distance - Range at which the sounds will be heard
|
||||
* * volume - Volume the sounds will play at
|
||||
* * speed - How fast the bloopers will be, percentage between 0 - 100, converted and clamped to datum's min/max values
|
||||
* * pitch - How high-pitched the bloopers will be, percentage between 0 - 100, converted and clamped to datum's min/max values
|
||||
* * pitch_range - Amount of pitch variance for each blooper, percentage between 0 - 100, converted and clamped to datum's max/min values
|
||||
*/
|
||||
/datum/blooper/proc/play_bloop(atom/movable/speaker, list/listeners, message, distance, volume, speed, pitch, pitch_range)
|
||||
if(!COOLDOWN_FINISHED(speaker, blooper_cooldown))
|
||||
return
|
||||
volume = min(volume, 100)
|
||||
// convert passed values (which are percentages) into value clamped between min and max of blooper datum
|
||||
speed = round(min_speed + ((max_speed - min_speed) * ((100 - speed) / 100)), 0.01) // this one gets inverted because lower % = faster isn't intuitive
|
||||
pitch = round(min_pitch + ((max_pitch - min_pitch) * (pitch / 100)), 0.01)
|
||||
pitch_range = round(min_vary + ((max_vary - min_vary) * (pitch_range / 100)), 0.01)
|
||||
for(var/mob/target_mob in listeners)
|
||||
if(target_mob.client && !(target_mob.client.prefs.read_preference(/datum/preference/toggle/hear_blooper)))
|
||||
listeners -= target_mob
|
||||
var/sound/blooper_pick = pick(soundpath_list)
|
||||
var/num_bloopers = min(round(length(message) / speed, 1) + 1, BLOOPER_MAX_BLOOPERS)
|
||||
var/total_delay = 0
|
||||
for(var/i in 1 to num_bloopers)
|
||||
if(total_delay > BLOOPER_MAX_TIME)
|
||||
break
|
||||
addtimer(CALLBACK(src, PROC_REF(play_callback), speaker, listeners, distance, volume, BLOOPER_DO_VARY(pitch, pitch_range), blooper_pick), total_delay)
|
||||
total_delay += rand(DS2TICKS(speed / BLOOPER_SPEED_BASELINE), DS2TICKS(speed / BLOOPER_SPEED_BASELINE) + DS2TICKS(speed / BLOOPER_SPEED_BASELINE)) TICKS
|
||||
COOLDOWN_START(speaker, blooper_cooldown, total_delay)
|
||||
|
||||
/// Private callback function to actually play the sound, used for timers scheduled in play_bloop
|
||||
/datum/blooper/proc/play_callback(atom/movable/speaker, list/listeners, distance, volume, pitch, sound/voice)
|
||||
PRIVATE_PROC(TRUE)
|
||||
for(var/mob/target_mob in listeners)
|
||||
target_mob.playsound_local(
|
||||
turf_source = get_turf(speaker),
|
||||
soundin = voice,
|
||||
vol = volume,
|
||||
vary = TRUE,
|
||||
frequency = pitch,
|
||||
falloff_distance = 0,
|
||||
falloff_exponent = BLOOPER_SOUND_FALLOFF_EXPONENT,
|
||||
max_distance = distance,
|
||||
)
|
||||
@@ -0,0 +1,102 @@
|
||||
/datum/quirk/prosthetic_organ
|
||||
name = "Prosthetic Organ"
|
||||
desc = "An accident caused you to lose one of your organs. Because of this, you now have a surplus prosthetic!"
|
||||
icon = FA_ICON_LUNGS
|
||||
value = -3
|
||||
medical_record_text = "During physical examination, patient was found to have a low-budget prosthetic organ. \
|
||||
<b>Removal of these organs is known to be dangerous to the patient as well as the practitioner.</b>"
|
||||
hardcore_value = 3
|
||||
mail_goodies = list(/obj/item/storage/organbox)
|
||||
/// The slot to replace, in string form
|
||||
var/slot_string = "organ"
|
||||
/// The original organ from before the prosthetic was applied
|
||||
var/obj/item/organ/old_organ
|
||||
|
||||
/datum/quirk_constant_data/prosthetic_organ
|
||||
associated_typepath = /datum/quirk/prosthetic_organ
|
||||
customization_options = list(/datum/preference/choiced/prosthetic_organ)
|
||||
|
||||
/datum/quirk/prosthetic_organ/add_unique(client/client_source)
|
||||
var/mob/living/carbon/human/human_holder = quirk_holder
|
||||
var/static/list/organ_slots = list(
|
||||
ORGAN_SLOT_HEART,
|
||||
ORGAN_SLOT_LUNGS,
|
||||
ORGAN_SLOT_LIVER,
|
||||
ORGAN_SLOT_STOMACH,
|
||||
ORGAN_SLOT_BRAIN,
|
||||
)
|
||||
var/preferred_organ = GLOB.organ_choice[client_source?.prefs?.read_preference(/datum/preference/choiced/prosthetic_organ)]
|
||||
if(isnull(preferred_organ)) //Client is gone or they chose a random prosthetic
|
||||
preferred_organ = GLOB.organ_choice[pick(GLOB.organ_choice)]
|
||||
|
||||
var/list/possible_organ_slots = organ_slots.Copy()
|
||||
if(!CAN_HAVE_BLOOD(human_holder))
|
||||
possible_organ_slots -= ORGAN_SLOT_HEART
|
||||
if(HAS_TRAIT(human_holder, TRAIT_NOBREATH))
|
||||
possible_organ_slots -= ORGAN_SLOT_LUNGS
|
||||
if(HAS_TRAIT(human_holder, TRAIT_LIVERLESS_METABOLISM))
|
||||
possible_organ_slots -= ORGAN_SLOT_LIVER
|
||||
if(HAS_TRAIT(human_holder, TRAIT_NOHUNGER))
|
||||
possible_organ_slots -= ORGAN_SLOT_STOMACH
|
||||
if(HAS_TRAIT(human_holder, TRAIT_BRAINLESS_CARBON))
|
||||
possible_organ_slots -= ORGAN_SLOT_BRAIN
|
||||
if(!length(organ_slots)) //what the hell
|
||||
return
|
||||
|
||||
var/organ_slot = pick(possible_organ_slots)
|
||||
if(preferred_organ in possible_organ_slots)
|
||||
organ_slot = preferred_organ
|
||||
var/obj/item/organ/prosthetic
|
||||
switch(organ_slot)
|
||||
if(ORGAN_SLOT_HEART)
|
||||
prosthetic = new /obj/item/organ/heart/cybernetic/surplus
|
||||
slot_string = "heart"
|
||||
if(ORGAN_SLOT_LUNGS)
|
||||
prosthetic = new /obj/item/organ/lungs/cybernetic/surplus
|
||||
slot_string = "lungs"
|
||||
if(ORGAN_SLOT_LIVER)
|
||||
prosthetic = new /obj/item/organ/liver/cybernetic/surplus
|
||||
slot_string = "liver"
|
||||
if(ORGAN_SLOT_STOMACH)
|
||||
prosthetic = new /obj/item/organ/stomach/cybernetic/surplus
|
||||
slot_string = "stomach"
|
||||
if(ORGAN_SLOT_BRAIN)
|
||||
prosthetic = new /obj/item/organ/brain/cybernetic/surplus
|
||||
slot_string = "brain"
|
||||
medical_record_text = "During physical examination, patient was found to have a low-budget prosthetic [slot_string]. \
|
||||
Removal of these organs is known to be dangerous to the patient as well as the practitioner."
|
||||
old_organ = human_holder.get_organ_slot(organ_slot)
|
||||
prosthetic.Insert(human_holder, special = TRUE)
|
||||
old_organ.moveToNullspace()
|
||||
STOP_PROCESSING(SSobj, old_organ)
|
||||
|
||||
/datum/quirk/prosthetic_organ/post_add()
|
||||
to_chat(quirk_holder, span_bolddanger("Your [slot_string] has been replaced with a surplus organ. It is weak and highly unstable. \
|
||||
Additionally, any EMP will make it cease full functions for a time."))
|
||||
|
||||
/datum/quirk/prosthetic_organ/remove()
|
||||
var/mob/living/carbon/human/human_holder = quirk_holder
|
||||
if(old_organ)
|
||||
if(old_organ.slot == AUGMENT_SLOT_BRAIN) //there's no way this works again
|
||||
|
||||
var/obj/item/organ/brain/current_brain = human_holder.get_organ_slot(ORGAN_SLOT_BRAIN)
|
||||
var/obj/item/organ/brain/insert_brain = old_organ //less confusing name
|
||||
|
||||
var/datum/mind/holder_mind = human_holder.mind
|
||||
|
||||
insert_brain.modular_persistence = current_brain.modular_persistence
|
||||
insert_brain.modular_persistence?.owner = insert_brain
|
||||
current_brain.modular_persistence = null
|
||||
|
||||
insert_brain.copy_traits_from(current_brain)
|
||||
insert_brain.Insert(human_holder, special = TRUE)
|
||||
current_brain.moveToNullspace() // Maybe this works also lmao
|
||||
STOP_PROCESSING(SSobj, current_brain)
|
||||
|
||||
if(!holder_mind)
|
||||
return
|
||||
|
||||
holder_mind.transfer_to(human_holder, TRUE)
|
||||
else
|
||||
old_organ.Insert(quirk_holder, special = TRUE)
|
||||
old_organ = null
|
||||
@@ -0,0 +1,15 @@
|
||||
/atom/movable
|
||||
// Text-to-blooper sounds
|
||||
// yes. all atoms can have a say.
|
||||
var/datum/blooper/blooper
|
||||
var/blooper_speed = 50
|
||||
var/blooper_pitch = 50
|
||||
var/blooper_pitch_range = 50 //Actual pitch is (pitch - (blooper_pitch_range*0.5)) to (pitch + (blooper_pitch_range*0.5))
|
||||
COOLDOWN_DECLARE(blooper_cooldown)
|
||||
|
||||
/atom/movable/send_speech(message, range = 7, obj/source = src, bubble_type, list/spans, datum/language/message_language, list/message_mods = list(), forced = FALSE, tts_message, list/tts_filter)
|
||||
. = ..()
|
||||
if(!blooper)
|
||||
return
|
||||
var/list/listeners = get_hearers_in_view(range, source)
|
||||
blooper.play_bloop(source, listeners, message, range, BLOOPER_TRANSMIT_VOLUME, blooper_speed, blooper_pitch, blooper_pitch_range)
|
||||
@@ -264,7 +264,6 @@
|
||||
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)
|
||||
|
||||
// plushie for BeoTheKobold
|
||||
// sprite by Cepha, code by Mitryll
|
||||
|
||||
@@ -6,3 +6,8 @@
|
||||
. = ..()
|
||||
new /obj/item/stamp/granted(src)
|
||||
new /obj/item/stamp/denied(src)
|
||||
new /obj/item/autosurgeon/paperwork(src)
|
||||
|
||||
/obj/structure/closet/secure_closet/nanotrasen_consultant/PopulateContents()
|
||||
. = ..()
|
||||
new /obj/item/autosurgeon/paperwork(src)
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
/datum/changeling_profile
|
||||
/// The blooper voice used by the profile source
|
||||
var/datum/blooper/blooper
|
||||
/// The blooper speed used by the profile source
|
||||
var/blooper_speed
|
||||
/// The blooper pitch used by the profile source
|
||||
var/blooper_pitch
|
||||
/// The blooper pitch range used by the profile source
|
||||
var/blooper_pitch_range
|
||||
@@ -1,109 +0,0 @@
|
||||
/* Originally written by Bhijn & Myr on Citadel[1], with various other contributions since- see the Splurt & Citadel github for a full list of contributors.
|
||||
It has also been further modified by Rashcat & other Fluffyfrontier contributors on Fluffy Frontier!
|
||||
[1]https://github.com/Citadel-Station-13/Citadel-Station-13/pull/15677
|
||||
*/
|
||||
/atom/movable
|
||||
// Text-to-blooper sounds
|
||||
// yes. all atoms can have a say.
|
||||
var/sound/blooper
|
||||
var/blooper_id
|
||||
var/blooper_pitch = 1
|
||||
var/blooper_pitch_range = 0.2 //Actual pitch is (pitch - (blooper_pitch_range*0.5)) to (pitch + (blooper_pitch_range*0.5))
|
||||
var/blooper_volume = 50
|
||||
var/blooper_speed = 4 //Lower values are faster, higher values are slower
|
||||
var/blooper_current_blooper //When bloopers are queued, this gets passed to the blooper proc. If blooper_current_blooper doesn't match the args passed to the blooper proc (if passed at all), then the blooper simply doesn't play. Basic curtailing of spam~
|
||||
|
||||
/atom/movable/proc/set_blooper(id)
|
||||
if(!id)
|
||||
return FALSE
|
||||
var/datum/blooper/B = GLOB.blooper_list[id]
|
||||
if(!B)
|
||||
return FALSE
|
||||
blooper = sound(initial(B.soundpath))
|
||||
blooper_id = id
|
||||
return blooper
|
||||
|
||||
/atom/movable/proc/blooper(list/listeners, distance, volume, pitch, queue_time)
|
||||
if(!GLOB.blooper_allowed)
|
||||
return
|
||||
if(queue_time && blooper_current_blooper != queue_time)
|
||||
return
|
||||
if(!blooper)
|
||||
if(!blooper_id || !set_blooper(blooper_id)) //just-in-time blooper generation
|
||||
return
|
||||
volume = min(volume, 100)
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/mob/M in listeners)
|
||||
M.playsound_local(T, vol = volume, vary = TRUE, frequency = pitch, max_distance = distance, falloff_distance = 0, falloff_exponent = BLOOPER_SOUND_FALLOFF_EXPONENT, sound_to_use = blooper, distance_multiplier = 1)
|
||||
|
||||
/atom/movable/send_speech(message, range = 7, obj/source = src, bubble_type, list/spans, datum/language/message_language, list/message_mods = list(), forced = FALSE, tts_message, list/tts_filter)
|
||||
. = ..()
|
||||
var/list/listeners = get_hearers_in_view(range, source)
|
||||
if(blooper || blooper_id)
|
||||
for(var/mob/M in listeners)
|
||||
if(!M.client)
|
||||
continue
|
||||
if(!(M.client.prefs?.read_preference(/datum/preference/toggle/hear_sound_blooper)))
|
||||
listeners -= M
|
||||
var/bloopers = min(round((LAZYLEN(message) / blooper_speed)) + 1, BLOOPER_MAX_BLOOPERS)
|
||||
var/total_delay
|
||||
blooper_current_blooper = world.time //this is juuuuust random enough to reliably be unique every time send_speech() is called, in most scenarios
|
||||
for(var/i in 1 to bloopers)
|
||||
if(total_delay > BLOOPER_MAX_TIME)
|
||||
break
|
||||
addtimer(CALLBACK(src, PROC_REF(blooper), listeners, range, blooper_volume, BLOOPER_DO_VARY(blooper_pitch, blooper_pitch_range), blooper_current_blooper), total_delay)
|
||||
total_delay += rand(DS2TICKS(blooper_speed / BLOOPER_SPEED_BASELINE), DS2TICKS(blooper_speed / BLOOPER_SPEED_BASELINE) + DS2TICKS(blooper_speed / BLOOPER_SPEED_BASELINE)) TICKS
|
||||
|
||||
/mob/living/carbon/human/Initialize(mapload)
|
||||
. = ..()
|
||||
// This gives a random vocal bark to a random created person
|
||||
if(!client)
|
||||
set_blooper(pick(GLOB.blooper_list))
|
||||
blooper_pitch = BLOOPER_PITCH_RAND(gender)
|
||||
blooper_pitch_range = BLOOPER_VARIANCE_RAND
|
||||
blooper_speed = rand(BLOOPER_DEFAULT_MINSPEED, BLOOPER_DEFAULT_MAXSPEED)
|
||||
|
||||
/mob/living/send_speech(message_raw, message_range = 6, obj/source = src, bubble_type = bubble_icon, list/spans, datum/language/message_language = null, list/message_mods = list(), forced = null, tts_message, list/tts_filter)
|
||||
. = ..()
|
||||
|
||||
if(!(client?.prefs.read_preference(/datum/preference/toggle/send_sound_blooper)))
|
||||
return
|
||||
blooper_volume = client?.prefs.read_preference(/datum/preference/numeric/sound_blooper_volume) //volume scales with your volume slider in game preferences.
|
||||
if(HAS_TRAIT(src, TRAIT_SIGN_LANG) && !HAS_TRAIT(src, TRAIT_MUTE)) //if you can speak and you sign, your hands don't make a bark. Unless you are completely mute, you can have some hand bark.
|
||||
return
|
||||
if(message_mods[WHISPER_MODE])
|
||||
blooper_volume = (client?.prefs.read_preference(/datum/preference/numeric/sound_blooper_volume)*0.5) //Whispered barked are half as loud.
|
||||
message_range++
|
||||
var/list/listening = get_hearers_in_view(message_range, source)
|
||||
var/is_yell = (say_test(message_raw) == "2")
|
||||
//Listening gets trimmed here if a blooper blooper's present. If anyone ever makes this proc return listening, make sure to instead initialize a copy of listening in here to avoid wonkiness
|
||||
if(blooper || blooper_id)
|
||||
for(var/mob/M in listening)
|
||||
if(!M.client)
|
||||
continue
|
||||
|
||||
var/tts_pref = M.client.prefs?.read_preference(/datum/preference/choiced/sound_tts)
|
||||
var/hear_blooper = M.client.prefs?.read_preference(/datum/preference/toggle/hear_sound_blooper)
|
||||
|
||||
if(!hear_blooper) // Check pref for blooper
|
||||
listening -= M
|
||||
|
||||
else if (CONFIG_GET(string/tts_http_url) && SStts.tts_enabled == TRUE) // TTS for vocal barks.
|
||||
if (source.voice == "" || source.voice == "None") // "None" is for borgs
|
||||
continue
|
||||
if (tts_pref == TTS_SOUND_OFF)
|
||||
continue
|
||||
listening -= M
|
||||
|
||||
|
||||
|
||||
var/bloopers = min(round((LAZYLEN(message_raw) / blooper_speed)) + 1, BLOOPER_MAX_BLOOPERS)
|
||||
var/total_delay
|
||||
blooper_current_blooper = world.time
|
||||
for(var/i in 1 to bloopers)
|
||||
if(total_delay > BLOOPER_MAX_TIME)
|
||||
break
|
||||
addtimer(CALLBACK(src, TYPE_PROC_REF(/atom/movable, blooper), listening, message_range + 1, (blooper_volume * (is_yell ? 2 : 1)), BLOOPER_DO_VARY(blooper_pitch, blooper_pitch_range), blooper_current_blooper), total_delay) //The function is zero on the seventh tile. This makes it a maximum of 1 more.
|
||||
total_delay += rand(DS2TICKS(blooper_speed / BLOOPER_SPEED_BASELINE), DS2TICKS(blooper_speed / BLOOPER_SPEED_BASELINE) + DS2TICKS((blooper_speed / BLOOPER_SPEED_BASELINE) * (is_yell ? 0.5 : 1))) TICKS
|
||||
|
||||
|
||||
@@ -1,180 +0,0 @@
|
||||
GLOBAL_VAR_INIT(blooper_allowed, TRUE) // For administrators
|
||||
|
||||
// we let borgs have some bark too
|
||||
/mob/living/silicon/Login()
|
||||
// This is the only found function that updates the client for borgs.
|
||||
set_blooper(client.prefs.read_preference(/datum/preference/choiced/blooper))
|
||||
blooper_pitch = client.prefs.read_preference(/datum/preference/numeric/blooper_speech_pitch)
|
||||
blooper_speed = client.prefs.read_preference(/datum/preference/numeric/blooper_speech_speed)
|
||||
blooper_pitch_range = client.prefs.read_preference(/datum/preference/numeric/blooper_pitch_range)
|
||||
. = ..()
|
||||
|
||||
// Mechanics for Changelings
|
||||
/datum/changeling_profile
|
||||
var/blooper_id
|
||||
var/blooper_pitch
|
||||
var/blooper_pitch_range
|
||||
var/blooper_speed
|
||||
|
||||
/datum/smite/normalblooper
|
||||
name = "Normal blooper"
|
||||
|
||||
/datum/smite/normalblooper/effect(client/user, mob/living/carbon/human/target)
|
||||
. = ..()
|
||||
target.blooper = null
|
||||
target.blooper_id = pick(GLOB.blooper_random_list)
|
||||
target.blooper_speed = round((BLOOPER_DEFAULT_MINSPEED + BLOOPER_DEFAULT_MAXSPEED) / 2)
|
||||
target.blooper_pitch = round((BLOOPER_DEFAULT_MINPITCH + BLOOPER_DEFAULT_MAXPITCH) / 2)
|
||||
target.blooper_pitch_range = 0.2
|
||||
|
||||
/datum/admins/proc/toggleblooper()
|
||||
set category = "Server"
|
||||
set desc = "Toggle the annoying voices."
|
||||
set name = "Toggle Vocal Barks"
|
||||
toggle_blooper()
|
||||
log_admin("[key_name(usr)] toggled Voice Barks.")
|
||||
message_admins("[key_name_admin(usr)] toggled Voice Barks.")
|
||||
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Voice Bark", "[GLOB.blooper_allowed ? "Enabled" : "Disabled"]")) // If you are copy-pasting this, ensure the 4th parameter is unique to the new proc!
|
||||
|
||||
/* /world/AVerbsAdmin()
|
||||
. = ..()
|
||||
return . + /datum/admins/proc/toggleblooper */
|
||||
|
||||
/proc/toggle_blooper(toggle = null)
|
||||
if(toggle != null)
|
||||
if(toggle != GLOB.blooper_allowed)
|
||||
GLOB.blooper_allowed = toggle
|
||||
else
|
||||
return
|
||||
else
|
||||
GLOB.blooper_allowed = !GLOB.blooper_allowed
|
||||
to_chat(world, "<span class='oocplain'><B>Vocal barks have been globally [GLOB.blooper_allowed ? "enabled" : "disabled"].</B></span>")
|
||||
|
||||
/datum/preference/choiced/blooper
|
||||
category = PREFERENCE_CATEGORY_NON_CONTEXTUAL
|
||||
savefile_identifier = PREFERENCE_CHARACTER
|
||||
savefile_key = "blooper_speech"
|
||||
|
||||
/datum/preference/choiced/blooper/init_possible_values()
|
||||
return assoc_to_keys(GLOB.blooper_list)
|
||||
|
||||
/datum/preference/choiced/blooper/apply_to_human(mob/living/carbon/human/target, value)
|
||||
target.set_blooper(value)
|
||||
|
||||
/datum/preference/choiced/blooper/compile_constant_data()
|
||||
var/list/data = ..()
|
||||
var/list/display_names = list()
|
||||
for(var/id in GLOB.blooper_list)
|
||||
var/datum/blooper/blooper_path = GLOB.blooper_list[id]
|
||||
display_names[id] = blooper_path::name
|
||||
data[CHOICED_PREFERENCE_DISPLAY_NAMES] = display_names
|
||||
return data
|
||||
|
||||
/datum/preference_middleware/blooper
|
||||
/// Cooldown on requesting a Blooper preview.
|
||||
COOLDOWN_DECLARE(blooper_cooldown)
|
||||
|
||||
action_delegations = list(
|
||||
"play_blooper" = PROC_REF(play_blooper),
|
||||
)
|
||||
|
||||
/datum/preference_middleware/blooper/proc/play_blooper(list/params, mob/user)
|
||||
if(!COOLDOWN_FINISHED(src, blooper_cooldown))
|
||||
return TRUE
|
||||
var/atom/movable/blooperbox = new(get_turf(user))
|
||||
blooperbox.set_blooper(preferences.read_preference(/datum/preference/choiced/blooper))
|
||||
blooperbox.blooper_pitch = preferences.read_preference(/datum/preference/numeric/blooper_speech_pitch)
|
||||
blooperbox.blooper_speed = preferences.read_preference(/datum/preference/numeric/blooper_speech_speed)
|
||||
blooperbox.blooper_pitch_range = preferences.read_preference(/datum/preference/numeric/blooper_pitch_range)
|
||||
var/total_delay
|
||||
for(var/i in 1 to (round((32 / blooperbox.blooper_speed)) + 1))
|
||||
addtimer(CALLBACK(blooperbox, TYPE_PROC_REF(/atom/movable, blooper), list(user), 7, 70, BLOOPER_DO_VARY(blooperbox.blooper_pitch, blooperbox.blooper_pitch_range)), total_delay)
|
||||
total_delay += rand(DS2TICKS(blooperbox.blooper_speed/4), DS2TICKS(blooperbox.blooper_speed/4) + DS2TICKS(blooperbox.blooper_speed/4)) TICKS
|
||||
QDEL_IN(blooperbox, total_delay)
|
||||
COOLDOWN_START(src, blooper_cooldown, 2 SECONDS)
|
||||
return TRUE
|
||||
|
||||
/datum/preference/numeric/blooper_speech_speed
|
||||
category = PREFERENCE_CATEGORY_NON_CONTEXTUAL
|
||||
savefile_identifier = PREFERENCE_CHARACTER
|
||||
savefile_key = "blooper_speech_speed"
|
||||
minimum = BLOOPER_DEFAULT_MINSPEED
|
||||
maximum = BLOOPER_DEFAULT_MAXSPEED
|
||||
step = 0.01
|
||||
|
||||
/datum/preference/numeric/blooper_speech_speed/apply_to_human(mob/living/carbon/human/target, value)
|
||||
target.blooper_speed = value
|
||||
|
||||
/datum/preference/numeric/blooper_speech_speed/create_default_value()
|
||||
return round((BLOOPER_DEFAULT_MINSPEED + BLOOPER_DEFAULT_MAXSPEED) / 2)
|
||||
|
||||
/datum/preference/numeric/blooper_speech_pitch
|
||||
category = PREFERENCE_CATEGORY_NON_CONTEXTUAL
|
||||
savefile_identifier = PREFERENCE_CHARACTER
|
||||
savefile_key = "blooper_speech_pitch"
|
||||
minimum = BLOOPER_DEFAULT_MINPITCH
|
||||
maximum = BLOOPER_DEFAULT_MAXPITCH
|
||||
step = 0.01
|
||||
|
||||
/datum/preference/numeric/blooper_speech_pitch/apply_to_human(mob/living/carbon/human/target, value)
|
||||
target.blooper_pitch = value
|
||||
|
||||
/datum/preference/numeric/blooper_speech_pitch/create_default_value()
|
||||
return round((BLOOPER_DEFAULT_MINPITCH + BLOOPER_DEFAULT_MAXPITCH) / 2)
|
||||
|
||||
/datum/preference/numeric/blooper_pitch_range
|
||||
category = PREFERENCE_CATEGORY_NON_CONTEXTUAL
|
||||
savefile_identifier = PREFERENCE_CHARACTER
|
||||
savefile_key = "blooper_pitch_range"
|
||||
minimum = BLOOPER_DEFAULT_MINVARY
|
||||
maximum = BLOOPER_DEFAULT_MAXVARY
|
||||
step = 0.01
|
||||
|
||||
/datum/preference/numeric/blooper_pitch_range/apply_to_human(mob/living/carbon/human/target, value)
|
||||
target.blooper_pitch_range = value
|
||||
|
||||
/datum/preference/numeric/blooper_pitch_range/create_default_value()
|
||||
return 0.2
|
||||
|
||||
/// Can I use the blooper?
|
||||
/datum/preference/toggle/send_sound_blooper
|
||||
category = PREFERENCE_CATEGORY_GAME_PREFERENCES
|
||||
savefile_key = "send_sound_blooper"
|
||||
savefile_identifier = PREFERENCE_PLAYER
|
||||
default_value = TRUE
|
||||
|
||||
/// Can I hear everyone else's bloops?
|
||||
/datum/preference/toggle/hear_sound_blooper
|
||||
category = PREFERENCE_CATEGORY_GAME_PREFERENCES
|
||||
savefile_key = "hear_sound_blooper"
|
||||
savefile_identifier = PREFERENCE_PLAYER
|
||||
default_value = TRUE
|
||||
|
||||
/// Can I have a slider to adjust the volume of the barks?
|
||||
/datum/preference/numeric/sound_blooper_volume
|
||||
category = PREFERENCE_CATEGORY_GAME_PREFERENCES
|
||||
savefile_key = "sound_blooper_volume"
|
||||
savefile_identifier = PREFERENCE_PLAYER
|
||||
minimum = 0
|
||||
maximum = 60
|
||||
step = 5
|
||||
|
||||
/// It's was stoolen from Splurt build >:3 and from fluffySTG!! nyeehehehheee!~
|
||||
/datum/blooper
|
||||
var/name = "None"
|
||||
var/id = "No Voice"
|
||||
var/soundpath
|
||||
|
||||
var/minpitch = BLOOPER_DEFAULT_MINPITCH
|
||||
var/maxpitch = BLOOPER_DEFAULT_MAXPITCH
|
||||
var/minvariance = BLOOPER_DEFAULT_MINVARY
|
||||
var/maxvariance = BLOOPER_DEFAULT_MAXVARY
|
||||
|
||||
// Speed vars. Speed determines the number of characters required for each blooper, with lower speeds being faster with higher blooper density
|
||||
var/minspeed = BLOOPER_DEFAULT_MINSPEED
|
||||
var/maxspeed = BLOOPER_DEFAULT_MAXSPEED
|
||||
|
||||
// Visibility vars. Regardless of what's set below, these can still be obtained via adminbus and genetics. Rule of fun.
|
||||
var/list/ckeys_allowed
|
||||
var/ignore = FALSE // If TRUE - only for admins
|
||||
var/allow_random = FALSE
|
||||
@@ -1,438 +0,0 @@
|
||||
/datum/blooper/mutedc2
|
||||
name = "Muted String (Low)"
|
||||
id = "mutedc2"
|
||||
soundpath = 'sound/runtime/instruments/synthesis_samples/guitar/crisis_muted/C2.ogg'
|
||||
allow_random = TRUE
|
||||
|
||||
/datum/blooper/mutedc3
|
||||
name = "Muted String (Medium)"
|
||||
id = "mutedc3"
|
||||
soundpath = 'sound/runtime/instruments/synthesis_samples/guitar/crisis_muted/C3.ogg'
|
||||
allow_random = TRUE
|
||||
|
||||
/datum/blooper/mutedc4
|
||||
name = "Muted String (High)"
|
||||
id = "mutedc4"
|
||||
soundpath = 'sound/runtime/instruments/synthesis_samples/guitar/crisis_muted/C4.ogg'
|
||||
allow_random = TRUE
|
||||
|
||||
/datum/blooper/banjoc3
|
||||
name = "Banjo (Medium)"
|
||||
id = "banjoc3"
|
||||
soundpath = 'sound/runtime/instruments/banjo/Cn3.ogg'
|
||||
allow_random = TRUE
|
||||
|
||||
/datum/blooper/banjoc4
|
||||
name = "Banjo (High)"
|
||||
id = "banjoc4"
|
||||
soundpath = 'sound/runtime/instruments/banjo/Cn4.ogg'
|
||||
allow_random = TRUE
|
||||
|
||||
/datum/blooper/squeaky
|
||||
name = "Squeaky"
|
||||
id = "squeak"
|
||||
soundpath = 'sound/items/toy_squeak/toysqueak1.ogg'
|
||||
maxspeed = 4
|
||||
|
||||
/datum/blooper/beep
|
||||
name = "Beepy"
|
||||
id = "beep"
|
||||
soundpath = 'sound/machines/terminal/terminal_select.ogg'
|
||||
maxpitch = 1 //Bringing the pitch higher just hurts your ears :<
|
||||
maxspeed = 4 //This soundbyte's too short for larger speeds to not sound awkward
|
||||
|
||||
/datum/blooper/chitter
|
||||
name = "Chittery"
|
||||
id = "chitter"
|
||||
minspeed = 4 //Even with the sound being replaced with a unique, shorter sound, this is still a little too long for higher speeds
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/chitter.ogg'
|
||||
|
||||
/datum/blooper/synthetic_grunt
|
||||
name = "Synthetic (Grunt)"
|
||||
id = "synthgrunt"
|
||||
soundpath = 'sound/misc/bloop.ogg'
|
||||
|
||||
/datum/blooper/synthetic
|
||||
name = "Synthetic (Normal)"
|
||||
id = "synth"
|
||||
soundpath = 'sound/machines/uplink/uplinkerror.ogg'
|
||||
|
||||
/datum/blooper/bullet
|
||||
name = "Windy"
|
||||
id = "bullet"
|
||||
maxpitch = 1.6
|
||||
soundpath = 'sound/items/weapons/bulletflyby.ogg'
|
||||
|
||||
/datum/blooper/coggers
|
||||
name = "Brassy"
|
||||
id = "coggers"
|
||||
soundpath = 'sound/machines/clockcult/integration_cog_install.ogg'
|
||||
|
||||
/datum/blooper/moff/short
|
||||
name = "Moff squeak"
|
||||
id = "moffsqueak"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/mothsqueak.ogg'
|
||||
allow_random = TRUE
|
||||
ignore = FALSE
|
||||
|
||||
/datum/blooper/meow //Meow blooper?
|
||||
name = "Meow"
|
||||
id = "meow"
|
||||
allow_random = TRUE
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/meow1.ogg'
|
||||
minspeed = 5
|
||||
maxspeed = 11
|
||||
|
||||
/datum/blooper/chirp
|
||||
name = "Chirp"
|
||||
id = "chirp"
|
||||
allow_random = TRUE
|
||||
soundpath = 'modular_zubbers/sound/voice/chirp.ogg'
|
||||
|
||||
/datum/blooper/caw
|
||||
name = "Caw"
|
||||
id = "caw"
|
||||
allow_random = TRUE
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/caw.ogg'
|
||||
|
||||
//Undertale
|
||||
/datum/blooper/alphys
|
||||
name = "Alphys"
|
||||
id = "alphys"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/undertale/voice_alphys.ogg'
|
||||
minvariance = 0
|
||||
|
||||
/datum/blooper/asgore
|
||||
name = "Asgore"
|
||||
id = "asgore"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/undertale/voice_asgore.ogg'
|
||||
minvariance = 0
|
||||
|
||||
/datum/blooper/flowey
|
||||
name = "Flowey (normal)"
|
||||
id = "flowey1"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/undertale/voice_flowey_1.ogg'
|
||||
minvariance = 0
|
||||
|
||||
/datum/blooper/flowey/evil
|
||||
name = "Flowey (evil)"
|
||||
id = "flowey2"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/undertale/voice_flowey_2.ogg'
|
||||
minvariance = 0
|
||||
|
||||
/datum/blooper/papyrus
|
||||
name = "Papyrus"
|
||||
id = "papyrus"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/undertale/voice_papyrus.ogg'
|
||||
minvariance = 0
|
||||
|
||||
/datum/blooper/ralsei
|
||||
name = "Ralsei"
|
||||
id = "ralsei"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/undertale/voice_ralsei.ogg'
|
||||
minvariance = 0
|
||||
|
||||
/datum/blooper/sans //real
|
||||
name = "Sans"
|
||||
id = "sans"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/undertale/voice_sans.ogg'
|
||||
minvariance = 0
|
||||
|
||||
/datum/blooper/toriel
|
||||
name = "Toriel"
|
||||
id = "toriel"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/undertale/voice_toriel.ogg'
|
||||
minvariance = 0
|
||||
maxpitch = BLOOPER_DEFAULT_MAXPITCH*2
|
||||
|
||||
/datum/blooper/undyne
|
||||
name = "Undyne"
|
||||
id = "undyne"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/undertale/voice_undyne.ogg'
|
||||
minvariance = 0
|
||||
|
||||
/datum/blooper/temmie
|
||||
name = "Temmie"
|
||||
id = "temmie"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/undertale/voice_temmie.ogg'
|
||||
minvariance = 0
|
||||
|
||||
/datum/blooper/susie
|
||||
name = "Susie"
|
||||
id = "susie"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/undertale/voice_susie.ogg'
|
||||
minvariance = 0
|
||||
|
||||
/datum/blooper/gaster
|
||||
name = "Gaster"
|
||||
id = "gaster"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/undertale/voice_gaster_1.ogg'
|
||||
minvariance = 0
|
||||
|
||||
/datum/blooper/mettaton
|
||||
name = "Mettaton"
|
||||
id = "mettaton"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/undertale/voice_metta_1.ogg'
|
||||
minvariance = 0
|
||||
|
||||
/datum/blooper/gen_monster
|
||||
name = "Generic Monster 1"
|
||||
id = "gen_monster_1"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/undertale/voice_monster1.ogg'
|
||||
minvariance = 0
|
||||
|
||||
/datum/blooper/gen_monster/alt
|
||||
name = "Generic Monster 2"
|
||||
id = "gen_monster_2"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/undertale/voice_monster2.ogg'
|
||||
minvariance = 0
|
||||
|
||||
/datum/blooper/wilson
|
||||
name = "Wilson"
|
||||
id = "wilson"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/dont_starve/wilson_blooper.ogg'
|
||||
|
||||
/datum/blooper/wolfgang
|
||||
name = "Wolfgang"
|
||||
id = "wolfgang"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/dont_starve/wolfgang_blooper.ogg'
|
||||
minspeed = 4
|
||||
maxspeed = 10
|
||||
|
||||
/datum/blooper/woodie
|
||||
name = "Woodie"
|
||||
id = "woodie"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/dont_starve/woodie_blooper.ogg'
|
||||
minspeed = 4
|
||||
maxspeed = 10
|
||||
|
||||
/datum/blooper/wurt
|
||||
name = "Wurt"
|
||||
id = "wurt"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/dont_starve/wurt_blooper.ogg'
|
||||
|
||||
/datum/blooper/wx78
|
||||
name = "wx78"
|
||||
id = "wx78"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/dont_starve/wx78_blooper.ogg'
|
||||
minspeed = 3
|
||||
maxspeed = 9
|
||||
|
||||
/datum/blooper/blub
|
||||
name = "Blub"
|
||||
id = "blub"
|
||||
soundpath = 'goon/sounds/blub.ogg'
|
||||
|
||||
/datum/blooper/bottalk
|
||||
name = "Bottalk 1"
|
||||
id = "bottalk1"
|
||||
soundpath = 'goon/sounds/bottalk_1.ogg'
|
||||
minspeed = 3
|
||||
maxspeed = 9
|
||||
|
||||
/datum/blooper/bottalk/alt1
|
||||
name = "Bottalk 2"
|
||||
id = "bottalk2"
|
||||
soundpath = 'goon/sounds/bottalk_2.ogg'
|
||||
|
||||
/datum/blooper/bottalk/alt2
|
||||
name = "Bottalk 3"
|
||||
id = "bottalk3"
|
||||
soundpath = 'goon/sounds/bottalk_3.ogg'
|
||||
|
||||
/datum/blooper/bottalk/alt3
|
||||
name = "Bottalk 4"
|
||||
id = "bottalk4"
|
||||
soundpath = 'goon/sounds/bottalk_4.ogg'
|
||||
|
||||
/datum/blooper/buwoo
|
||||
name = "Buwoo"
|
||||
id = "buwoo"
|
||||
soundpath = 'goon/sounds/buwoo.ogg'
|
||||
|
||||
/datum/blooper/cow
|
||||
name = "Cow"
|
||||
id = "cow"
|
||||
soundpath = 'goon/sounds/cow.ogg'
|
||||
|
||||
/datum/blooper/lizard
|
||||
name = "Lizard"
|
||||
id = "lizard"
|
||||
soundpath = 'goon/sounds/lizard.ogg'
|
||||
|
||||
/datum/blooper/pug
|
||||
name = "Pug"
|
||||
id = "pug"
|
||||
soundpath = 'goon/sounds/pug.ogg'
|
||||
|
||||
/datum/blooper/pugg
|
||||
name = "Pugg"
|
||||
id = "pugg"
|
||||
soundpath = 'goon/sounds/pugg.ogg'
|
||||
|
||||
/datum/blooper/radio
|
||||
name = "Radio 1"
|
||||
id = "radio1"
|
||||
soundpath = 'goon/sounds/radio.ogg'
|
||||
|
||||
/datum/blooper/radio/short
|
||||
name = "Radio 2"
|
||||
id = "radio2"
|
||||
soundpath = 'goon/sounds/radio2.ogg'
|
||||
|
||||
/datum/blooper/radio/ai
|
||||
name = "Radio (AI)"
|
||||
id = "radio_ai"
|
||||
soundpath = 'goon/sounds/radio_ai.ogg'
|
||||
|
||||
/datum/blooper/roach //Turkish characters be like
|
||||
name = "Roach"
|
||||
id = "roach"
|
||||
soundpath = 'goon/sounds/roach.ogg'
|
||||
|
||||
/datum/blooper/skelly
|
||||
name = "Skelly"
|
||||
id = "skelly"
|
||||
soundpath = 'goon/sounds/skelly.ogg'
|
||||
|
||||
/datum/blooper/speak
|
||||
name = "Speak 1"
|
||||
id = "speak1"
|
||||
soundpath = 'goon/sounds/speak_1.ogg'
|
||||
|
||||
/datum/blooper/speak/alt1
|
||||
name = "Speak 2"
|
||||
id = "speak2"
|
||||
soundpath = 'goon/sounds/speak_2.ogg'
|
||||
|
||||
/datum/blooper/speak/alt2
|
||||
name = "Speak 3"
|
||||
id = "speak3"
|
||||
soundpath = 'goon/sounds/speak_3.ogg'
|
||||
|
||||
/datum/blooper/speak/alt3
|
||||
name = "Speak 4"
|
||||
id = "speak4"
|
||||
soundpath = 'goon/sounds/speak_4.ogg'
|
||||
|
||||
/datum/blooper/chitter/alt
|
||||
name = "Chittery Alt"
|
||||
id = "chitter2"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/moth/mothchitter2.ogg'
|
||||
|
||||
// The Mayhem Special
|
||||
/datum/blooper/whistle
|
||||
name = "Whistle 1"
|
||||
id = "whistle1"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/kazooie/birdwhistle.ogg'
|
||||
|
||||
/datum/blooper/whistle/alt1
|
||||
name = "Whistle 2"
|
||||
id = "whistle2"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/kazooie/birdwhistle2.ogg'
|
||||
|
||||
/datum/blooper/caw/alt1
|
||||
name = "Caw 2"
|
||||
id = "caw2"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/kazooie/caw.ogg'
|
||||
minspeed = 4
|
||||
maxspeed = 9
|
||||
|
||||
/datum/blooper/caw/alt2
|
||||
name = "Caw 3"
|
||||
id = "caw3"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/kazooie/caw2.ogg'
|
||||
minspeed = 3
|
||||
maxspeed = 9
|
||||
|
||||
/datum/blooper/caw/alt3
|
||||
name = "Caw 4"
|
||||
id = "caw4"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/kazooie/caw3.ogg'
|
||||
minspeed = 3
|
||||
maxspeed = 9
|
||||
|
||||
/datum/blooper/ehh
|
||||
name = "Ehh 1"
|
||||
id = "ehh1"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/kazooie/ehh.ogg'
|
||||
minspeed = 3
|
||||
maxspeed = 9
|
||||
|
||||
/datum/blooper/ehh/alt1
|
||||
name = "Ehh 2"
|
||||
id = "ehh2"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/kazooie/ehh2.ogg'
|
||||
|
||||
/datum/blooper/ehh/alt2
|
||||
name = "Ehh 3"
|
||||
id = "ehh3"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/kazooie/ehh3.ogg'
|
||||
|
||||
/datum/blooper/ehh/alt3
|
||||
name = "Ehh 4"
|
||||
id = "ehh4"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/kazooie/ehh4.ogg'
|
||||
minspeed = 3
|
||||
maxspeed = 9
|
||||
|
||||
/datum/blooper/ehh/alt5
|
||||
name = "Ehh 5"
|
||||
id = "ehh5"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/kazooie/ehh5.ogg'
|
||||
|
||||
/datum/blooper/faucet
|
||||
name = "Faucet 1"
|
||||
id = "faucet1"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/kazooie/faucet.ogg'
|
||||
|
||||
/datum/blooper/faucet/alt1
|
||||
name = "Faucet 2"
|
||||
id = "faucet2"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/kazooie/faucet2.ogg'
|
||||
|
||||
/datum/blooper/ribbit
|
||||
name = "Ribbit"
|
||||
id = "ribbit"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/kazooie/ribbit.ogg'
|
||||
|
||||
/datum/blooper/hoot
|
||||
name = "Hoot"
|
||||
id = "hoot"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/kazooie/hoot.ogg'
|
||||
minspeed = 4
|
||||
maxspeed = 9
|
||||
|
||||
/datum/blooper/tweet
|
||||
name = "Tweet"
|
||||
id = "tweet"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/kazooie/tweet.ogg'
|
||||
|
||||
/datum/blooper/dwoop
|
||||
name = "Dwoop"
|
||||
id = "dwoop"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/kazooie/dwoop.ogg'
|
||||
minspeed = 3
|
||||
maxspeed = 9
|
||||
|
||||
/datum/blooper/uhm
|
||||
name = "Uhm"
|
||||
id = "uhm"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/kazooie/uhm.ogg'
|
||||
|
||||
/datum/blooper/wurtesh
|
||||
name = "Wurtesh"
|
||||
id = "wurtesh"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/kazooie/wurble1.ogg'
|
||||
|
||||
/datum/blooper/chitter2
|
||||
name = "Chitter2"
|
||||
id = "chitter2"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/kazooie/chitter1.ogg'
|
||||
|
||||
/datum/blooper/xenohiss
|
||||
name = "Xenohiss"
|
||||
id = "Xenohiss"
|
||||
soundpath = 'modular_zubbers/code/modules/blooper/voice/bloopers/Xenohiss.ogg'
|
||||
minspeed = 10
|
||||
maxspeed = 16
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1
-1
@@ -4,7 +4,7 @@
|
||||
icon_state = "moth_head_m"
|
||||
limb_id = SPECIES_MOTH
|
||||
is_dimorphic = TRUE
|
||||
head_flags = HEAD_HAIR|HEAD_FACIAL_HAIR|HEAD_LIPS|HEAD_EYESPRITES|HEAD_EYEHOLES|HEAD_DEBRAIN //what the fuck, moths have lips?
|
||||
head_flags = HEAD_HAIR|HEAD_FACIAL_HAIR|HEAD_LIPS|HEAD_EYESPRITES|HEAD_EYEHOLES|HEAD_DEBRAIN|HEAD_EYECOLOR //what the fuck, moths have lips?
|
||||
teeth_count = 0
|
||||
|
||||
/obj/item/bodypart/chest/moth
|
||||
@@ -0,0 +1,88 @@
|
||||
/datum/preference/choiced/blooper
|
||||
category = PREFERENCE_CATEGORY_NON_CONTEXTUAL
|
||||
savefile_identifier = PREFERENCE_CHARACTER
|
||||
savefile_key = "blooper_choice"
|
||||
|
||||
/datum/preference/choiced/blooper/init_possible_values()
|
||||
// no bloopers configured, return dummy list to avoid runtimes
|
||||
if(!length(SSblooper.blooper_list))
|
||||
return list("none")
|
||||
return assoc_to_keys(SSblooper.blooper_list)
|
||||
|
||||
/datum/preference/choiced/blooper/apply_to_human(mob/living/carbon/human/target, value)
|
||||
target.blooper = SSblooper.blooper_list[value]
|
||||
|
||||
/datum/preference/choiced/blooper/is_accessible(datum/preferences/preferences)
|
||||
return ..() && length(SSblooper.blooper_list)
|
||||
|
||||
/datum/preference/choiced/blooper/compile_constant_data()
|
||||
var/list/data = ..()
|
||||
if(!length(SSblooper.blooper_list))
|
||||
return data
|
||||
var/list/display_names = list()
|
||||
for(var/id in get_choices())
|
||||
display_names[id] = astype(SSblooper.blooper_list[id], /datum/blooper).name
|
||||
data[CHOICED_PREFERENCE_DISPLAY_NAMES] = display_names
|
||||
return data
|
||||
|
||||
/datum/preference/numeric/blooper_speed
|
||||
category = PREFERENCE_CATEGORY_NON_CONTEXTUAL
|
||||
savefile_identifier = PREFERENCE_CHARACTER
|
||||
savefile_key = "blooper_speed"
|
||||
minimum = 0
|
||||
maximum = 100
|
||||
|
||||
/datum/preference/numeric/blooper_speed/apply_to_human(mob/living/carbon/human/target, value)
|
||||
target.blooper_speed = value
|
||||
|
||||
/datum/preference/numeric/blooper_speed/create_default_value()
|
||||
return 50
|
||||
|
||||
/datum/preference/numeric/blooper_speed/is_accessible(datum/preferences/preferences)
|
||||
return ..() && length(SSblooper.blooper_list)
|
||||
|
||||
/datum/preference/numeric/blooper_pitch
|
||||
category = PREFERENCE_CATEGORY_NON_CONTEXTUAL
|
||||
savefile_identifier = PREFERENCE_CHARACTER
|
||||
savefile_key = "blooper_pitch"
|
||||
minimum = 0
|
||||
maximum = 100
|
||||
|
||||
/datum/preference/numeric/blooper_pitch/apply_to_human(mob/living/carbon/human/target, value)
|
||||
target.blooper_pitch = value
|
||||
|
||||
/datum/preference/numeric/blooper_pitch/create_default_value()
|
||||
return 50
|
||||
|
||||
/datum/preference/numeric/blooper_pitch/is_accessible(datum/preferences/preferences)
|
||||
return ..() && length(SSblooper.blooper_list)
|
||||
|
||||
/datum/preference/numeric/blooper_pitch_range
|
||||
category = PREFERENCE_CATEGORY_NON_CONTEXTUAL
|
||||
savefile_identifier = PREFERENCE_CHARACTER
|
||||
savefile_key = "blooper_pitch_range"
|
||||
minimum = 0
|
||||
maximum = 100
|
||||
|
||||
/datum/preference/numeric/blooper_pitch_range/apply_to_human(mob/living/carbon/human/target, value)
|
||||
target.blooper_pitch_range = value
|
||||
|
||||
/datum/preference/numeric/blooper_pitch_range/create_default_value()
|
||||
return 30
|
||||
|
||||
/datum/preference/numeric/blooper_pitch_range/is_accessible(datum/preferences/preferences)
|
||||
return ..() && length(SSblooper.blooper_list)
|
||||
|
||||
// Send vocal bloopers
|
||||
/datum/preference/toggle/send_blooper
|
||||
category = PREFERENCE_CATEGORY_GAME_PREFERENCES
|
||||
savefile_identifier = PREFERENCE_PLAYER
|
||||
savefile_key = "blooper_send"
|
||||
default_value = TRUE
|
||||
|
||||
// Hear vocal bloopers
|
||||
/datum/preference/toggle/hear_blooper
|
||||
category = PREFERENCE_CATEGORY_GAME_PREFERENCES
|
||||
savefile_identifier = PREFERENCE_PLAYER
|
||||
savefile_key = "blooper_hear"
|
||||
default_value = TRUE
|
||||
@@ -0,0 +1,12 @@
|
||||
/datum/preference_middleware/blooper
|
||||
action_delegations = list(
|
||||
"play_blooper" = PROC_REF(play_blooper),
|
||||
)
|
||||
|
||||
/datum/preference_middleware/blooper/proc/play_blooper(list/params, mob/user)
|
||||
var/datum/blooper/blooper_to_use = SSblooper.blooper_list[preferences.read_preference(/datum/preference/choiced/blooper)]
|
||||
var/blooper_speed = preferences.read_preference(/datum/preference/numeric/blooper_speed)
|
||||
var/blooper_pitch = preferences.read_preference(/datum/preference/numeric/blooper_pitch)
|
||||
var/blooper_pitch_range = preferences.read_preference(/datum/preference/numeric/blooper_pitch_range)
|
||||
blooper_to_use.play_bloop(user, list(user), "This is a test message to hear a blooper.", 7, 70, blooper_speed, blooper_pitch, blooper_pitch_range)
|
||||
return TRUE
|
||||
@@ -294,3 +294,12 @@
|
||||
name = "Eastern Dragon 2"
|
||||
icon_state = "easternd2"
|
||||
affected_bodyparts = HEAD | CHEST | ARM_LEFT | ARM_RIGHT | HAND_LEFT | HAND_RIGHT | LEG_RIGHT | LEG_LEFT
|
||||
|
||||
/datum/body_marking_set/zombie
|
||||
name = "Zombie"
|
||||
body_marking_list = list("Zombie")
|
||||
|
||||
/datum/body_marking/bubber/zombie
|
||||
name = "Zombie"
|
||||
icon_state = "zombie"
|
||||
affected_bodyparts = HEAD | CHEST | ARM_LEFT | ARM_RIGHT | HAND_LEFT | HAND_RIGHT | LEG_RIGHT | LEG_LEFT
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user