Adds Trait Genetics (#16921)

* Adds Trait Genetics from Outpost21

Adds trait genetics from Outpost 21
- Tried to update each file it touched to be equivalent to their Chomp specific variants in order to maintain functionality and make sure no oddities would happen due to code differences. (Some things like the eardeaf loop were left there but commented out)

* Morph trait

* Fixes a server crashing bug with flip

aa

* flip

* Makes morph superpower better

- Makes it use the appearance_changer instead of 1000 different  procs

- Makes cocoon weaver able to change eye and skin color.

I did NOT select you. BAD

* begone

* fix dna modifier

* Fixes massive memory leak

* Brain Runtime Fix

* There was no reason for this to be a spawn(0)

And no I didn't spawn with no blood - https://i.imgur.com/vPizqCD.png

* revert

revert the dna changes there

* Deconf

* gets rid of unused proc vars that did nothing

* expects enough free slots

* glob

* fixed and added two other tests

* another few tests

* this is a list

* fixed bad injector

* lets wrap these for sanity

* better feedback

* wrong name

* don't allow multiple occupants into the dna pod

* future traits will have activation levels instead of binary on/off

---------

Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
Co-authored-by: Willburd <7099514+Willburd@users.noreply.github.com>
This commit is contained in:
Cameron Lennox
2025-02-11 02:01:27 -05:00
committed by GitHub
co-authored by Kashargul Willburd
parent 408b765def
commit cdafe425a5
108 changed files with 3805 additions and 2014 deletions
@@ -588,6 +588,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
return ..()
/mob/observer/dead/Destroy()
visualnet.addVisibility(src, src.client)
visualnet = null
if(ismob(following))
var/mob/M = following
+2
View File
@@ -16,6 +16,8 @@
var/mob/living/silicon/ai/ai = owner
ai.all_eyes -= src
owner = null
visualnet.clear_references(src, src.client)
visualnet = null
. = ..()
/mob/observer/eye/aiEye/setLoc(var/T, var/cancel_tracking = 1)
+15
View File
@@ -157,3 +157,18 @@
var/datum/chunk/chunk = cameranet.getCameraChunk(x, y, z)
usr.client.debug_variables(chunk)
*/
/datum/visualnet/proc/clear_references(list/moved_eyes, client/C)
if(!islist(moved_eyes))
moved_eyes = moved_eyes ? list(moved_eyes) : list()
var/list/chunks_pre_seen = list()
for(var/mob/observer/eye/eye as anything in moved_eyes)
if(C)
chunks_pre_seen |= eye.visibleChunks
if(C)
for(var/datum/chunk/c as anything in chunks_pre_seen)
for(var/mob/observer/eye/eye as anything in moved_eyes)
c.remove(eye)
+5 -4
View File
@@ -147,10 +147,11 @@ var/list/slot_equipment_priority = list( \
// If canremove or other conditions need to be checked then use unEquip instead.
/mob/proc/drop_from_inventory(var/obj/item/W, var/atom/target)
if(W)
remove_from_mob(W, target)
return TRUE
return FALSE
if(!W)
return FALSE
if(isnull(target) && istype( src.loc,/obj/structure/disposalholder))
return remove_from_mob(W, src.loc)
return remove_from_mob(W, target)
//Drops the item in our left hand
/mob/proc/drop_l_hand(var/atom/Target)
+1 -1
View File
@@ -77,7 +77,7 @@
/datum/language/xenocommon
name = "Xenomorph"
colour = "alien"
desc = "The common tongue of the xenomorphs."
desc = "The common tongue of both the xenomorphs and the Genaprawns."
speech_verb = "hisses"
ask_verb = "hisses"
exclaim_verb = "hisses"
@@ -10,9 +10,9 @@
to_chat(src, span_notice("There are three to choose from:"))
to_chat(src, span_bold("Hunters") + span_notice(" are strong and agile, able to hunt away from the hive and rapidly move through ventilation shafts. Hunters generate plasma slowly and have low reserves."))
to_chat(src, span_bold("Sentinels") + span_notice(" are tasked with protecting the hive and are deadly up close and at a range. They are not as physically imposing nor fast as the hunters."))
to_chat(src, span_bold("Drones") + span_notice(" are the working class, offering the largest plasma storage and generation. They are the only caste which may evolve again, turning into the dreaded alien queen."))
to_chat(src, span_bold("Drones") + span_notice(" are the working class, offering the largest plasma storage and generation. They are the only caste which may evolve again, turning into the dreaded Genaprawn queen."))
var/alien_caste = tgui_alert(src, "Please choose which alien caste you shall belong to.","Alien Choice",list("Hunter","Sentinel","Drone"))
return alien_caste ? "Xenomorph [alien_caste]" : null
return alien_caste ? "Genaprawn [alien_caste]" : null
/mob/living/carbon/alien/larva/show_evolution_blurb()
return
@@ -8,7 +8,7 @@
use_me = 0 //Can't use the me verb, it's a freaking immobile brain
icon = 'icons/obj/surgery.dmi'
icon_state = "brain1"
no_vore = TRUE //VOREStation Edit - PLEASE. lol.
no_vore = TRUE
/mob/living/carbon/brain/Initialize()
. = ..()
+69 -51
View File
@@ -27,9 +27,12 @@
var/can_defib = 1 //Horrible damage (like beheadings) will prevent defibbing organics.
var/active_regen = FALSE //Used for the regenerate proc in human_powers.dm
var/active_regen_delay = 300
var/last_breath_sound //Allows us to store the value across proc calls per-mob.
var/list/teleporters = list() //Used for lleill abilities
var/rest_dir = 0 //To lay down in a specific direction
var/gutdeathpressure = 0 //For GIBBING trait
var/list/datum/genetics/side_effect/genetic_side_effects = list() //For any genetic side effects we currently have.
/mob/living/carbon/human/Initialize(mapload, var/new_species = null)
if(!dna)
@@ -38,7 +41,7 @@
if(!species)
if(new_species)
set_species(new_species,1)
set_species(new_species)
else
set_species()
@@ -61,18 +64,16 @@
if(dna)
dna.ready_dna(src)
dna.real_name = real_name
sync_dna_traits(FALSE) // Traitgenes Sync traits to genetics if needed
sync_organ_dna()
AddComponent(/datum/component/personal_crafting)
/mob/living/carbon/human/Destroy()
human_mob_list -= src
/* //REMOVE - this is done on mob/living/Destroy
for(var/organ in organs)
qdel(organ)
*/
QDEL_NULL_LIST(organs)
if(nif)
QDEL_NULL(nif) //VOREStation Add
QDEL_NULL(nif)
worn_clothing.Cut()
@@ -114,7 +115,6 @@
. += "Chemical Storage: [mind.changeling.chem_charges]"
. += "Genetic Damage Time: [mind.changeling.geneticdamage]"
. += "Re-Adaptations: [mind.changeling.readapts]/[mind.changeling.max_readapts]"
if(species)
species.get_status_tab_items(src)
@@ -193,6 +193,7 @@
if (!get_ear_protection() >= 2)
ear_damage += 30
ear_deaf += 120
// deaf_loop.start() // Used downstream
if (prob(70) && !shielded)
Paralyse(10)
@@ -203,6 +204,7 @@
if (!get_ear_protection() >= 2)
ear_damage += 15
ear_deaf += 60
// deaf_loop.start() // Used downstream
if (prob(50) && !shielded)
Paralyse(10)
@@ -738,7 +740,7 @@
src << browse(null, "window=flavor_changes")
return
if("general")
var/msg = strip_html_simple(tgui_input_text(usr,"Update the general description of your character. This will be shown regardless of clothing.","Flavor Text",html_decode(flavor_texts[href_list["flavor_change"]]), multiline = TRUE, prevent_enter = TRUE)) //VOREStation Edit: separating out OOC notes
var/msg = strip_html_simple(tgui_input_text(usr,"Update the general description of your character. This will be shown regardless of clothing.","Flavor Text",html_decode(flavor_texts[href_list["flavor_change"]]), multiline = TRUE, prevent_enter = TRUE)) //Separating out OOC notes
if(msg)
flavor_texts[href_list["flavor_change"]] = msg
set_flavor()
@@ -816,11 +818,9 @@
return 1
/mob/living/carbon/human/IsAdvancedToolUser(var/silent)
// VOREstation start
if(feral)
to_chat(src, span_warning("Your primitive mind can't grasp the concept of that thing."))
return 0
// VOREstation end
if(species.has_fine_manipulation)
return 1
if(!silent)
@@ -956,6 +956,8 @@
return
var/list/creatures = list()
for(var/mob/living/carbon/h in mob_list)
if(h == src) // Don't target self
continue
creatures += h
var/mob/target = tgui_input_list(src, "Who do you want to project your mind to?", "Project Mind", creatures)
if (isnull(target))
@@ -984,18 +986,20 @@
remoteview_target = null
reset_view(0)
remove_verb(src, /mob/living/carbon/human/proc/remoteobserve)
return
if(client.eye != client.mob)
remoteview_target = null
reset_view(0)
return
var/list/mob/creatures = list()
var/turf/current = get_turf(src) // Needs to be on station or same z to perform telepathy
for(var/mob/living/carbon/h in mob_list)
var/turf/temp_turf = get_turf(h)
if((temp_turf.z != 1 && temp_turf.z != 5) || h.stat!=CONSCIOUS) //Not on mining or the station. Or dead
if(!istype(temp_turf,/turf/)) // Nullcheck fix
continue
if(h == src) // Traitgenes edit - Don't target self
continue
if(!((temp_turf.z in using_map.station_levels) || current.z == temp_turf.z) || h.stat!=CONSCIOUS) // Needs to be on station or same z to perform telepathy
continue
creatures += h
@@ -1051,13 +1055,19 @@
H.brainmob.mind.transfer_to(src)
qdel(H)
// Vorestation Addition - reapply markings/appearance from prefs for player mobs
// Traitgenes Disable all traits currently active, before prefs.copy_to() is applied, as it refreshes the traits list!
for(var/datum/gene/trait/gene in GLOB.dna_genes)
if(gene.name in active_genes)
gene.deactivate(src)
active_genes -= gene.name
// Reapply markings/appearance from prefs for player mobs
if(client) //just to be sure
client.prefs.copy_to(src)
if(dna)
dna.ResetUIFrom(src)
sync_dna_traits(TRUE) // Traitgenes Sync traits to genetics if needed
sync_organ_dna()
// end vorestation addition
losebreath = 0
@@ -1220,7 +1230,7 @@
else
to_chat(usr, span_warning("You failed to check the pulse. Try again."))
/mob/living/carbon/human/proc/set_species(var/new_species, var/default_colour, var/regen_icons = TRUE, var/mob/living/carbon/human/example = null) //VOREStation Edit - send an example
/mob/living/carbon/human/proc/set_species(var/new_species)
if(!dna)
if(!new_species)
@@ -1237,7 +1247,7 @@
if(species)
if(species.name && species.name == new_species && species.name != "Custom Species") //VOREStation Edit
if(species.name && species.name == new_species && species.name != "Custom Species")
return
if(species.language)
remove_language(species.language)
@@ -1248,7 +1258,7 @@
// Clear out their species abilities.
species.remove_inherent_verbs(src)
holder_type = null
hunger_rate = initial(hunger_rate) //VOREStation Add
hunger_rate = initial(hunger_rate)
species = GLOB.all_species[new_species]
@@ -1261,13 +1271,8 @@
if(species.icon_scale_x != DEFAULT_ICON_SCALE_X || species.icon_scale_y != DEFAULT_ICON_SCALE_Y)
update_transform()
if(example) //VOREStation Edit begin
if(!(example == src))
r_skin = example.r_skin
g_skin = example.g_skin
b_skin = example.b_skin
else if(species.base_color) //VOREStation Edit end
//Apply colour.
if(species.base_color)
//Apply color.
r_skin = hex2num(copytext(species.base_color,2,4))
g_skin = hex2num(copytext(species.base_color,4,6))
b_skin = hex2num(copytext(species.base_color,6,8))
@@ -1284,16 +1289,18 @@
//icon_state = lowertext(species.name) //Necessary?
//VOREStation Edit start: swap places of those two procs
species.handle_post_spawn(src)
species.create_organs(src)
//VOREStation Edit end: swap places of those two procs
maxHealth = species.total_health
hunger_rate = species.hunger_factor //VOREStation Add
hunger_rate = species.hunger_factor
default_pixel_x = initial(pixel_x) + species.pixel_offset_x //For giving datum/species ways to change 64x64 sprite offsets
default_pixel_y = initial(pixel_y) + species.pixel_offset_y
pixel_x = default_pixel_x
pixel_y = default_pixel_y
center_offset = species.center_offset
if(LAZYLEN(descriptors))
@@ -1305,6 +1312,23 @@
var/datum/mob_descriptor/descriptor = species.descriptors[desctype]
descriptors[desctype] = descriptor.default_value
addtimer(CALLBACK(src, PROC_REF(initialize_vessel)), 0, TIMER_DELETE_ME) //Doing ASYNC fails here. This used to be a spawn(0)
// Rebuild the HUD. If they aren't logged in then login() should reinstantiate it for them.
update_hud()
//A slew of bits that may be affected by our species change
regenerate_icons()
if(species)
return 1
else
return 0
/mob/living/carbon/human/proc/initialize_vessel() //This needs fixing. For some reason mob species is not immediately set in set_species.
PRIVATE_PROC(TRUE)
SHOULD_NOT_OVERRIDE(TRUE)
regenerate_icons()
make_blood()
if(vessel.total_volume < species.blood_volume)
vessel.maximum_volume = species.blood_volume
@@ -1316,19 +1340,6 @@
species.update_attack_types() //Required for any trait that updates unarmed_types in setup.
species.update_vore_belly_def_variant()
// Rebuild the HUD. If they aren't logged in then login() should reinstantiate it for them.
update_hud()
//A slew of bits that may be affected by our species change
regenerate_icons()
if(species)
//if(mind) //VOREStation Removal
//apply_traits() //VOREStation Removal
return 1
else
return 0
/mob/living/carbon/human/proc/bloody_doodle()
set category = "IC.Game"
set name = "Write in blood"
@@ -1495,9 +1506,14 @@
if(C.body_parts_covered & FEET)
footcoverage_check = TRUE
break
if(lying)
playsound(src, 'sound/misc/slip.ogg', 25, 1, -1)
drop_both_hands()
return 0
if((species.flags & NO_SLIP && !footcoverage_check) || (shoes && (shoes.item_flags & NOSLIP))) //Footwear negates a species' natural traction.
return 0
if(..(slipped_on,stun_duration))
drop_both_hands()
return 1
/mob/living/carbon/human/proc/relocate()
@@ -1553,7 +1569,11 @@
current_limb.relocate()
/mob/living/carbon/human/drop_from_inventory(var/obj/item/W, var/atom/target = null)
return !(W in organs) && ..()
if(W in organs)
return FALSE
if(isnull(target) && istype( src.loc,/obj/structure/disposalholder))
return remove_from_mob(W, src.loc)
return ..()
/mob/living/carbon/human/reset_view(atom/A, update_hud = 1)
..()
@@ -1563,8 +1583,8 @@
/mob/living/carbon/human/Check_Shoegrip()
if(shoes && (shoes.item_flags & NOSLIP) && istype(shoes, /obj/item/clothing/shoes/magboots)) //magboots + dense_object = no floating
return 1
if(flying) //VOREStation Edit. Checks to see if they have wings and are flying.
return 1 //VOREStation Edit.
if(flying) // Checks to see if they have wings and are flying.
return 1
return 0
//Puts the item into our active hand if possible. returns 1 on success.
@@ -1661,12 +1681,10 @@
/mob/living/carbon/human/can_feel_pain(var/obj/item/organ/check_organ)
if(isSynthetic())
return 0
//RS ADD START
if(!digest_pain && (isbelly(src.loc) || istype(src.loc, /turf/simulated/floor/water/digestive_enzymes)))
var/obj/belly/b = src.loc
if(b.digest_mode == DM_DIGEST || b.digest_mode == DM_SELECT)
return FALSE
//RS ADD END
for(var/datum/modifier/M in modifiers)
if(M.pain_immunity == TRUE)
return 0
@@ -1712,8 +1730,8 @@
/mob/living/carbon/human/proc/get_display_species()
//Shows species in tooltip
if(src.custom_species) //VOREStation Add
return custom_species //VOREStation Add
if(src.custom_species)
return custom_species
//Beepboops get special text if obviously beepboop
if(looksSynthetic())
if(gender == MALE)
@@ -1818,7 +1836,7 @@
/mob/living/carbon/human/verb/lay_down_left()
set name = "Rest-Left"
rest_dir = -1
rest_dir = 1
resting = !resting
to_chat(src, span_notice("You are now [resting ? "resting" : "getting up"]."))
update_canmove()
@@ -1826,7 +1844,7 @@
/mob/living/carbon/human/verb/lay_down_right()
set name = "Rest-Right"
rest_dir = 1
rest_dir = 0
resting = !resting
to_chat(src, span_notice("You are now [resting ? "resting" : "getting up"]."))
update_canmove()
@@ -166,3 +166,6 @@
var/block_hud
var/phobias //For holding a list of phobias
var/loneliness_stage = 0
var/next_loneliness_time = 0
@@ -5,17 +5,6 @@
update_icons_body() //Body handles eyes
update_eyes() //For floating eyes only
/*
/mob/living/carbon/var/list/internal_organs = list()
/mob/living/carbon/human/var/list/organs = list()
/mob/living/carbon/human/var/list/organs_by_name = list() // map organ names to organs
/mob/living/carbon/human/var/list/internal_organs_by_name = list() // so internal organs have less ickiness too
/mob/living/carbon/human/proc/get_bodypart_name(var/zone)
var/obj/item/organ/external/E = get_organ(zone)
if(E) . = E.name
*/
/mob/living/carbon/human/proc/recheck_bad_external_organs()
var/damage_this_tick = getToxLoss()
for(var/obj/item/organ/external/O in organs)
@@ -47,7 +36,7 @@
if(!force_process && !bad_external_organs.len)
return
number_wounds = 0 //VOREStation Add - You have to reduce this at some point...
number_wounds = 0
for(var/obj/item/organ/external/E in bad_external_organs)
if(!E)
continue
@@ -62,6 +51,7 @@
//Moving around with fractured ribs won't do you any good
if (prob(10) && !stat && can_feel_pain() && chem_effects[CE_PAINKILLER] < 50 && E.is_broken() && E.internal_organs.len)
custom_pain("Pain jolts through your broken [E.encased ? E.encased : E.name], staggering you!", 50)
emote("pain")
drop_item(loc)
Stun(2)
@@ -104,7 +94,7 @@
else if (E.is_dislocated())
stance_damage += 0.5
if(E && (!E.is_usable() || E.is_broken() || E.is_dislocated())) //VOREStation Edit
if(E && (!E.is_usable() || E.is_broken() || E.is_dislocated()))
limb_pain = E.organ_can_feel_pain()
// Canes and crutches help you stand (if the latter is ever added)
@@ -117,7 +107,7 @@
// standing is poor
if(stance_damage >= 4 || (stance_damage >= 2 && prob(5)))
if(!(lying || resting) && !isbelly(loc)) //VOREStation Edit
if(!(lying || resting) && !isbelly(loc))
if(limb_pain)
emote("scream")
custom_emote(1, "collapses!")
@@ -147,7 +137,6 @@
// Check again...
if(!l_hand && !r_hand)
return
for (var/obj/item/organ/external/E in organs)
if(!E || !E.can_grasp)
continue
@@ -163,9 +152,11 @@
continue
drop_from_inventory(r_hand)
if(!isbelly(loc)) //VOREStation Add
if(!isbelly(loc))
var/emote_scream = pick("screams in pain and ", "lets out a sharp cry and ", "cries out and ")
custom_emote(VISIBLE_MESSAGE, "[(can_feel_pain()) ? "" : emote_scream ]drops what they were holding in their [E.name]!")
if(can_feel_pain())
emote("pain")
else if(E.is_malfunctioning())
switch(E.body_part)
@@ -178,7 +169,7 @@
continue
drop_from_inventory(r_hand)
if(!isbelly(loc)) //VOREStation Add
if(!isbelly(loc))
custom_emote(VISIBLE_MESSAGE, "drops what they were holding, their [E.name] malfunctioning!")
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
@@ -195,6 +186,31 @@
var/obj/item/organ/O = pick(organs)
O.trace_chemicals[A.name] = 100
// Traitgenes Init genes based on the traits currently active
/mob/living/carbon/human/proc/sync_dna_traits(var/refresh_traits, var/hide_message = TRUE)
if(!dna || !species)
return
// Traitgenes NO_SCAN and Synthetics cannot be mutated
if(isSynthetic())
return
if(species.flags & NO_SCAN)
return
if(refresh_traits && species.traits)
for(var/TR in species.traits)
var/datum/trait/T = all_traits[TR]
if(!T)
continue
if(!T.linked_gene)
continue
var/datum/gene/trait/gene = T.linked_gene
dna.SetSEState(gene.block, TRUE, TRUE)
// testing("[gene.name] Setup activated!")
dna.UpdateSE()
var/flgs = MUTCHK_FORCED
if(hide_message)
flgs |= MUTCHK_HIDEMSG
domutcheck( src, null, flgs)
/mob/living/carbon/human/proc/sync_organ_dna()
var/list/all_bits = internal_organs|organs
for(var/obj/item/organ/O in all_bits)
+200 -117
View File
@@ -4,15 +4,14 @@
#define HUMAN_MAX_OXYLOSS 1 //Defines how much oxyloss humans can get per tick. A tile with no air at all (such as space) applies this value, otherwise it's a percentage of it.
#define HUMAN_CRIT_MAX_OXYLOSS ( 2.0 / 6) //The amount of damage you'll get when in critical condition. We want this to be a 5 minute deal = 300s. There are 50HP to get through, so (1/6)*last_tick_duration per second. Breaths however only happen every 4 ticks. last_tick_duration = ~2.0 on average
#define HEAT_DAMAGE_LEVEL_1 2 //VOREStation Edit //Amount of damage applied when your body temperature just passes the 360.15k safety point
#define HEAT_DAMAGE_LEVEL_2 4 //VOREStation Edit //Amount of damage applied when your body temperature passes the 400K point
#define HEAT_DAMAGE_LEVEL_3 8 //VOREStation Edit //Amount of damage applied when your body temperature passes the 1000K point
#define HEAT_DAMAGE_LEVEL_1 2 //Amount of damage applied when your body temperature just passes the 360.15k safety point
#define HEAT_DAMAGE_LEVEL_2 4 //Amount of damage applied when your body temperature passes the 400K point
#define HEAT_DAMAGE_LEVEL_3 8 //Amount of damage applied when your body temperature passes the 1000K point
#define COLD_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when your body temperature just passes the 260.15k safety point
#define COLD_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when your body temperature passes the 200K point
#define COLD_DAMAGE_LEVEL_3 3 //Amount of damage applied when your body temperature passes the 120K point
#define RADIATION_SPEED_COEFFICIENT 0.1
#define HUMAN_COMBUSTION_TEMP 524 //524k is the sustained combustion temperature of human fat
/mob/living/carbon/human
@@ -53,7 +52,7 @@
Sleeping(20)
//No need to update all of these procs if the guy is dead.
fall() //VORESTATION EDIT. Prevents people from floating
fall() //Prevents people from floating
if(stat != DEAD && !stasis)
//Updates the number of stored chemicals for powers
handle_changeling()
@@ -61,8 +60,8 @@
//Organs and blood
handle_organs()
stabilize_body_temperature() //Body temperature adjusts itself (self-regulation)
weightgain() //VOREStation Addition
process_weaver_silk() //VOREStation Addition
weightgain()
process_weaver_silk()
handle_shock()
handle_pain()
@@ -72,7 +71,7 @@
handle_medical_side_effects()
handle_heartbeat()
handle_nif() //VOREStation Addition
handle_nif()
if(phobias)
handle_phobias()
if(!client)
@@ -182,7 +181,7 @@
return
if (disabilities & EPILEPSY)
if ((prob(1) && paralysis < 1))
if ((prob(1) && prob(1) && paralysis < 1))
to_chat(src, span_red("You have a seizure!"))
for(var/mob/O in viewers(src, null))
if(O == src)
@@ -193,23 +192,57 @@
if (disabilities & COUGHING)
if ((prob(5) && paralysis <= 1))
drop_item()
spawn(0)
emote("cough")
return
emote("cough")
if(dna)
if(disabilities & DETERIORATE && prob(2) && prob(3)) // stacked percents for rarity
// random strange symptoms from organ/limb
custom_emote(VISIBLE_MESSAGE, "flinches slightly.")
switch(rand(1,4))
if(1)
adjustToxLoss(rand(2,8))
if(2)
adjustCloneLoss(rand(1,2))
if(3)
add_chemical_effect(CE_PAINKILLER, rand(8,28))
else
adjustOxyLoss(rand(13,26))
// external organs need to fall off if damaged enough
var/obj/item/organ/O = pick(organs)
if(O && !(O.organ_tag == BP_GROIN || O.organ_tag == BP_TORSO) && istype(O,/obj/item/organ/external))
var/obj/item/organ/external/E = O
if(O.damage >= O.min_broken_damage && O.robotic <= ORGAN_ASSISTED && prob(70))
add_chemical_effect(CE_PAINKILLER, 120) // what limb? Extreme nerve damage. Can't feel a thing + shock
E.droplimb(TRUE, DROPLIMB_ACID)
if(disabilities & GIBBING)
gutdeathpressure += 0.01
if(gutdeathpressure > 0 && prob(gutdeathpressure))
emote(pick("whimper","belch","belch","belch","choke","shiver"))
Weaken(gutdeathpressure / 3)
if((gutdeathpressure/3) >= 1 && prob(gutdeathpressure/3))
gutdeathpressure = 0 // to stop retriggering
spawn(1)
emote(pick("whimper","shiver"))
spawn(3)
emote(pick("whimper","belch","shiver"))
spawn(4)
emote(pick("whimper","shiver"))
spawn(6)
emote(pick("belch"))
gib()
if (disabilities & TOURETTES)
if ((prob(10) && paralysis <= 1))
if ((prob(1) && prob(2) && paralysis <= 1))
Stun(10)
spawn(0)
switch(rand(1, 3))
if(1)
emote("twitch")
if(2 to 3)
say("[prob(50) ? ";" : ""][pick("SHIT", "PISS", "FUCK", "CUNT", "COCKSUCKER", "MOTHERFUCKER", "TITS")]")
make_jittery(100)
return
make_jittery(100)
switch(rand(1, 3))
if(1)
emote("twitch")
if(2 to 3)
say("[prob(50) ? ";" : ""][pick("SHIT", "PISS", "FUCK", "CUNT", "COCKSUCKER", "MOTHERFUCKER", "TITS")]")
if (disabilities & NERVOUS)
if (prob(10))
stuttering = max(10, stuttering)
if (prob(5) && prob(7))
stuttering = max(15, stuttering)
if(jitteriness < 50)
make_jittery(65)
var/rn = rand(0, 200)
if(getBrainLoss() >= 5)
@@ -261,17 +294,25 @@
if((COLD_RESISTANCE in mutations) || (prob(1)))
heal_organ_damage(0,1)
// DNA2 - Gene processing.
// The HULK stuff that was here is now in the hulk gene.
if(!isSynthetic())
for(var/datum/dna/gene/gene in dna_genes)
if(!gene.block)
continue
if(gene.is_active(src))
gene.OnMobLife(src)
if(stat != DEAD)
if((mRegen in mutations))
var/heal = rand(0.2,1.3)
if(prob(50))
for(var/obj/item/organ/external/O in bad_external_organs)
for(var/datum/wound/W in O.wounds)
if(W.bleeding())
W.damage = max(W.damage - heal, 0)
if(W.damage <= 0)
O.wounds -= W
if(W.internal)
W.damage = max(W.damage - heal, 0)
if(W.damage <= 0)
O.wounds -= W
else
heal_organ_damage(heal,heal)
radiation = CLAMP(radiation,0,2500) //Max of 50Gy. If you reach that...You're going to wish you were dead. You probably will be dead.
accumulated_rads = CLAMP(accumulated_rads,0,2500) //Max of 50Gy as well. You should never get higher than this. You will be dead before you can reach this.
radiation = CLAMP(radiation,0,5000) //Max of 100Gy. If you reach that...You're going to wish you were dead. You probably will be dead.
accumulated_rads = CLAMP(accumulated_rads,0,5000) //Max of 100Gy as well. You should never get higher than this. You will be dead before you can reach this.
var/obj/item/organ/internal/I = null //Used for further down below when an organ is picked.
if(!radiation)
if(species.appearance_flags & RADIATION_GLOWS)
@@ -288,12 +329,12 @@
var/obj/item/organ/internal/diona/nutrients/rad_organ = locate() in internal_organs
if(rad_organ && !rad_organ.is_broken())
var/rads = radiation/25
radiation -= rads
adjust_nutrition(rads)
adjustBruteLoss(-(rads))
adjustFireLoss(-(rads))
adjustOxyLoss(-(rads))
adjustToxLoss(-(rads))
radiation -= (rads * species.rad_removal_mod)
adjust_nutrition(rads * species.rad_removal_mod)
adjustBruteLoss(-(rads * species.rad_removal_mod))
adjustFireLoss(-(rads * species.rad_removal_mod))
adjustOxyLoss(-(rads * species.rad_removal_mod))
adjustToxLoss(-(rads * species.rad_removal_mod))
updatehealth()
return
@@ -301,25 +342,26 @@
if(core)
return
//VOREStation Addition start: shadekin
var/obj/item/organ/internal/brain/shadekin/s_brain = locate() in internal_organs
if(s_brain)
return
//VOREStation Addition end: shadekin
if(reagents.has_reagent(REAGENT_ID_PRUSSIANBLUE)) //Prussian Blue temporarily stops radiation effects.
return
var/damage = 0
if(!species.radiation_mod) //If we are rad immune, stop here and remove rads if we have any.
radiation -= 10 * RADIATION_SPEED_COEFFICIENT * species.rad_removal_mod
return
if (radiation < 50) //Less than 1.0 Gy. No side effects.
radiation -= 10 * RADIATION_SPEED_COEFFICIENT
if (radiation < species.rad_levels["safe"]) //Less than 1.0 Gy. No side effects.
radiation -= 10 * RADIATION_SPEED_COEFFICIENT * species.rad_removal_mod
accumulated_rads += 10 * RADIATION_SPEED_COEFFICIENT //No escape from accumulated rads.
else if (radiation >= 50 && radiation < 100) //Equivalent of 1.0-2.0 Gy. Minimum stage you start seeing effects.
else if (radiation >= species.rad_levels["safe"] && radiation < species.rad_levels["danger_1"]) //Equivalent of 1.0-2.0 Gy. Minimum stage you start seeing effects.
damage = 1
radiation -= 10 * RADIATION_SPEED_COEFFICIENT
radiation -= 10 * RADIATION_SPEED_COEFFICIENT * species.rad_removal_mod
accumulated_rads += 10 * RADIATION_SPEED_COEFFICIENT
if(!isSynthetic())
if(prob(5) && prob(100 * RADIATION_SPEED_COEFFICIENT) && !weakened)
@@ -334,9 +376,9 @@
if(prob(1) && prob(100 * RADIATION_SPEED_COEFFICIENT)) //Rare chance of vomiting.
spawn vomit()
else if (radiation >= 100 && radiation < 300) //Equivalent of 2.0 to 6.0 Gy. Nobody should ever be above this without extreme negligence.
else if (radiation >= species.rad_levels["danger_1"] && radiation < species.rad_levels["danger_2"]) //Equivalent of 2.0 to 6.0 Gy. Nobody should ever be above this without extreme negligence.
damage = 3
radiation -= 30 * RADIATION_SPEED_COEFFICIENT
radiation -= 30 * RADIATION_SPEED_COEFFICIENT * species.rad_removal_mod
accumulated_rads += 30 * RADIATION_SPEED_COEFFICIENT
if(!isSynthetic())
if(prob(5))
@@ -350,9 +392,9 @@
to_chat(src, span_warning("You feel sick."))
AdjustWeakened(3)
else if (radiation >= 300 && radiation < 400) //Equivalent of 6.0 to 8.0 Gy.
else if (radiation >= species.rad_levels["danger_2"] && radiation < species.rad_levels["danger_3"]) //Equivalent of 6.0 to 8.0 Gy.
damage = 5
radiation -= 50 * RADIATION_SPEED_COEFFICIENT
radiation -= 50 * RADIATION_SPEED_COEFFICIENT * species.rad_removal_mod
accumulated_rads += 50 * RADIATION_SPEED_COEFFICIENT
if(!isSynthetic())
if(prob(15))
@@ -365,15 +407,15 @@
if(prob(15) && !weakened)
to_chat(src, span_warning("You feel horribly ill."))
AdjustWeakened(3)
if(prob(5) && internal_organs.len)
if(prob(5) && internal_organs.len) //TODO: Add malignant organs. - The person that wrote radcode.
I = pick(internal_organs) //Internal organ damage...Not good. Not good at all.
if(istype(I)) I.add_autopsy_data("Radiation Induced Cancerous Growth", damage)
I.take_damage(damage * species.radiation_mod * RADIATION_SPEED_COEFFICIENT)
else if (radiation >= 400 && radiation < 1500) //Equivalent of 8.0 to 30 Gy.
else if (radiation >= species.rad_levels["danger_3"] && radiation < species.rad_levels["danger_4"]) //Equivalent of 8.0 to 30 Gy.
damage = 10
radiation -= 100 * RADIATION_SPEED_COEFFICIENT
radiation -= 100 * RADIATION_SPEED_COEFFICIENT * species.rad_removal_mod
accumulated_rads += 100 * RADIATION_SPEED_COEFFICIENT
if(!isSynthetic())
if(prob(25))
@@ -396,14 +438,14 @@
if(prob(5))
to_chat(src, span_critical("Your entire body feels like it's on fire!"))
adjustHalLoss(5)
if(prob(10) && internal_organs.len)
if(prob(10) && internal_organs.len) //TODO: Add malignant organs. - The person that wrote radcode.
I = pick(internal_organs) //Internal organ damage...Not good. Not good at all.
if(istype(I)) I.add_autopsy_data("Radiation Induced Cancerous Growth", damage)
I.take_damage(damage * species.radiation_mod * RADIATION_SPEED_COEFFICIENT)
else if (radiation >= 1500) //Above 30Gy. You had to get absolutely blasted with rads for this.
else if (radiation >= species.rad_levels["danger_4"]) //Above 30Gy. You had to get absolutely blasted with rads for this.
damage = 30
radiation -= 300 * RADIATION_SPEED_COEFFICIENT
radiation -= 300 * RADIATION_SPEED_COEFFICIENT * species.rad_removal_mod
accumulated_rads += 300 * RADIATION_SPEED_COEFFICIENT
if(!isSynthetic())
@@ -427,7 +469,7 @@
if(get_active_hand() && prob(15)) //CNS is shutting down.
to_chat(src, span_danger("Your hand won't respond properly, you drop what you're holding!"))
drop_item()
if(internal_organs.len)
if(internal_organs.len) //TODO: Add malignant organs. - The person that wrote radcode.
I = pick(internal_organs) //Internal organ damage...Not good. Not good at all.
if(istype(I)) I.add_autopsy_data("Radiation Induced Cancerous Growth", damage * species.radiation_mod * RADIATION_SPEED_COEFFICIENT)
I.take_damage(damage * species.radiation_mod * RADIATION_SPEED_COEFFICIENT)
@@ -540,6 +582,9 @@
if(status_flags & GODMODE)
return
if(mNobreath in mutations)
return
if(suiciding)
failed_last_breath = 1
adjustOxyLoss(2)//If you are suiciding, you should die a little bit faster
@@ -729,6 +774,16 @@
failed_last_breath = 0
adjustOxyLoss(-5)
if(!does_not_breathe && client) // If we breathe, and have an active client, check if we have synthetic lungs.
var/obj/item/organ/internal/lungs/L = internal_organs_by_name[O_LUNGS]
var/turf = get_turf(src)
var/mob/living/carbon/human/M = src
if(L.robotic < ORGAN_ROBOT && is_below_sound_pressure(turf) && M.internal) // Only non-synthetic lungs, please, and only play these while the pressure is below that which we can hear sounds normally AND we're on internals.
if(!failed_inhale && (world.time >= (last_breath_sound + 7 SECONDS))) // Were we able to inhale successfully? Play inhale.
var/exhale = failed_exhale // Pass through if we passed exhale or not
play_inhale(M, exhale)
last_breath_sound = world.time
// Hot air hurts :(
if((breath.temperature <= species.cold_discomfort_level || breath.temperature >= species.heat_discomfort_level) && !(COLD_RESISTANCE in mutations))
@@ -795,6 +850,26 @@
breath.update_values()
return 1
/mob/living/carbon/human/proc/play_inhale(var/mob/living/M, var/exhale)
var/suit_inhale_sound
if(species.suit_inhale_sound)
suit_inhale_sound = species.suit_inhale_sound
else // Failsafe
suit_inhale_sound = 'sound/effects/mob_effects/suit_breathe_in.ogg'
playsound_local(get_turf(src), suit_inhale_sound, 100, pressure_affected = FALSE, volume_channel = VOLUME_CHANNEL_AMBIENCE)
if(!exhale) // Did we fail exhale? If no, play it after inhale finishes.
addtimer(CALLBACK(src, PROC_REF(play_exhale), M), 5 SECONDS)
/mob/living/carbon/human/proc/play_exhale(var/mob/living/M)
var/suit_exhale_sound
if(species.suit_exhale_sound)
suit_exhale_sound = species.suit_exhale_sound
else // Failsafe
suit_exhale_sound = 'sound/effects/mob_effects/suit_breathe_out.ogg'
playsound_local(get_turf(src), suit_exhale_sound, 100, pressure_affected = FALSE, volume_channel = VOLUME_CHANNEL_AMBIENCE)
/mob/living/carbon/human/proc/handle_allergens()
if(chem_effects[CE_ALLERGEN])
//first, multiply the basic species-level value by our allergen effect rating, so consuming multiple seperate allergen typess simultaneously hurts more
@@ -843,7 +918,7 @@
pl_effects()
break
if(istype(loc, /turf/space)) //VOREStation Edit - No FBPs overheating on space turfs inside mechs or people.
if(istype(loc, /turf/space)) //No FBPs overheating on space turfs inside mechs or people.
//Don't bother if the temperature drop is less than 0.1 anyways. Hopefully BYOND is smart enough to turn this constant expression into a constant
if(bodytemperature > (0.1 * HUMAN_HEAT_CAPACITY/(HUMAN_EXPOSED_SURFACE_AREA*STEFAN_BOLTZMANN_CONSTANT))**(1/4) + COSMIC_RADIATION_TEMPERATURE)
//Thermal radiation into space
@@ -944,7 +1019,7 @@
throw_alert("pressure", /obj/screen/alert/lowpressure, 1)
else
if( !(COLD_RESISTANCE in mutations))
if(!isSynthetic() || !nif || !nif.flag_check(NIF_O_PRESSURESEAL,NIF_FLAGS_OTHER)) //VOREStation Edit - NIF pressure seals
if(!isSynthetic() || !nif || !nif.flag_check(NIF_O_PRESSURESEAL,NIF_FLAGS_OTHER))
var/pressure_damage = LOW_PRESSURE_DAMAGE
if(stat==DEAD)
pressure_damage = pressure_damage/2
@@ -968,25 +1043,6 @@
return
/*
/mob/living/carbon/human/proc/adjust_body_temperature(current, loc_temp, boost)
var/temperature = current
var/difference = abs(current-loc_temp) //get difference
var/increments// = difference/10 //find how many increments apart they are
if(difference > 50)
increments = difference/5
else
increments = difference/10
var/change = increments*boost // Get the amount to change by (x per increment)
var/temp_change
if(current < loc_temp)
temperature = min(loc_temp, temperature+change)
else if(current > loc_temp)
temperature = max(loc_temp, temperature-change)
temp_change = (temperature - current)
return temp_change
*/
/mob/living/carbon/human/proc/stabilize_body_temperature()
// We produce heat naturally.
if (species.passive_temp_gain)
@@ -996,7 +1052,7 @@
// FBPs will overheat when alive, prosthetic limbs are fine.
if(stat != DEAD && robobody_count)
if(!nif || !nif.flag_check(NIF_O_HEATSINKS,NIF_FLAGS_OTHER)) //VOREStation Edit - NIF heatsinks prevent the base heat increase per tick if installed.
if(!nif || !nif.flag_check(NIF_O_HEATSINKS,NIF_FLAGS_OTHER))
bodytemperature += round(robobody_count*1.15)
var/obj/item/organ/internal/robotic/heatsink/HS = internal_organs_by_name[O_HEATSINK]
if(!HS || HS.is_broken()) // However, NIF Heatsinks will not compensate for a core FBP component (your heatsink) being lost.
@@ -1129,8 +1185,8 @@
var/total_phoronloss = 0
for(var/obj/item/I in src)
if(I.contaminated)
if(check_belly(I)) continue //VOREStation Edit
if(src.species && src.species.get_bodytype() != "Vox" && src.species.get_bodytype() != "Shadekin") //VOREStation Edit: shadekin
if(check_belly(I)) continue
if(src.species && src.species.get_bodytype() != "Vox" && src.species.get_bodytype() != "Shadekin")
// This is hacky, I'm so sorry.
if(I != l_hand && I != r_hand) //If the item isn't in your hands, you're probably wearing it. Full damage for you.
total_phoronloss += vsc.plc.CONTAMINATION_LOSS
@@ -1158,22 +1214,41 @@
take_overall_damage(1,1)
else //heal in the dark
heal_overall_damage(1,1)
if(species.photosynthesizing && nutrition < 1000)
var/light_amount = 0
if(isturf(loc))
var/turf/T = loc
light_amount = T.get_lumcount() / 10
adjust_nutrition(light_amount)
// nutrition decrease
if (nutrition > 0 && stat != DEAD)
if(nutrition <= 0 && species.shrinks && size_multiplier > RESIZE_TINY)
nutrition = 0.1
if(nutrition > 0 && stat != DEAD)
var/nutrition_reduction = species.hunger_factor
for(var/datum/modifier/mod in modifiers)
if(!isnull(mod.metabolism_percent))
nutrition_reduction *= mod.metabolism_percent
if(nutrition > 1000 && species.grows) //Removing the strict check against normal max/min size to support dorms/VR oversizing
nutrition_reduction *= 5
resize(size_multiplier+0.01, animate = FALSE, uncapped = has_large_resize_bounds()) //Bringing this code in line with micro and macro shrooms
if(nutrition < 50 && species.shrinks)
nutrition_reduction *= 0.3
resize(size_multiplier-0.01, animate = FALSE, uncapped = has_large_resize_bounds()) //Bringing this code in line with micro and macro shrooms
adjust_nutrition(-nutrition_reduction)
if(noisy == TRUE && nutrition < 250 && prob(10)) //VOREStation edit for hunger noises.
if(noisy == TRUE && nutrition < 250 && prob(10))
var/sound/growlsound = sound(get_sfx("hunger_sounds"))
var/growlmultiplier = 100 - (nutrition / 250 * 100)
playsound(src, growlsound, vol = growlmultiplier, vary = 1, falloff = 0.1, ignore_walls = TRUE, preference = /datum/preference/toggle/digestion_noises)
// VOREStation Edit End
/* //Unused here, used downstream.
if(nutrition > 500 && noisy_full == TRUE)
var/belch_prob = 5 //Maximum belch prob.
if(nutrition < 4075)
belch_prob = ((nutrition-500)/3575)*5 //Scale belch prob with fullness if not already at max. If editing make sure the multiplier matches the max prob above.
if(prob(belch_prob))
src.emote("belch")
*/
if((CE_DARKSIGHT in chem_effects) && chemical_darksight == 0)
recalculate_vis()
chemical_darksight = 1
@@ -1187,7 +1262,7 @@
updatehealth()
return //TODO: DEFERRED
return
//DO NOT CALL handle_statuses() from this proc, it's called from living/Life() as long as this returns a true value.
/mob/living/carbon/human/handle_regular_status_updates()
@@ -1202,6 +1277,7 @@
if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP
blinded = 1
silent = 0
// deaf_loop.stop() //Unused. Used downstream.
else //ALIVE. LIGHTS ARE ON
updatehealth() //TODO
@@ -1209,22 +1285,23 @@
death()
blinded = 1
silent = 0
// deaf_loop.stop() //Unused. Used downstream.
return 1
//UNCONSCIOUS. NO-ONE IS HOME
if((getOxyLoss() > (species.total_health/2)) || (health <= CONFIG_GET(number/health_threshold_crit)))
if((getOxyLoss() > (species.total_health/2)) || (health <= (CONFIG_GET(number/health_threshold_crit) * species.crit_mod)))
Paralyse(3)
if(hallucination)
if(hallucination >= 20 && !(species.flags & (NO_POISON|IS_PLANT|NO_HALLUCINATION)) )
if(prob(3))
fake_attack(src)
if(!handling_hal)
spawn handle_hallucinations() //The not boring kind!
/* Stop spinning the view, it breaks too much.
if(client && prob(5))
client.dir = pick(2,4,8)
spawn(rand(20,50))
client.dir = 1
*/
hallucination = max(0, hallucination - 2)
else
@@ -1278,6 +1355,16 @@
adjustHalLoss(-3)
if(sleeping)
if(prob(2))
if(prob(50))
adjustBruteLoss(-1)
else
adjustFireLoss(-1)
if(bad_external_organs.len && prob(45))
var/obj/item/organ/badorgan = pick(bad_external_organs)
if(!badorgan.is_broken() && badorgan.is_bruised())
badorgan.damage -= 1
handle_dreams()
if (mind)
//Are they SSD? If so we'll keep them asleep but work off some of that sleep var in case of stoxin or similar.
@@ -1349,6 +1436,7 @@
//Ears
if(sdisabilities & DEAF) //disabled-deaf, doesn't get better on its own
ear_deaf = max(ear_deaf, 1)
// deaf_loop.start(skip_start_sound = TRUE) //Used downstream.
else if(ear_deaf) //deafness, heals slowly over time
ear_deaf = max(ear_deaf-1, 0)
else if(get_ear_protection() >= 2) //resting your ears with earmuffs heals ear damage faster
@@ -1357,6 +1445,11 @@
else if(ear_damage < 25) //ear damage heals slowly under this threshold. otherwise you'll need earmuffs
ear_damage = max(ear_damage-0.05, 0)
/* //Used downstream. Add someday to here.
if(ear_deaf <= 0)
deaf_loop.stop()
*/
//Resting
if(resting)
dizziness = max(0, dizziness - 15)
@@ -1530,14 +1623,12 @@
fat_alert = /obj/screen/alert/fat/synth
hungry_alert = /obj/screen/alert/hungry/synth
starving_alert = /obj/screen/alert/starving/synth
//VOREStation Add - Vampire hunger alert
else if(get_species() == SPECIES_CUSTOM)
var/datum/species/custom/C = species
if(/datum/trait/neutral/bloodsucker in C.traits)
fat_alert = /obj/screen/alert/fat/vampire
hungry_alert = /obj/screen/alert/hungry/vampire
starving_alert = /obj/screen/alert/starving/vampire
//VOREStation Add End
switch(nutrition)
if(450 to INFINITY)
@@ -1567,7 +1658,7 @@
if(G.prescription)
apply_nearsighted_overlay = FALSE
if(nif && nif.flag_check(NIF_V_CORRECTIVE, NIF_FLAGS_VISION)) // VOREStation Edit - NIF
if(nif && nif.flag_check(NIF_V_CORRECTIVE, NIF_FLAGS_VISION))
apply_nearsighted_overlay = FALSE
set_fullscreen(apply_nearsighted_overlay, "nearsighted", /obj/screen/fullscreen/impaired, 1)
@@ -1579,7 +1670,7 @@
else
clear_alert("high")
if(!isbelly(loc)) //VOREStation Add - Belly fullscreens safety
if(!isbelly(loc))
clear_fullscreen("belly")
clear_fullscreen("belly2")
clear_fullscreen("belly3")
@@ -1594,7 +1685,7 @@
var/obj/item/clothing/glasses/welding/O = glasses
if(!O.up)
found_welder = 1
if(!found_welder && nif && nif.flag_check(NIF_V_UVFILTER,NIF_FLAGS_VISION)) found_welder = 1 //VOREStation Add - NIF
if(!found_welder && nif && nif.flag_check(NIF_V_UVFILTER,NIF_FLAGS_VISION)) found_welder = 1
if(istype(glasses, /obj/item/clothing/glasses/sunglasses/thinblindfold))
found_welder = 1
if(!found_welder && istype(head, /obj/item/clothing/head/welding))
@@ -1606,7 +1697,7 @@
if(O.helmet && O.helmet == head && (O.helmet.body_parts_covered & EYES))
if((O.offline && O.offline_vision_restriction == 1) || (!O.offline && O.vision_restriction == 1))
found_welder = 1
if(absorbed) found_welder = 1 //VOREStation Code
if(absorbed) found_welder = 1
if(found_welder)
client.screen |= global_hud.darkMask
@@ -1769,12 +1860,10 @@
if(isturf(loc) && rand(1,1000) == 1)
var/turf/T = loc
if(T.get_lumcount() <= LIGHTING_SOFT_THRESHOLD)
//VOREStation Add Start
if(text2num(time2text(world.timeofday, "MM")) == 4)
if(text2num(time2text(world.timeofday, "DD")) == 1)
playsound_local(src,pick(scawwySownds),50, 0)
return
//VOREStation Add End
playsound_local(src,pick(scarySounds),50, 1, -1)
/mob/living/carbon/human/handle_stomach()
@@ -1842,19 +1931,15 @@
/mob/living/carbon/human/handle_shock()
..()
if(status_flags & GODMODE) return 0 //godmode
if(!can_feel_pain()) return
if(health < CONFIG_GET(number/health_threshold_softcrit))// health 0 makes you immediately collapse
shock_stage = max(shock_stage, 61)
if(traumatic_shock >= 80)
if(traumatic_shock >= 80 && can_feel_pain())
shock_stage += 1
else if(health < CONFIG_GET(number/health_threshold_softcrit))
shock_stage = max(shock_stage, 61)
else
shock_stage = min(shock_stage, 160)
shock_stage = max(shock_stage-1, 0)
if(!can_feel_pain()) return
if(health < (CONFIG_GET(number/health_threshold_softcrit) * species.crit_mod))
shock_stage = max(shock_stage, 61)
if(stat)
return 0
@@ -1863,7 +1948,7 @@
custom_pain("[pick("It hurts so much", "You really need some painkillers", "Dear god, the pain")]!", 40)
if(shock_stage >= 30)
if(shock_stage == 30 && !isbelly(loc)) //VOREStation Edit
if(shock_stage == 30 && !isbelly(loc))
custom_emote(VISIBLE_MESSAGE, "is having trouble keeping their eyes open.")
eye_blurry = max(2, eye_blurry)
if(traumatic_shock >= 80)
@@ -1875,7 +1960,7 @@
to_chat(src, span_danger("[pick("The pain is excruciating", "Please&#44; just end the pain", "Your whole body is going numb")]!"))
if (shock_stage >= 60)
if(shock_stage == 60 && !isbelly(loc)) //VOREStation Edit
if(shock_stage == 60 && !isbelly(loc))
custom_emote(VISIBLE_MESSAGE, "'s body becomes limp.")
if (prob(2))
if(traumatic_shock >= 80)
@@ -1886,17 +1971,23 @@
if (prob(5))
if(traumatic_shock >= 80)
to_chat(src, span_danger("[pick("The pain is excruciating", "Please&#44; just end the pain", "Your whole body is going numb")]!"))
if(prob(20) && !isbelly(loc))
emote("pain")
Weaken(20)
if(shock_stage >= 120)
if (prob(2))
if(traumatic_shock >= 80)
to_chat(src, span_danger("[pick("You black out", "You feel like you could die any moment now", "You are about to lose consciousness")]!"))
if(prob(40) && !isbelly(loc))
emote("pain")
Paralyse(5)
if(shock_stage == 150)
if(!isbelly(loc)) //VOREStation Edit
if(!isbelly(loc))
custom_emote(VISIBLE_MESSAGE, "can no longer stand, collapsing!")
if(prob(60))
emote("pain")
Weaken(20)
if(shock_stage >= 150)
@@ -2057,13 +2148,6 @@
holder2.icon_state = "huddead"
else if(has_virus())
holder.icon_state = "hudill"
else if(has_brain_worms())
var/mob/living/simple_mob/animal/borer/B = has_brain_worms()
if(B.controlling)
holder.icon_state = "hudbrainworm"
else
holder.icon_state = "hudhealthy"
holder2.icon_state = "hudbrainworm"
else
holder.icon_state = "hudhealthy"
if(has_virus())
@@ -2178,7 +2262,7 @@
holder.icon_state = "hudblank"
apply_hud(BACKUP_HUD, holder)
//VOREStation Antag Hud
//Vore Antag Hud
if (BITTEST(hud_updateflag, VANTAG_HUD))
var/image/vantag = grab_hud(VANTAG_HUD)
if(vantag_pref)
@@ -2248,5 +2332,4 @@
#undef COLD_DAMAGE_LEVEL_2
#undef COLD_DAMAGE_LEVEL_3
#undef RADIATION_SPEED_COEFFICIENT
#undef HUMAN_COMBUSTION_TEMP
@@ -331,7 +331,7 @@
H.health = H.maxHealth
/datum/species/shadekin/produceCopy(var/list/traits, var/mob/living/carbon/human/H, var/custom_base, var/reset_dna = TRUE)
/datum/species/shadekin/produceCopy(var/list/traits, var/mob/living/carbon/human/H, var/custom_base, var/reset_dna = TRUE) // Traitgenes reset_dna flag required, or genes get reset on resleeve
var/datum/species/shadekin/new_copy = ..()
@@ -140,6 +140,8 @@
var/poison_type = GAS_PHORON // Poisonous air.
var/exhale_type = GAS_CO2 // Exhaled gas type.
var/water_breather = FALSE
var/suit_inhale_sound = 'sound/effects/mob_effects/suit_breathe_in.ogg'
var/suit_exhale_sound = 'sound/effects/mob_effects/suit_breathe_out.ogg'
var/bad_swimmer = FALSE
var/body_temperature = 310.15 // Species will try to stabilize at this temperature. (also affects temperature processing)
@@ -226,6 +228,18 @@
var/gluttonous // Can eat some mobs. 1 for mice, 2 for monkeys, 3 for people.
var/soft_landing = FALSE // Can fall down and land safely on small falls.
var/drippy = FALSE // If we drip or not. Primarily for goo beings.
var/photosynthesizing = FALSE // If we get nutrition from light or not.
var/shrinks = FALSE // If we shrink when we have no nutrition. Not added but here for downstream's sake.
var/grows = FALSE // Same as above but if we grow when >1000 nutrition.
var/crit_mod = 1 // Used for when we go unconscious. Used downstream.
var/list/env_traits = list()
var/pixel_offset_x = 0 // Used for offsetting 64x64 and up icons.
var/pixel_offset_y = 0 // Used for offsetting 64x64 and up icons.
var/rad_levels = list("safe" = 50, "danger_1" = 100, "danger_2" = 300, "danger_3" = 400, "danger_4" = 1500) //For handle_mutations_and_radiation
var/rad_removal_mod = 1
var/rarity_value = 1 // Relative rarity/collector value for this species.
var/economic_modifier = 2 // How much money this species makes
@@ -12,7 +12,6 @@ var/list/wrapped_species_by_ref = list()
)
var/list/valid_transform_species = list()
var/monochromatic
//var/default_form = SPECIES_HUMAN //VOREStation edit
/datum/species/shapeshifter/get_valid_shapeshifter_forms(var/mob/living/carbon/human/H)
@@ -64,13 +63,6 @@ var/list/wrapped_species_by_ref = list()
/datum/species/shapeshifter/handle_post_spawn(var/mob/living/carbon/human/H)
..()
wrapped_species_by_ref["\ref[H]"] = base_species //VOREStation edit
if(monochromatic)
H.r_hair = H.r_skin
H.g_hair = H.g_skin
H.b_hair = H.b_skin
H.r_facial = H.r_skin
H.g_facial = H.g_skin
H.b_facial = H.b_skin
for(var/obj/item/organ/external/E in H.organs)
E.sync_colour_to_human(H)
@@ -193,14 +185,6 @@ var/list/wrapped_species_by_ref = list()
g_synth = g_skin
b_synth = b_skin
var/datum/species/shapeshifter/S = species
if(S.monochromatic)
r_hair = r_skin
g_hair = g_skin
b_hair = b_skin
r_facial = r_skin
g_facial = g_skin
b_facial = b_skin
for(var/obj/item/organ/external/E in organs)
E.sync_colour_to_human(src)
@@ -280,7 +280,7 @@
else
to_chat(character, span_notice("You need to be aggressively grabbing someone before you can copy their form."))
return
if (!istype(victim))
if (!ishuman(victim))
to_chat(character, span_warning("You can only perform this on human mobs!"))
return
if (!victim.client)
@@ -72,7 +72,7 @@
else
..()
/datum/species/proc/produceCopy(var/list/traits, var/mob/living/carbon/human/H, var/custom_base, var/reset_dna = TRUE)
/datum/species/proc/produceCopy(var/list/traits, var/mob/living/carbon/human/H, var/custom_base, var/reset_dna = TRUE) // Traitgenes reset_dna flag required, or genes get reset on resleeve
ASSERT(src)
ASSERT(istype(H))
var/datum/species/new_copy = new src.type()
@@ -57,16 +57,46 @@
/datum/species/monkey/handle_npc(var/mob/living/carbon/human/H)
if(H.stat != CONSCIOUS)
return
if(prob(33) && H.canmove && isturf(H.loc) && !H.pulledby) //won't move if being pulled
step(H, pick(cardinal))
if(prob(1))
H.emote(pick("scratch","jump","roll","tail"))
// Traitgenes Monkeys perform emotes based on their traits
if(H.canmove && isturf(H.loc) && !H.pulledby) //won't move if being pulled
if(prob(33))
step(H, pick(cardinal))
if(prob(5))
// Handle generic gene expression emotes
if(!H.species || !H.species.traits || H.species.traits.len == 0)
H.emote(pick("scratch","jump","roll","tail")) // fallbacks
else
var/datum/trait/T = all_traits[pick(H.species.traits)]
if(T)
var/geneexpression
if(T.primitive_expression_messages.len)
geneexpression = pick(T.primitive_expression_messages)
if(geneexpression)
H.custom_emote(VISIBLE_MESSAGE, "[geneexpression]")
else
H.emote(pick("scratch","jump","roll","tail"))
// More... intense, expressions...
if(prob(5) && H.mutations.len)
if((LASER in H.mutations))
// zappy monkeys
var/list/targs = list()
for(var/atom/X in orange(7, H))
targs.Add(X)
if(targs.len)
H.LaserEyes(pick(targs))
..()
/datum/species/monkey/get_random_name()
return "[lowertext(name)] ([rand(100,999)])"
/datum/species/monkey/handle_post_spawn(var/mob/living/carbon/human/H)
if(!H.ckey)
H.can_be_drop_prey = TRUE
H.digest_leave_remains = 1
H.low_priority = TRUE
return ..()
/datum/species/monkey/tajaran
name = SPECIES_MONKEY_TAJ
name_plural = "Farwa"
@@ -60,8 +60,12 @@
/obj/item/rig/protean/Destroy()
if(myprotean)
var/mob/living/carbon/human/P = myprotean
var/datum/species/protean/S = P?.species
S?.OurRig = null
if(!ishuman(P) && isprotblob(myprotean))
var/mob/living/simple_mob/protean_blob/blob = myprotean
P = blob.humanform
if(ishuman(P))
var/datum/species/protean/S = P?.species
S?.OurRig = null
myprotean = null
. = ..()
@@ -118,8 +118,6 @@
var/global/list/abilities = list()
var/monochromatic = FALSE //IGNORE ME
var/blob_appearance = "puddle1"
var/blob_color_1 = "#363636"
var/blob_color_2 = "#ba3636"
@@ -32,6 +32,12 @@
var_changes = list("item_slowdown_mod" = 2.0)
custom_only = FALSE
banned_species = list(SPECIES_TESHARI) //These are already this weak.
//Traitgenes
is_genetrait = TRUE
hidden = FALSE
activation_message="Everything feels so much heavier"
primitive_expression_messages=list("hunches forwards")
/datum/trait/negative/endurance_low
name = "Low Endurance"
@@ -112,6 +118,13 @@
custom_only = FALSE
varchange_type = TRAIT_VARCHANGE_LESS_BETTER
//Traitgenes
is_genetrait = TRUE
hidden = FALSE
activation_message="You recieve a sudden shock of static."
primitive_expression_messages=list("shudders as their hair stands on end")
/datum/trait/negative/haemophilia
name = "Haemophilia - Organics only"
desc = "When you bleed, you bleed a LOT."
@@ -139,6 +152,13 @@
var_changes = list("lightweight" = 1)
custom_only = FALSE
//Traitgenes
is_genetrait = TRUE
hidden = FALSE
activation_message="You feel off balance..."
primitive_expression_messages=list("staggers")
/datum/trait/negative/neural_hypersensitivity
name = "Neural Hypersensitivity"
desc = "Your nerves are particularly sensitive to physical changes, leading to experiencing twice the intensity of pain and pleasure alike. Makes all pain effects twice as strong, and occur at half as much damage."
@@ -151,6 +171,13 @@
cost = -2
can_take = ORGANICS
//Traitgenes
is_genetrait = TRUE
hidden = FALSE
activation_message="You feel like breathing is more difficult..."
primitive_expression_messages=list("gasps")
/datum/trait/negative/breathes/phoron
name = "Phoron Breather"
desc = "You breathe phoron instead of oxygen (which is poisonous to you), much like a Vox."
@@ -161,6 +188,7 @@
desc = "You breathe nitrogen instead of oxygen (which is poisonous to you). Incidentally, phoron isn't poisonous to breathe to you."
var_changes = list("breath_type" = GAS_N2, "poison_type" = GAS_O2, "ideal_air_type" = /datum/gas_mixture/belly_air/nitrogen_breather)
/datum/trait/negative/monolingual
name = "Monolingual"
desc = "You are not good at learning languages."
@@ -178,6 +206,13 @@
custom_only = FALSE
varchange_type = TRAIT_VARCHANGE_MORE_BETTER
//Traitgenes
is_genetrait = TRUE
hidden = FALSE
activation_message="The dark seems darker than usual."
primitive_expression_messages=list("looks towards the light")
/datum/trait/negative/bad_shooter
name = "Bad Shot"
desc = "You are terrible at aiming."
@@ -186,6 +221,13 @@
custom_only = FALSE
varchange_type = TRAIT_VARCHANGE_MORE_BETTER
//Traitgenes
is_genetrait = TRUE
hidden = FALSE
activation_message="Your hands quiver"
primitive_expression_messages=list("hands quiver uncontrollably")
/datum/trait/negative/bad_swimmer
name = "Bad Swimmer"
desc = "You can't swim very well, all water slows you down a lot and you drown in deep water. You also swim up and down 25% slower."
@@ -195,6 +237,466 @@
varchange_type = TRAIT_VARCHANGE_LESS_BETTER
excludes = list(/datum/trait/positive/good_swimmer)
/datum/trait/negative/less_blood
name = "Low Blood Volume"
desc = "You have 33.3% less blood volume compared to most species, making you more prone to blood loss issues."
cost = -3
var_changes = list("blood_volume" = 375)
excludes = list(/datum/trait/negative/less_blood_extreme)
can_take = ORGANICS
/datum/trait/negative/less_blood_extreme
name = "Low Blood Volume, Extreme"
desc = "You have 60% less blood volume compared to most species, making you much more prone to blood loss issues."
cost = -5
var_changes = list("blood_volume" = 224)
excludes = list(/datum/trait/negative/less_blood)
can_take = ORGANICS
/datum/trait/negative/extreme_slowdown
name = "Slowdown, Extreme"
desc = "You move EXTREMELY slower than baseline"
cost = -8
var_changes = list("slowdown" = 4.0)
//Traitgenes
is_genetrait = TRUE
hidden = FALSE
activation_message="You feel like moving is more difficult..."
primitive_expression_messages=list("moves sluggishly")
/datum/trait/negative/low_blood_sugar
name = "Low Blood Sugar"
desc = "If you let your nutrition get too low, you will start to experience adverse affects including hallucinations, unconsciousness, and weakness"
cost = -1
special_env = TRUE
// Traitgenes Made into a gene trait
is_genetrait = TRUE
hidden = FALSE
activation_message="You feel drowsy..."
primitive_expression_messages=list("looks drowsy")
/datum/trait/negative/low_blood_sugar/handle_environment_special(var/mob/living/carbon/human/H)
if(H.nutrition > 200) //Sanity check because stupid bugs >:v
return
if((H.nutrition < 200) && prob(5))
if(H.nutrition > 100)
to_chat(H,span_warning("You start to feel noticeably weak as your stomach rumbles, begging for more food. Maybe you should eat something to keep your blood sugar up"))
else if(H.nutrition > 50)
to_chat(H,span_warning("You begin to feel rather weak, and your stomach rumbles loudly. You feel lightheaded and it's getting harder to think. You really need to eat something."))
else if(H.nutrition > 25)
to_chat(H,span_danger("You're feeling very weak and lightheaded, and your stomach continously rumbles at you. You really need to eat something!"))
else
to_chat(H,span_critical("You're feeling extremely weak and lightheaded. You feel as though you might pass out any moment and your stomach is screaming for food by now! You should really find something to eat!"))
if((H.nutrition < 100) && prob(10))
H.Confuse(10)
if((H.nutrition < 50) && prob(25))
H.hallucination = max(30,H.hallucination+8)
if((H.nutrition < 25) && prob(5))
H.drowsyness = max(100,H.drowsyness+30)
/datum/trait/negative/blindness
name = "Permanently blind"
desc = "You are blind. For whatever reason, nothing is able to change this fact, not even surgery. WARNING: YOU WILL NOT BE ABLE TO SEE ANY POSTS USING THE ME VERB, ONLY SUBTLE AND DIALOGUE ARE VIEWABLE TO YOU, YOU HAVE BEEN WARNED."
cost = -12
special_env = TRUE
custom_only = FALSE
// Traitgenes Replaces /datum/trait/negative/disability_blind, made into a gene trait
is_genetrait = TRUE
hidden = TRUE //Making this so people can't pick it in character select. While a blind character makes senese, not being able to see posts is a massive issue that needs to be addressed some other time.
sdisability=BLIND
activation_message="You can't seem to see anything."
primitive_expression_messages=list("stumbles aimlessly.")
/datum/trait/negative/blindness/handle_environment_special(var/mob/living/carbon/human/H)
H.sdisabilities |= sdisability //no matter what you do, the blindess still comes for you // Traitgenes tweaked to be consistant with other gene traits by using var
/datum/trait/negative/agoraphobia
name = "Agoraphobia"
desc = "You very much dislike being in crowded places. When in the company of more than two other people, you start to panic and experience adverse effects."
cost = -3
var/warning_cap = 400
var/hallucination_cap = 25
var/escalation_speed = 0.8
special_env = TRUE
excludes = list(/datum/trait/negative/lonely,/datum/trait/negative/lonely/major)
//Traitgenes
is_genetrait = TRUE
hidden = FALSE
activation_message="You feel like you need some space"
primitive_expression_messages=list("keeps their distance from others")
/datum/trait/negative/agoraphobia/handle_environment_special(var/mob/living/carbon/human/H)
spawn(0)
var/list/in_range = list()
// If they're dead or unconcious they're a bit beyond this kind of thing.
if(H.stat)
return
// No point processing if we're already stressing the hell out.
if(H.hallucination >= hallucination_cap && H.loneliness_stage >= warning_cap)
return
in_range |= check_mob_company(H,H) //Checks our item slots and bellies for any people.
in_range |= belly_check(H,H.loc) //Recursive check if we're in anyones bellies, are they in anyone's belly, etc.
in_range |= holder_check(H,H.loc) //Recursive check if someone's holding us, is anyone holding them, etc.
// Check for company.
for(var/mob/living/M in viewers(get_turf(H)))
in_range |= check_mob_company(H,M)
for(var/obj/effect/overlay/aiholo/A in range(5, H))
in_range |= A
if(in_range.len > 2)
if(H.loneliness_stage < warning_cap)
H.loneliness_stage = min(warning_cap,H.loneliness_stage+escalation_speed)
handle_loneliness(H)
if(H.loneliness_stage >= warning_cap && H.hallucination < hallucination_cap)
H.hallucination = min(hallucination_cap,H.hallucination+2.5*escalation_speed)
else
H.loneliness_stage = max(H.loneliness_stage-4,0)
/datum/trait/negative/agoraphobia/proc/handle_loneliness(var/mob/living/carbon/human/H)
if(world.time < H.next_loneliness_time)
return //Moved this at the top so we dont waste time assigning vars we will never use
var/ms = handle_loneliness_message(H)
if(ms)
to_chat(H, ms)
H.next_loneliness_time = world.time+500
H.fear = min((H.fear + 3), 102)
/datum/trait/negative/agoraphobia/proc/handle_loneliness_message(var/mob/living/carbon/human/H)
var/Lonely = H.loneliness_stage
if(Lonely == escalation_speed)
return "You notice there's more people than you feel comfortable with around you..."
else if(Lonely >= 50 && Lonely < 250)
return "You start to feel anxious from the number of people around you."
else if(Lonely >= 250 && Lonely < warning_cap)
if(H.stuttering < hallucination_cap)
H.stuttering += 5
return "[pick("You don't think you can last much longer with this much company!", "You should go find some space!")]" //if we add more here make it a list for readability
else if(Lonely >= warning_cap)
var/list/panicmessages = list( "Why am I still here? I have to leave and get some space!",
"Please, just let me be alone!",
"I need to be alone!")
return span_bolddanger("[pick(panicmessages)]")
return FALSE
/datum/trait/negative/agoraphobia/proc/find_held_by(var/atom/item)
if(!item || !istype(item))
return null
else if(istype(item,/mob/living))
return item
else
return find_held_by(item.loc)
/datum/trait/negative/agoraphobia/proc/holder_check(var/mob/living/carbon/human/H,var/obj/item/holder/H_holder)
var/list/in_range = list()
if(istype(H_holder))
var/mob/living/held_by = find_held_by(H_holder)
if(held_by)
in_range |= check_mob_company(H,held_by,FALSE)
in_range |= holder_check(H,held_by)
return in_range
/datum/trait/negative/agoraphobia/proc/belly_check(var/mob/living/carbon/human/H,var/obj/belly/B)
var/list/in_range = list()
if(istype(B))
in_range |= check_mob_company(H,B.owner,FALSE)
if(isbelly(B.owner.loc))
in_range |= belly_check(H,B.owner.loc)
return in_range
/datum/trait/negative/agoraphobia/proc/check_mob_company(var/mob/living/carbon/human/H,var/mob/living/M,var/invis_matters = TRUE)
var/list/in_range = list()
if(!istype(M))
return in_range
var/social_check = !istype(M, /mob/living/carbon) && !istype(M, /mob/living/silicon/robot)
var/ckey_check = !M.ckey
var/overall_checks = M == H || M.stat == DEAD || social_check || ckey_check
if(invis_matters && M.invisibility > H.see_invisible)
return in_range
if(!overall_checks)
in_range |= M
in_range |= check_contents(M,H)
return in_range
/datum/trait/negative/agoraphobia/proc/check_contents(var/atom/item,var/mob/living/carbon/human/H,var/max_layer = 3,var/current_layer = 1)
var/list/in_range = list()
if(!item || !istype(item) || current_layer > max_layer)
return in_range
for(var/datum/content in item.contents)
if(istype(content,/obj/item/holder))
var/obj/item/holder/contentholder = content
in_range |= check_mob_company(H,contentholder.held_mob)
else
in_range |= check_contents(content,H,max_layer,current_layer+1)
return in_range
/datum/trait/negative/lonely
name = "Minor loneliness vulnerability"
desc = "You're very prone to loneliness! Being alone for extended periods of time causes adverse effects. Most mobs will cure this loneliness as long as they aren't hostile."
cost = -1
var/warning_cap = 400
var/only_people = FALSE
var/hallucination_cap = 25
var/escalation_speed = 0.8
special_env = TRUE
excludes = list(/datum/trait/negative/lonely/major,/datum/trait/negative/agoraphobia)
/datum/trait/negative/lonely/major
name = "Major loneliness vulnerability"
desc = "You're extremely prone to loneliness! Being alone for extended periods of time causes adverse effects. Most mobs won't be enough to cure this loneliness, you need other social beings."
cost = -3
warning_cap = 300
hallucination_cap = 50
escalation_speed = 1.3
only_people = TRUE
special_env = TRUE
excludes = list(/datum/trait/negative/lonely,/datum/trait/negative/agoraphobia)
//Traitgenes
is_genetrait = TRUE
hidden = FALSE
activation_message="You feel like you are in desperate need of company..."
primitive_expression_messages=list("Looks up at you pleadingly")
/datum/trait/negative/lonely/proc/sub_loneliness(var/mob/living/carbon/human/H,var/amount = 4)
H.loneliness_stage = max(H.loneliness_stage - 4, 0)
if(world.time >= H.next_loneliness_time && H.loneliness_stage > 0)
to_chat(H, span_infoplain("The nearby company calms you down..."))
H.next_loneliness_time = world.time+500
/datum/trait/negative/lonely/proc/check_mob_company(var/mob/living/carbon/human/H,var/mob/living/M)
if(!istype(M))
return 0
var/social_check = only_people && !istype(M, /mob/living/carbon) && !istype(M, /mob/living/silicon/robot)
var/self_invisible_check = M == H || M.invisibility > H.see_invisible
var/ckey_check = only_people && !M.ckey
var/overall_checks = M.stat == DEAD || social_check || ckey_check
if(self_invisible_check)
return 0
if((M.faction == "neutral" || M.faction == H.faction) && !overall_checks)
sub_loneliness(H)
return 1
else
if(M.vore_organs)
for(var/obj/belly/B in M.vore_organs)
for(var/mob/living/content in B.contents)
if(istype(content))
check_mob_company(H,content)
return 0
/datum/trait/negative/lonely/proc/check_contents(var/atom/item,var/mob/living/carbon/human/H,var/max_layer = 3,var/current_layer = 1)
if(!item || !istype(item) || current_layer > max_layer)
return 0
for(var/datum/content in item.contents)
if(istype(content,/obj/item/holder))
var/obj/item/holder/contentholder = content
if(check_mob_company(H,contentholder.held_mob))
return 1
else
if(check_contents(content,H,max_layer,current_layer+1))
return 1
return 0
/datum/trait/negative/lonely/handle_environment_special(var/mob/living/carbon/human/H)
spawn(0)
// If they're dead or unconcious they're a bit beyond this kind of thing.
if(H.stat)
return
// No point processing if we're already stressing the hell out.
if(H.hallucination >= hallucination_cap && H.loneliness_stage >= warning_cap)
return
// Outpost 21 addition begin - extended loneliness mechanics
if(H.mind && H.mind.changeling) // We are never alone~
H.loneliness_stage = 0
return
if(H.has_brain_worms()) // Brain friends!
sub_loneliness(H)
return
// Outpost 21 addition end
// Vored? Not gonna get frightened.
if(isbelly(H.loc))
sub_loneliness(H)
return
if(istype(H.loc, /obj/item/holder))
sub_loneliness(H)
return
// Check for company.
if(check_contents(H,H)) //Check our item slots and storage for any micros.
sub_loneliness(H)
return
for(var/mob/living/M in viewers(get_turf(H)))
if(check_mob_company(H,M))
return
//Check to see if there's anyone in our belly
if(H.vore_organs)
for(var/obj/belly/B in H.vore_organs)
for(var/mob/living/content in B.contents)
if(istype(content))
if(check_mob_company(H,content))
return
for(var/obj/item/holder/micro/M in range(1, H))
sub_loneliness(H)
for(var/obj/effect/overlay/aiholo/A in range(5, H))
sub_loneliness(H)
for(var/obj/item/toy/plushie/teshari/P in range(5, H))
sub_loneliness(H)
// No company? Suffer :(
if(H.loneliness_stage < warning_cap)
H.loneliness_stage = min(warning_cap,H.loneliness_stage+escalation_speed)
handle_loneliness(H)
if(H.loneliness_stage >= warning_cap && H.hallucination < hallucination_cap)
H.hallucination = min(hallucination_cap,H.hallucination+2.5*escalation_speed)
/datum/trait/negative/lonely/proc/handle_loneliness(var/mob/living/carbon/human/H)
var/ms = ""
if(H.loneliness_stage == escalation_speed)
ms = "[pick("Well.. No one is around you anymore...","Well.. You're alone now...","You suddenly feel alone...")]" // Outpost 21 edit - More variety
if(H.loneliness_stage >= 50)
ms = "[pick("You begin to feel alone...","You feel isolated...","You need company...","Where is everyone?...","You need to find someone...")]" // Outpost 21 edit - More variety
if(H.loneliness_stage >= 250)
ms = "[pick("You don't think you can last much longer without some visible company!", "You should go find someone to be with!","You need to find company!","Find someone to be with!")]" // Outpost 21 edit - More variety
if(H.stuttering < hallucination_cap)
H.stuttering += 5
if(H.loneliness_stage >= warning_cap)
ms = span_danger(span_bold("[pick("Where are the others?", "Please, there has to be someone nearby!", "I don't want to be alone!","Please, anyone! I don't want to be alone!")]")) // Outpost 21 edit - More variety
if(world.time < H.next_loneliness_time)
return
if(ms != "")
to_chat(H, ms)
H.next_loneliness_time = world.time+500
H.fear = min((H.fear + 3), 102)
/datum/trait/negative/endurance_glass // Glass Cannon
name = "Glass Endurance"
desc = "Your body is very fragile. Reduces your maximum hitpoints to 25. Beware sneezes. You require only 50 damage in total to die, compared to 200 normally. You will go into crit after losing 25 HP, compared to crit at 100 HP."
cost = -12 // Similar to Very Low Endurance, this straight up will require you NEVER getting in a fight. This is extremely crippling. I salute the madlad that takes this.
var_changes = list("total_health" = 25)
/datum/trait/negative/endurance_glass/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
H.setMaxHealth(S.total_health)
/datum/trait/negative/endurance_glass // Glass Cannon
name = "Glass Endurance"
desc = "Your body is very fragile. Reduces your maximum hitpoints to 25. Beware sneezes. You require only 50 damage in total to die, compared to 200 normally. You will go into crit after losing 25 HP, compared to crit at 100 HP."
cost = -12 // Similar to Very Low Endurance, this straight up will require you NEVER getting in a fight. This is extremely crippling. I salute the madlad that takes this.
var_changes = list("total_health" = 25)
/datum/trait/negative/endurance_glass/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
H.setMaxHealth(S.total_health)
/datum/trait/negative/reduced_biocompat_minor
name = "Reduced Biocompatibility, Minor"
desc = "For whatever reason, you're one of the unlucky few who don't get as much benefit from modern-day chemicals. Remember to note this down in your medical records! Chems are only 80% as effective on you!"
cost = -2
var_changes = list("chem_strength_heal" = 0.8)
can_take = ORGANICS
/datum/trait/negative/reduced_biocompat
name = "Reduced Biocompatibility"
desc = "For whatever reason, you're one of the unlucky few who don't get as much benefit from modern-day chemicals. Remember to note this down in your medical records! Chems are only 60% as effective on you!"
cost = -4
var_changes = list("chem_strength_heal" = 0.6)
can_take = ORGANICS
/datum/trait/negative/reduced_biocompat_extreme
name = "Reduced Biocompatibility, Major"
desc = "For whatever reason, you're one of the unlucky few who don't get as much benefit from modern-day chemicals. Remember to note this down in your medical records! Chems are only 30% as effective on you!"
cost = -8
var_changes = list("chem_strength_heal" = 0.3)
can_take = ORGANICS
//Traitgenes
is_genetrait = TRUE
hidden = FALSE
activation_message="You feel no different"
primitive_expression_messages=list("blinks")
// Rykkanote: Relocated these here as we're no longer a YW downstream.
/datum/trait/negative/light_sensitivity
name = "Photosensitivity"
desc = "You have trouble dealing with sudden flashes of light, taking some time for you to recover. The effects of flashes from cameras and security equipment leaves you stunned for some time. 50% increased stun duration from flashes."
cost = -1
var_changes = list("flash_mod" = 1.5)
/datum/trait/negative/light_sensitivity_plus
name = "Photosensitivity, Major"
desc = "You have trouble dealing with sudden flashes of light, taking quite a long time for you to be able to recover. The effects of flashes from cameras and security equipment leave you stunned for some time. 100% (2x) stun duration from flashes."
cost = -2
var_changes = list("flash_mod" = 2.0)
//Traitgenes
is_genetrait = TRUE
hidden = FALSE
activation_message="Lights feel painful to look at..."
primitive_expression_messages=list("holds a hand up to their eyes")
/datum/trait/negative/haemophilia_plus
name = "Haemophilia, Major"
desc = "Some say that when it rains, it pours. Unfortunately, this is also true for yourself if you get cut. You bleed much faster than average, at 3x the normal rate."
cost = -3
can_take = ORGANICS
activation_message="You feel "
primitive_expression_messages=list("bumps their toe, screaming in pain")
/datum/trait/negative/haemophilia_plus/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
H.add_modifier(/datum/modifier/trait/haemophilia)
/datum/trait/negative/haemophilia_plus/unapply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
H.remove_modifiers_of_type(/datum/modifier/trait/haemophilia)
/datum/trait/negative/pain_intolerance_basic
name = "Pain Intolerance"
desc = "You are frail and sensitive to pain. You experience 25% more pain from all sources."
cost = -2
var_changes = list("pain_mod" = 1.2)
/datum/trait/negative/pain_intolerance_advanced
name = "Pain Intolerance, Major"
desc = "You are highly sensitive to all sources of pain, and experience 50% more pain."
cost = -3
var_changes = list("pain_mod" = 1.5) //this makes you extremely vulnerable to most sources of pain, a stunbaton bop or shotgun beanbag will do around 90 agony, almost enough to drop you in one hit.
//Traitgenes
is_genetrait = TRUE
hidden = FALSE
activation_message="You feel as though the airflow around you is painful..."
primitive_expression_messages=list("bumps their toe, screaming in pain")
/datum/trait/negative/sensitive_biochem
name = "Sensitive Biochemistry"
desc = "Your biochemistry is a little delicate, rendering you more susceptible to both deadly toxins and the more subtle ones. You'll probably want to list this in your medical records, and perhaps in your exploitable info as well. Toxin damages and knockout drugs are 25% stronger on you."
cost = -1
var_changes = list("chem_strength_tox" = 1.25)
//Traitgenes
is_genetrait = TRUE
hidden = FALSE
/datum/trait/negative/slipperydirt
name = "Dirt Vulnerability"
desc = "Even the tiniest particles of dirt give you uneasy footing, even through several layers of footwear."
@@ -0,0 +1,209 @@
/datum/trait/negative
category = TRAIT_TYPE_NEGATIVE
/* Was disabled in setupgame.dm, likely nonfunctional
/datum/trait/negative/disability_hallucinations
name = "Disability: Hallucinations"
desc = "..."
cost = -3
custom_only = FALSE
is_genetrait = TRUE
hidden = FALSE
mutation = mHallucination
activation_message="Your mind says 'Hello'."
*/
/datum/trait/negative/disability_epilepsy
name = "Epilepsy"
desc = "You experience periodic seizures."
cost = -3
custom_only = FALSE
is_genetrait = TRUE
hidden = FALSE
disability=EPILEPSY
activation_message="You get a headache."
primitive_expression_messages=list("shudders and twitches.")
/datum/trait/negative/disability_cough
name = "Coughing Fits"
desc = "You can't stop yourself from coughing."
cost = -1
custom_only = FALSE
is_genetrait = TRUE
hidden = FALSE
disability=COUGHING
activation_message="You start coughing."
/datum/trait/negative/disability_clumsy
name = "Clumsy"
desc = "You often make silly mistakes, or drop things."
cost = -2
custom_only = FALSE
is_genetrait = TRUE
hidden = FALSE
mutation=CLUMSY
activation_message="You feel lightheaded."
primitive_expression_messages=list("trips.")
/datum/trait/negative/disability_tourettes
name = "Tourettes Syndrome"
desc = "You have periodic motor seizures, and cannot stop yourself from yelling profanity."
cost = -2
custom_only = FALSE
is_genetrait = TRUE
hidden = FALSE
disability=TOURETTES
activation_message="You twitch."
primitive_expression_messages=list("twitches and chitters.")
/datum/trait/negative/disability_anxiety
name = "Anxiety Disorder"
desc = "You have extreme anxiety, often stuttering words."
cost = -1
custom_only = FALSE
is_genetrait = TRUE
hidden = FALSE
disability=NERVOUS
activation_message="You feel nervous."
primitive_expression_messages=list("anxiously chitters.")
/* Replaced by /datum/trait/negative/blindness
/datum/trait/negative/disability_blind
name = "Blinded"
desc = "You are unable to see anything."
cost = -3
custom_only = FALSE
is_genetrait = TRUE
hidden = FALSE
sdisability=BLIND
activation_message="You can't seem to see anything."
/datum/trait/negative/disability_blind/handle_environment_special(var/mob/living/carbon/human/H)
H.sdisabilities |= sdisability // In space, no one can hear you scream
*/
/datum/trait/negative/disability_mute
name = "Mute"
desc = "You are unable to speak."
cost = -3
custom_only = FALSE
is_genetrait = TRUE
hidden = FALSE
sdisability=MUTE
activation_message="Your throat feels strange..."
primitive_expression_messages=list("screams without a sound.")
/datum/trait/negative/disability_mute/handle_environment_special(var/mob/living/carbon/human/H)
H.sdisabilities |= sdisability // In space, no one can hear you scream
/datum/trait/negative/disability_deaf
name = "Deaf"
desc = "You are unable to hear anything."
cost = -3
custom_only = FALSE
is_genetrait = TRUE
hidden = FALSE
sdisability=DEAF
activation_message="It's kinda quiet."
primitive_expression_messages=list("stares blanky.")
/datum/trait/negative/disability_deaf/handle_environment_special(var/mob/living/carbon/human/H)
H.sdisabilities |= sdisability // In space, I can't hear shit
/datum/trait/negative/disability_deaf/apply(var/datum/species/S,var/mob/living/carbon/human/H)
. = ..()
H.ear_deaf = 1
/* //Not used here, used downstream.
if(H.stat != DEAD)
H.deaf_loop.start(skip_start_sound = TRUE) // Ear Ringing/Deafness
*/
/datum/trait/negative/disability_deaf/unapply(datum/species/S, mob/living/carbon/human/H)
. = ..()
H.ear_deaf = 0
/* //Not used here, used downstream.
H.deaf_loop.stop()
*/
/datum/trait/negative/disability_nearsighted
name = "Nearsighted"
desc = "You have difficulty seeing things far away."
cost = -2
custom_only = FALSE
is_genetrait = TRUE
hidden = FALSE
disability=NEARSIGHTED
activation_message="Your eyes feel weird..."
primitive_expression_messages=list("squints and stares.")
/datum/trait/negative/disability_wingdings
name = "Incomprehensible"
desc = "You are unable to speak normally, everything you say comes out as insane gibberish."
cost = -2
custom_only = FALSE
is_genetrait = TRUE
hidden = FALSE
disability=WINGDINGS
activation_message="You feel a little... Ga-hoo!"
primitive_expression_messages=list("zooks!","bloops!","boinks!")
/datum/trait/negative/disability_deteriorating
name = "Rotting Genetics"
desc = "Your body is slowly failing due to a chronic genetic disorder, expect to lose limbs or have organs shutdown randomly."
cost = -4
custom_only = FALSE
is_genetrait = TRUE
hidden = FALSE
disability=DETERIORATE
activation_message="You feel sore..."
primitive_expression_messages=list("shudders.","gasps.","chokes.")
/datum/trait/negative/disability_gibbing
name = "Gibbingtons"
desc = "Your body is on the edge of exploding, anything could set it off! A rare genetic disorder, only discovered with the invention of resleeving technology!"
cost = -5
custom_only = FALSE
is_genetrait = TRUE
hidden = TRUE
disability=GIBBING
activation_message="You feel bloated..."
primitive_expression_messages=list("shudders.","gasps.","chokes.")
/datum/trait/negative/disability_censored
name = "Censored"
desc = "You are unable to speak profanity. To an excessive degree..."
cost = -1
custom_only = FALSE
is_genetrait = TRUE
hidden = FALSE
disability=CENSORED
activation_message="You feel less rude..."
primitive_expression_messages=list("BEEPS!")
@@ -7,6 +7,7 @@
cost = 0
var_changes = list("metabolic_rate" = 1.2, "hunger_factor" = 0.2, "metabolism" = 0.06) // +20% rate and 4x hunger (Teshari level)
excludes = list(/datum/trait/neutral/metabolism_down, /datum/trait/neutral/metabolism_apex)
custom_only = FALSE
/datum/trait/neutral/metabolism_down
name = "Metabolism, Slow"
@@ -14,6 +15,7 @@
cost = 0
var_changes = list("metabolic_rate" = 0.8, "hunger_factor" = 0.04, "metabolism" = 0.0012) // -20% of default.
excludes = list(/datum/trait/neutral/metabolism_up, /datum/trait/neutral/metabolism_apex)
custom_only = FALSE
/datum/trait/neutral/metabolism_apex
name = "Metabolism, Apex"
@@ -21,6 +23,7 @@
cost = 0
var_changes = list("metabolic_rate" = 1.4, "hunger_factor" = 0.4, "metabolism" = 0.012) // +40% rate and 8x hunger (Double Teshari)
excludes = list(/datum/trait/neutral/metabolism_up, /datum/trait/neutral/metabolism_down)
custom_only = FALSE
/datum/trait/neutral/coldadapt
name = "Temp. Adapted, Cold"
@@ -30,6 +33,13 @@
can_take = ORGANICS
excludes = list(/datum/trait/neutral/hotadapt)
// Traitgenes Replaces /datum/trait/positive/superpower_cold_resist, made into a genetrait
is_genetrait = TRUE
hidden = FALSE
activation_message="Your body is filled with warmth."
primitive_expression_messages=list("pants, sweat dripping down their head.")
/datum/trait/neutral/hotadapt
name = "Temp. Adapted, Heat"
desc = "You are able to withstand much hotter temperatures than other species, and can even be comfortable in extremely hot environments. You are also more vulnerable to cold environments, and have a higher body temperature as a consequence of these adaptations."
@@ -38,6 +48,14 @@
can_take = ORGANICS // negates the need for suit coolers entirely for synths, so no
excludes = list(/datum/trait/neutral/coldadapt)
// Traitgenes Made into a genetrait
is_genetrait = TRUE
hidden = FALSE
activation_message="Your body feels chilly."
primitive_expression_messages=list("shivers.")
/datum/trait/neutral/autohiss_unathi
name = "Autohiss (Unathi)"
desc = "You roll your S's and x's"
@@ -50,10 +68,8 @@
"x" = list("ks", "kss", "ksss")
),
autohiss_exempt = list(LANGUAGE_UNATHI))
excludes = list(/datum/trait/neutral/autohiss_tajaran, /datum/trait/neutral/autohiss_zaddat)
excludes = list(/datum/trait/neutral/autohiss_tajaran)
custom_only = FALSE
banned_species = list(SPECIES_TAJARAN, SPECIES_UNATHI, SPECIES_ZADDAT)
/datum/trait/neutral/autohiss_tajaran
name = "Autohiss (Tajaran)"
@@ -64,9 +80,8 @@
"r" = list("rr", "rrr", "rrrr")
),
autohiss_exempt = list(LANGUAGE_SIIK,LANGUAGE_AKHANI,LANGUAGE_ALAI))
excludes = list(/datum/trait/neutral/autohiss_unathi, /datum/trait/neutral/autohiss_zaddat)
excludes = list(/datum/trait/neutral/autohiss_unathi)
custom_only = FALSE
banned_species = list(SPECIES_TAJARAN, SPECIES_UNATHI, SPECIES_ZADDAT)
/datum/trait/neutral/autohiss_zaddat
name = "Autohiss (Zaddat)"
@@ -84,9 +99,8 @@
"v" = list("vv", "vvv")
),
autohiss_exempt = list(LANGUAGE_ZADDAT,LANGUAGE_VESPINAE))
excludes = list(/datum/trait/neutral/autohiss_tajaran, /datum/trait/neutral/autohiss_unathi)
excludes = list(/datum/trait/neutral/autohiss_tajaran)
custom_only = FALSE
banned_species = list(SPECIES_TAJARAN, SPECIES_UNATHI, SPECIES_ZADDAT)
/datum/trait/neutral/bloodsucker
name = "Bloodsucker, Obligate"
@@ -103,7 +117,7 @@
cost = 0
custom_only = FALSE
var_changes = list("organic_food_coeff" = 0, "bloodsucker" = TRUE)
var_changes = list("organic_food_coeff" = 0, "bloodsucker" = TRUE) //The verb is given in human.dm
excludes = list(/datum/trait/neutral/bloodsucker_freeform)
/datum/trait/neutral/bloodsucker/apply(var/datum/species/S,var/mob/living/carbon/human/H)
@@ -225,7 +239,7 @@
add_verb(H, /mob/living/proc/toggle_stuffing_mode)
/datum/trait/neutral/hard_vore
name = "Brutal Predation"
name = "Hard Vore"
desc = "Allows you to tear off limbs & tear out internal organs."
cost = 0
custom_only = FALSE
@@ -241,10 +255,25 @@
custom_only = FALSE
var_changes = list("trashcan" = 1)
// Traitgenes made into a genetrait
is_genetrait = TRUE
hidden = FALSE
activation_message="Your stomach feels strange."
primitive_expression_messages=list("eats something off the ground.")
/datum/trait/neutral/trashcan/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
add_verb(H, /mob/living/proc/eat_trash)
add_verb(H, /mob/living/proc/toggle_trash_catching) //Ported from chompstation
add_verb(H, /mob/living/proc/toggle_trash_catching)
// Traitgenes made into a genetrait
/datum/trait/neutral/trashcan/unapply(datum/species/S, mob/living/carbon/human/H, trait_prefs)
..()
if(!(/mob/living/proc/eat_trash in S.inherent_verbs))
remove_verb(H,/mob/living/proc/eat_trash)
if(!(/mob/living/proc/toggle_trash_catching in S.inherent_verbs))
remove_verb(H,/mob/living/proc/toggle_trash_catching)
/datum/trait/neutral/gem_eater
name = "Expensive Taste"
@@ -253,17 +282,30 @@
custom_only = FALSE
var_changes = list("organic_food_coeff" = 0, "eat_minerals" = 1)
// Traitgenes made into a genetrait
is_genetrait = TRUE
hidden = FALSE
activation_message="Your stomach feels strange."
primitive_expression_messages=list("picks up and eats something shiny off the ground.")
/datum/trait/neutral/gem_eater/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
add_verb(H, /mob/living/proc/eat_minerals)
// Traitgenes made into a genetrait
/datum/trait/neutral/gem_eater/unapply(datum/species/S, mob/living/carbon/human/H, trait_prefs)
..()
if(!(/mob/living/proc/eat_minerals in S.inherent_verbs))
remove_verb(H,/mob/living/proc/eat_minerals)
/datum/trait/neutral/synth_chemfurnace
name = "Biofuel Processor"
desc = "You are able to gain energy through consuming and processing normal food, at the cost of significantly slower recharging via cyborg chargers. Energy-dense foods such as protein bars and survival food will yield the best results."
cost = 0
custom_only = FALSE
can_take = SYNTHETICS
var_changes = list("organic_food_coeff" = 0, "synthetic_food_coeff" = 0.6)
var_changes = list("organic_food_coeff" = 0.75, "synthetic_food_coeff" = 1)
excludes = list(/datum/trait/neutral/biofuel_value_down)
/datum/trait/neutral/synth_ethanolburner
@@ -290,10 +332,23 @@
var_changes = list("has_glowing_eyes" = 1)
has_preferences = list("has_glowing_eyes" = list(TRAIT_PREF_TYPE_BOOLEAN, "Glowing on spawn", TRAIT_VAREDIT_TARGET_SPECIES))
// Traitgenes Made into a genetrait
is_genetrait = TRUE
hidden = FALSE
activation_message="Your eyes feel brighter."
primitive_expression_messages=list("eyes twinkle.")
/datum/trait/neutral/glowing_eyes/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
add_verb(H, /mob/living/carbon/human/proc/toggle_eye_glow)
// Traitgenes Made into a genetrait
/datum/trait/neutral/glowing_eyes/unapply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
if(!(/mob/living/carbon/human/proc/toggle_eye_glow in S.inherent_verbs))
remove_verb(H,/mob/living/carbon/human/proc/toggle_eye_glow)
/datum/trait/neutral/glowing_body
name = "Glowing Body"
desc = "Your body glows about as much as a PDA light! Settable color and toggle in Abilities tab ingame."
@@ -302,11 +357,26 @@
has_preferences = list("glow_toggle" = list(TRAIT_PREF_TYPE_BOOLEAN, "Glowing on spawn", TRAIT_VAREDIT_TARGET_MOB, FALSE), \
"glow_color" = list(TRAIT_PREF_TYPE_COLOR, "Glow color", TRAIT_VAREDIT_TARGET_MOB))
// Traitgenes Made into a genetrait
is_genetrait = TRUE
hidden = FALSE
activation_message="You feel enlightened."
primitive_expression_messages=list("shines and sparkles.")
/datum/trait/neutral/glowing_body/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
add_verb(H, /mob/living/proc/glow_toggle)
add_verb(H, /mob/living/proc/glow_color)
// Traitgenes Made into a genetrait
/datum/trait/neutral/glowing_body/unapply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
if(!(/mob/living/proc/glow_toggle in S.inherent_verbs))
remove_verb(H,/mob/living/proc/glow_toggle)
if(!(/mob/living/proc/glow_color in S.inherent_verbs))
remove_verb(H,/mob/living/proc/glow_color)
//Allergen traits! Not available to any species with a base allergens var.
/datum/trait/neutral/allergy
name = "Allergy: Gluten"
@@ -315,10 +385,22 @@
custom_only = FALSE
var/allergen = ALLERGEN_GRAINS
// Traitgenes Made ALL ALLERGYS into gene traits
is_genetrait = TRUE
hidden = FALSE
activation_message="Something feels odd..."
/datum/trait/neutral/allergy/apply(var/datum/species/S,var/mob/living/carbon/human/H)
S.allergens |= allergen
..()
// Traitgenes edit begin - Made ALL ALLERGYS into gene traits
/datum/trait/neutral/allergy/unapply(var/datum/species/S,var/mob/living/carbon/human/H)
S.allergens &= ~allergen
..()
// Traitgenes edit end
/datum/trait/neutral/allergy/meat
name = "Allergy: Meat"
desc = "You're highly allergic to just about any form of meat. You're probably better off just sticking to vegetables. NB: By taking this trait, you acknowledge there is a significant risk your character may suffer a fatal reaction if exposed to this substance."
@@ -480,6 +562,12 @@
custom_only = FALSE
var_changes = list("spice_mod" = 3) // 300% as effective if spice_mod is set to 1. If it's not 1 in species.dm, update this!
// Traitgenes Made into a gene trait
is_genetrait = TRUE
hidden = FALSE
activation_message="Your belly feels strange..."
/datum/trait/neutral/spice_intolerance_basic
name = "Spice Intolerance, Heavy"
desc = "Spicy (and chilly) peppers are twice as strong. (This does not affect pepperspray.)"
@@ -515,6 +603,12 @@
custom_only = FALSE
var_changes = list("spice_mod" = 0.25) // 25% as effective if spice_mod is set to 1. If it's not 1 in species.dm, update this!
// Traitgenes Made into a gene trait
is_genetrait = TRUE
hidden = FALSE
activation_message="Your belly feels strange..."
// Alcohol Traits Start Here, from negative to positive.
/datum/trait/neutral/alcohol_intolerance_advanced
name = "Liver of Air"
@@ -523,6 +617,12 @@
custom_only = FALSE
var_changes = list("chem_strength_alcohol" = 0.33)
// Traitgenes Made into a gene trait
is_genetrait = TRUE
hidden = FALSE
activation_message="Your belly feels strange..."
/datum/trait/neutral/alcohol_intolerance_basic
name = "Liver of Lilies"
desc = "You have a hard time with alcohol. Maybe you just never took to it, or maybe it doesn't agree with your system... either way, alcohol hits you twice as hard."
@@ -565,35 +665,77 @@
cost = 0
custom_only = FALSE
var_changes = list("chem_strength_alcohol" = 4)
// Traitgenes Made into a gene trait
is_genetrait = TRUE
hidden = FALSE
activation_message="Your belly feels strange..."
// Alcohol Traits End Here.
/datum/trait/neutral/colorblind/mono
name = "Colorblindness (Monochromancy)"
desc = "You simply can't see colors at all, period. You are 100% colorblind."
cost = 0
custom_only = FALSE
// Traitgenes Made into a gene trait
is_genetrait = TRUE
hidden = FALSE
activation_message="Your eyes feel strange..."
/datum/trait/neutral/colorblind/mono/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
H.add_modifier(/datum/modifier/trait/colorblind_monochrome)
// Traitgenes Made into a gene trait
/datum/trait/neutral/colorblind/mono/unapply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
H.remove_a_modifier_of_type(/datum/modifier/trait/colorblind_monochrome)
/datum/trait/neutral/colorblind/para_vulp
name = "Colorblindness (Para Vulp)"
desc = "You have a severe issue with green colors and have difficulty recognizing them from red colors."
cost = 0
custom_only = FALSE
// Traitgenes Made into a gene trait
is_genetrait = TRUE
hidden = FALSE
activation_message="Your eyes feel strange..."
/datum/trait/neutral/colorblind/para_vulp/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
H.add_modifier(/datum/modifier/trait/colorblind_vulp)
// Traitgenes Made into a gene trait
/datum/trait/neutral/colorblind/para_vulp/unapply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
H.remove_a_modifier_of_type(/datum/modifier/trait/colorblind_vulp)
/datum/trait/neutral/colorblind/para_taj
name = "Colorblindness (Para Taj)"
desc = "You have a minor issue with blue colors and have difficulty recognizing them from red colors."
cost = 0
custom_only = FALSE
// Traitgenes - Made into a gene trait
is_genetrait = TRUE
hidden = FALSE
activation_message="Your eyes feel strange..."
/datum/trait/neutral/colorblind/para_taj/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
H.add_modifier(/datum/modifier/trait/colorblind_taj)
// Traitgenes Made into a gene trait
/datum/trait/neutral/colorblind/para_taj/unapply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
H.remove_a_modifier_of_type(/datum/modifier/trait/colorblind_taj)
// Body shape traits
/datum/trait/neutral/taller
name = "Tall"
@@ -731,30 +873,66 @@
cost = 0
custom_only = FALSE
// Traitgenes made into a genetrait
is_genetrait = TRUE
hidden = FALSE
activation_message="Your mind feels more powerful."
/datum/trait/neutral/dominate_predator/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
add_verb(H, /mob/proc/dominate_predator)
// Traitgenes made into a genetrait
/datum/trait/neutral/dominate_predator/unapply(datum/species/S, mob/living/carbon/human/H, trait_prefs)
..()
if(!(/mob/proc/dominate_predator in S.inherent_verbs))
remove_verb(H,/mob/proc/dominate_predator)
/datum/trait/neutral/dominate_prey
name = "Dominate Prey"
desc = "Connect to and dominate the brain of your prey."
cost = 0
custom_only = FALSE
// Traitgenes made into a genetrait
is_genetrait = TRUE
hidden = FALSE
activation_message="Your mind feels more powerful."
/datum/trait/neutral/dominate_prey/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
add_verb(H, /mob/living/proc/dominate_prey)
// Traitgenes made into a genetrait
/datum/trait/neutral/dominate_prey/unapply(datum/species/S, mob/living/carbon/human/H, trait_prefs)
..()
if(!(/mob/living/proc/dominate_prey in S.inherent_verbs))
remove_verb(H,/mob/living/proc/dominate_prey)
/datum/trait/neutral/submit_to_prey
name = "Submit To Prey"
desc = "Allow prey's mind to control your own body."
cost = 0
custom_only = FALSE
// Traitgenes made into a genetrait
is_genetrait = TRUE
hidden = FALSE
activation_message="Your mind feels more fluid."
/datum/trait/neutral/submit_to_prey/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..()
add_verb(H, /mob/living/proc/lend_prey_control)
// Traitgenes made into a genetrait
/datum/trait/neutral/submit_to_prey/unapply(datum/species/S, mob/living/carbon/human/H, trait_prefs)
..()
if(!(/mob/living/proc/lend_prey_control in S.inherent_verbs))
remove_verb(H,/mob/living/proc/lend_prey_control)
/datum/trait/neutral/vertical_nom
name = "Vertical Nom"
desc = "Allows you to consume people from up above."
@@ -1217,6 +1395,19 @@
input += "s"
return input
/datum/trait/neutral/drippy
name = "Drippy"
desc = "You cannot hold your form together, or produce a constant film of sludge that drips off of your body. Hope the station has a janitor."
cost = 0
var_changes = list("drippy" = 1)
// Traitgenes Made into a genetrait
is_genetrait = TRUE
hidden = FALSE
activation_message="You feel softer..."
primitive_expression_messages=list("drips.")
/datum/trait/neutral/mudking
name = "Mudking"
desc = "Somehow you are so filthy that tiles get dirty four times as quick from you walking on them."
@@ -9,6 +9,13 @@
// banned_species = list(SPECIES_ALRAUNE, SPECIES_SHADEKIN_CREW, SPECIES_TESHARI, SPECIES_TAJARAN, SPECIES_DIONA, SPECIES_UNATHI) //Either not applicable or buffs ruin species flavour/balance
// custom_only = FALSE //Keeping these in comments in case we decide to open them up in future, so the species are already organised.
// Traitgenes Replaces /datum/trait/positive/superpower_increaserun, made into a genetrait
is_genetrait = TRUE
hidden = FALSE
activation_message="Your leg muscles pulsate."
primitive_expression_messages=list("dances around.")
/datum/trait/positive/hardy
name = "Hardy"
desc = "Allows you to carry heavy equipment with less slowdown."
@@ -27,8 +34,8 @@
/datum/trait/positive/endurance_high
name = "High Endurance"
desc = "Increases your maximum total hitpoints to 125"
cost = 4
desc = "Increases your maximum total hitpoints to 125. You require 250 damage in total to die, compared to 200 normally. You will still go into crit after losing 125 HP, compared to crit at 100 HP."
cost = 3
var_changes = list("total_health" = 125)
custom_only = FALSE
banned_species = list(SPECIES_TESHARI, SPECIES_UNATHI, SPECIES_SHADEKIN_CREW) //Either not applicable or buffs are too strong
@@ -39,19 +46,19 @@
/datum/trait/positive/nonconductive
name = "Non-Conductive"
desc = "Decreases your susceptibility to electric shocks by a 10% amount."
cost = 1 //This effects tasers!
var_changes = list("siemens_coefficient" = 0.9)
desc = "Decreases your susceptibility to electric shocks by 25%."
cost = 2
var_changes = list("siemens_coefficient" = 0.75)
/datum/trait/positive/nonconductive_plus
name = "Non-Conductive, Major"
desc = "Decreases your susceptibility to electric shocks by a 25% amount."
cost = 2 //Let us not forget this effects tasers!
var_changes = list("siemens_coefficient" = 0.75)
desc = "Decreases your susceptibility to electric shocks by 50%."
cost = 3
var_changes = list("siemens_coefficient" = 0.5)
/datum/trait/positive/darksight
name = "Darksight"
desc = "Allows you to see a short distance in the dark."
desc = "Allows you to see a short distance in the dark and 10% more susceptible to flashes."
cost = 1
var_changes = list("darksight" = 5, "flash_mod" = 1.1)
custom_only = FALSE
@@ -59,7 +66,7 @@
/datum/trait/positive/darksight_plus
name = "Darksight, Major"
desc = "Allows you to see in the dark for the whole screen."
desc = "Allows you to see in the dark for almost the whole screen and 20% more susceptible to flashes."
cost = 2
var_changes = list("darksight" = 8, "flash_mod" = 1.2)
custom_only = FALSE
@@ -190,6 +197,7 @@
name = "Aquatic"
desc = "You can breathe under water and can traverse water more efficiently. Additionally, you can eat others in the water."
cost = 1
custom_only = FALSE
var_changes = list("water_breather" = 1, "water_movement" = -4) //Negate shallow water. Half the speed in deep water.
allowed_species = list(SPECIES_HANNER, SPECIES_CUSTOM) //So it only shows up for custom species and hanner
custom_only = FALSE
@@ -301,3 +309,59 @@
varchange_type = TRAIT_VARCHANGE_LESS_BETTER
excludes = list(/datum/trait/negative/bad_swimmer)
banned_species = list(SPECIES_AKULA) // They already swim better than this
/datum/trait/positive/table_passer
name = "Table Passer"
desc = "You move over or under tables with ease of a Teshari."
cost = 2
// Traitgenes Replacement for /datum/trait/positive/superpower_midget, made into a genetrait
is_genetrait = TRUE
hidden = FALSE
activation_message="Your skin feels rubbery."
has_preferences = list("pass_table" = list(TRAIT_PREF_TYPE_BOOLEAN, "On spawn", TRAIT_NO_VAREDIT_TARGET, TRUE))
/datum/trait/positive/table_passer/apply(var/datum/species/S,var/mob/living/carbon/human/H, var/list/trait_prefs)
..()
if (trait_prefs?["pass_table"] || !trait_prefs)
H.pass_flags |= PASSTABLE
add_verb(H,/mob/living/proc/toggle_pass_table)
// Traitgenes All genetraits need an unapply proc if they do anything special
/datum/trait/positive/table_passer/unapply(datum/species/S, mob/living/carbon/human/H)
. = ..()
if (H.pass_flags & PASSTABLE)
H.pass_flags ^= PASSTABLE
if(!(/mob/living/proc/toggle_pass_table in S.inherent_verbs)) // Teshari shouldn't lose agility
remove_verb(H,/mob/living/proc/toggle_pass_table)
/datum/trait/positive/photosynth
name = "Photosynthesis"
desc = "Your body is able to produce nutrition from being in light."
cost = 3
var_changes = list("photosynthesizing" = TRUE)
can_take = ORGANICS|SYNTHETICS //Synths actually use nutrition, just with a fancy covering.
/datum/trait/positive/rad_resistance
name = "Radiation Resistance"
desc = "You are generally more resistant to radiation, and it dissipates faster from your body."
cost = 1
var_changes = list("radiation_mod" = 0.65, "rad_removal_mod" = 3.5, "rad_levels" = list("safe" = 70, "danger_1" = 150, "danger_2" = 450, "danger_3" = 600, "danger_4" = 2250))
/datum/trait/positive/rad_resistance_extreme
name = "Radiation Resistance, Major"
desc = "You are much more resistant to radiation, and it dissipates much faster from your body."
cost = 2
var_changes = list("radiation_mod" = 0.5, "rad_removal_mod" = 5, "rad_levels" = list("safe" = 150, "danger_1" = 300, "danger_2" = 600, "danger_3" = 1000, "danger_4" = 3000))
/datum/trait/positive/rad_immune
name = "Radiation Immunity"
desc = "For whatever reason, be it a more dense build or some quirk of your genetic code, your body is completely immune to radiation."
cost = 3
var_changes = list("radiation_mod" = 0.0, "rad_removal_mod" = 10, "rad_levels" = list("safe" = 10000, "danger_1" = 10001, "danger_2" = 10002, "danger_3" = 10003, "danger_4" = 10004))
// Traitgenes
is_genetrait = TRUE
hidden = FALSE
activation_message="Your body feels mundane."
@@ -0,0 +1,206 @@
/datum/trait/positive/superpower_nobreathe
name = "No Breathing"
desc = "You do not need to breathe."
cost = 5
custom_only = FALSE
is_genetrait = TRUE
hidden = TRUE // Cannot start with superpowers
mutation = mNobreath
activity_bounds = DNA_HARD_BOUNDS
activation_message="You feel no need to breathe."
/*
/datum/trait/positive/superpower_remoteview
name = "Remote Viewing"
desc = "Remotely view other locations."
cost = 5
custom_only = FALSE
is_genetrait = TRUE
activity_bounds = DNA_HARDER_BOUNDS
hidden = TRUE // Cannot start with superpowers
mutation = mRemote
activation_message="Your mind expands."
/datum/trait/positive/superpower_remoteview/apply(datum/species/S, mob/living/carbon/human/H)
. = ..()
add_verb(H, /mob/living/carbon/human/proc/remoteobserve)
/datum/trait/positive/superpower_remoteview/unapply(datum/species/S, mob/living/carbon/human/H)
. = ..()
if(/mob/living/carbon/human/proc/remoteobserve in S.inherent_verbs)
remove_verb(H, /mob/living/carbon/human/proc/remoteobserve)
*/
/datum/trait/positive/superpower_regenerate
name = "Regenerate"
desc = "Repairs wounds slowly, including internal bleeding."
cost = 5
custom_only = FALSE
is_genetrait = TRUE
activity_bounds = DNA_HARDER_BOUNDS
hidden = TRUE // Cannot start with superpowers
mutation = mRegen
activation_message="You feel better."
primitive_expression_messages=list("'s skin shift's strangely.")
/* Replaced by /datum/trait/positive/speed_fast
/datum/trait/positive/superpower_increaserun
name = "Super Speed"
desc = "Remotely communicate"
cost = 5
custom_only = FALSE
is_genetrait = TRUE
activity_bounds = DNA_HARDER_BOUNDS
hidden = TRUE // Cannot start with superpowers
mutation = mRun
activation_message="Your leg muscles pulsate."
*/
/datum/trait/positive/superpower_remotetalk
name = "Telepathy"
desc = "Remotely communicate"
cost = 5
custom_only = FALSE
is_genetrait = TRUE
hidden = TRUE // Cannot start with superpowers
mutation = mRemotetalk
activity_bounds = DNA_HARDER_BOUNDS
activation_message="You expand your mind outwards."
primitive_expression_messages=list("makes noises to itself.")
/datum/trait/positive/superpower_remotetalk/apply(datum/species/S, mob/living/carbon/human/H)
. = ..()
add_verb(H, /mob/living/carbon/human/proc/remotesay)
/datum/trait/positive/superpower_remotetalk/unapply(datum/species/S, mob/living/carbon/human/H)
. = ..()
if(!(/mob/living/carbon/human/proc/remotesay in S.inherent_verbs))
remove_verb(H, /mob/living/carbon/human/proc/remotesay)
/datum/trait/positive/superpower_noprints
name = "No Prints"
desc = "Your hands leave no fingerprints behind."
cost = 5
custom_only = FALSE
is_genetrait = TRUE
hidden = TRUE // Cannot start with superpowers
mutation = mFingerprints
activation_message="Your fingers feel numb."
primitive_expression_messages=list("flexes its digits.")
/datum/trait/positive/superpower_xray //This is effectively thermals.
name = "X-Ray Vision"
desc = "You can see through walls."
cost = 5
custom_only = FALSE
is_genetrait = TRUE
activity_bounds = DNA_HARDER_BOUNDS
hidden = TRUE // Cannot start with superpowers
mutation = XRAY
activation_message="The walls suddenly disappear."
primitive_expression_messages=list("stares at something it cannot see.")
/datum/trait/positive/superpower_tk
name = "Telekenesis"
desc = "You can move objects with your mind."
cost = 5
custom_only = FALSE
is_genetrait = TRUE
activity_bounds = DNA_HARD_BOUNDS
hidden = TRUE // Cannot start with superpowers
mutation = TK
activation_message="You feel smarter."
primitive_expression_messages=list("grabs at something it cannot reach.")
/datum/trait/positive/superpower_laser
name = "Laser Vision"
desc = "You can blast lasers from your eyes."
cost = 5
custom_only = FALSE
is_genetrait = TRUE
activity_bounds = DNA_HARD_BOUNDS
hidden = TRUE // Cannot start with superpowers
mutation = LASER
activation_message="Your eyes feel strange..."
/datum/trait/positive/superpower_hulk
name = "Hulk"
desc = "UURGG SMASH TINY TESHARI"
cost = 5
custom_only = FALSE
is_genetrait = TRUE
activity_bounds = DNA_HARD_BOUNDS
hidden = TRUE // Cannot start with superpowers
mutation = HULK
activation_message="Your muscles hurt."
deactivation_message=span_warning("You suddenly feel very weak.")
/datum/trait/positive/superpower_hulk/handle_environment_special(mob/living/carbon/human/H)
if(H.health <= 25)
if(H.dna)
H.dna.SetSEState(linked_gene.block, FALSE, FALSE) // Turn this thing off or so help me--
domutcheck(H,null,MUTCHK_FORCED)
H.mutations.Remove(HULK)
H.Weaken(3)
H.emote("collapse")
/datum/trait/positive/superpower_flashproof
name = "Flash Resistance"
desc = "Your eyes are protected against sudden flashes of intense light."
cost = 5
custom_only = FALSE
is_genetrait = TRUE
activity_bounds = DNA_HARDER_BOUNDS
hidden = TRUE // Cannot start with superpowers
mutation = FLASHPROOF
activation_message="Your eyes feel more robust, how nifty..."
/datum/trait/positive/superpower_morph
name = "Morph"
desc = "Allows complex bodily transformations."
cost = 5
custom_only = FALSE
is_genetrait = TRUE
activity_bounds = DNA_HARDER_BOUNDS
hidden = TRUE // Cannot start with superpowers
activation_message="You feel more fluid."
primitive_expression_messages=list("twitches and distorts.")
/datum/trait/positive/superpower_morph/apply(datum/species/S, mob/living/carbon/human/H)
. = ..()
add_verb(H, /mob/living/carbon/human/proc/shapeshfit_form)
/datum/trait/positive/superpower_morph/unapply(datum/species/S, mob/living/carbon/human/H)
. = ..()
remove_verb(H, /mob/living/carbon/human/proc/shapeshfit_form)
/mob/living/carbon/human/proc/shapeshfit_form()
set name = "Transform Shape"
set category = "Abilities.Superpower"
var/datum/tgui_module/appearance_changer/superpower/V = new(src, src)
V.tgui_interact(src)
@@ -11,18 +11,44 @@
var/list/excludes // Store a list of paths of traits to exclude, but done automatically if they change the same vars.
var/can_take = ORGANICS|SYNTHETICS // Can freaking synths use those.
var/list/banned_species // A list of species that can't take this trait
var/list/allowed_species // VORESTATION EDIT:chomp port. A list of species that CAN take this trait, use this if only a few species can use it. -shark
var/list/allowed_species // A list of species that CAN take this trait, use this if only a few species can use it. -shark
var/custom_only = TRUE // Trait only available for custom species
var/varchange_type = TRAIT_VARCHANGE_ALWAYS_OVERRIDE //Mostly used for non-custom species.
var/has_preferences //if set, should be a list of the preferences for this trait in the format: list("identifier/name of var to edit" = list(typeofpref, "text to display in prefs", TRAIT_NO_VAREDIT_TARGET/TRAIT_VAREDIT_TARGET_SPECIES/etc, (optional: default value)), etc) typeofpref should follow the defines in _traits.dm (eg. TRAIT_PREF_TYPE_BOOLEAN)
var/special_env = FALSE
// Traitgenes Traits can toggle mutations and disabilities
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IMPORTANT - in 99% of situations you should NOT need to edit gene code when adding a new traitgene. Genes only handle the on/off state of traits, traits control the changes and behaviors!
// Just keep pretending genecode doesn't exist and you should be fine. Traitgenes were made with that in mind, and are not intended to be something you need to edit every time you add a traitgene.
// Traitgenes only require that your trait has both an apply() and unapply() if it does anything like adding verbs. Otherwise, you don't even need to add trait exceptions. traitgenes handle it automatically.
// You probably shouldn't mark traits as traitgenes if they are custom species only, species locked, or species banned traits however... - Willbird
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var/is_genetrait = FALSE // When their trait's datum is init, it will be added to the library of genes a carbon can be mutated to have or not have
var/list/activity_bounds = DNA_DEFAULT_BOUNDS // Activation requirement for trait to turn on/off. Dna is automatically configured for this when first spawned
var/hidden = FALSE // If a trait does not show on the list, only useful for genetics only traits that cannot be taken at character creation
var/mutation = 0 // Mutation to give (or 0)
var/disability = 0 // Disability to give (or 0)
var/sdisability = 0 // SDisability to give (or 0)
var/activation_message = null // If not null, shows a message when activated as a gene
var/deactivation_message = null // If not null, shows a message when deactivated as a gene
var/list/primitive_expression_messages=list() // Monkey's custom emote when they have this gene!
var/datum/gene/trait/linked_gene = null // Internal use, do not assign.
//Proc can be overridden lower to include special changes, make sure to call up though for the vars changes
/datum/trait/proc/apply(var/datum/species/S,var/mob/living/carbon/human/H, var/trait_prefs = null) //VOREStation edit: trait_prefs is a list in the format: list(identifier = value, etc)
/datum/trait/proc/apply(var/datum/species/S,var/mob/living/carbon/human/H, var/trait_prefs = null)
ASSERT(S)
if(var_changes)
for(var/V in var_changes)
if((category == TRAIT_TYPE_POSITIVE && ((varchange_type == TRAIT_VARCHANGE_LESS_BETTER && var_changes[V] > S.vars[V]) || (varchange_type == TRAIT_VARCHANGE_MORE_BETTER && var_changes[V] < S.vars[V]))) || (category == TRAIT_TYPE_NEGATIVE && ((varchange_type == TRAIT_VARCHANGE_LESS_BETTER && var_changes[V] < S.vars[V]) || (varchange_type == TRAIT_VARCHANGE_MORE_BETTER && var_changes[V] > S.vars[V]))))
continue
S.vars[V] = var_changes[V]
if (trait_prefs)
for (var/trait in trait_prefs)
@@ -33,9 +59,55 @@
S.vars[trait] = trait_prefs[trait]
if(TRAIT_VAREDIT_TARGET_MOB)
H.vars[trait] = trait_prefs[trait]
// Traitgenes Traits can toggle mutations and disabilities
if(mutation)
if(!(mutation in H.mutations))
H.mutations.Add(mutation)
if(disability)
H.disabilities |= disability // bitflag
if(sdisability)
H.sdisabilities |= sdisability // bitflag
add_verb(H, /mob/living/carbon/human/proc/trait_tutorial)
if(special_env)
S.env_traits += src
return
// Traitgenes Disabling traits, genes can be turned off after all!
/datum/trait/proc/unapply(var/datum/species/S,var/mob/living/carbon/human/H, var/trait_prefs = null)
ASSERT(S)
if(var_changes)
for(var/V in var_changes)
S.vars[V] = initial(S.vars[V])
if (trait_prefs)
for (var/trait in trait_prefs)
switch(has_preferences[trait][3])
if(TRAIT_NO_VAREDIT_TARGET)
continue
if(TRAIT_VAREDIT_TARGET_SPECIES)
S.vars[trait] = initial(S.vars[trait])
if(TRAIT_VAREDIT_TARGET_MOB)
H.vars[trait] = initial(H.vars[trait])
if(mutation)
H.mutations.Remove(mutation)
if(disability)
H.disabilities &= ~disability // bitflag
if(sdisability)
H.sdisabilities &= ~sdisability // bitflag
if(special_env)
S.env_traits -= src
return
/datum/trait/proc/send_message(var/mob/living/carbon/human/H, var/enabled)
if(enabled)
if(!activation_message)
return
to_chat(H,activation_message)
else
if(!deactivation_message)
return
to_chat(H,deactivation_message)
// Traitgenes edit end
//Applying trait to preferences rather than just us.
/datum/trait/proc/apply_pref(var/datum/preferences/P)
ASSERT(P)
@@ -57,7 +129,6 @@
P.vars[V] = initial(P.vars[V])
return
//VOREStation edit: trait preferences
/datum/trait/proc/get_default_prefs()
if (!LAZYLEN(has_preferences))
return null
@@ -86,3 +157,6 @@
if (length(input) <= 0)
return default_value_for_pref(pref)
return input
/datum/trait/proc/handle_environment_special(var/mob/living/carbon/human/H)
return
@@ -2,6 +2,8 @@
Global associative list for caching humanoid icons.
Index format m or f, followed by a string of 0 and 1 to represent bodyparts followed by husk fat hulk skeleton 1 or 0.
*/
//TODO: Get all these up to date with Chomp. I'd rather not do an entire caching update with the genetics PR, thanks.
var/global/list/human_icon_cache = list() //key is incredibly complex, see update_icons_body()
var/global/list/tail_icon_cache = list() //key is [species.race_key][r_skin][g_skin][b_skin]
var/global/list/wing_icon_cache = list() // See tail.
@@ -599,21 +601,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
if(!LAZYLEN(mutations))
return //No mutations, no icons.
//TODO: THIS PROC???
var/fat
if(FAT in mutations)
fat = "fat"
var/image/standing = image(icon = 'icons/effects/genetics.dmi', layer = BODY_LAYER+MUTATIONS_LAYER)
var/g = gender == FEMALE ? "f" : "m"
for(var/datum/dna/gene/gene in dna_genes)
if(!gene.block)
continue
if(gene.is_active(src))
var/underlay = gene.OnDrawUnderlays(src,g,fat)
if(underlay)
standing.underlays += underlay
for(var/mut in mutations)
if(mut == LASER)
+4 -5
View File
@@ -6,7 +6,7 @@
if (transforming)
return
handle_modifiers() //VOREStation Edit - Needs to be done even if in nullspace.
handle_modifiers() //Needs to be done even if in nullspace.
if(!loc)
return
@@ -16,8 +16,6 @@
else
environment = loc.return_air()
//handle_modifiers() // Do this early since it might affect other things later. //VOREStation Edit
handle_light()
if(stat != DEAD)
@@ -66,7 +64,6 @@
handle_ambience()
//stuff in the stomach
//handle_stomach() //VOREStation Code
update_gravity(mob_get_gravity())
@@ -85,7 +82,9 @@
handle_vision()
handle_tf_holder() //VOREStation Addition
handle_tf_holder()
handle_dripping()
/mob/living/proc/handle_breathing()
return
+51
View File
@@ -840,6 +840,13 @@
/mob/living/carbon/drop_from_inventory(var/obj/item/W, var/atom/target = null)
return !(W in internal_organs) && ..()
/mob/living/proc/drop_both_hands()
if(l_hand)
unEquip(l_hand)
if(r_hand)
unEquip(r_hand)
return
/mob/living/touch_map_edge()
//check for nuke disks
@@ -1352,3 +1359,47 @@
to_chat(src, span_notice("You are [toggled_sleeping ? "now sleeping. Use the Sleep verb again to wake up" : "no longer sleeping"]."))
if(toggled_sleeping)
Sleeping(1)
/mob/living/proc/handle_dripping()
if(prob(95))
return
if(!isturf(src.loc))
return
if(ishuman(src))
var/mob/living/carbon/human/H = src
if(H.species && H.species.drippy)
// drip body color if human
var/obj/effect/decal/cleanable/blood/B
var/decal_type = /obj/effect/decal/cleanable/blood/splatter
var/turf/T = get_turf(src.loc)
// Are we dripping or splattering?
var/list/drips = list()
// Only a certain number of drips (or one large splatter) can be on a given turf.
for(var/obj/effect/decal/cleanable/blood/drip/drop in T)
drips |= drop.drips
qdel(drop)
if(drips.len < 6)
decal_type = /obj/effect/decal/cleanable/blood/drip
// Find a blood decal or create a new one.
B = locate(decal_type) in T
if(!B)
B = new decal_type(T)
var/obj/effect/decal/cleanable/blood/drip/drop = B
if(istype(drop) && drips && drips.len)
drop.add_overlay(drips)
drop.drips |= drips
// Update appearance.
drop.name = "drips of something"
drop.desc = "It's thick and gooey. Perhaps it's the chef's cooking?"
drop.dryname = "dried something"
drop.drydesc = "It's dry and crusty. The janitor isn't doing their job."
drop.basecolor = rgb(H.r_skin,H.g_skin,H.b_skin)
drop.update_icon()
drop.fluorescent = 0
drop.invisibility = 0
//else
// come up with drips for other mobs someday
+2 -4
View File
@@ -126,12 +126,10 @@ default behaviour is:
tmob.forceMove(oldloc)
now_pushing = 0
return
//VOREStation Edit - Begin
else if((tmob.mob_always_swap || (tmob.a_intent == I_HELP || tmob.restrained()) && (a_intent == I_HELP || src.restrained())) && canmove && can_swap && handle_micro_bump_helping(tmob))
forceMove(tmob.loc)
now_pushing = 0
return
//VOREStation Edit - End
if(!can_move_mob(tmob, 0, 0))
now_pushing = 0
@@ -139,11 +137,12 @@ default behaviour is:
if(a_intent == I_HELP || src.restrained())
now_pushing = 0
return
// VOREStation Edit - Begin
// Plow that nerd.
if(ishuman(tmob))
var/mob/living/carbon/human/H = tmob
if(H.species.lightweight == 1 && prob(50))
if(HULK in H.mutations) //No knocking over the hulk
return
H.visible_message(span_warning("[src] bumps into [H], knocking them off balance!"))
H.Weaken(5)
now_pushing = 0
@@ -151,7 +150,6 @@ default behaviour is:
// Handle grabbing, stomping, and such of micros!
if(step_mechanics_pref && tmob.step_mechanics_pref)
if(handle_micro_bump_other(tmob)) return
// VOREStation Edit - End
if(ishuman(tmob) && (FAT in tmob.mutations))
if(prob(40) && !(FAT in src.mutations))
to_chat(src, span_danger("You fail to push [tmob]'s fat ass out of the way."))
+9 -2
View File
@@ -100,6 +100,10 @@ var/list/channel_to_radio_key = new
if(S.speaking && (S.speaking.flags & NO_STUTTER || S.speaking.flags & SIGNLANG))
continue
if(disabilities & CENSORED)
S.message = censor_swears(S.message) // Googlybonkers
. = 1
if((HULK in mutations) && health >= 25 && length(S.message))
S.message = "[uppertext(S.message)]!!!"
verb = pick("yells","roars","hollers")
@@ -113,12 +117,15 @@ var/list/channel_to_radio_key = new
S.message = stutter(S.message)
verb = pick("stammers","stutters")
. = 1
//VOREStation Edit Start
if(muffled)
verb = pick("muffles")
whispering = 1
. = 1
//VOREStation Edit End
if(disabilities & WINGDINGS)
verb = pick("gibbers","gabbers","gahoos","gazonks") // Yeah lets just be stupid
S.message = Gibberish(S.message, 100) // Googlybonkers
S.message = span_wingdings((S.message))
. = 1
message_data[1] = message_pieces
message_data[2] = verb
@@ -468,6 +468,14 @@
var/obj/belly/B = loc
src.forceMove(card)
card.forceMove(B)
if(istype( src.loc,/obj/structure/disposalholder))
var/obj/structure/disposalholder/hold = loc
src.loc = card
card.loc = hold
src.forceMove(card)
card.forceMove(hold)
else //Otherwise go on floor
src.loc = card
card.loc = get_turf(card)
+43 -1
View File
@@ -253,8 +253,11 @@
if(p >= 70)
letter = ""
var/rand_set = list("#","@","*","&","%","$","/", "<", ">", ";","*","*","*","*","*","*","*")
if(p >= 80)
rand_set += alphabet_uppercase
for(var/j = 1, j <= rand(0, 2), j++)
letter += pick("#","@","*","&","%","$","/", "<", ">", ";","*","*","*","*","*","*","*")
letter += pick(rand_set)
returntext += letter
@@ -686,3 +689,42 @@ var/global/image/backplane
/mob/proc/can_feed()
return TRUE
/proc/censor_swears(t)
/* Bleeps our swearing */
var/static/swear_censoring_list = list("fuck",
"shit",
"damn",
"piss",
"whore",
"cunt",
"bitch",
"bastard",
"dick",
"cock",
"slut",
"dong",
"pussy",
"twat",
"snatch",
"schlong",
"damn",
"dammit",
"damnit",
"ass",
"tit",
"douch",
"prick",
"hell",
"crap")
var/haystack = t
for(var/filter in swear_censoring_list)
var/regex/needle = regex(filter, "i")
while(TRUE)
var/pos = needle.Find(haystack)
if(!pos)
break
var/partial_start = copytext(haystack,1,pos)
var/partial_end = copytext(haystack,pos+length(filter),length(haystack)+1)
haystack = "[partial_start][pick("BEEP","BLEEP","BOINK","BEEEEEP")][partial_end]"
return haystack
+21 -37
View File
@@ -61,9 +61,10 @@
output += "<p>\[ " + span_linkOn(span_bold("Ready")) + " | <a href='byond://?src=\ref[src];ready=0'>Not Ready</a> \]</p>"
else
output += "<p>\[ <a href='byond://?src=\ref[src];ready=1'>Ready</a> | " + span_linkOn(span_bold("Not Ready")) + " \]</p>"
output += "<p><s>Join Game!</s></p>"
else
output += "<a href='byond://?src=\ref[src];manifest=1'>View the Crew Manifest</A><br><br>"
output += "<p><a href='byond://?src=\ref[src];manifest=1'>View the Crew Manifest</A></p>"
output += "<p><a href='byond://?src=\ref[src];late_join=1'>Join Game!</A></p>"
output += "<p><a href='byond://?src=\ref[src];observe=1'>Observe</A></p>"
@@ -86,21 +87,31 @@
qdel(query)
if(newpoll)
output += "<p><b><a href='byond://?src=\ref[src];showpoll=1'>Show Player Polls</A> (NEW!)</b></p>"
output += "<p><b><a href='byond://?src=\ref[src];showpoll=1'>Show Player Polls</A><br>(NEW!)</b></p>"
else
output += "<p><a href='byond://?src=\ref[src];showpoll=1'>Show Player Polls</A></p>"
output += "<p><a href='byond://?src=\ref[src];showpoll=1'>Show Player Polls</A><br><i>No Changes</i></p>"
*/
output += "<p><a href='byond://?src=\ref[src];open_changelog=1'>View Changelog</A></p>"
if(client?.check_for_new_server_news())
output += "<p><b><a href='byond://?src=\ref[src];shownews=1'>Show Server News</A><br>(NEW!)</b></p>"
else
output += "<p><a href='byond://?src=\ref[src];shownews=1'>Show Server News</A><br><i>No Changes</i></p>"
if(SSsqlite.can_submit_feedback(client))
output += "<p>[href(src, list("give_feedback" = 1), "Give Feedback")]</p>"
if(GLOB.news_data.station_newspaper)
if(client.prefs.lastlorenews == GLOB.news_data.newsindex)
output += "<p><a href='byond://?src=\ref[src];open_station_news=1'>Show [using_map.station_name] News</A></p>"
output += "<p><a href='byond://?src=\ref[src];open_station_news=1'>Show [using_map.station_name] News<br><i>No Changes</i></A></p>"
else
output += "<p><b><a href='byond://?src=\ref[src];open_station_news=1'>Show [using_map.station_name] News (NEW!)</A></b></p>"
output += "<p><b><a href='byond://?src=\ref[src];open_station_news=1'>Show [using_map.station_name] News<br>(NEW!)</A></b></p>"
/* //TODO: Actually add the fukin changelog. We need it DESPERATELY but this isn't the PR for it.
if(client.prefs.lastchangelog == changelog_hash)
output += "<p><a href='byond://?src=\ref[src];open_changelog=1'>Show Changelog</A><br><i>No Changes</i></p>"
else
output += "<p><b><a href='byond://?src=\ref[src];open_changelog=1'>Show Changelog</A><br>(NEW!)</b></p>"
*/
output += "</div>"
@@ -112,7 +123,7 @@
client.prefs.lastlorenews = GLOB.news_data.newsindex
SScharacter_setup.queue_preferences_save(client.prefs)
panel = new(src, "Welcome","Welcome", 210, 320, src) // VOREStation Edit
panel = new(src, "Welcome","Welcome", 210, 500, src)
panel.set_window_options("can_close=0")
panel.set_content(output)
panel.open()
@@ -166,7 +177,6 @@
ready = 0
if(href_list["refresh"])
//src << browse(null, "window=playersetup") //closes the player setup window
panel.close()
new_player_panel_proc()
@@ -179,7 +189,6 @@
client.prefs.dress_preview_mob(mannequin)
var/mob/observer/dead/observer = new(mannequin)
observer.moveToNullspace() //Let's not stay in our doomed mannequin
//qdel(mannequin)
spawning = 1
if(client.media)
@@ -207,7 +216,7 @@
observer.client.init_verbs()
qdel(src)
return 1
return TRUE
if(href_list["late_join"])
@@ -221,13 +230,6 @@
else if(time_till_respawn) // Nonzero time to respawn
to_chat(usr, span_warning("You can't respawn yet! You need to wait another [round(time_till_respawn/10/60, 0.1)] minutes."))
return
/*
if(client.prefs.species != "Human" && !check_rights(R_ADMIN, 0)) //VORESTATION EDITS: THE COMMENTED OUT AREAS FROM LINE 154 TO 178
if (config.usealienwhitelist)
if(!is_alien_whitelisted(src, client.prefs.species))
tgui_alert(src, "You are currently not whitelisted to Play [client.prefs.species].")
return 0
*/
LateChoices()
if(href_list["manifest"])
@@ -401,14 +403,12 @@
return 0
if(!job.player_old_enough(src.client))
return 0
//VOREStation Add
if(!job.player_has_enough_playtime(src.client))
return 0
if(!is_job_whitelisted(src,rank))
return 0
if(!job.player_has_enough_pto(src.client))
return 0
//VOREStation Add End
return 1
@@ -424,7 +424,7 @@
if(!IsJobAvailable(rank))
tgui_alert_async(src,"[rank] is not available. Please try another.")
return 0
if(!spawn_checks_vr(rank)) return 0 // VOREStation Insert
if(!spawn_checks_vr(rank)) return 0
if(!client)
return 0
@@ -474,11 +474,6 @@
qdel(src) //Deletes new_player
return
// Equip our custom items only AFTER deploying to spawn points eh?
//equip_custom_items(character) //VOREStation Removal
//character.apply_traits() //VOREStation Removal
// Moving wheelchair if they have one
if(character.buckled && istype(character.buckled, /obj/structure/bed/chair/wheelchair))
character.buckled.loc = character.loc
@@ -547,27 +542,17 @@
if(mind)
mind.active = 0 //we wish to transfer the key manually
// VOREStation edit to disable the destructive forced renaming for our responsible whitelist clowns.
//if(mind.assigned_role == JOB_CLOWN) //give them a clownname if they are a clown
// new_character.real_name = pick(clown_names) //I hate this being here of all places but unfortunately dna is based on real_name!
// new_character.rename_self("clown")
mind.original = new_character
// VOREStation
mind.loaded_from_ckey = client.ckey
mind.loaded_from_slot = client.prefs.default_slot
// VOREStation
//mind.traits = client.prefs.traits.Copy() // VOREStation conflict
mind.transfer_to(new_character) //won't transfer key since the mind is not active
new_character.name = real_name
client.init_verbs()
new_character.dna.ready_dna(new_character)
new_character.dna.b_type = client.prefs.b_type
new_character.sync_dna_traits(TRUE) // Traitgenes Sync traits to genetics if needed
new_character.sync_organ_dna()
if(client.prefs.disabilities)
// Set defer to 1 if you add more crap here so it only recalculates struc_enzymes once. - N3X
new_character.dna.SetSEState(GLASSESBLOCK,1,0)
new_character.disabilities |= NEARSIGHTED
for(var/lang in client.prefs.alternate_languages)
var/datum/language/chosen_language = GLOB.all_languages[lang]
@@ -612,7 +597,6 @@
src << browse(null, "window=latechoices") //closes late choices window
src << browse(null, "window=preferences_window") //VOREStation Edit?
src << browse(null, "window=News") //closes news window
//src << browse(null, "window=playersetup") //closes the player setup window
panel.close()
/mob/new_player/proc/has_admin_rights()
@@ -224,7 +224,7 @@
// Determine what job is marked as 'High' priority, and dress them up as such.
if(job_civilian_low & ASSISTANT)
previewJob = job_master.GetJob(JOB_ALT_VISITOR)
else if(ispAI(client.mob)) //VOREStation Edit! - pAIs shouldn't wear job gear~!
else if(client && ispAI(client.mob)) //VOREStation Edit! - pAIs shouldn't wear job gear~!
//Don't do anything!
else
for(var/datum/job/job in job_master.occupations)
-4
View File
@@ -33,8 +33,6 @@
for(var/obj/item/W in src)
drop_from_inventory(W)
set_species(species.primitive_form)
dna.SetSEState(MONKEYBLOCK,1)
dna.SetSEValueRange(MONKEYBLOCK,0xDAC, 0xFFF)
to_chat(src, span_infoplain(span_bold("You are now [species.name]. ")))
qdel(animation)
@@ -51,12 +49,10 @@
for(var/t in organs)
qdel(t)
//VOREStation Edit Start - Hologram examine flavor
var/mob/living/silicon/ai/O = ..(move)
if(O)
O.flavor_text = O.client?.prefs?.flavor_texts["general"]
return O
//VOREStation Edit End
return ..(move)