diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm index bdd7ac4179..7e095329af 100644 --- a/_maps/map_files/generic/CentCom.dmm +++ b/_maps/map_files/generic/CentCom.dmm @@ -2109,7 +2109,6 @@ /turf/closed/indestructible/riveted, /area/space) "fy" = ( -/obj/machinery/igniter/on, /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/tdome/arena_source) @@ -15119,7 +15118,6 @@ /turf/open/floor/plasteel, /area/tdome/tdomeobserve) "Is" = ( -/obj/machinery/igniter/on, /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/tdome/arena) diff --git a/_maps/templates/shelter_3.dmm b/_maps/templates/shelter_3.dmm new file mode 100644 index 0000000000..b71da1fba0 --- /dev/null +++ b/_maps/templates/shelter_3.dmm @@ -0,0 +1,414 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/closed/wall/mineral/titanium/survival/pod, +/area/survivalpod) +"b" = ( +/obj/structure/sign/mining/survival{ + dir = 1 + }, +/turf/closed/wall/mineral/titanium/survival/pod, +/area/survivalpod) +"c" = ( +/turf/closed/wall/mineral/titanium/survival/nodiagonal, +/area/survivalpod) +"d" = ( +/obj/structure/sign/mining/survival{ + dir = 1 + }, +/turf/closed/wall/mineral/titanium/survival/nodiagonal, +/area/survivalpod) +"e" = ( +/obj/structure/sign/mining/survival{ + dir = 8 + }, +/turf/closed/wall/mineral/titanium/survival/nodiagonal, +/area/survivalpod) +"f" = ( +/obj/structure/table/wood/fancy/black, +/obj/machinery/chem_dispenser/drinks, +/turf/open/floor/pod/dark, +/area/survivalpod) +"g" = ( +/obj/structure/table/wood/fancy/black, +/obj/machinery/chem_dispenser/drinks/beer, +/obj/machinery/light{ + dir = 1 + }, +/turf/open/floor/pod/dark, +/area/survivalpod) +"h" = ( +/obj/machinery/vending/boozeomat, +/turf/open/floor/pod/dark, +/area/survivalpod) +"i" = ( +/obj/item/book/manual/wiki/barman_recipes, +/obj/item/reagent_containers/food/drinks/shaker, +/obj/item/reagent_containers/rag, +/obj/structure/table/wood/fancy/black, +/turf/open/floor/pod/dark, +/area/survivalpod) +"j" = ( +/obj/structure/table/wood/fancy/black, +/obj/item/clipboard, +/obj/item/toy/figure/bartender, +/turf/open/floor/pod/dark, +/area/survivalpod) +"k" = ( +/obj/structure/table/wood/fancy/black, +/obj/item/storage/fancy/cigarettes/cigars, +/obj/item/storage/fancy/cigarettes/cigars/cohiba{ + pixel_y = 4 + }, +/obj/item/storage/fancy/cigarettes/cigars/havana{ + pixel_y = 8 + }, +/turf/open/floor/pod/dark, +/area/survivalpod) +"l" = ( +/obj/structure/table/wood/fancy/black, +/obj/structure/reagent_dispensers/beerkeg, +/turf/open/floor/pod/dark, +/area/survivalpod) +"m" = ( +/obj/structure/closet/secure_closet/bar, +/obj/machinery/light{ + dir = 1 + }, +/turf/open/floor/pod/dark, +/area/survivalpod) +"n" = ( +/obj/structure/disposalpipe/trunk{ + dir = 4 + }, +/obj/machinery/disposal/bin, +/turf/open/floor/pod/dark, +/area/survivalpod) +"o" = ( +/obj/structure/sign/mining/survival{ + dir = 4 + }, +/obj/structure/disposalpipe/junction{ + dir = 4 + }, +/turf/closed/wall/mineral/titanium/survival/pod, +/area/survivalpod) +"p" = ( +/obj/machinery/door/airlock/survival_pod/glass{ + req_access_txt = "25" + }, +/obj/structure/fans/tiny, +/turf/open/floor/pod/dark, +/area/survivalpod) +"q" = ( +/turf/open/floor/pod/dark, +/area/survivalpod) +"r" = ( +/obj/structure/disposalpipe/segment, +/turf/closed/wall/mineral/titanium/survival/nodiagonal, +/area/survivalpod) +"s" = ( +/obj/structure/table/reinforced, +/obj/item/lighter{ + pixel_x = -4; + pixel_y = 4 + }, +/obj/item/lighter, +/turf/open/floor/pod/dark, +/area/survivalpod) +"t" = ( +/obj/structure/table/reinforced, +/turf/open/floor/pod/dark, +/area/survivalpod) +"u" = ( +/obj/structure/table/reinforced, +/obj/item/storage/box/matches{ + pixel_x = -4; + pixel_y = 8 + }, +/turf/open/floor/pod/dark, +/area/survivalpod) +"v" = ( +/obj/machinery/door/window/survival_pod{ + req_access_txt = "25" + }, +/turf/open/floor/pod/dark, +/area/survivalpod) +"w" = ( +/obj/structure/sign/mining/survival{ + dir = 4 + }, +/obj/structure/disposalpipe/segment, +/turf/closed/wall/mineral/titanium/survival/nodiagonal, +/area/survivalpod) +"x" = ( +/obj/structure/chair/stool/bar, +/turf/open/floor/carpet/black, +/area/survivalpod) +"y" = ( +/turf/open/floor/carpet/black, +/area/survivalpod) +"z" = ( +/obj/machinery/vending/cigarette/beach, +/turf/open/floor/carpet/black, +/area/survivalpod) +"A" = ( +/obj/structure/disposalpipe/trunk{ + dir = 4 + }, +/obj/machinery/disposal/bin, +/turf/open/floor/carpet/black, +/area/survivalpod) +"B" = ( +/obj/structure/sign/mining/survival{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/turf/closed/wall/mineral/titanium/survival/nodiagonal, +/area/survivalpod) +"C" = ( +/obj/structure/window/reinforced/survival_pod{ + dir = 8 + }, +/obj/structure/window/reinforced/survival_pod{ + dir = 4 + }, +/obj/structure/window/reinforced/survival_pod{ + dir = 1 + }, +/obj/structure/window/reinforced/survival_pod, +/obj/structure/grille, +/turf/open/floor/pod/dark, +/area/survivalpod) +"D" = ( +/obj/structure/chair/comfy/black, +/turf/open/floor/carpet/black, +/area/survivalpod) +"E" = ( +/obj/machinery/door/airlock/survival_pod, +/turf/open/floor/pod/light, +/area/survivalpod) +"F" = ( +/obj/structure/table/wood/fancy, +/obj/item/reagent_containers/food/condiment/peppermill{ + pixel_x = -4; + pixel_y = 12 + }, +/obj/item/reagent_containers/food/condiment/saltshaker{ + pixel_x = 4; + pixel_y = 4 + }, +/turf/open/floor/carpet/black, +/area/survivalpod) +"G" = ( +/obj/structure/urinal{ + pixel_y = 24 + }, +/turf/open/floor/pod/light, +/area/survivalpod) +"H" = ( +/turf/open/floor/pod/light, +/area/survivalpod) +"I" = ( +/obj/structure/sink{ + dir = 4; + pixel_x = 11 + }, +/obj/machinery/light/small{ + dir = 4 + }, +/turf/open/floor/pod/light, +/area/survivalpod) +"J" = ( +/obj/structure/sign/mining/survival{ + dir = 4 + }, +/turf/closed/wall/mineral/titanium/survival/nodiagonal, +/area/survivalpod) +"K" = ( +/obj/structure/chair/comfy/black{ + dir = 1 + }, +/turf/open/floor/carpet/black, +/area/survivalpod) +"L" = ( +/obj/machinery/vending/snack/random, +/turf/open/floor/carpet/black, +/area/survivalpod) +"M" = ( +/obj/machinery/light, +/turf/open/floor/carpet/black, +/area/survivalpod) +"N" = ( +/obj/structure/toilet{ + dir = 8 + }, +/obj/machinery/light/small{ + dir = 4 + }, +/turf/open/floor/pod/light, +/area/survivalpod) +"O" = ( +/obj/structure/sign/mining/survival{ + dir = 4 + }, +/turf/closed/wall/mineral/titanium/survival/pod, +/area/survivalpod) +"P" = ( +/obj/structure/sign/mining/survival, +/turf/closed/wall/mineral/titanium/survival/pod, +/area/survivalpod) +"Q" = ( +/obj/structure/sign/mining/survival, +/turf/closed/wall/mineral/titanium/survival/nodiagonal, +/area/survivalpod) +"R" = ( +/obj/machinery/door/airlock/survival_pod/glass, +/obj/structure/fans/tiny, +/turf/open/floor/carpet/black, +/area/survivalpod) + +(1,1,1) = {" +a +e +p +e +c +e +C +e +C +e +a +"} +(2,1,1) = {" +b +f +q +s +x +y +D +F +K +L +P +"} +(3,1,1) = {" +c +g +q +t +x +y +y +y +y +M +c +"} +(4,1,1) = {" +d +h +q +t +x +y +D +F +K +y +Q +"} +(5,1,1) = {" +c +i +q +u +x +y +D +F +K +y +c +"} +(6,1,1) = {" +d +j +q +t +x +y +y +y +y +y +R +"} +(7,1,1) = {" +c +k +q +t +x +y +c +c +c +c +c +"} +(8,1,1) = {" +d +l +q +t +x +y +c +G +H +H +Q +"} +(9,1,1) = {" +c +m +q +v +y +y +E +H +c +E +c +"} +(10,1,1) = {" +b +n +q +t +z +A +c +I +c +N +P +"} +(11,1,1) = {" +a +o +r +w +r +B +c +J +c +O +a +"} diff --git a/code/__DEFINES/atmospherics.dm b/code/__DEFINES/atmospherics.dm index 74a6796bd2..41b5deb302 100644 --- a/code/__DEFINES/atmospherics.dm +++ b/code/__DEFINES/atmospherics.dm @@ -9,13 +9,12 @@ #define META_GAS_FUSION_POWER 7 //ATMOS //stuff you should probably leave well alone! -#define R_IDEAL_GAS_EQUATION 8.31446261815324 //kPa*L/(K*mol) -#define ONE_ATMOSPHERE 101.325 //kPa -#define TCMB 2.7 // -270.3degC -#define TCRYO 225 // -48.15degC -#define T0C 273.15 // 0degC -#define T20C 293.15 // 20degC -#define STEFANBOLTZMANN (5.670373*10e-8) // W/(m^2*K^4) +#define R_IDEAL_GAS_EQUATION 8.31 //kPa*L/(K*mol) +#define ONE_ATMOSPHERE 101.325 //kPa +#define TCMB 2.7 // -270.3degC +#define TCRYO 225 // -48.15degC +#define T0C 273.15 // 0degC +#define T20C 293.15 // 20degC #define MOLES_CELLSTANDARD (ONE_ATMOSPHERE*CELL_VOLUME/(T20C*R_IDEAL_GAS_EQUATION)) //moles in a 2.5 m^3 cell at 101.325 Pa and 20 degC #define M_CELL_WITH_RATIO (MOLES_CELLSTANDARD * 0.005) //compared against for superconductivity @@ -150,9 +149,9 @@ //OPEN TURF ATMOS #define OPENTURF_DEFAULT_ATMOS "o2=22;n2=82;TEMP=293.15" //the default air mix that open turfs spawn -#define TCOMMS_ATMOS "n2=100;TEMP=80" //-193,15°C telecommunications. also used for xenobiology slime killrooms +#define TCOMMS_ATMOS "n2=100;TEMP=80" //-193,15°C telecommunications. also used for xenobiology slime killrooms #define AIRLESS_ATMOS "TEMP=2.7" //space -#define FROZEN_ATMOS "o2=22;n2=82;TEMP=180" //-93.15°C snow and ice turfs +#define FROZEN_ATMOS "o2=22;n2=82;TEMP=180" //-93.15°C snow and ice turfs #define BURNMIX_ATMOS "o2=2500;plasma=5000;TEMP=370" //used in the holodeck burn test program //ATMOSPHERICS DEPARTMENT GAS TANK TURFS diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm index 47b5c2f602..e29be375e6 100644 --- a/code/__DEFINES/citadel_defines.dm +++ b/code/__DEFINES/citadel_defines.dm @@ -109,8 +109,16 @@ #define MEDIHOUND_SLEEPER (1<<0) #define EATING_NOISES (1<<1) #define DIGESTION_NOISES (1<<2) +#define BREAST_ENLARGEMENT (1<<3) +#define PENIS_ENLARGEMENT (1<<4) +#define FORCED_FEM (1<<5) +#define FORCED_MASC (1<<6) +#define HYPNO (1<<7) +#define NEVER_HYPNO (1<<8) +#define NO_APHRO (1<<9) +#define NO_ASS_SLAP (1<<10) -#define TOGGLES_CITADEL (EATING_NOISES|DIGESTION_NOISES) +#define TOGGLES_CITADEL (EATING_NOISES|DIGESTION_NOISES|BREAST_ENLARGEMENT|PENIS_ENLARGEMENT) //component stuff #define COMSIG_COMBAT_TOGGLED "combatmode_toggled" //called by combat mode toggle on all equipped items. args: (mob/user, combatmode) diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 29ff0a8fae..d89743d2d2 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -528,3 +528,5 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S #define FOURSPACES " " #define CRYOMOBS 'icons/obj/cryo_mobs.dmi' + +#define CANT_REENTER_ROUND -1 diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 78cc7def60..0412e7b62b 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -134,6 +134,7 @@ #define TRAIT_NORUNNING "norunning" // You walk! #define TRAIT_NOMARROW "nomarrow" // You don't make blood, with chemicals or nanites. #define TRAIT_NOPULSE "nopulse" // Your heart doesn't beat. +#define TRAIT_EXEMPT_HEALTH_EVENTS "exempt-health-events" //non-mob traits @@ -160,17 +161,15 @@ #define TRAIT_TAGGER "tagger" #define TRAIT_PHOTOGRAPHER "photographer" #define TRAIT_MUSICIAN "musician" -#define TRAIT_CROCRIN_IMMUNE "crocin_immune" #define TRAIT_NYMPHO "nymphomania" #define TRAIT_MASO "masochism" #define TRAIT_EXHIBITIONIST "exhibitionist" #define TRAIT_HIGH_BLOOD "high_blood" -#define TRAIT_PHARMA "hepatic_pharmacokinesis" #define TRAIT_PARA "paraplegic" #define TRAIT_EMPATH "empath" #define TRAIT_FRIENDLY "friendly" -#define TRAIT_ASSBLASTUSA "assblastusa" #define TRAIT_CULT_EYES "cult_eyes" +#define TRAIT_CLOWN_MENTALITY "clown_mentality" // The future is now, clownman. #define TRAIT_FREESPRINT "free_sprinting" #define TRAIT_XRAY_VISION "xray_vision" #define TRAIT_THERMAL_VISION "thermal_vision" @@ -195,6 +194,7 @@ #define ABSTRACT_ITEM_TRAIT "abstract-item" #define STATUS_EFFECT_TRAIT "status-effect" #define ROUNDSTART_TRAIT "roundstart" //cannot be removed without admin intervention +#define GHOSTROLE_TRAIT "ghostrole" // unique trait sources, still defines #define STATUE_MUTE "statue" @@ -230,6 +230,7 @@ #define SLEEPING_CARP_TRAIT "sleeping_carp" #define RISING_BASS_TRAIT "rising_bass" #define ABDUCTOR_ANTAGONIST "abductor-antagonist" +#define NUKEOP_ANTAGONIST "nukeop-antagonist" #define MADE_UNCLONEABLE "made-uncloneable" #define NUKEOP_TRAIT "nuke-op" #define DEATHSQUAD_TRAIT "deathsquad" diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index d76fc7731a..222002f512 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -447,7 +447,7 @@ var/list/candidates = list() for(var/mob/dead/observer/G in GLOB.player_list) - if(G.reenter_round_timeout < world.realtime) + if(G.can_reenter_round(TRUE)) candidates += G return pollCandidates(Question, jobbanType, gametypeCheck, be_special_flag, poll_time, ignore_category, flashwindow, candidates) diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index ce8b2e4cf0..cdf0f604b8 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -20,8 +20,6 @@ else return "000" -#define UNDIE_COLORABLE(U) (U?.has_color) - /proc/random_underwear(gender) if(!GLOB.underwear_list.len) init_sprite_accessory_subtypes(/datum/sprite_accessory/underwear/bottom, GLOB.underwear_list, GLOB.underwear_m, GLOB.underwear_f) diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 27f1a81fef..49825bcb50 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -19,6 +19,9 @@ var/list/mob_data = list() if(isnewplayer(m)) continue + if (m.client && m.client.prefs && m.client.prefs.auto_ooc) + if (!(m.client.prefs.chat_toggles & CHAT_OOC)) + m.client.prefs.chat_toggles ^= CHAT_OOC if(m.mind) if(m.stat != DEAD && !isbrain(m) && !iscameramob(m)) num_survivors++ diff --git a/code/_globalvars/lists/maintenance_loot.dm b/code/_globalvars/lists/maintenance_loot.dm index c25ebf5b0a..914e45add5 100644 --- a/code/_globalvars/lists/maintenance_loot.dm +++ b/code/_globalvars/lists/maintenance_loot.dm @@ -115,5 +115,6 @@ GLOBAL_LIST_INIT(maintenance_loot, list( /obj/item/clothing/shoes/kindleKicks = 1, /obj/item/autosurgeon/penis = 1, /obj/item/autosurgeon/testicles = 1, + /obj/item/storage/box/marshmallow = 2, "" = 3 )) diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 890725fbb1..974d870a8a 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -401,6 +401,9 @@ SUBSYSTEM_DEF(ticker) qdel(player) living.notransform = TRUE if(living.client) + if (living.client.prefs && living.client.prefs.auto_ooc) + if (living.client.prefs.chat_toggles & CHAT_OOC) + living.client.prefs.chat_toggles ^= CHAT_OOC var/obj/screen/splash/S = new(living.client, TRUE) S.Fade(TRUE) livings += living diff --git a/code/datums/components/butchering.dm b/code/datums/components/butchering.dm index d5af47ea1f..06169f64bf 100644 --- a/code/datums/components/butchering.dm +++ b/code/datums/components/butchering.dm @@ -32,7 +32,7 @@ if(ishuman(M) && source.force && source.get_sharpness()) var/mob/living/carbon/human/H = M - if((H.health <= H.crit_threshold || (user.pulling == H && user.grab_state >= GRAB_NECK) || H.IsSleeping()) && user.zone_selected == BODY_ZONE_HEAD) // Only sleeping, neck grabbed, or crit, can be sliced. + if((H.health <= H.crit_threshold || (user.pulling == H && user.grab_state >= GRAB_NECK) || H.IsSleeping()) && user.zone_selected == BODY_ZONE_PRECISE_MOUTH) // Only sleeping, neck grabbed, or crit, can be sliced. if(H.has_status_effect(/datum/status_effect/neck_slice)) user.show_message("[H]'s neck has already been already cut, you can't make the bleeding any worse!", 1, \ "Their neck has already been already cut, you can't make the bleeding any worse!") @@ -120,4 +120,4 @@ if(eater.safety_mode || (eater.stat & (BROKEN|NOPOWER))) //I'm so sorry. return if(L.stat == DEAD && (L.butcher_results || L.guaranteed_butcher_results)) - Butcher(parent, L) \ No newline at end of file + Butcher(parent, L) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index d1b4e51a7d..a0aa729a8d 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -135,6 +135,9 @@ if(L.client && L.client.prefs) L.canbearoused = L.client.prefs.arousable //Technically this should make taking over a character mean the body gain the new minds setting... L.update_arousal_hud() //Removes the old icon + if (L.client.prefs.auto_ooc) + if (L.client.prefs.chat_toggles & CHAT_OOC) + L.client.prefs.chat_toggles ^= CHAT_OOC SEND_SIGNAL(src, COMSIG_MIND_TRANSFER, new_character, old_character) diff --git a/code/datums/radiation_wave.dm b/code/datums/radiation_wave.dm index 8555e4cf3f..4795f8da60 100644 --- a/code/datums/radiation_wave.dm +++ b/code/datums/radiation_wave.dm @@ -3,6 +3,7 @@ var/turf/master_turf //The center of the wave var/steps=0 //How far we've moved var/intensity //How strong it was originaly + var/remaining_contam //How much contaminated material it still has var/range_modifier //Higher than 1 makes it drop off faster, 0.5 makes it drop off half etc var/move_dir //The direction of movement var/list/__dirs //The directions to the side of the wave, stored for easy looping @@ -18,6 +19,7 @@ __dirs+=turn(dir, -90) intensity = _intensity + remaining_contam = intensity range_modifier = _range_modifier can_contaminate = _can_contaminate @@ -46,8 +48,9 @@ qdel(src) return - radiate(atoms, FLOOR(strength, 1)) - + if(radiate(atoms, FLOOR(min(strength,remaining_contam), 1))) + //oof ow ouch + remaining_contam = max(0,remaining_contam-((min(strength,remaining_contam)-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_STR_COEFFICIENT)) check_obstructions(atoms) // reduce our overall strength if there are radiation insulators /datum/radiation_wave/proc/get_rad_atoms() @@ -89,7 +92,8 @@ intensity *= (1-((1-thing.rad_insulation)/width)) /datum/radiation_wave/proc/radiate(list/atoms, strength) - var/contamination_chance = (strength-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_CHANCE_COEFFICIENT * min(1, 1/(steps*range_modifier)) + var/can_contam = strength >= RAD_MINIMUM_CONTAMINATION + var/list/contam_atoms = list() for(var/k in 1 to atoms.len) var/atom/thing = atoms[k] if(!thing) @@ -109,8 +113,14 @@ )) if(!can_contaminate || blacklisted[thing.type]) continue - if(prob(contamination_chance)) // Only stronk rads get to have little baby rads - if(CHECK_BITFIELD(thing.rad_flags, RAD_NO_CONTAMINATE) || SEND_SIGNAL(thing, COMSIG_ATOM_RAD_CONTAMINATING, strength) & COMPONENT_BLOCK_CONTAMINATION) - continue - var/rad_strength = (strength-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_STR_COEFFICIENT + if(CHECK_BITFIELD(thing.rad_flags, RAD_NO_CONTAMINATE) || SEND_SIGNAL(thing, COMSIG_ATOM_RAD_CONTAMINATING, strength) & COMPONENT_BLOCK_CONTAMINATION) + continue + contam_atoms += thing + var/did_contam = 0 + if(length(can_contam)) + var/rad_strength = ((strength-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_STR_COEFFICIENT)/contam_atoms.len + for(var/k in 1 to contam_atoms.len) + var/atom/thing = contam_atoms[k] thing.AddComponent(/datum/component/radioactive, rad_strength, source) + did_contam = 1 + return did_contam diff --git a/code/datums/traits/neutral.dm b/code/datums/traits/neutral.dm index eae2db6a5f..911929896b 100644 --- a/code/datums/traits/neutral.dm +++ b/code/datums/traits/neutral.dm @@ -88,15 +88,6 @@ if(quirk_holder) quirk_holder.remove_client_colour(/datum/client_colour/monochrome) -/datum/quirk/crocrin_immunity - name = "Crocin Immunity" - desc = "You're one of the few people in the galaxy who are genetically immune to Crocin and Hexacrocin products and their addictive properties! However, you can still get brain damage from Hexacrocin addiction." - mob_trait = TRAIT_CROCRIN_IMMUNE - value = 0 - gain_text = "You feel more prudish." - lose_text = "You don't feel as prudish as before." - medical_record_text = "Patient exhibits a special gene that makes them immune to aphrodisiacs." - /datum/quirk/libido name = "Nymphomania" desc = "You're always feeling a bit in heat. Also, you get aroused faster than usual." @@ -130,23 +121,3 @@ mob_trait = TRAIT_EXHIBITIONIST gain_text = "You feel like exposing yourself to the world." lose_text = "Indecent exposure doesn't sound as charming to you anymore." - -/datum/quirk/pharmacokinesis //Prevents unwanted organ additions. - name = "Acute hepatic pharmacokinesis" - desc = "You've a rare genetic disorder that causes Incubus draft and Sucubus milk to be absorbed by your liver instead." - value = 0 - mob_trait = TRAIT_PHARMA - lose_text = "Your liver feels different." - medical_record_text = "Non-invasive tests report that the patient's metabolism is indeed incompatible with a certain \"stimulants\"." - var/active = FALSE - var/power = 0 - var/cachedmoveCalc = 1 - -/datum/quirk/assblastusa - name = "Buns of Steel" - desc = "You've never skipped ass day. With this trait, you are completely immune to all forms of ass slapping and anyone who tries to slap your rock hard ass usually gets a broken hand." - mob_trait = TRAIT_ASSBLASTUSA - value = 0 - medical_record_text = "Patient never skipped ass day." - gain_text = "Your ass rivals those of golems." - lose_text = "Your butt feels more squishy and slappable." \ No newline at end of file diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index ef20b6e35e..7c57de74a4 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -515,10 +515,10 @@ step(src, AM.dir) ..() -/atom/movable/proc/safe_throw_at(atom/target, range, speed, mob/thrower, spin=TRUE, diagonals_first = FALSE, var/datum/callback/callback) - return throw_at(target, range, speed, thrower, spin, diagonals_first, callback) +/atom/movable/proc/safe_throw_at(atom/target, range, speed, mob/thrower, spin=TRUE, diagonals_first = FALSE, var/datum/callback/callback, messy_throw = TRUE) + return throw_at(target, range, speed, thrower, spin, diagonals_first, callback, messy_throw) -/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin=TRUE, diagonals_first = FALSE, var/datum/callback/callback) //If this returns FALSE then callback will not be called. +/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin=TRUE, diagonals_first = FALSE, var/datum/callback/callback, messy_throw = TRUE) //If this returns FALSE then callback will not be called. . = FALSE if (!target || speed <= 0) return diff --git a/code/game/gamemodes/clown_ops/clown_ops.dm b/code/game/gamemodes/clown_ops/clown_ops.dm index 49a336e16a..11898701fa 100644 --- a/code/game/gamemodes/clown_ops/clown_ops.dm +++ b/code/game/gamemodes/clown_ops/clown_ops.dm @@ -57,7 +57,6 @@ ..() if(visualsOnly) return - H.dna.add_mutation(CLOWNMUT) H.dna.add_mutation(SMILE) /datum/outfit/syndicate/clownop/leader diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index 075184046d..0890d81dfb 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -741,7 +741,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) if (M.mind && (M.mind.special_role || M.mind.antag_datums?.len > 0)) current_players[CURRENT_LIVING_ANTAGS].Add(M) else - if (istype(M,/mob/dead/observer)) + if (isobserver(M)) var/mob/dead/observer/O = M if (O.started_as_observer) // Observers current_players[CURRENT_OBSERVERS].Add(M) diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm index aee1cf4f69..6d19776d86 100644 --- a/code/game/machinery/iv_drip.dm +++ b/code/game/machinery/iv_drip.dm @@ -222,5 +222,21 @@ . += "\t[attached ? attached : "No one"] is attached." +/obj/machinery/iv_drip/telescopic + name = "telescopic IV drip" + desc = "An IV drip with an advanced infusion pump that can both drain blood into and inject liquids from attached containers. Blood packs are processed at an accelerated rate. This one is telescopic, and can be picked up and put down." + icon_state = "iv_drip" + +/obj/machinery/iv_drip/telescopic/update_icon() + ..() + icon_state = icon_state + "_tele" + +/obj/machinery/iv_drip/telescopic/AltClick(mob/user) + if (attached || beaker || !user.canUseTopic(src, BE_CLOSE)) + return ..() + new /obj/item/tele_iv(get_turf(src)) + qdel(src) + return TRUE + #undef IV_TAKING -#undef IV_INJECTING \ No newline at end of file +#undef IV_INJECTING diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index c5d198c05f..a410827347 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -578,21 +578,22 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) itempush = 0 //too light to push anything return A.hitby(src, 0, itempush) -/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback) +/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, messy_throw = TRUE) thrownby = thrower - callback = CALLBACK(src, .proc/after_throw, callback) //replace their callback with our own + callback = CALLBACK(src, .proc/after_throw, callback, (spin && messy_throw)) //replace their callback with our own . = ..(target, range, speed, thrower, spin, diagonals_first, callback) -/obj/item/proc/after_throw(datum/callback/callback) +/obj/item/proc/after_throw(datum/callback/callback, messy_throw) if (callback) //call the original callback . = callback.Invoke() throw_speed = initial(throw_speed) //explosions change this. item_flags &= ~IN_INVENTORY - var/matrix/M = matrix(transform) - M.Turn(rand(-170, 170)) - transform = M - pixel_x = rand(-8, 8) - pixel_y = rand(-8, 8) + if(messy_throw) + var/matrix/M = matrix(transform) + M.Turn(rand(-170, 170)) + transform = M + pixel_x = rand(-8, 8) + pixel_y = rand(-8, 8) /obj/item/proc/remove_item_from_storage(atom/newLoc) //please use this if you're going to snowflake an item out of a obj/item/storage if(!newLoc) diff --git a/code/game/objects/items/storage/boxes.dm b/code/game/objects/items/storage/boxes.dm index e214db3c71..4b2b3e2203 100644 --- a/code/game/objects/items/storage/boxes.dm +++ b/code/game/objects/items/storage/boxes.dm @@ -1259,3 +1259,12 @@ var/obj/item/stack/sheet/cardboard/I = new(user.drop_location()) qdel(src) user.put_in_hands(I) + +/obj/item/storage/box/marshmallow + name = "box of marshmallows" + desc = "A box of marshmallows." + illustration = "marshmallow" + +/obj/item/storage/box/marshmallow/PopulateContents() + for (var/i in 1 to 5) + new /obj/item/reagent_containers/food/snacks/marshmallow(src) \ No newline at end of file diff --git a/code/game/objects/items/telescopic_iv.dm b/code/game/objects/items/telescopic_iv.dm new file mode 100644 index 0000000000..9b0b714ea5 --- /dev/null +++ b/code/game/objects/items/telescopic_iv.dm @@ -0,0 +1,17 @@ +/obj/item/tele_iv + name = "telescopic IV drip" + desc = "An IV drip with an advanced infusion pump that can both drain blood into and inject liquids from attached containers. Blood packs are processed at an accelerated rate. This one is telescopic, and can be picked up and put down." + icon = 'icons/obj/iv_drip.dmi' + icon_state = "tele_iv" + +/obj/item/tele_iv/attack_self(mob/user) + deploy_iv(user, user.loc) + +/obj/item/tele_iv/afterattack(atom/target, mob/user, proximity) + . = ..() + if(proximity && isopenturf(target) && user.CanReach(target)) + deploy_iv(user, target) + +/obj/item/tele_iv/proc/deploy_iv(mob/user, atom/location) + new /obj/machinery/iv_drip/telescopic(location) + qdel(src) diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index f5dfa690db..14ac2f037e 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -80,13 +80,12 @@ SEND_SIGNAL(src, COMSIG_OBJ_SETANCHORED, anchorvalue) anchored = anchorvalue -/obj/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback) - ..() +/obj/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, messy_throw) + . = ..() if(obj_flags & FROZEN) visible_message("[src] shatters into a million pieces!") qdel(src) - /obj/assume_air(datum/gas_mixture/giver) if(loc) return loc.assume_air(giver) diff --git a/code/game/objects/structures/dresser.dm b/code/game/objects/structures/dresser.dm index 05e62c196f..7f0c3c6eb8 100644 --- a/code/game/objects/structures/dresser.dm +++ b/code/game/objects/structures/dresser.dm @@ -30,11 +30,11 @@ return var/list/undergarment_choices = list("Underwear", "Underwear Color", "Undershirt", "Undershirt Color", "Socks", "Socks Color") - if(!UNDIE_COLORABLE(GLOB.underwear_list[H.underwear])) + if(!(GLOB.underwear_list[H.underwear]?.has_color)) undergarment_choices -= "Underwear Color" - if(!UNDIE_COLORABLE(GLOB.undershirt_list[H.undershirt])) + if(!(GLOB.undershirt_list[H.undershirt]?.has_color)) undergarment_choices -= "Undershirt Color" - if(!UNDIE_COLORABLE(GLOB.socks_list[H.socks])) + if(!(GLOB.socks_list[H.socks]?.has_color)) undergarment_choices -= "Socks Color" var/choice = input(H, "Underwear, Undershirt, or Socks?", "Changing") as null|anything in undergarment_choices diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm index fdc85475fb..4304e275d1 100644 --- a/code/game/objects/structures/ghost_role_spawners.dm +++ b/code/game/objects/structures/ghost_role_spawners.dm @@ -30,6 +30,8 @@ new/obj/structure/fluff/empty_terrarium(get_turf(src)) return ..() +/obj/effect/mob_spawn/human/seed_vault/special(mob/living/carbon/human/new_spawn) + ADD_TRAIT(new_spawn,TRAIT_EXEMPT_HEALTH_EVENTS,GHOSTROLE_TRAIT) //Ash walker eggs: Spawns in ash walker dens in lavaland. Ghosts become unbreathing lizards that worship the Necropolis and are advised to retrieve corpses to create more ash walkers. /obj/effect/mob_spawn/human/ash_walker @@ -251,6 +253,9 @@ new/obj/structure/fluff/empty_cryostasis_sleeper(get_turf(src)) return ..() +/obj/effect/mob_spawn/human/hermit/special(mob/living/carbon/human/new_spawn) + ADD_TRAIT(new_spawn,TRAIT_EXEMPT_HEALTH_EVENTS,GHOSTROLE_TRAIT) + //Broken rejuvenation pod: Spawns in animal hospitals in lavaland. Ghosts become disoriented interns and are advised to search for help. /obj/effect/mob_spawn/human/doctor/alive/lavaland name = "broken rejuvenation pod" @@ -353,6 +358,9 @@ new/obj/structure/fluff/empty_sleeper/syndicate(get_turf(src)) ..() +/obj/effect/mob_spawn/human/hotel_staff/special(mob/living/carbon/human/new_spawn) + ADD_TRAIT(new_spawn,TRAIT_EXEMPT_HEALTH_EVENTS,GHOSTROLE_TRAIT) + /obj/effect/mob_spawn/human/demonic_friend name = "Essence of friendship" desc = "Oh boy! Oh boy! A friend!" @@ -618,6 +626,7 @@ O.equip(new_spawn, FALSE, new_spawn.client) SSjob.equip_loadout(null, new_spawn, FALSE) SSquirks.AssignQuirks(new_spawn, new_spawn.client, TRUE, TRUE, null, FALSE, new_spawn) + ADD_TRAIT(new_spawn,TRAIT_EXEMPT_HEALTH_EVENTS,GHOSTROLE_TRAIT) /datum/outfit/ghostcafe name = "ID, jumpsuit and shoes" @@ -639,4 +648,4 @@ uniform = /obj/item/clothing/under/color/random else uniform = /obj/item/clothing/under/skirt/color/random - + diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 53fdb315b5..f08112939a 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -492,7 +492,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention) message_admins("[key_name_admin(usr)] assumed direct control of [M].") log_admin("[key_name(usr)] assumed direct control of [M].") var/mob/adminmob = src.mob - M.ckey = src.ckey + adminmob.transfer_ckey(M, send_signal = FALSE) if( isobserver(adminmob) ) qdel(adminmob) SSblackbox.record_feedback("tally", "admin_verb", 1, "Assume Direct Control") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/antagonists/blob/blob/blobs/shield.dm b/code/modules/antagonists/blob/blob/blobs/shield.dm index 33e7e4392f..da165adef2 100644 --- a/code/modules/antagonists/blob/blob/blobs/shield.dm +++ b/code/modules/antagonists/blob/blob/blobs/shield.dm @@ -3,6 +3,7 @@ icon = 'icons/mob/blob.dmi' icon_state = "blob_shield" desc = "A solid wall of slightly twitching tendrils." + var/damaged_desc = "A wall of twitching tendrils." max_integrity = 150 brute_resist = 0.25 explosion_block = 3 @@ -21,10 +22,10 @@ /obj/structure/blob/shield/update_icon() ..() - if(obj_integrity <= 70) - icon_state = "blob_shield_damaged" - name = "weakened strong blob" - desc = "A wall of twitching tendrils." + if(obj_integrity < max_integrity * 0.5) + icon_state = "[initial(icon_state)]_damaged" + name = "weakened [initial(name)]" + desc = "[damaged_desc]" atmosblock = FALSE if(!weakened) armor = armor.setRating("melee" = 15, "bullet" = 15, "laser" = 5, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90) @@ -37,4 +38,27 @@ if(weakened) armor = armor.setRating("melee" = 25, "bullet" = 25, "laser" = 15, "energy" = 10, "bomb" = 20, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90) weakened = FALSE - air_update_turf(1) \ No newline at end of file + air_update_turf(1) + +/obj/structure/blob/shield/reflective + name = "reflective blob" + desc = "A solid wall of slightly twitching tendrils with a reflective glow." + damaged_desc = "A wall of twitching tendrils with a reflective glow." + icon_state = "blob_glow" + flags_1 = CHECK_RICOCHET_1 + point_return = 8 + max_integrity = 50 + brute_resist = 1 + explosion_block = 2 + +/obj/structure/blob/shield/reflective/handle_ricochet(obj/item/projectile/P) + var/turf/p_turf = get_turf(P) + var/face_direction = get_dir(src, p_turf) + var/face_angle = dir2angle(face_direction) + var/incidence_s = GET_ANGLE_OF_INCIDENCE(face_angle, (P.Angle + 180)) + if(abs(incidence_s) > 90 && abs(incidence_s) < 270) + return FALSE + var/new_angle_s = SIMPLIFY_DEGREES(face_angle + incidence_s) + P.setAngle(new_angle_s) + visible_message("[P] reflects off [src]!") + return TRUE \ No newline at end of file diff --git a/code/modules/antagonists/blob/blob/powers.dm b/code/modules/antagonists/blob/blob/powers.dm index e49d186362..73c0776ad7 100644 --- a/code/modules/antagonists/blob/blob/powers.dm +++ b/code/modules/antagonists/blob/blob/powers.dm @@ -113,12 +113,22 @@ /mob/camera/blob/verb/create_shield_power() set category = "Blob" - set name = "Create Shield Blob (15)" - set desc = "Create a shield blob, which will block fire and is hard to kill." + set name = "Create/Upgrade Shield Blob (15)" + set desc = "Create a shield blob, which will block fire and is hard to kill. Using this on an existing shield blob turns it into a reflective blob, capable of reflecting most projectiles but making it much weaker than usual to brute attacks." create_shield() /mob/camera/blob/proc/create_shield(turf/T) - createSpecial(15, /obj/structure/blob/shield, 0, 0, T) + var/obj/structure/blob/shield/S = locate(/obj/structure/blob/shield) in T + if(S) + if(!can_buy(15)) + return + if(S.obj_integrity < S.max_integrity * 0.5) + to_chat(src, "This shield blob is too damaged to be modified properly!") + return + to_chat(src, "You secrete a reflective ooze over the shield blob, allowing it to reflect projectiles at the cost of reduced intregrity.") + S.change_to(/obj/structure/blob/shield/reflective, src) + else + createSpecial(15, /obj/structure/blob/shield, 0, 0, T) /mob/camera/blob/verb/create_resource() set category = "Blob" @@ -359,7 +369,7 @@ to_chat(src, "You can expand, which will attack people, damage objects, or place a Normal Blob if the tile is clear.") to_chat(src, "Normal Blobs will expand your reach and can be upgraded into special blobs that perform certain functions.") to_chat(src, "You can upgrade normal blobs into the following types of blob:") - to_chat(src, "Shield Blobs are strong and expensive blobs which take more damage. In additon, they are fireproof and can block air, use these to protect yourself from station fires.") + to_chat(src, "Shield Blobs are strong and expensive blobs which take more damage. In additon, they are fireproof and can block air, use these to protect yourself from station fires. Upgrading them again will result in a reflective blob, capable of reflecting most projectiles at the cost of the strong blob's extra health.") to_chat(src, "Resource Blobs are blobs which produce more resources for you, build as many of these as possible to consume the station. This type of blob must be placed near node blobs or your core to work.") to_chat(src, "Factory Blobs are blobs that spawn blob spores which will attack nearby enemies. This type of blob must be placed near node blobs or your core to work.") to_chat(src, "Blobbernauts can be produced from factories for a cost, and are hard to kill, powerful, and moderately smart. The factory used to create one will become fragile and briefly unable to produce spores.") diff --git a/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm b/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm index febf53c324..97b4437298 100644 --- a/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm +++ b/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm @@ -183,7 +183,7 @@ BuyPower(new /datum/action/bloodsucker/masquerade) BuyPower(new /datum/action/bloodsucker/veil) // Traits - for (var/T in defaultTraits) + for(var/T in defaultTraits) ADD_TRAIT(owner.current, T, "bloodsucker") if(HAS_TRAIT(owner.current, TRAIT_TOXINLOVER)) //No slime bonuses here, no thank you had_toxlover = TRUE @@ -200,10 +200,10 @@ var/mob/living/carbon/human/H = owner.current var/datum/species/S = H.dna.species // Make Changes - S.brutemod *= 0.5 // <-------------------- Start small, but burn mod increases based on rank! - S.coldmod = 0 - S.stunmod *= 0.25 - S.siemens_coeff *= 0.75 //base electrocution coefficient 1 + H.physiology.brute_mod *= 0.8 // <-------------------- Start small, but burn mod increases based on rank! + H.physiology.cold_mod = 0 + H.physiology.stun_mod *= 0.35 + H.physiology.siemens_coeff *= 0.75 //base electrocution coefficient 1 //S.heatmod += 0.5 // Heat shouldn't affect. Only Fire. //S.punchstunthreshold = 8 //damage at which punches from this race will stun 9 S.punchdamagelow += 1 //lowest possible punch damage 0 @@ -319,12 +319,10 @@ datum/antagonist/bloodsucker/proc/SpendRank() if(ishuman(owner.current)) var/mob/living/carbon/human/H = owner.current var/datum/species/S = H.dna.species - S.burnmod *= 0.025 // Slightly more burn damage - S.stunmod *= 0.95 // Slightly less stun time. S.punchdamagelow += 0.5 S.punchdamagehigh += 0.5 // NOTE: This affects the hitting power of Brawn. // More Health - owner.current.setMaxHealth(owner.current.maxHealth + 5) + owner.current.setMaxHealth(owner.current.maxHealth + 10) // Vamp Stats regenRate += 0.05 // Points of brute healed (starts at 0.3) feedAmount += 2 // Increase how quickly I munch down vics (15) diff --git a/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm b/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm index f73912d0f5..3493622945 100644 --- a/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm +++ b/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm @@ -275,7 +275,7 @@ // All done! if(convert_progress <= 0) // FAIL: Can't be Vassal - if(!SSticker.mode.can_make_vassal(target, user, display_warning=FALSE) && HAS_TRAIT(target, TRAIT_MINDSHIELD)) // If I'm an unconvertable Antag ONLY + if(!SSticker.mode.can_make_vassal(target, user, display_warning=FALSE) || HAS_TRAIT(target, TRAIT_MINDSHIELD)) // If I'm an unconvertable Antag ONLY to_chat(user, "[target] doesn't respond to your persuasion. It doesn't appear they can be converted to follow you, they either have a mindshield or their external loyalties are too difficult for you to break.\[ALT+click to release\]") convert_progress ++ // Pop it back up some. Avoids wasting Blood on a lost cause. // SUCCESS: All done! diff --git a/code/modules/antagonists/nukeop/clownop.dm b/code/modules/antagonists/nukeop/clownop.dm index 43e62c4638..58b492b578 100644 --- a/code/modules/antagonists/nukeop/clownop.dm +++ b/code/modules/antagonists/nukeop/clownop.dm @@ -5,6 +5,14 @@ antagpanel_category = "ClownOp" nukeop_outfit = /datum/outfit/syndicate/clownop +/datum/antagonist/nukeop/clownop/on_gain() + . = ..() + ADD_TRAIT(owner, TRAIT_CLOWN_MENTALITY, NUKEOP_ANTAGONIST) + +/datum/antagonist/nukeop/clownop/on_removal() + REMOVE_TRAIT(owner, TRAIT_CLOWN_MENTALITY, NUKEOP_ANTAGONIST) + return ..() + /datum/antagonist/nukeop/leader/clownop name = "Clown Operative Leader" roundend_category = "clown operatives" diff --git a/code/modules/atmospherics/machinery/datum_pipeline.dm b/code/modules/atmospherics/machinery/datum_pipeline.dm index 19f3f58708..38178a4339 100644 --- a/code/modules/atmospherics/machinery/datum_pipeline.dm +++ b/code/modules/atmospherics/machinery/datum_pipeline.dm @@ -154,11 +154,6 @@ var/partial_heat_capacity = total_heat_capacity*(share_volume/air.volume) var/target_temperature var/target_heat_capacity - // first calculate heat from radiation. there's an implied "* 1 tick" here. - // 0.05 magic multiplicand is, first, 0.1 deciseconds; second, half of the radiation's going right back into the gas. - var/share_constant = STEFANBOLTZMANN*(share_volume**(2/3))*0.05 - // Minimizing temp to 4 billion is mostly to prevent -infinity temperatures. - var/heat = share_constant*(min(air.temperature,4000000000)**4) if(isopenturf(target)) @@ -170,8 +165,8 @@ if((modeled_location.heat_capacity>0) && (partial_heat_capacity>0)) var/delta_temperature = air.temperature - target_temperature - heat -= share_constant*(min(target_temperature,4000000000)**4) - heat += thermal_conductivity*delta_temperature* \ + + var/heat = thermal_conductivity*delta_temperature* \ (partial_heat_capacity*target_heat_capacity/(partial_heat_capacity+target_heat_capacity)) air.temperature -= heat/total_heat_capacity @@ -188,8 +183,7 @@ var/sharer_temperature_delta = 0 if((sharer_heat_capacity>0) && (partial_heat_capacity>0)) - heat -= share_constant*(min(target_temperature,4000000000)**4) - heat += thermal_conductivity*delta_temperature* \ + var/heat = thermal_conductivity*delta_temperature* \ (partial_heat_capacity*sharer_heat_capacity/(partial_heat_capacity+sharer_heat_capacity)) self_temperature_delta = -heat/total_heat_capacity @@ -205,12 +199,10 @@ if((target.heat_capacity>0) && (partial_heat_capacity>0)) var/delta_temperature = air.temperature - target.temperature - heat -= share_constant*(min(target.temperature,4000000000)**4) - heat += thermal_conductivity*delta_temperature* \ + var/heat = thermal_conductivity*delta_temperature* \ (partial_heat_capacity*target.heat_capacity/(partial_heat_capacity+target.heat_capacity)) air.temperature -= heat/total_heat_capacity - air.temperature = CLAMP(air.temperature,TCMB,INFINITY) // i have no idea why TCMB needs to be the min but i ain't changing it update = TRUE /datum/pipeline/proc/return_air() diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm index 79aa957d97..b087859a47 100644 --- a/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm +++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm @@ -26,7 +26,9 @@ var/turf/T = loc if(istype(T)) - if(T.blocks_air) + if(islava(T)) + environment_temperature = 5000 + else if(T.blocks_air) environment_temperature = T.temperature else var/turf/open/OT = T diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index a54584d6cc..ae9932e96f 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -79,4 +79,8 @@ var/client_keysend_amount = 0 var/next_keysend_reset = 0 var/next_keysend_trip_reset = 0 - var/keysend_tripped = FALSE \ No newline at end of file + var/keysend_tripped = FALSE + + // stops players from coming back through ghost/midround roles after suicide/cryo + // for a duration set by CONFIG_GET(number/suicide_reenter_round_timer) and CONFIG_GET(number/roundstart_suicide_time_limit) + var/reenter_round_timeout = 0 diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 00cc01105d..48489df4c7 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -245,6 +245,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "Character Appearance" dat += "Loadout" dat += "Game Preferences" + dat += "Content Preferences" if(!path) dat += "
"
dat += "Clothing & Equipment" dat += "Underwear:[underwear]" - if(UNDIE_COLORABLE(GLOB.underwear_list[underwear])) + if(GLOB.underwear_list[underwear]?.has_color) dat += "Underwear Color: Change" dat += "Undershirt:[undershirt]" - if(UNDIE_COLORABLE(GLOB.undershirt_list[undershirt])) + if(GLOB.undershirt_list[undershirt]?.has_color) dat += "Undershirt Color: Change " dat += "Socks:[socks]" - if(UNDIE_COLORABLE(GLOB.socks_list[socks])) + if(GLOB.socks_list[socks]?.has_color) dat += "Socks Color: Change " dat += "Backpack:[backbag]" dat += "Jumpsuit: [jumpsuit_style] " @@ -834,13 +835,9 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat +=" | "
dat += "Citadel Preferences" //Because fuck me if preferences can't be fucking modularized and expected to update in a reasonable timeframe. - dat += "Arousal:[arousable == TRUE ? "Enabled" : "Disabled"]" - dat += "Voracious MediHound sleepers: [(cit_toggles & MEDIHOUND_SLEEPER) ? "Yes" : "No"] " - dat += "Hear Vore Sounds: [(cit_toggles & EATING_NOISES) ? "Yes" : "No"] " - dat += "Hear Vore Digestion Sounds: [(cit_toggles & DIGESTION_NOISES) ? "Yes" : "No"] " - dat += "Lewdchem:[lewdchem == TRUE ? "Enabled" : "Disabled"] " dat += "Widescreen: [widescreenpref ? "Enabled ([CONFIG_GET(string/default_view)])" : "Disabled (15x15)"] " dat += "Auto stand: [autostand ? "Enabled" : "Disabled"] " + dat += "Auto OOC: [auto_ooc ? "Enabled" : "Disabled"] " dat += "Screen Shake: [(screenshake==100) ? "Full" : ((screenshake==0) ? "None" : "[screenshake]")] " if (user && user.client && !user.client.prefs.screenshake==0) dat += "Damage Screen Shake: [(damagescreenshake==1) ? "On" : ((damagescreenshake==0) ? "Off" : "Only when down")] " @@ -991,6 +988,26 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "" dat += " | [gear.description] |
"
+ dat += "Fetish content prefs" + dat += "Arousal:[arousable == TRUE ? "Enabled" : "Disabled"]" + dat += "Voracious MediHound sleepers: [(cit_toggles & MEDIHOUND_SLEEPER) ? "Yes" : "No"] " + dat += "Hear Vore Sounds: [(cit_toggles & EATING_NOISES) ? "Yes" : "No"] " + dat += "Hear Vore Digestion Sounds: [(cit_toggles & DIGESTION_NOISES) ? "Yes" : "No"] " + dat += "Forced Feminization: [(cit_toggles & FORCED_FEM) ? "Allowed" : "Disallowed"] " + dat += "Forced Masculinization: [(cit_toggles & FORCED_MASC) ? "Allowed" : "Disallowed"] " + dat += "Lewd Hypno: [(cit_toggles & HYPNO) ? "Allowed" : "Disallowed"] " + dat += " | "
+ dat +=""
+ dat += "Other content prefs" + dat += "Breast Enlargement: [(cit_toggles & BREAST_ENLARGEMENT) ? "Allowed" : "Disallowed"]" + dat += "Penis Enlargement: [(cit_toggles & PENIS_ENLARGEMENT) ? "Allowed" : "Disallowed"] " + dat += "Hypno: [(cit_toggles & NEVER_HYPNO) ? "Disallowed" : "Allowed"] " + dat += "Aphrodisiacs: [(cit_toggles & NO_APHRO) ? "Disallowed" : "Allowed"] " + dat += "Ass Slapping: [(cit_toggles & NO_ASS_SLAP) ? "Disallowed" : "Allowed"] " + dat += " " + dat += " - [name] - - Head: [(head && !(head.item_flags & ABSTRACT)) ? head : "Nothing"] - Mask: [(wear_mask && !(wear_mask.item_flags & ABSTRACT)) ? wear_mask : "Nothing"] - Neck: [(wear_neck && !(wear_neck.item_flags & ABSTRACT)) ? wear_neck : "Nothing"]"} - - for(var/i in 1 to held_items.len) - var/obj/item/I = get_item_for_held_index(i) - dat += " [get_held_index_name(i)]: | [(I && !(I.item_flags & ABSTRACT)) ? I : "Nothing"]"
-
- dat += " Back: [back ? back : "Nothing"]" - - if(istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/tank)) - dat += " [internal ? "Disable Internals" : "Set Internals"]" - - if(handcuffed) - dat += " Handcuffed" - if(legcuffed) - dat += " Legcuffed" - - dat += {" - - Close - "} - user << browse(dat, "window=mob[REF(src)];size=325x500") - onclose(user, "mob[REF(src)]") - -/mob/living/carbon/Topic(href, href_list) - ..() - //strip panel - if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY)) - if(href_list["internal"]) - var/slot = text2num(href_list["internal"]) - var/obj/item/ITEM = get_item_by_slot(slot) - if(ITEM && istype(ITEM, /obj/item/tank) && wear_mask && (wear_mask.clothing_flags & ALLOWINTERNALS)) - visible_message("[usr] tries to [internal ? "close" : "open"] the valve on [src]'s [ITEM.name].", \ - "[usr] tries to [internal ? "close" : "open"] the valve on [src]'s [ITEM.name].") - if(do_mob(usr, src, POCKET_STRIP_DELAY)) - if(internal) - internal = null - update_internals_hud_icon(0) - else if(ITEM && istype(ITEM, /obj/item/tank)) - if((wear_mask && (wear_mask.clothing_flags & ALLOWINTERNALS)) || getorganslot(ORGAN_SLOT_BREATHING_TUBE)) - internal = ITEM - update_internals_hud_icon(1) - - visible_message("[usr] [internal ? "opens" : "closes"] the valve on [src]'s [ITEM.name].", \ - "[usr] [internal ? "opens" : "closes"] the valve on [src]'s [ITEM.name].") - - -/mob/living/carbon/fall(forced) - loc.handle_fall(src, forced)//it's loc so it doesn't call the mob's handle_fall which does nothing - -/mob/living/carbon/is_muzzled() - return(istype(src.wear_mask, /obj/item/clothing/mask/muzzle)) - -/mob/living/carbon/hallucinating() - if(hallucination) - return TRUE - else - return FALSE - -/mob/living/carbon/resist_buckle() - if(restrained()) - changeNext_move(CLICK_CD_BREAKOUT) - last_special = world.time + CLICK_CD_BREAKOUT - var/buckle_cd = 600 - if(handcuffed) - var/obj/item/restraints/O = src.get_item_by_slot(SLOT_HANDCUFFED) - buckle_cd = O.breakouttime - visible_message("[src] attempts to unbuckle [p_them()]self!", \ - "You attempt to unbuckle yourself... (This will take around [round(buckle_cd/600,1)] minute\s, and you need to stay still.)") - if(do_after(src, buckle_cd, 0, target = src)) - if(!buckled) - return - buckled.user_unbuckle_mob(src,src) - else - if(src && buckled) - to_chat(src, "You fail to unbuckle yourself!") - else - buckled.user_unbuckle_mob(src,src) - -/mob/living/carbon/resist_fire() - fire_stacks -= 5 - Knockdown(60, TRUE, TRUE) - spin(32,2) - visible_message("[src] rolls on the floor, trying to put [p_them()]self out!", \ - "You stop, drop, and roll!") - sleep(30) - if(fire_stacks <= 0) - visible_message("[src] has successfully extinguished [p_them()]self!", \ - "You extinguish yourself.") - ExtinguishMob() - return - -/mob/living/carbon/resist_restraints() - var/obj/item/I = null - var/type = 0 - if(handcuffed) - I = handcuffed - type = 1 - else if(legcuffed) - I = legcuffed - type = 2 - if(I) - if(type == 1) - changeNext_move(CLICK_CD_BREAKOUT) - last_special = world.time + CLICK_CD_BREAKOUT - if(type == 2) - changeNext_move(CLICK_CD_RANGE) - last_special = world.time + CLICK_CD_RANGE - cuff_resist(I) - - -/mob/living/carbon/proc/cuff_resist(obj/item/I, breakouttime = 600, cuff_break = 0) - if(I.item_flags & BEING_REMOVED) - to_chat(src, "You're already attempting to remove [I]!") - return - I.item_flags |= BEING_REMOVED - breakouttime = I.breakouttime - if(!cuff_break) - visible_message("[src] attempts to remove [I]!") - to_chat(src, "You attempt to remove [I]... (This will take around [DisplayTimeText(breakouttime)] and you need to stand still.)") - if(do_after(src, breakouttime, 0, target = src)) - clear_cuffs(I, cuff_break) - else - to_chat(src, "You fail to remove [I]!") - - else if(cuff_break == FAST_CUFFBREAK) - breakouttime = 50 - visible_message("[src] is trying to break [I]!") - to_chat(src, "You attempt to break [I]... (This will take around 5 seconds and you need to stand still.)") - if(do_after(src, breakouttime, 0, target = src)) - clear_cuffs(I, cuff_break) - else - to_chat(src, "You fail to break [I]!") - - else if(cuff_break == INSTANT_CUFFBREAK) - clear_cuffs(I, cuff_break) - I.item_flags &= ~BEING_REMOVED - -/mob/living/carbon/proc/uncuff() - if (handcuffed) - var/obj/item/W = handcuffed - handcuffed = null - if (buckled && buckled.buckle_requires_restraints) - buckled.unbuckle_mob(src) - update_handcuffed() - if (client) - client.screen -= W - if (W) - W.forceMove(drop_location()) - W.dropped(src) - if (W) - W.layer = initial(W.layer) - W.plane = initial(W.plane) - changeNext_move(0) - if (legcuffed) - var/obj/item/W = legcuffed - legcuffed = null - update_inv_legcuffed() - if (client) - client.screen -= W - if (W) - W.forceMove(drop_location()) - W.dropped(src) - if (W) - W.layer = initial(W.layer) - W.plane = initial(W.plane) - changeNext_move(0) - -/mob/living/carbon/proc/clear_cuffs(obj/item/I, cuff_break) - if(!I.loc || buckled) - return - visible_message("[src] manages to [cuff_break ? "break" : "remove"] [I]!") - to_chat(src, "You successfully [cuff_break ? "break" : "remove"] [I].") - - if(cuff_break) - . = !((I == handcuffed) || (I == legcuffed)) - qdel(I) - return - - else - if(I == handcuffed) - handcuffed.forceMove(drop_location()) - handcuffed.dropped(src) - handcuffed = null - if(buckled && buckled.buckle_requires_restraints) - buckled.unbuckle_mob(src) - update_handcuffed() - return - if(I == legcuffed) - legcuffed.forceMove(drop_location()) - legcuffed.dropped() - legcuffed = null - update_inv_legcuffed() - return - else - dropItemToGround(I) - return - return TRUE - -/mob/living/carbon/get_standard_pixel_y_offset(lying = 0) - if(lying) - return -6 - else - return initial(pixel_y) - -/mob/living/carbon/proc/accident(obj/item/I) - if(!I || (I.item_flags & ABSTRACT) || HAS_TRAIT(I, TRAIT_NODROP)) - return - - //dropItemToGround(I) CIT CHANGE - makes it so the item doesn't drop if the modifier rolls above 100 - - var/modifier = 0 - - if(HAS_TRAIT(src, TRAIT_CLUMSY)) - modifier -= 40 //Clumsy people are more likely to hit themselves -Honk! - - //CIT CHANGES START HERE - else if(combatmode) - modifier += 50 - - if(modifier < 100) - dropItemToGround(I) - //END OF CIT CHANGES - - switch(rand(1,100)+modifier) //91-100=Nothing special happens - if(-INFINITY to 0) //attack yourself - I.attack(src,src) - if(1 to 30) //throw it at yourself - I.throw_impact(src) - if(31 to 60) //Throw object in facing direction - var/turf/target = get_turf(loc) - var/range = rand(2,I.throw_range) - for(var/i = 1; i < range; i++) - var/turf/new_turf = get_step(target, dir) - target = new_turf - if(new_turf.density) - break - I.throw_at(target,I.throw_range,I.throw_speed,src) - if(61 to 90) //throw it down to the floor - var/turf/target = get_turf(loc) - I.throw_at(target,I.throw_range,I.throw_speed,src) - -/mob/living/carbon/Stat() - ..() - if(statpanel("Status")) - var/obj/item/organ/alien/plasmavessel/vessel = getorgan(/obj/item/organ/alien/plasmavessel) - if(vessel) - stat(null, "Plasma Stored: [vessel.storedPlasma]/[vessel.max_plasma]") - if(locate(/obj/item/assembly/health) in src) - stat(null, "Health: [health]") - - add_abilities_to_panel() - -/mob/living/carbon/attack_ui(slot) - if(!has_hand_for_held_index(active_hand_index)) - return 0 - return ..() - -/mob/living/carbon/proc/vomit(lost_nutrition = 10, blood = FALSE, stun = TRUE, distance = 1, message = TRUE, toxic = FALSE) - if(HAS_TRAIT(src, TRAIT_NOHUNGER)) - return 1 - - if(nutrition < 100 && !blood) - if(message) - visible_message("[src] dry heaves!", \ - "You try to throw up, but there's nothing in your stomach!") - if(stun) - Knockdown(200) - return 1 - - if(is_mouth_covered()) //make this add a blood/vomit overlay later it'll be hilarious - if(message) - visible_message("[src] throws up all over [p_them()]self!", \ - "You throw up all over yourself!") - SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "vomit", /datum/mood_event/vomitself) - distance = 0 - else - if(message) - visible_message("[src] throws up!", "You throw up!") - if(!isflyperson(src)) - SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "vomit", /datum/mood_event/vomit) - if(stun) - Stun(80) - - playsound(get_turf(src), 'sound/effects/splat.ogg', 50, 1) - var/turf/T = get_turf(src) - if(!blood) - nutrition -= lost_nutrition - adjustToxLoss(-3) - for(var/i=0 to distance) - if(blood) - if(T) - add_splatter_floor(T) - if(stun) - adjustBruteLoss(3) - else if(src.reagents.has_reagent("blazaam")) - if(T) - T.add_vomit_floor(src, VOMIT_PURPLE) - else - if(T) - T.add_vomit_floor(src, VOMIT_TOXIC)//toxic barf looks different - T = get_step(T, dir) - if (is_blocked_turf(T)) - break - return 1 - -/mob/living/carbon/proc/spew_organ(power = 5, amt = 1) - for(var/i in 1 to amt) - if(!internal_organs.len) - break //Guess we're out of organs! - var/obj/item/organ/guts = pick(internal_organs) - var/turf/T = get_turf(src) - guts.Remove(src) - guts.forceMove(T) - var/atom/throw_target = get_edge_target_turf(guts, dir) - guts.throw_at(throw_target, power, 4, src) - - -/mob/living/carbon/fully_replace_character_name(oldname,newname) - ..() - if(dna) - dna.real_name = real_name - -//Updates the mob's health from bodyparts and mob damage variables -/mob/living/carbon/updatehealth() - if(status_flags & GODMODE) - return - var/total_burn = 0 - var/total_brute = 0 - var/total_stamina = 0 - for(var/X in bodyparts) //hardcoded to streamline things a bit - var/obj/item/bodypart/BP = X - total_brute += (BP.brute_dam * BP.body_damage_coeff) - total_burn += (BP.burn_dam * BP.body_damage_coeff) - total_stamina += (BP.stamina_dam * BP.stam_damage_coeff) - health = round(maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute, DAMAGE_PRECISION) - staminaloss = round(total_stamina, DAMAGE_PRECISION) - update_stat() - if(((maxHealth - total_burn) < HEALTH_THRESHOLD_DEAD) && stat == DEAD ) - become_husk("burn") - med_hud_set_health() - if(stat == SOFT_CRIT) - add_movespeed_modifier(MOVESPEED_ID_CARBON_SOFTCRIT, TRUE, multiplicative_slowdown = SOFTCRIT_ADD_SLOWDOWN) - else - remove_movespeed_modifier(MOVESPEED_ID_CARBON_SOFTCRIT, TRUE) - -/mob/living/carbon/update_stamina() - var/stam = getStaminaLoss() - if(stam > DAMAGE_PRECISION) - var/total_health = (health - stam) - if(total_health <= crit_threshold && !stat) - if(!IsKnockdown()) - to_chat(src, "You're too exhausted to keep going...") - Knockdown(100) - update_health_hud() - -/mob/living/carbon/update_sight() - if(!client) - return - if(stat == DEAD) - sight = (SEE_TURFS|SEE_MOBS|SEE_OBJS) - see_in_dark = 8 - see_invisible = SEE_INVISIBLE_OBSERVER - return - - sight = initial(sight) - lighting_alpha = initial(lighting_alpha) - var/obj/item/organ/eyes/E = getorganslot(ORGAN_SLOT_EYES) - if(!E) - update_tint() - else - see_invisible = E.see_invisible - see_in_dark = E.see_in_dark - sight |= E.sight_flags - if(!isnull(E.lighting_alpha)) - lighting_alpha = E.lighting_alpha - if(HAS_TRAIT(src, TRAIT_NIGHT_VISION)) - lighting_alpha = min(LIGHTING_PLANE_ALPHA_NV_TRAIT, lighting_alpha) - see_in_dark = max(NIGHT_VISION_DARKSIGHT_RANGE, see_in_dark) - - if(client.eye && client.eye != src) - var/atom/A = client.eye - if(A.update_remote_sight(src)) //returns 1 if we override all other sight updates. - return - - if(glasses) - var/obj/item/clothing/glasses/G = glasses - sight |= G.vision_flags - see_in_dark = max(G.darkness_view, see_in_dark) - if(G.invis_override) - see_invisible = G.invis_override - else - see_invisible = min(G.invis_view, see_invisible) - if(!isnull(G.lighting_alpha)) - lighting_alpha = min(lighting_alpha, G.lighting_alpha) - if(dna) - for(var/X in dna.mutations) - var/datum/mutation/M = X - if(M.name == XRAY) - sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS) - see_in_dark = max(see_in_dark, 8) - if(HAS_TRAIT(src, TRAIT_THERMAL_VISION)) - sight |= (SEE_MOBS) - lighting_alpha = min(lighting_alpha, LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE) - - if(HAS_TRAIT(src, TRAIT_XRAY_VISION)) - sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS) - see_in_dark = max(see_in_dark, 8) - if(see_override) - see_invisible = see_override - . = ..() - - -//to recalculate and update the mob's total tint from tinted equipment it's wearing. -/mob/living/carbon/proc/update_tint() - if(!GLOB.tinted_weldhelh) - return - tinttotal = get_total_tint() - if(tinttotal >= TINT_BLIND) - become_blind(EYES_COVERED) - else if(tinttotal >= TINT_DARKENED) - cure_blind(EYES_COVERED) - overlay_fullscreen("tint", /obj/screen/fullscreen/impaired, 2) - else - cure_blind(EYES_COVERED) - clear_fullscreen("tint", 0) - -/mob/living/carbon/proc/get_total_tint() - . = 0 - if(istype(head, /obj/item/clothing/head)) - var/obj/item/clothing/head/HT = head - . += HT.tint - if(wear_mask) - . += wear_mask.tint - - var/obj/item/organ/eyes/E = getorganslot(ORGAN_SLOT_EYES) - if(E) - . += E.tint - - else - . += INFINITY - -/mob/living/carbon/get_permeability_protection(list/target_zones = list(HANDS,CHEST,GROIN,LEGS,FEET,ARMS,HEAD)) - var/list/tally = list() - for(var/obj/item/I in get_equipped_items()) - for(var/zone in target_zones) - if(I.body_parts_covered & zone) - tally["[zone]"] = max(1 - I.permeability_coefficient, target_zones["[zone]"]) - var/protection = 0 - for(var/key in tally) - protection += tally[key] - protection *= INVERSE(target_zones.len) - return protection - -//this handles hud updates -/mob/living/carbon/update_damage_hud() - - if(!client) - return - - if(health <= crit_threshold) - var/severity = 0 - switch(health) - if(-20 to -10) - severity = 1 - if(-30 to -20) - severity = 2 - if(-40 to -30) - severity = 3 - if(-50 to -40) - severity = 4 - if(-50 to -40) - severity = 5 - if(-60 to -50) - severity = 6 - if(-70 to -60) - severity = 7 - if(-90 to -70) - severity = 8 - if(-95 to -90) - severity = 9 - if(-INFINITY to -95) - severity = 10 - if(!InFullCritical()) - var/visionseverity = 4 - switch(health) - if(-8 to -4) - visionseverity = 5 - if(-12 to -8) - visionseverity = 6 - if(-16 to -12) - visionseverity = 7 - if(-20 to -16) - visionseverity = 8 - if(-24 to -20) - visionseverity = 9 - if(-INFINITY to -24) - visionseverity = 10 - overlay_fullscreen("critvision", /obj/screen/fullscreen/crit/vision, visionseverity) - else - clear_fullscreen("critvision") - overlay_fullscreen("crit", /obj/screen/fullscreen/crit, severity) - else - clear_fullscreen("crit") - clear_fullscreen("critvision") - - //Oxygen damage overlay - var/windedup = getOxyLoss() + getStaminaLoss() * 0.2 - if(windedup) - var/severity = 0 - switch(windedup) - if(10 to 20) - severity = 1 - if(20 to 25) - severity = 2 - if(25 to 30) - severity = 3 - if(30 to 35) - severity = 4 - if(35 to 40) - severity = 5 - if(40 to 45) - severity = 6 - if(45 to INFINITY) - severity = 7 - overlay_fullscreen("oxy", /obj/screen/fullscreen/oxy, severity) - else - clear_fullscreen("oxy") - - //Fire and Brute damage overlay (BSSR) - var/hurtdamage = getBruteLoss() + getFireLoss() + damageoverlaytemp - if(hurtdamage) - var/severity = 0 - switch(hurtdamage) - if(5 to 15) - severity = 1 - if(15 to 30) - severity = 2 - if(30 to 45) - severity = 3 - if(45 to 70) - severity = 4 - if(70 to 85) - severity = 5 - if(85 to INFINITY) - severity = 6 - overlay_fullscreen("brute", /obj/screen/fullscreen/brute, severity) - else - clear_fullscreen("brute") - -/mob/living/carbon/update_health_hud(shown_health_amount) - if(!client || !hud_used) - return - if(hud_used.healths) - if(stat != DEAD) - . = 1 - if(!shown_health_amount) - shown_health_amount = health - if(shown_health_amount >= maxHealth) - hud_used.healths.icon_state = "health0" - else if(shown_health_amount > maxHealth*0.8) - hud_used.healths.icon_state = "health1" - else if(shown_health_amount > maxHealth*0.6) - hud_used.healths.icon_state = "health2" - else if(shown_health_amount > maxHealth*0.4) - hud_used.healths.icon_state = "health3" - else if(shown_health_amount > maxHealth*0.2) - hud_used.healths.icon_state = "health4" - else if(shown_health_amount > 0) - hud_used.healths.icon_state = "health5" - else - hud_used.healths.icon_state = "health6" - else - hud_used.healths.icon_state = "health7" - -/mob/living/carbon/proc/update_internals_hud_icon(internal_state = 0) - if(hud_used && hud_used.internals) - hud_used.internals.icon_state = "internal[internal_state]" - -/mob/living/carbon/update_stat() - if(status_flags & GODMODE) - return - if(stat != DEAD) - if(health <= HEALTH_THRESHOLD_DEAD && !HAS_TRAIT(src, TRAIT_NODEATH)) - death() - return - if(IsUnconscious() || IsSleeping() || getOxyLoss() > 50 || (HAS_TRAIT(src, TRAIT_DEATHCOMA)) || (health <= HEALTH_THRESHOLD_FULLCRIT && !HAS_TRAIT(src, TRAIT_NOHARDCRIT))) - stat = UNCONSCIOUS - blind_eyes(1) - if(combatmode) - toggle_combat_mode(TRUE, TRUE) - else - if(health <= crit_threshold && !HAS_TRAIT(src, TRAIT_NOSOFTCRIT)) - stat = SOFT_CRIT - if(combatmode) - toggle_combat_mode(TRUE, TRUE) - else - stat = CONSCIOUS - adjust_blindness(-1) - update_canmove() - update_damage_hud() - update_health_hud() - med_hud_set_status() - -//called when we get cuffed/uncuffed -/mob/living/carbon/proc/update_handcuffed() - if(handcuffed) - drop_all_held_items() - stop_pulling() - throw_alert("handcuffed", /obj/screen/alert/restrained/handcuffed, new_master = src.handcuffed) - if(handcuffed.demoralize_criminals) - SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "handcuffed", /datum/mood_event/handcuffed) - else - clear_alert("handcuffed") - SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "handcuffed") - update_action_buttons_icon() //some of our action buttons might be unusable when we're handcuffed. - update_inv_handcuffed() - update_hud_handcuffed() - -/mob/living/carbon/fully_heal(admin_revive = FALSE) - if(reagents) - reagents.clear_reagents() - var/obj/item/organ/brain/B = getorgan(/obj/item/organ/brain) - if(B) - B.brain_death = FALSE - for(var/thing in diseases) - var/datum/disease/D = thing - if(D.severity != DISEASE_SEVERITY_POSITIVE) - D.cure(FALSE) - if(admin_revive) - regenerate_limbs() - regenerate_organs() - handcuffed = initial(handcuffed) - for(var/obj/item/restraints/R in contents) //actually remove cuffs from inventory - qdel(R) - update_handcuffed() - if(reagents) - reagents.addiction_list = list() - cure_all_traumas(TRAUMA_RESILIENCE_MAGIC) - ..() - // heal ears after healing traits, since ears check TRAIT_DEAF trait - // when healing. - restoreEars() - -/mob/living/carbon/can_be_revived() - . = ..() - if(!getorgan(/obj/item/organ/brain) && (!mind || !mind.has_antag_datum(/datum/antagonist/changeling))) - return 0 - -/mob/living/carbon/harvest(mob/living/user) - if(QDELETED(src)) - return - var/organs_amt = 0 - for(var/X in internal_organs) - var/obj/item/organ/O = X - if(prob(50)) - organs_amt++ - O.Remove(src) - O.forceMove(drop_location()) - if(organs_amt) - to_chat(user, "You retrieve some of [src]\'s internal organs!") - -/mob/living/carbon/ExtinguishMob() - for(var/X in get_equipped_items()) - var/obj/item/I = X - I.acid_level = 0 //washes off the acid on our clothes - I.extinguish() //extinguishes our clothes - ..() - -/mob/living/carbon/fakefire(var/fire_icon = "Generic_mob_burning") - var/mutable_appearance/new_fire_overlay = mutable_appearance('icons/mob/OnFire.dmi', fire_icon, -FIRE_LAYER) - new_fire_overlay.appearance_flags = RESET_COLOR - overlays_standing[FIRE_LAYER] = new_fire_overlay - apply_overlay(FIRE_LAYER) - -/mob/living/carbon/fakefireextinguish() - remove_overlay(FIRE_LAYER) - - -/mob/living/carbon/proc/devour_mob(mob/living/carbon/C, devour_time = 130) - C.visible_message("[src] is attempting to devour [C]!", \ - "[src] is attempting to devour you!") - if(!do_mob(src, C, devour_time)) - return - if(pulling && pulling == C && grab_state >= GRAB_AGGRESSIVE && a_intent == INTENT_GRAB) - C.visible_message("[src] devours [C]!", \ - "[src] devours you!") - C.forceMove(src) - stomach_contents.Add(C) - log_combat(src, C, "devoured") - -/mob/living/carbon/proc/create_bodyparts() - var/l_arm_index_next = -1 - var/r_arm_index_next = 0 - for(var/X in bodyparts) - var/obj/item/bodypart/O = new X() - O.owner = src - bodyparts.Remove(X) - bodyparts.Add(O) - if(O.body_part == ARM_LEFT) - l_arm_index_next += 2 - O.held_index = l_arm_index_next //1, 3, 5, 7... - hand_bodyparts += O - else if(O.body_part == ARM_RIGHT) - r_arm_index_next += 2 - O.held_index = r_arm_index_next //2, 4, 6, 8... - hand_bodyparts += O - -/mob/living/carbon/do_after_coefficent() - . = ..() - var/datum/component/mood/mood = src.GetComponent(/datum/component/mood) //Currently, only carbons or higher use mood, move this once that changes. - if(mood) - switch(mood.sanity) //Alters do_after delay based on how sane you are - if(SANITY_INSANE to SANITY_DISTURBED) - . *= 1.25 - if(SANITY_NEUTRAL to SANITY_GREAT) - . *= 0.90 - - -/mob/living/carbon/proc/create_internal_organs() - for(var/X in internal_organs) - var/obj/item/organ/I = X - I.Insert(src) - -/mob/living/carbon/proc/update_disabled_bodyparts() - for(var/B in bodyparts) - var/obj/item/bodypart/BP = B - BP.update_disabled() - -/mob/living/carbon/vv_get_dropdown() - . = ..() - . += "---" - .["Make AI"] = "?_src_=vars;[HrefToken()];makeai=[REF(src)]" - .["Modify bodypart"] = "?_src_=vars;[HrefToken()];editbodypart=[REF(src)]" - .["Modify organs"] = "?_src_=vars;[HrefToken()];editorgans=[REF(src)]" - .["Hallucinate"] = "?_src_=vars;[HrefToken()];hallucinate=[REF(src)]" - .["Give martial arts"] = "?_src_=vars;[HrefToken()];givemartialart=[REF(src)]" - .["Give brain trauma"] = "?_src_=vars;[HrefToken()];givetrauma=[REF(src)]" - .["Cure brain traumas"] = "?_src_=vars;[HrefToken()];curetraumas=[REF(src)]" - -/mob/living/carbon/can_resist() - return bodyparts.len > 2 && ..() - -/mob/living/carbon/proc/hypnosis_vulnerable()//unused atm, but added in case - if(HAS_TRAIT(src, TRAIT_MINDSHIELD)) - return FALSE - if(hallucinating()) - return TRUE - if(IsSleeping()) - return TRUE - if(HAS_TRAIT(src, TRAIT_DUMB)) - return TRUE - var/datum/component/mood/mood = src.GetComponent(/datum/component/mood) - if(mood) - if(mood.sanity < SANITY_UNSTABLE) - return TRUE - -/mob/living/carbon/transfer_ckey(mob/new_mob, send_signal = TRUE) - if(combatmode) - toggle_combat_mode(TRUE, TRUE) - return ..() - -/mob/living/carbon/can_see_reagents() - . = ..() - if(.) //No need to run through all of this if it's already true. - return - if(isclothing(head)) - var/obj/item/clothing/H = head - if(H.clothing_flags & SCAN_REAGENTS) - return TRUE - if(isclothing(wear_mask) && (wear_mask.clothing_flags & SCAN_REAGENTS)) - return TRUE +/mob/living/carbon + blood_volume = BLOOD_VOLUME_NORMAL + +/mob/living/carbon/Initialize() + . = ..() + create_reagents(1000) + update_body_parts() //to update the carbon's new bodyparts appearance + GLOB.carbon_list += src + blood_volume = (BLOOD_VOLUME_NORMAL * blood_ratio) + +/mob/living/carbon/Destroy() + //This must be done first, so the mob ghosts correctly before DNA etc is nulled + . = ..() + + QDEL_LIST(internal_organs) + QDEL_LIST(stomach_contents) + QDEL_LIST(bodyparts) + QDEL_LIST(implants) + remove_from_all_data_huds() + QDEL_NULL(dna) + GLOB.carbon_list -= src + +/mob/living/carbon/initialize_footstep() + AddComponent(/datum/component/footstep, 0.6, 2) + +/mob/living/carbon/relaymove(mob/user, direction) + if(user in src.stomach_contents) + if(prob(40)) + if(prob(25)) + audible_message("You hear something rumbling inside [src]'s stomach...", \ + "You hear something rumbling.", 4,\ + "Something is rumbling inside your stomach!") + var/obj/item/I = user.get_active_held_item() + if(I && I.force) + var/d = rand(round(I.force / 4), I.force) + var/obj/item/bodypart/BP = get_bodypart(BODY_ZONE_CHEST) + if(BP.receive_damage(d, 0)) + update_damage_overlays() + visible_message("[user] attacks [src]'s stomach wall with the [I.name]!", \ + "[user] attacks your stomach wall with the [I.name]!") + playsound(user.loc, 'sound/effects/attackblob.ogg', 50, 1) + + if(prob(src.getBruteLoss() - 50)) + for(var/atom/movable/A in stomach_contents) + A.forceMove(drop_location()) + stomach_contents.Remove(A) + src.gib() + + +/mob/living/carbon/swap_hand(held_index) + if(!held_index) + held_index = (active_hand_index % held_items.len)+1 + + var/obj/item/item_in_hand = src.get_active_held_item() + if(item_in_hand) //this segment checks if the item in your hand is twohanded. + var/obj/item/twohanded/TH = item_in_hand + if(istype(TH)) + if(TH.wielded == 1) + to_chat(usr, "Your other hand is too busy holding [TH]") + return + var/oindex = active_hand_index + active_hand_index = held_index + if(hud_used) + var/obj/screen/inventory/hand/H + H = hud_used.hand_slots["[oindex]"] + if(H) + H.update_icon() + H = hud_used.hand_slots["[held_index]"] + if(H) + H.update_icon() + + +/mob/living/carbon/activate_hand(selhand) //l/r OR 1-held_items.len + if(!selhand) + selhand = (active_hand_index % held_items.len)+1 + + if(istext(selhand)) + selhand = lowertext(selhand) + if(selhand == "right" || selhand == "r") + selhand = 2 + if(selhand == "left" || selhand == "l") + selhand = 1 + + if(selhand != active_hand_index) + swap_hand(selhand) + else + mode() // Activate held item + +/mob/living/carbon/attackby(obj/item/I, mob/user, params) + if(lying && surgeries.len) + if(user != src && (user.a_intent == INTENT_HELP || user.a_intent == INTENT_DISARM)) + for(var/datum/surgery/S in surgeries) + if(S.next_step(user,user.a_intent)) + return 1 + return ..() + +/mob/living/carbon/throw_impact(atom/hit_atom, throwingdatum) + . = ..() + var/hurt = TRUE + if(istype(throwingdatum, /datum/thrownthing)) + var/datum/thrownthing/D = throwingdatum + if(iscyborg(D.thrower)) + var/mob/living/silicon/robot/R = D.thrower + if(!R.emagged) + hurt = FALSE + if(hit_atom.density && isturf(hit_atom)) + if(hurt) + Knockdown(20) + take_bodypart_damage(10) + if(iscarbon(hit_atom) && hit_atom != src) + var/mob/living/carbon/victim = hit_atom + if(victim.movement_type & FLYING) + return + if(hurt) + victim.take_bodypart_damage(10) + take_bodypart_damage(10) + victim.Knockdown(20) + Knockdown(20) + visible_message("[src] crashes into [victim], knocking them both over!",\ + "You violently crash into [victim]!") + playsound(src,'sound/weapons/punch1.ogg',50,1) + + +//Throwing stuff +/mob/living/carbon/proc/toggle_throw_mode() + if(stat) + return + if(in_throw_mode) + throw_mode_off() + else + throw_mode_on() + + +/mob/living/carbon/proc/throw_mode_off() + in_throw_mode = 0 + if(client && hud_used) + hud_used.throw_icon.icon_state = "act_throw_off" + + +/mob/living/carbon/proc/throw_mode_on() + in_throw_mode = 1 + if(client && hud_used) + hud_used.throw_icon.icon_state = "act_throw_on" + +/mob/proc/throw_item(atom/target) + SEND_SIGNAL(src, COMSIG_MOB_THROW, target) + return + +/mob/living/carbon/throw_item(atom/target) + throw_mode_off() + if(!target || !isturf(loc)) + return + if(istype(target, /obj/screen)) + return + + //CIT CHANGES - makes it impossible to throw while in stamina softcrit + if(getStaminaLoss() >= STAMINA_SOFTCRIT) + to_chat(src, "You're too exhausted.") + return + var/random_turn = a_intent == INTENT_HARM + //END OF CIT CHANGES + + var/obj/item/I = src.get_active_held_item() + + var/atom/movable/thrown_thing + var/mob/living/throwable_mob + + if(istype(I, /obj/item/clothing/head/mob_holder)) + var/obj/item/clothing/head/mob_holder/holder = I + if(holder.held_mob) + throwable_mob = holder.held_mob + holder.release() + + if(!I || throwable_mob) + if(!throwable_mob && pulling && isliving(pulling) && grab_state >= GRAB_AGGRESSIVE) + throwable_mob = pulling + + if(throwable_mob && !throwable_mob.buckled) + thrown_thing = throwable_mob + if(pulling) + stop_pulling() + if(HAS_TRAIT(src, TRAIT_PACIFISM)) + to_chat(src, "You gently let go of [throwable_mob].") + return + + adjustStaminaLossBuffered(25)//CIT CHANGE - throwing an entire person shall be very tiring + var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors + var/turf/end_T = get_turf(target) + if(start_T && end_T) + log_combat(src, throwable_mob, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]") + + else if(!CHECK_BITFIELD(I.item_flags, ABSTRACT) && !HAS_TRAIT(I, TRAIT_NODROP)) + thrown_thing = I + dropItemToGround(I) + + if(HAS_TRAIT(src, TRAIT_PACIFISM) && I.throwforce) + to_chat(src, "You set [I] down gently on the ground.") + return + + adjustStaminaLossBuffered(I.getweight()*2)//CIT CHANGE - throwing items shall be more tiring than swinging em. Doubly so. + + if(thrown_thing) + visible_message("[src] has thrown [thrown_thing].") + src.log_message("has thrown [thrown_thing]", LOG_ATTACK) + do_attack_animation(target, no_effect = 1) + playsound(loc, 'sound/weapons/punchmiss.ogg', 50, 1, -1) + newtonian_move(get_dir(target, src)) + thrown_thing.throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src, null, null, null, random_turn) + + + +/mob/living/carbon/restrained(ignore_grab) + . = (handcuffed || (!ignore_grab && pulledby && pulledby.grab_state >= GRAB_AGGRESSIVE)) + +/mob/living/carbon/proc/canBeHandcuffed() + return 0 + + +/mob/living/carbon/show_inv(mob/user) + user.set_machine(src) + var/dat = {" + + [name] + + Head: [(head && !(head.item_flags & ABSTRACT)) ? head : "Nothing"] + Mask: [(wear_mask && !(wear_mask.item_flags & ABSTRACT)) ? wear_mask : "Nothing"] + Neck: [(wear_neck && !(wear_neck.item_flags & ABSTRACT)) ? wear_neck : "Nothing"]"} + + for(var/i in 1 to held_items.len) + var/obj/item/I = get_item_for_held_index(i) + dat += " [get_held_index_name(i)]: | [(I && !(I.item_flags & ABSTRACT)) ? I : "Nothing"]"
+
+ dat += " Back: [back ? back : "Nothing"]" + + if(istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/tank)) + dat += " [internal ? "Disable Internals" : "Set Internals"]" + + if(handcuffed) + dat += " Handcuffed" + if(legcuffed) + dat += " Legcuffed" + + dat += {" + + Close + "} + user << browse(dat, "window=mob[REF(src)];size=325x500") + onclose(user, "mob[REF(src)]") + +/mob/living/carbon/Topic(href, href_list) + ..() + //strip panel + if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY)) + if(href_list["internal"]) + var/slot = text2num(href_list["internal"]) + var/obj/item/ITEM = get_item_by_slot(slot) + if(ITEM && istype(ITEM, /obj/item/tank) && wear_mask && (wear_mask.clothing_flags & ALLOWINTERNALS)) + visible_message("[usr] tries to [internal ? "close" : "open"] the valve on [src]'s [ITEM.name].", \ + "[usr] tries to [internal ? "close" : "open"] the valve on [src]'s [ITEM.name].") + if(do_mob(usr, src, POCKET_STRIP_DELAY)) + if(internal) + internal = null + update_internals_hud_icon(0) + else if(ITEM && istype(ITEM, /obj/item/tank)) + if((wear_mask && (wear_mask.clothing_flags & ALLOWINTERNALS)) || getorganslot(ORGAN_SLOT_BREATHING_TUBE)) + internal = ITEM + update_internals_hud_icon(1) + + visible_message("[usr] [internal ? "opens" : "closes"] the valve on [src]'s [ITEM.name].", \ + "[usr] [internal ? "opens" : "closes"] the valve on [src]'s [ITEM.name].") + + +/mob/living/carbon/fall(forced) + loc.handle_fall(src, forced)//it's loc so it doesn't call the mob's handle_fall which does nothing + +/mob/living/carbon/is_muzzled() + return(istype(src.wear_mask, /obj/item/clothing/mask/muzzle)) + +/mob/living/carbon/hallucinating() + if(hallucination) + return TRUE + else + return FALSE + +/mob/living/carbon/resist_buckle() + if(restrained()) + changeNext_move(CLICK_CD_BREAKOUT) + last_special = world.time + CLICK_CD_BREAKOUT + var/buckle_cd = 600 + if(handcuffed) + var/obj/item/restraints/O = src.get_item_by_slot(SLOT_HANDCUFFED) + buckle_cd = O.breakouttime + visible_message("[src] attempts to unbuckle [p_them()]self!", \ + "You attempt to unbuckle yourself... (This will take around [round(buckle_cd/600,1)] minute\s, and you need to stay still.)") + if(do_after(src, buckle_cd, 0, target = src)) + if(!buckled) + return + buckled.user_unbuckle_mob(src,src) + else + if(src && buckled) + to_chat(src, "You fail to unbuckle yourself!") + else + buckled.user_unbuckle_mob(src,src) + +/mob/living/carbon/resist_fire() + fire_stacks -= 5 + Knockdown(60, TRUE, TRUE) + spin(32,2) + visible_message("[src] rolls on the floor, trying to put [p_them()]self out!", \ + "You stop, drop, and roll!") + sleep(30) + if(fire_stacks <= 0) + visible_message("[src] has successfully extinguished [p_them()]self!", \ + "You extinguish yourself.") + ExtinguishMob() + return + +/mob/living/carbon/resist_restraints() + var/obj/item/I = null + var/type = 0 + if(handcuffed) + I = handcuffed + type = 1 + else if(legcuffed) + I = legcuffed + type = 2 + if(I) + if(type == 1) + changeNext_move(CLICK_CD_BREAKOUT) + last_special = world.time + CLICK_CD_BREAKOUT + if(type == 2) + changeNext_move(CLICK_CD_RANGE) + last_special = world.time + CLICK_CD_RANGE + cuff_resist(I) + + +/mob/living/carbon/proc/cuff_resist(obj/item/I, breakouttime = 600, cuff_break = 0) + if(I.item_flags & BEING_REMOVED) + to_chat(src, "You're already attempting to remove [I]!") + return + I.item_flags |= BEING_REMOVED + breakouttime = I.breakouttime + if(!cuff_break) + visible_message("[src] attempts to remove [I]!") + to_chat(src, "You attempt to remove [I]... (This will take around [DisplayTimeText(breakouttime)] and you need to stand still.)") + if(do_after(src, breakouttime, 0, target = src)) + clear_cuffs(I, cuff_break) + else + to_chat(src, "You fail to remove [I]!") + + else if(cuff_break == FAST_CUFFBREAK) + breakouttime = 50 + visible_message("[src] is trying to break [I]!") + to_chat(src, "You attempt to break [I]... (This will take around 5 seconds and you need to stand still.)") + if(do_after(src, breakouttime, 0, target = src)) + clear_cuffs(I, cuff_break) + else + to_chat(src, "You fail to break [I]!") + + else if(cuff_break == INSTANT_CUFFBREAK) + clear_cuffs(I, cuff_break) + I.item_flags &= ~BEING_REMOVED + +/mob/living/carbon/proc/uncuff() + if (handcuffed) + var/obj/item/W = handcuffed + handcuffed = null + if (buckled && buckled.buckle_requires_restraints) + buckled.unbuckle_mob(src) + update_handcuffed() + if (client) + client.screen -= W + if (W) + W.forceMove(drop_location()) + W.dropped(src) + if (W) + W.layer = initial(W.layer) + W.plane = initial(W.plane) + changeNext_move(0) + if (legcuffed) + var/obj/item/W = legcuffed + legcuffed = null + update_inv_legcuffed() + if (client) + client.screen -= W + if (W) + W.forceMove(drop_location()) + W.dropped(src) + if (W) + W.layer = initial(W.layer) + W.plane = initial(W.plane) + changeNext_move(0) + +/mob/living/carbon/proc/clear_cuffs(obj/item/I, cuff_break) + if(!I.loc || buckled) + return + visible_message("[src] manages to [cuff_break ? "break" : "remove"] [I]!") + to_chat(src, "You successfully [cuff_break ? "break" : "remove"] [I].") + + if(cuff_break) + . = !((I == handcuffed) || (I == legcuffed)) + qdel(I) + return + + else + if(I == handcuffed) + handcuffed.forceMove(drop_location()) + handcuffed.dropped(src) + handcuffed = null + if(buckled && buckled.buckle_requires_restraints) + buckled.unbuckle_mob(src) + update_handcuffed() + return + if(I == legcuffed) + legcuffed.forceMove(drop_location()) + legcuffed.dropped() + legcuffed = null + update_inv_legcuffed() + return + else + dropItemToGround(I) + return + return TRUE + +/mob/living/carbon/get_standard_pixel_y_offset(lying = 0) + if(lying) + return -6 + else + return initial(pixel_y) + +/mob/living/carbon/proc/accident(obj/item/I) + if(!I || (I.item_flags & ABSTRACT) || HAS_TRAIT(I, TRAIT_NODROP)) + return + + //dropItemToGround(I) CIT CHANGE - makes it so the item doesn't drop if the modifier rolls above 100 + + var/modifier = 0 + + if(HAS_TRAIT(src, TRAIT_CLUMSY)) + modifier -= 40 //Clumsy people are more likely to hit themselves -Honk! + + //CIT CHANGES START HERE + else if(combatmode) + modifier += 50 + + if(modifier < 100) + dropItemToGround(I) + //END OF CIT CHANGES + + switch(rand(1,100)+modifier) //91-100=Nothing special happens + if(-INFINITY to 0) //attack yourself + I.attack(src,src) + if(1 to 30) //throw it at yourself + I.throw_impact(src) + if(31 to 60) //Throw object in facing direction + var/turf/target = get_turf(loc) + var/range = rand(2,I.throw_range) + for(var/i = 1; i < range; i++) + var/turf/new_turf = get_step(target, dir) + target = new_turf + if(new_turf.density) + break + I.throw_at(target,I.throw_range,I.throw_speed,src) + if(61 to 90) //throw it down to the floor + var/turf/target = get_turf(loc) + I.throw_at(target,I.throw_range,I.throw_speed,src) + +/mob/living/carbon/Stat() + ..() + if(statpanel("Status")) + var/obj/item/organ/alien/plasmavessel/vessel = getorgan(/obj/item/organ/alien/plasmavessel) + if(vessel) + stat(null, "Plasma Stored: [vessel.storedPlasma]/[vessel.max_plasma]") + if(locate(/obj/item/assembly/health) in src) + stat(null, "Health: [health]") + + add_abilities_to_panel() + +/mob/living/carbon/attack_ui(slot) + if(!has_hand_for_held_index(active_hand_index)) + return 0 + return ..() + +/mob/living/carbon/proc/vomit(lost_nutrition = 10, blood = FALSE, stun = TRUE, distance = 1, message = TRUE, toxic = FALSE) + if(HAS_TRAIT(src, TRAIT_NOHUNGER)) + return 1 + + if(nutrition < 100 && !blood) + if(message) + visible_message("[src] dry heaves!", \ + "You try to throw up, but there's nothing in your stomach!") + if(stun) + Knockdown(200) + return 1 + + if(is_mouth_covered()) //make this add a blood/vomit overlay later it'll be hilarious + if(message) + visible_message("[src] throws up all over [p_them()]self!", \ + "You throw up all over yourself!") + SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "vomit", /datum/mood_event/vomitself) + distance = 0 + else + if(message) + visible_message("[src] throws up!", "You throw up!") + if(!isflyperson(src)) + SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "vomit", /datum/mood_event/vomit) + if(stun) + Stun(80) + + playsound(get_turf(src), 'sound/effects/splat.ogg', 50, 1) + var/turf/T = get_turf(src) + if(!blood) + nutrition -= lost_nutrition + adjustToxLoss(-3) + for(var/i=0 to distance) + if(blood) + if(T) + add_splatter_floor(T) + if(stun) + adjustBruteLoss(3) + else if(src.reagents.has_reagent("blazaam")) + if(T) + T.add_vomit_floor(src, VOMIT_PURPLE) + else + if(T) + T.add_vomit_floor(src, VOMIT_TOXIC)//toxic barf looks different + T = get_step(T, dir) + if (is_blocked_turf(T)) + break + return 1 + +/mob/living/carbon/proc/spew_organ(power = 5, amt = 1) + for(var/i in 1 to amt) + if(!internal_organs.len) + break //Guess we're out of organs! + var/obj/item/organ/guts = pick(internal_organs) + var/turf/T = get_turf(src) + guts.Remove(src) + guts.forceMove(T) + var/atom/throw_target = get_edge_target_turf(guts, dir) + guts.throw_at(throw_target, power, 4, src) + + +/mob/living/carbon/fully_replace_character_name(oldname,newname) + ..() + if(dna) + dna.real_name = real_name + +//Updates the mob's health from bodyparts and mob damage variables +/mob/living/carbon/updatehealth() + if(status_flags & GODMODE) + return + var/total_burn = 0 + var/total_brute = 0 + var/total_stamina = 0 + for(var/X in bodyparts) //hardcoded to streamline things a bit + var/obj/item/bodypart/BP = X + total_brute += (BP.brute_dam * BP.body_damage_coeff) + total_burn += (BP.burn_dam * BP.body_damage_coeff) + total_stamina += (BP.stamina_dam * BP.stam_damage_coeff) + health = round(maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute, DAMAGE_PRECISION) + staminaloss = round(total_stamina, DAMAGE_PRECISION) + update_stat() + if(((maxHealth - total_burn) < HEALTH_THRESHOLD_DEAD) && stat == DEAD ) + become_husk("burn") + med_hud_set_health() + if(stat == SOFT_CRIT) + add_movespeed_modifier(MOVESPEED_ID_CARBON_SOFTCRIT, TRUE, multiplicative_slowdown = SOFTCRIT_ADD_SLOWDOWN) + else + remove_movespeed_modifier(MOVESPEED_ID_CARBON_SOFTCRIT, TRUE) + +/mob/living/carbon/update_stamina() + var/stam = getStaminaLoss() + if(stam > DAMAGE_PRECISION) + var/total_health = (health - stam) + if(total_health <= crit_threshold && !stat) + if(!IsKnockdown()) + to_chat(src, "You're too exhausted to keep going...") + Knockdown(100) + update_health_hud() + +/mob/living/carbon/update_sight() + if(!client) + return + if(stat == DEAD) + sight = (SEE_TURFS|SEE_MOBS|SEE_OBJS) + see_in_dark = 8 + see_invisible = SEE_INVISIBLE_OBSERVER + return + + sight = initial(sight) + lighting_alpha = initial(lighting_alpha) + var/obj/item/organ/eyes/E = getorganslot(ORGAN_SLOT_EYES) + if(!E) + update_tint() + else + see_invisible = E.see_invisible + see_in_dark = E.see_in_dark + sight |= E.sight_flags + if(!isnull(E.lighting_alpha)) + lighting_alpha = E.lighting_alpha + if(HAS_TRAIT(src, TRAIT_NIGHT_VISION)) + lighting_alpha = min(LIGHTING_PLANE_ALPHA_NV_TRAIT, lighting_alpha) + see_in_dark = max(NIGHT_VISION_DARKSIGHT_RANGE, see_in_dark) + + if(client.eye && client.eye != src) + var/atom/A = client.eye + if(A.update_remote_sight(src)) //returns 1 if we override all other sight updates. + return + + if(glasses) + var/obj/item/clothing/glasses/G = glasses + sight |= G.vision_flags + see_in_dark = max(G.darkness_view, see_in_dark) + if(G.invis_override) + see_invisible = G.invis_override + else + see_invisible = min(G.invis_view, see_invisible) + if(!isnull(G.lighting_alpha)) + lighting_alpha = min(lighting_alpha, G.lighting_alpha) + if(dna) + for(var/X in dna.mutations) + var/datum/mutation/M = X + if(M.name == XRAY) + sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS) + see_in_dark = max(see_in_dark, 8) + if(HAS_TRAIT(src, TRAIT_THERMAL_VISION)) + sight |= (SEE_MOBS) + lighting_alpha = min(lighting_alpha, LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE) + + if(HAS_TRAIT(src, TRAIT_XRAY_VISION)) + sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS) + see_in_dark = max(see_in_dark, 8) + + if(see_override) + see_invisible = see_override + . = ..() + + +//to recalculate and update the mob's total tint from tinted equipment it's wearing. +/mob/living/carbon/proc/update_tint() + if(!GLOB.tinted_weldhelh) + return + tinttotal = get_total_tint() + if(tinttotal >= TINT_BLIND) + become_blind(EYES_COVERED) + else if(tinttotal >= TINT_DARKENED) + cure_blind(EYES_COVERED) + overlay_fullscreen("tint", /obj/screen/fullscreen/impaired, 2) + else + cure_blind(EYES_COVERED) + clear_fullscreen("tint", 0) + +/mob/living/carbon/proc/get_total_tint() + . = 0 + if(istype(head, /obj/item/clothing/head)) + var/obj/item/clothing/head/HT = head + . += HT.tint + if(wear_mask) + . += wear_mask.tint + + var/obj/item/organ/eyes/E = getorganslot(ORGAN_SLOT_EYES) + if(E) + . += E.tint + + else + . += INFINITY + +/mob/living/carbon/get_permeability_protection(list/target_zones = list(HANDS,CHEST,GROIN,LEGS,FEET,ARMS,HEAD)) + var/list/tally = list() + for(var/obj/item/I in get_equipped_items()) + for(var/zone in target_zones) + if(I.body_parts_covered & zone) + tally["[zone]"] = max(1 - I.permeability_coefficient, target_zones["[zone]"]) + var/protection = 0 + for(var/key in tally) + protection += tally[key] + protection *= INVERSE(target_zones.len) + return protection + +//this handles hud updates +/mob/living/carbon/update_damage_hud() + + if(!client) + return + + if(health <= crit_threshold) + var/severity = 0 + switch(health) + if(-20 to -10) + severity = 1 + if(-30 to -20) + severity = 2 + if(-40 to -30) + severity = 3 + if(-50 to -40) + severity = 4 + if(-50 to -40) + severity = 5 + if(-60 to -50) + severity = 6 + if(-70 to -60) + severity = 7 + if(-90 to -70) + severity = 8 + if(-95 to -90) + severity = 9 + if(-INFINITY to -95) + severity = 10 + if(!InFullCritical()) + var/visionseverity = 4 + switch(health) + if(-8 to -4) + visionseverity = 5 + if(-12 to -8) + visionseverity = 6 + if(-16 to -12) + visionseverity = 7 + if(-20 to -16) + visionseverity = 8 + if(-24 to -20) + visionseverity = 9 + if(-INFINITY to -24) + visionseverity = 10 + overlay_fullscreen("critvision", /obj/screen/fullscreen/crit/vision, visionseverity) + else + clear_fullscreen("critvision") + overlay_fullscreen("crit", /obj/screen/fullscreen/crit, severity) + else + clear_fullscreen("crit") + clear_fullscreen("critvision") + + //Oxygen damage overlay + var/windedup = getOxyLoss() + getStaminaLoss() * 0.2 + if(windedup) + var/severity = 0 + switch(windedup) + if(10 to 20) + severity = 1 + if(20 to 25) + severity = 2 + if(25 to 30) + severity = 3 + if(30 to 35) + severity = 4 + if(35 to 40) + severity = 5 + if(40 to 45) + severity = 6 + if(45 to INFINITY) + severity = 7 + overlay_fullscreen("oxy", /obj/screen/fullscreen/oxy, severity) + else + clear_fullscreen("oxy") + + //Fire and Brute damage overlay (BSSR) + var/hurtdamage = getBruteLoss() + getFireLoss() + damageoverlaytemp + if(hurtdamage) + var/severity = 0 + switch(hurtdamage) + if(5 to 15) + severity = 1 + if(15 to 30) + severity = 2 + if(30 to 45) + severity = 3 + if(45 to 70) + severity = 4 + if(70 to 85) + severity = 5 + if(85 to INFINITY) + severity = 6 + overlay_fullscreen("brute", /obj/screen/fullscreen/brute, severity) + else + clear_fullscreen("brute") + +/mob/living/carbon/update_health_hud(shown_health_amount) + if(!client || !hud_used) + return + if(hud_used.healths) + if(stat != DEAD) + . = 1 + if(!shown_health_amount) + shown_health_amount = health + if(shown_health_amount >= maxHealth) + hud_used.healths.icon_state = "health0" + else if(shown_health_amount > maxHealth*0.8) + hud_used.healths.icon_state = "health1" + else if(shown_health_amount > maxHealth*0.6) + hud_used.healths.icon_state = "health2" + else if(shown_health_amount > maxHealth*0.4) + hud_used.healths.icon_state = "health3" + else if(shown_health_amount > maxHealth*0.2) + hud_used.healths.icon_state = "health4" + else if(shown_health_amount > 0) + hud_used.healths.icon_state = "health5" + else + hud_used.healths.icon_state = "health6" + else + hud_used.healths.icon_state = "health7" + +/mob/living/carbon/proc/update_internals_hud_icon(internal_state = 0) + if(hud_used && hud_used.internals) + hud_used.internals.icon_state = "internal[internal_state]" + +/mob/living/carbon/update_stat() + if(status_flags & GODMODE) + return + if(stat != DEAD) + if(health <= HEALTH_THRESHOLD_DEAD && !HAS_TRAIT(src, TRAIT_NODEATH)) + death() + return + if(IsUnconscious() || IsSleeping() || getOxyLoss() > 50 || (HAS_TRAIT(src, TRAIT_DEATHCOMA)) || (health <= HEALTH_THRESHOLD_FULLCRIT && !HAS_TRAIT(src, TRAIT_NOHARDCRIT))) + stat = UNCONSCIOUS + blind_eyes(1) + if(combatmode) + toggle_combat_mode(TRUE, TRUE) + else + if(health <= crit_threshold && !HAS_TRAIT(src, TRAIT_NOSOFTCRIT)) + stat = SOFT_CRIT + if(combatmode) + toggle_combat_mode(TRUE, TRUE) + else + stat = CONSCIOUS + adjust_blindness(-1) + update_canmove() + update_damage_hud() + update_health_hud() + med_hud_set_status() + +//called when we get cuffed/uncuffed +/mob/living/carbon/proc/update_handcuffed() + if(handcuffed) + drop_all_held_items() + stop_pulling() + throw_alert("handcuffed", /obj/screen/alert/restrained/handcuffed, new_master = src.handcuffed) + if(handcuffed.demoralize_criminals) + SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "handcuffed", /datum/mood_event/handcuffed) + else + clear_alert("handcuffed") + SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "handcuffed") + update_action_buttons_icon() //some of our action buttons might be unusable when we're handcuffed. + update_inv_handcuffed() + update_hud_handcuffed() + +/mob/living/carbon/fully_heal(admin_revive = FALSE) + if(reagents) + reagents.clear_reagents() + var/obj/item/organ/brain/B = getorgan(/obj/item/organ/brain) + if(B) + B.brain_death = FALSE + for(var/thing in diseases) + var/datum/disease/D = thing + if(D.severity != DISEASE_SEVERITY_POSITIVE) + D.cure(FALSE) + if(admin_revive) + regenerate_limbs() + regenerate_organs() + handcuffed = initial(handcuffed) + for(var/obj/item/restraints/R in contents) //actually remove cuffs from inventory + qdel(R) + update_handcuffed() + if(reagents) + reagents.addiction_list = list() + cure_all_traumas(TRAUMA_RESILIENCE_MAGIC) + ..() + // heal ears after healing traits, since ears check TRAIT_DEAF trait + // when healing. + restoreEars() + +/mob/living/carbon/can_be_revived() + . = ..() + if(!getorgan(/obj/item/organ/brain) && (!mind || !mind.has_antag_datum(/datum/antagonist/changeling))) + return 0 + +/mob/living/carbon/harvest(mob/living/user) + if(QDELETED(src)) + return + var/organs_amt = 0 + for(var/X in internal_organs) + var/obj/item/organ/O = X + if(prob(50)) + organs_amt++ + O.Remove(src) + O.forceMove(drop_location()) + if(organs_amt) + to_chat(user, "You retrieve some of [src]\'s internal organs!") + +/mob/living/carbon/ExtinguishMob() + for(var/X in get_equipped_items()) + var/obj/item/I = X + I.acid_level = 0 //washes off the acid on our clothes + I.extinguish() //extinguishes our clothes + ..() + +/mob/living/carbon/fakefire(var/fire_icon = "Generic_mob_burning") + var/mutable_appearance/new_fire_overlay = mutable_appearance('icons/mob/OnFire.dmi', fire_icon, -FIRE_LAYER) + new_fire_overlay.appearance_flags = RESET_COLOR + overlays_standing[FIRE_LAYER] = new_fire_overlay + apply_overlay(FIRE_LAYER) + +/mob/living/carbon/fakefireextinguish() + remove_overlay(FIRE_LAYER) + + +/mob/living/carbon/proc/devour_mob(mob/living/carbon/C, devour_time = 130) + C.visible_message("[src] is attempting to devour [C]!", \ + "[src] is attempting to devour you!") + if(!do_mob(src, C, devour_time)) + return + if(pulling && pulling == C && grab_state >= GRAB_AGGRESSIVE && a_intent == INTENT_GRAB) + C.visible_message("[src] devours [C]!", \ + "[src] devours you!") + C.forceMove(src) + stomach_contents.Add(C) + log_combat(src, C, "devoured") + +/mob/living/carbon/proc/create_bodyparts() + var/l_arm_index_next = -1 + var/r_arm_index_next = 0 + for(var/X in bodyparts) + var/obj/item/bodypart/O = new X() + O.owner = src + bodyparts.Remove(X) + bodyparts.Add(O) + if(O.body_part == ARM_LEFT) + l_arm_index_next += 2 + O.held_index = l_arm_index_next //1, 3, 5, 7... + hand_bodyparts += O + else if(O.body_part == ARM_RIGHT) + r_arm_index_next += 2 + O.held_index = r_arm_index_next //2, 4, 6, 8... + hand_bodyparts += O + +/mob/living/carbon/do_after_coefficent() + . = ..() + var/datum/component/mood/mood = src.GetComponent(/datum/component/mood) //Currently, only carbons or higher use mood, move this once that changes. + if(mood) + switch(mood.sanity) //Alters do_after delay based on how sane you are + if(SANITY_INSANE to SANITY_DISTURBED) + . *= 1.25 + if(SANITY_NEUTRAL to SANITY_GREAT) + . *= 0.90 + + +/mob/living/carbon/proc/create_internal_organs() + for(var/X in internal_organs) + var/obj/item/organ/I = X + I.Insert(src) + +/mob/living/carbon/proc/update_disabled_bodyparts() + for(var/B in bodyparts) + var/obj/item/bodypart/BP = B + BP.update_disabled() + +/mob/living/carbon/vv_get_dropdown() + . = ..() + . += "---" + .["Make AI"] = "?_src_=vars;[HrefToken()];makeai=[REF(src)]" + .["Modify bodypart"] = "?_src_=vars;[HrefToken()];editbodypart=[REF(src)]" + .["Modify organs"] = "?_src_=vars;[HrefToken()];editorgans=[REF(src)]" + .["Hallucinate"] = "?_src_=vars;[HrefToken()];hallucinate=[REF(src)]" + .["Give martial arts"] = "?_src_=vars;[HrefToken()];givemartialart=[REF(src)]" + .["Give brain trauma"] = "?_src_=vars;[HrefToken()];givetrauma=[REF(src)]" + .["Cure brain traumas"] = "?_src_=vars;[HrefToken()];curetraumas=[REF(src)]" + +/mob/living/carbon/can_resist() + return bodyparts.len > 2 && ..() + +/mob/living/carbon/proc/hypnosis_vulnerable()//unused atm, but added in case + if(HAS_TRAIT(src, TRAIT_MINDSHIELD)) + return FALSE + if(hallucinating()) + return TRUE + if(IsSleeping()) + return TRUE + if(HAS_TRAIT(src, TRAIT_DUMB)) + return TRUE + var/datum/component/mood/mood = src.GetComponent(/datum/component/mood) + if(mood) + if(mood.sanity < SANITY_UNSTABLE) + return TRUE + +/mob/living/carbon/transfer_ckey(mob/new_mob, send_signal = TRUE) + if(combatmode) + toggle_combat_mode(TRUE, TRUE) + return ..() + +/mob/living/carbon/can_see_reagents() + . = ..() + if(.) //No need to run through all of this if it's already true. + return + if(isclothing(head)) + var/obj/item/clothing/H = head + if(H.clothing_flags & SCAN_REAGENTS) + return TRUE + if(isclothing(wear_mask) && (wear_mask.clothing_flags & SCAN_REAGENTS)) + return TRUE +>>>>>>> 8ac23f41e62ae8cff0c4b7993b19775b4a8a3b21 diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 310ab6beeb..3a6f0e6724 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -308,7 +308,7 @@ var/obj/item/organ/vocal_cords/Vc = user.getorganslot(ORGAN_SLOT_VOICE) if(Vc) if(istype(Vc, /obj/item/organ/vocal_cords/velvet)) - if(client?.prefs.lewdchem) + if(client.prefs.cit_toggles & HYPNO) msg += "You feel your chords resonate looking at them.\n" diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 93f33c3a3d..165e1fdd31 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -652,7 +652,7 @@ if(mind) if((mind.assigned_role == "Station Engineer") || (mind.assigned_role == "Chief Engineer") ) gain = 100 - if(mind.assigned_role == "Clown") + if(HAS_TRAIT(mind, TRAIT_CLOWN_MENTALITY)) gain = rand(-300, 300) investigate_log("([key_name(src)]) has been consumed by the singularity.", INVESTIGATE_SINGULO) //Oh that's where the clown ended up! gib() diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index c22144f087..0564f175bd 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -554,6 +554,20 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) //Underwear, Undershirts & Socks if(!(NO_UNDERWEAR in species_traits)) + + if(H.socks && H.get_num_legs(FALSE) >= 2) + if(H.hidden_socks) + H.socks = "Nude" + else + H.socks = H.saved_socks + var/datum/sprite_accessory/underwear/socks/S = GLOB.socks_list[H.socks] + if(S) + var/digilegs = ((DIGITIGRADE in species_traits) && S.has_digitigrade) ? "_d" : "" + var/mutable_appearance/MA = mutable_appearance(S.icon, "[S.icon_state][digilegs]", -BODY_LAYER) + if(S.has_color) + MA.color = "#[H.socks_color]" + standing += MA + if(H.underwear) if(H.hidden_underwear) H.underwear = "Nude" @@ -561,8 +575,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) H.underwear = H.saved_underwear var/datum/sprite_accessory/underwear/bottom/B = GLOB.underwear_list[H.underwear] if(B) - var/mutable_appearance/MA = mutable_appearance(B.icon, B.icon_state, -BODY_LAYER) - if(UNDIE_COLORABLE(B)) + var/digilegs = ((DIGITIGRADE in species_traits) && B.has_digitigrade) ? "_d" : "" + var/mutable_appearance/MA = mutable_appearance(B.icon, "[B.icon_state][digilegs]", -BODY_LAYER) + if(B.has_color) MA.color = "#[H.undie_color]" standing += MA @@ -573,28 +588,16 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) H.undershirt = H.saved_undershirt var/datum/sprite_accessory/underwear/top/T = GLOB.undershirt_list[H.undershirt] if(T) + var/state = "[T.icon_state][((DIGITIGRADE in species_traits) && T.has_digitigrade) ? "_d" : ""]" var/mutable_appearance/MA if(H.dna.species.sexes && H.gender == FEMALE) - MA = wear_female_version(T.icon_state, T.icon, BODY_LAYER) + MA = wear_female_version(state, T.icon, BODY_LAYER) else - MA = mutable_appearance(T.icon, T.icon_state, -BODY_LAYER) - if(UNDIE_COLORABLE(T)) + MA = mutable_appearance(T.icon, state, -BODY_LAYER) + if(T.has_color) MA.color = "#[H.shirt_color]" standing += MA - if(H.socks && H.get_num_legs(FALSE) >= 2) - if(H.hidden_socks) - H.socks = "Nude" - else - H.socks = H.saved_socks - var/datum/sprite_accessory/underwear/socks/S = GLOB.socks_list[H.socks] - if(S) - var/digilegs = (DIGITIGRADE in species_traits) ? "_d" : "" - var/mutable_appearance/MA = mutable_appearance(S.icon, "[S.icon_state][digilegs]", -BODY_LAYER) - if(UNDIE_COLORABLE(S)) - MA.color = "#[H.socks_color]" - standing += MA - if(standing.len) H.overlays_standing[BODY_LAYER] = standing @@ -1598,20 +1601,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) user.adjustStaminaLossBuffered(3) return FALSE else if(aim_for_groin && (target == user || target.lying || same_dir) && (target_on_help || target_restrained || target_aiming_for_groin)) + if(target.client?.prefs.cit_toggles & NO_ASS_SLAP) + to_chat(user,"A force stays your hand, preventing you from slapping \the [target]'s ass!") + return FALSE user.do_attack_animation(target, ATTACK_EFFECT_ASS_SLAP) user.adjustStaminaLossBuffered(3) - if(HAS_TRAIT(target, TRAIT_ASSBLASTUSA)) - var/hit_zone = (user.held_index_to_dir(user.active_hand_index) == "l" ? "l_":"r_") + "arm" - user.adjustStaminaLoss(20, affected_zone = hit_zone) - user.visible_message(\ - "\The [user] slaps \the [target]'s ass, but their hand bounces off like they hit metal!",\ - "You slap [user == target ? "your" : "\the [target]'s"] ass, but feel an intense amount of pain as you realise their buns are harder than steel!",\ - "You hear a slap." - ) - playsound(target.loc, 'sound/weapons/tap.ogg', 50, 1, -1) - user.emote("scream") - return FALSE - playsound(target.loc, 'sound/weapons/slap.ogg', 50, 1, -1) user.visible_message(\ "\The [user] slaps \the [target]'s ass!",\ diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm index 3247c96632..52ae32b23c 100644 --- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm @@ -51,11 +51,7 @@ . = ..() to_chat(C, "[info_text]") - C.real_name = "[pick(GLOB.nightmare_names)]" - C.name = C.real_name - if(C.mind) - C.mind.name = C.real_name - C.dna.real_name = C.real_name + C.fully_replace_character_name("[pick(GLOB.nightmare_names)]") /datum/species/shadow/nightmare/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H) var/turf/T = H.loc @@ -127,8 +123,8 @@ /obj/item/organ/heart/nightmare/Remove(mob/living/carbon/M, special = 0) respawn_progress = 0 if(blade && special != HEART_SPECIAL_SHADOWIFY) - QDEL_NULL(blade) M.visible_message("\The [blade] disintegrates!") + QDEL_NULL(blade) ..() /obj/item/organ/heart/nightmare/Stop() @@ -183,15 +179,21 @@ . = ..() if(!proximity) return - if(isopenturf(AM)) //So you can actually melee with it - return - if(isliving(AM)) + if(isopenturf(AM)) + var/turf/open/T = AM + if(T.light_range && !isspaceturf(T)) //no fairy grass or light tile can escape the fury of the darkness. + to_chat(user, "You scrape away [T] with your [name] and snuff out its lights.") + T.ScrapeAway(flags = CHANGETURF_INHERIT_AIR) + else if(isliving(AM)) var/mob/living/L = AM if(iscyborg(AM)) var/mob/living/silicon/robot/borg = AM - if(!borg.lamp_cooldown) + if(borg.lamp_intensity) borg.update_headlamp(TRUE, INFINITY) to_chat(borg, "Your headlamp is fried! You'll need a human to help replace it.") + for(var/obj/item/assembly/flash/cyborg/F in borg.held_items) + if(!F.crit_fail) + F.burn_out() else for(var/obj/item/O in AM) if(O.light_range && O.light_power) diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm index 8345ef916d..1c6546fd83 100644 --- a/code/modules/mob/living/death.dm +++ b/code/modules/mob/living/death.dm @@ -91,7 +91,9 @@ if(mind && mind.name && mind.active && !istype(T.loc, /area/ctf) && !(signal & COMPONENT_BLOCK_DEATH_BROADCAST)) var/rendered = "[mind.name] has died at [get_area_name(T)]." deadchat_broadcast(rendered, follow_target = src, turf_target = T, message_type=DEADCHAT_DEATHRATTLE) - + if (client && client.prefs && client.prefs.auto_ooc) + if (!(client.prefs.chat_toggles & CHAT_OOC)) + client.prefs.chat_toggles ^= CHAT_OOC if (client) client.move_delay = initial(client.move_delay) diff --git a/code/modules/mob/living/silicon/pai/pai_defense.dm b/code/modules/mob/living/silicon/pai/pai_defense.dm index dda8ddfebd..dfc718f1ab 100644 --- a/code/modules/mob/living/silicon/pai/pai_defense.dm +++ b/code/modules/mob/living/silicon/pai/pai_defense.dm @@ -63,7 +63,8 @@ emitterhealth = CLAMP((emitterhealth - amount), -50, emittermaxhealth) if(emitterhealth < 0) fold_in(force = TRUE) - to_chat(src, "The impact degrades your holochassis!") + if(amount > 0) + to_chat(src, "The impact degrades your holochassis!") return amount /mob/living/silicon/pai/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm index 397d40925b..7cfae9310a 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm @@ -594,12 +594,15 @@ Difficulty: Normal var/list/hit_things = list() //we hit these already, ignore them var/friendly_fire_check = FALSE var/bursting = FALSE //if we're bursting and need to hit anyone crossing us + var/list/nohurt -/obj/effect/temp_visual/hierophant/blast/Initialize(mapload, new_caster, friendly_fire, list/only_hit_once) +/obj/effect/temp_visual/hierophant/blast/Initialize(mapload, new_caster, friendly_fire, list/only_hit_once, list/donthurt = null) . = ..() if(only_hit_once) hit_things = only_hit_once friendly_fire_check = friendly_fire + if(donthurt) + hit_things += donthurt if(new_caster) hit_things += new_caster if(ismineralturf(loc)) //drill mineral turfs diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm index 04a1b4a468..0a8320788e 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm @@ -24,7 +24,8 @@ var/list/attack_action_types = list() var/can_talk = FALSE var/obj/loot_drop = null - + var/owner + //Gives player-controlled variants the ability to swap attacks /mob/living/simple_animal/hostile/asteroid/elite/Initialize(mapload) . = ..() @@ -53,14 +54,14 @@ if(ismineralturf(target)) var/turf/closed/mineral/M = target M.gets_drilled() - + //Elites can't talk (normally)! /mob/living/simple_animal/hostile/asteroid/elite/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) if(can_talk) . = ..() return TRUE return FALSE - + /*Basic setup for elite attacks, based on Whoneedspace's megafauna attack setup. While using this makes the system rely on OnFire, it still gives options for timers not tied to OnFire, and it makes using attacks consistent accross the board for player-controlled elites.*/ @@ -82,11 +83,11 @@ While using this makes the system rely on OnFire, it still gives options for tim /datum/action/innate/elite_attack/Activate() M.chosen_attack = chosen_attack_num to_chat(M, chosen_message) - + /mob/living/simple_animal/hostile/asteroid/elite/updatehealth() . = ..() update_health_hud() - + /mob/living/simple_animal/hostile/asteroid/elite/update_health_hud() if(hud_used) var/severity = 0 @@ -144,7 +145,7 @@ While using this makes the system rely on OnFire, it still gives options for tim gpstag = "Menacing Signal" desc = "You're not quite sure how a signal can be menacing." invisibility = 100 - + /obj/structure/elite_tumor/attack_hand(mob/user) . = ..() if(ishuman(user)) @@ -179,7 +180,7 @@ While using this makes the system rely on OnFire, it still gives options for tim activity = TUMOR_INACTIVE activator = null - + obj/structure/elite_tumor/proc/spawn_elite(var/mob/dead/observer/elitemind) var/selectedspawn = pick(potentialspawns) mychild = new selectedspawn(loc) @@ -199,18 +200,18 @@ obj/structure/elite_tumor/proc/return_elite() if(boosted) mychild.maxHealth = mychild.maxHealth * 2 mychild.health = mychild.maxHealth - + /obj/structure/elite_tumor/Initialize(mapload) . = ..() internal = new/obj/item/gps/internal/elite(src) START_PROCESSING(SSobj, src) - + /obj/structure/elite_tumor/Destroy() STOP_PROCESSING(SSobj, src) mychild = null activator = null return ..() - + /obj/structure/elite_tumor/process() if(isturf(loc)) for(var/mob/living/simple_animal/hostile/asteroid/elite/elitehere in loc) @@ -218,7 +219,7 @@ obj/structure/elite_tumor/proc/return_elite() mychild.adjustHealth(-mychild.maxHealth*0.05) var/obj/effect/temp_visual/heal/H = new /obj/effect/temp_visual/heal(get_turf(mychild)) H.color = "#FF0000" - + /obj/structure/elite_tumor/attackby(obj/item/I, mob/user, params) . = ..() if(istype(I, /obj/item/organ/regenerative_core) && activity == TUMOR_INACTIVE && !boosted) @@ -232,7 +233,7 @@ obj/structure/elite_tumor/proc/return_elite() desc = "[desc] This one seems to glow with a strong intensity." qdel(core) return TRUE - + /obj/structure/elite_tumor/proc/arena_checks() if(activity != TUMOR_ACTIVE || QDELETED(src)) return @@ -240,13 +241,13 @@ obj/structure/elite_tumor/proc/return_elite() INVOKE_ASYNC(src, .proc/arena_trap) //Gets another arena trap queued up for when this one runs out. INVOKE_ASYNC(src, .proc/border_check) //Checks to see if our fighters got out of the arena somehow. addtimer(CALLBACK(src, .proc/arena_checks), 50) - + /obj/structure/elite_tumor/proc/fighters_check() if(activator != null && activator.stat == DEAD || activity == TUMOR_ACTIVE && QDELETED(activator)) onEliteWon() if(mychild != null && mychild.stat == DEAD || activity == TUMOR_ACTIVE && QDELETED(mychild)) onEliteLoss() - + /obj/structure/elite_tumor/proc/arena_trap() var/turf/T = get_turf(src) if(loc == null) @@ -257,7 +258,7 @@ obj/structure/elite_tumor/proc/return_elite() newwall = new /obj/effect/temp_visual/elite_tumor_wall(t, src) newwall.activator = src.activator newwall.ourelite = src.mychild - + /obj/structure/elite_tumor/proc/border_check() if(activator != null && get_dist(src, activator) >= 12) activator.forceMove(loc) @@ -267,7 +268,7 @@ obj/structure/elite_tumor/proc/return_elite() mychild.forceMove(loc) visible_message("[mychild] suddenly reappears above [src]!") playsound(loc,'sound/effects/phasein.ogg', 200, 0, 50, TRUE, TRUE) - + obj/structure/elite_tumor/proc/onEliteLoss() playsound(loc,'sound/effects/tendril_destroyed.ogg', 200, 0, 50, TRUE, TRUE) visible_message("[src] begins to convulse violently before beginning to dissipate.") @@ -286,7 +287,7 @@ obj/structure/elite_tumor/proc/onEliteLoss() mychild = null activator = null qdel(src) - + obj/structure/elite_tumor/proc/onEliteWon() activity = TUMOR_PASSIVE activator = null @@ -300,7 +301,7 @@ obj/structure/elite_tumor/proc/onEliteWon() to_chat(mychild, "As the life in the activator's eyes fade, the forcefield around you dies out and you feel your power subside.\nDespite this inferno being your home, you feel as if you aren't welcome here anymore.\nWithout any guidance, your purpose is now for you to decide.") to_chat(mychild, "Your max health has been halved, but can now heal by standing on your tumor. Note, it's your only way to heal.\nBear in mind, if anyone interacts with your tumor, you'll be resummoned here to carry out another fight. In such a case, you will regain your full max health.\nAlso, be weary of your fellow inhabitants, they likely won't be happy to see you!") to_chat(mychild, "Note that you are a lavaland monster, and thus not allied to the station. You should not cooperate or act friendly with any station crew unless under extreme circumstances!") - + /obj/item/tumor_shard name = "tumor shard" desc = "A strange, sharp, crystal shard from an odd tumor on Lavaland. Stabbing the corpse of a lavaland elite with this will revive them, assuming their soul still lingers. Revived lavaland elites only have half their max health, but are completely loyal to their reviver." @@ -313,7 +314,7 @@ obj/structure/elite_tumor/proc/onEliteWon() w_class = WEIGHT_CLASS_SMALL throw_speed = 3 throw_range = 5 - + /obj/item/tumor_shard/afterattack(atom/target, mob/user, proximity_flag) . = ..() if(istype(target, /mob/living/simple_animal/hostile/asteroid/elite) && proximity_flag) @@ -331,10 +332,11 @@ obj/structure/elite_tumor/proc/onEliteWon() E.health = E.maxHealth E.desc = "[E.desc] However, this one appears appears less wild in nature, and calmer around people." E.sentience_type = SENTIENCE_ORGANIC + E.owner = user qdel(src) else to_chat(user, "[src] only works on the corpse of a sentient lavaland elite.") - + /obj/effect/temp_visual/elite_tumor_wall name = "magic wall" icon = 'icons/turf/walls/hierophant_wall_temp.dmi' @@ -347,7 +349,7 @@ obj/structure/elite_tumor/proc/onEliteWon() color = rgb(255,0,0) light_range = MINIMUM_USEFUL_LIGHT_RANGE light_color = LIGHT_COLOR_RED - + /obj/effect/temp_visual/elite_tumor_wall/Initialize(mapload, new_caster) . = ..() queue_smooth_neighbors(src) diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm index 540470d505..e65c4f5b20 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/pandora.dm @@ -44,34 +44,34 @@ /datum/action/innate/elite_attack/magic_box, /datum/action/innate/elite_attack/pandora_teleport, /datum/action/innate/elite_attack/aoe_squares) - + var/sing_shot_length = 8 var/cooldown_time = 20 - + /datum/action/innate/elite_attack/singular_shot name = "Singular Shot" button_icon_state = "singular_shot" chosen_message = "You are now creating a single linear magic square." chosen_attack_num = SINGULAR_SHOT - + /datum/action/innate/elite_attack/magic_box name = "Magic Box" button_icon_state = "magic_box" chosen_message = "You are now attacking with a box of magic squares." chosen_attack_num = MAGIC_BOX - + /datum/action/innate/elite_attack/pandora_teleport name = "Line Teleport" button_icon_state = "pandora_teleport" chosen_message = "You will now teleport to your target." chosen_attack_num = PANDORA_TELEPORT - + /datum/action/innate/elite_attack/aoe_squares name = "AOE Blast" button_icon_state = "aoe_squares" chosen_message = "Your attacks will spawn an AOE blast at your target location." chosen_attack_num = AOE_SQUARES - + /mob/living/simple_animal/hostile/asteroid/elite/pandora/OpenFire() if(client) switch(chosen_attack) @@ -94,7 +94,7 @@ pandora_teleport(target) if(AOE_SQUARES) aoe_squares(target) - + /mob/living/simple_animal/hostile/asteroid/elite/pandora/Life() . = ..() if(health >= maxHealth * 0.5) @@ -105,28 +105,28 @@ return else cooldown_time = 10 - -/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/singular_shot(target) + +/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/singular_shot(target) ranged_cooldown = world.time + (cooldown_time * 0.5) var/dir_to_target = get_dir(get_turf(src), get_turf(target)) var/turf/T = get_step(get_turf(src), dir_to_target) singular_shot_line(sing_shot_length, dir_to_target, T) - + /mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/singular_shot_line(var/procsleft, var/angleused, var/turf/T) if(procsleft <= 0) return - new /obj/effect/temp_visual/hierophant/blast/pandora(T, src) + new /obj/effect/temp_visual/hierophant/blast/pandora(T, src, null, null, list(owner)) T = get_step(T, angleused) procsleft = procsleft - 1 addtimer(CALLBACK(src, .proc/singular_shot_line, procsleft, angleused, T), 2) - + /mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/magic_box(target) ranged_cooldown = world.time + cooldown_time var/turf/T = get_turf(target) for(var/t in spiral_range_turfs(3, T)) if(get_dist(t, T) > 1) - new /obj/effect/temp_visual/hierophant/blast/pandora(t, src) - + new /obj/effect/temp_visual/hierophant/blast/pandora(t, src, null, null, list(owner)) + /mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/pandora_teleport(target) ranged_cooldown = world.time + cooldown_time var/turf/T = get_turf(target) @@ -135,45 +135,45 @@ new /obj/effect/temp_visual/hierophant/telegraph(source, src) playsound(source,'sound/machines/airlockopen.ogg', 200, 1) addtimer(CALLBACK(src, .proc/pandora_teleport_2, T, source), 2) - + /mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/pandora_teleport_2(var/turf/T, var/turf/source) new /obj/effect/temp_visual/hierophant/telegraph/teleport(T, src) new /obj/effect/temp_visual/hierophant/telegraph/teleport(source, src) for(var/t in RANGE_TURFS(1, T)) - new /obj/effect/temp_visual/hierophant/blast/pandora(t, src) + new /obj/effect/temp_visual/hierophant/blast/pandora(t, src, null, null, list(owner)) for(var/t in RANGE_TURFS(1, source)) - new /obj/effect/temp_visual/hierophant/blast/pandora(t, src) + new /obj/effect/temp_visual/hierophant/blast/pandora(t, src, null, null, list(owner)) animate(src, alpha = 0, time = 2, easing = EASE_OUT) //fade out visible_message("[src] fades out!") density = FALSE addtimer(CALLBACK(src, .proc/pandora_teleport_3, T), 2) - + /mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/pandora_teleport_3(var/turf/T) forceMove(T) animate(src, alpha = 255, time = 2, easing = EASE_IN) //fade IN density = TRUE visible_message("[src] fades in!") - + /mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/aoe_squares(target) ranged_cooldown = world.time + cooldown_time var/turf/T = get_turf(target) - new /obj/effect/temp_visual/hierophant/blast/pandora(T, src) + new /obj/effect/temp_visual/hierophant/blast/pandora(T, src, null, null, list(owner)) var/max_size = 2 addtimer(CALLBACK(src, .proc/aoe_squares_2, T, 0, max_size), 2) - + /mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/aoe_squares_2(var/turf/T, var/ring, var/max_size) if(ring > max_size) return for(var/t in spiral_range_turfs(ring, T)) if(get_dist(t, T) == ring) - new /obj/effect/temp_visual/hierophant/blast/pandora(t, src) + new /obj/effect/temp_visual/hierophant/blast/pandora(t, src, null, null, list(owner)) addtimer(CALLBACK(src, .proc/aoe_squares_2, T, (ring + 1), max_size), 2) - + //The specific version of hiero's squares pandora uses /obj/effect/temp_visual/hierophant/blast/pandora damage = 20 monster_damage_boost = FALSE - + //Pandora's loot: Hope /obj/item/clothing/accessory/pandora_hope name = "Hope" @@ -181,7 +181,7 @@ icon = 'icons/obj/lavaland/elite_trophies.dmi' icon_state = "hope" resistance_flags = FIRE_PROOF - + /obj/item/clothing/accessory/pandora_hope/on_uniform_equip(obj/item/clothing/under/U, user) var/mob/living/L = user if(L && L.mind) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 1a3f2fca3b..427e30f2e2 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -459,6 +459,11 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA if(!ckey || !new_mob) CRASH("transfer_ckey() called [ckey ? "" : "on a ckey-less mob[new_mob ? "" : " and "]"][new_mob ? "" : "without a valid mob target"]!") SEND_SIGNAL(new_mob, COMSIG_MOB_PRE_PLAYER_CHANGE, new_mob, src) + if (client && client.prefs && client.prefs.auto_ooc) + if (client.prefs.chat_toggles & CHAT_OOC && isliving(new_mob)) + client.prefs.chat_toggles ^= CHAT_OOC + if (!(client.prefs.chat_toggles & CHAT_OOC) && isdead(new_mob)) + client.prefs.chat_toggles ^= CHAT_OOC new_mob.ckey = ckey if(send_signal) SEND_SIGNAL(src, COMSIG_MOB_KEY_CHANGE, new_mob, src) diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm index d1a5f12888..c2206fcea8 100644 --- a/code/modules/projectiles/guns/ballistic/revolver.dm +++ b/code/modules/projectiles/guns/ballistic/revolver.dm @@ -352,7 +352,7 @@ clumsy_check = 0 /obj/item/gun/ballistic/revolver/reverse/can_trigger_gun(mob/living/user) - if((HAS_TRAIT(user, TRAIT_CLUMSY)) || (user.mind && user.mind.assigned_role == "Clown")) + if((HAS_TRAIT(user, TRAIT_CLUMSY)) || (user.mind && HAS_TRAIT(user.mind, TRAIT_CLOWN_MENTALITY))) return ..() if(process_fire(user, user, FALSE, null, BODY_ZONE_HEAD)) user.visible_message("[user] somehow manages to shoot [user.p_them()]self in the face!", "You somehow shoot yourself in the face! How the hell?!") diff --git a/code/modules/projectiles/pins.dm b/code/modules/projectiles/pins.dm index 1e2070de1b..0465a611cd 100644 --- a/code/modules/projectiles/pins.dm +++ b/code/modules/projectiles/pins.dm @@ -135,7 +135,7 @@ // A gun with ultra-honk pin is useful for clown and useless for everyone else. /obj/item/firing_pin/clown/ultra/pin_auth(mob/living/user) playsound(src.loc, 'sound/items/bikehorn.ogg', 50, 1) - if(user && (!(HAS_TRAIT(user, TRAIT_CLUMSY)) && !(user.mind && user.mind.assigned_role == "Clown"))) + if(user && (!(HAS_TRAIT(user, TRAIT_CLUMSY)) && !(user.mind && HAS_TRAIT(user.mind, TRAIT_CLOWN_MENTALITY)))) return FALSE return TRUE diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index 23eb24ed15..64e693a326 100644 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -622,7 +622,7 @@ M.adjustBruteLoss(-1*REM, 0) M.adjustFireLoss(-1*REM, 0) M.adjustOxyLoss(-1*REM, 0) - M.adjustToxLoss(-1*REM, 0) + M.adjustToxLoss(-1*REM, 0, TRUE) //heals TOXINLOVERs ..() /datum/reagent/consumable/honey/reaction_mob(mob/living/M, method=TOUCH, reac_volume) diff --git a/code/modules/reagents/reagent_containers/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm index 2bd5fb2d9f..94ad5fdb2c 100644 --- a/code/modules/reagents/reagent_containers/borghydro.dm +++ b/code/modules/reagents/reagent_containers/borghydro.dm @@ -26,12 +26,11 @@ Borg Hypospray var/bypass_protection = 0 //If the hypospray can go through armor or thick material var/list/datum/reagents/reagent_list = list() - var/list/reagent_ids = list("dexalin", "kelotane", "bicaridine", "antitoxin", "epinephrine", "spaceacillin", "salglu_solution") + var/list/reagent_ids = list("dexalin", "kelotane", "bicaridine", "antitoxin", "epinephrine", "spaceacillin", "salglu_solution", "insulin") var/accepts_reagent_upgrades = TRUE //If upgrades can increase number of reagents dispensed. var/list/modes = list() //Basically the inverse of reagent_ids. Instead of having numbers as "keys" and strings as values it has strings as keys and numbers as values. //Used as list for input() in shakers. - /obj/item/reagent_containers/borghypo/Initialize() . = ..() @@ -40,12 +39,10 @@ Borg Hypospray START_PROCESSING(SSobj, src) - /obj/item/reagent_containers/borghypo/Destroy() STOP_PROCESSING(SSobj, src) return ..() - /obj/item/reagent_containers/borghypo/process() //Every [recharge_time] seconds, recharge some reagents for the cyborg charge_tick++ if(charge_tick >= recharge_time) @@ -162,7 +159,7 @@ Borg Hypospray icon_state = "borghypo_s" charge_cost = 20 recharge_time = 2 - reagent_ids = list("syndicate_nanites", "potass_iodide", "morphine") + reagent_ids = list("syndicate_nanites", "potass_iodide", "morphine", "insulin") bypass_protection = 1 accepts_reagent_upgrades = FALSE @@ -178,7 +175,6 @@ Borg Shaker charge_cost = 20 //Lots of reagents all regenerating at once, so the charge cost is lower. They also regenerate faster. recharge_time = 3 accepts_reagent_upgrades = FALSE - reagent_ids = list("beer", "orangejuice", "grenadine", "limejuice", "tomatojuice", "cola", "tonic", "sodawater", "ice", "cream", "whiskey", "vodka", "rum", "gin", "tequila", "vermouth", "wine", "kahlua", "cognac", "ale", "milk", "coffee", "banana", "lemonjuice") /obj/item/reagent_containers/borghypo/borgshaker/attack(mob/M, mob/user) @@ -234,23 +230,21 @@ Borg Shaker charge_cost = 20 //Lots of reagents all regenerating at once, so the charge cost is lower. They also regenerate faster. recharge_time = 3 accepts_reagent_upgrades = FALSE - reagent_ids = list("fakebeer", "fernet") /obj/item/reagent_containers/borghypo/peace name = "Peace Hypospray" - - reagent_ids = list("dizzysolution","tiresolution","synthpax") + reagent_ids = list("dizzysolution", "tiresolution", "synthpax", "insulin") accepts_reagent_upgrades = FALSE /obj/item/reagent_containers/borghypo/peace/hacked desc = "Everything's peaceful in death!" icon_state = "borghypo_s" - reagent_ids = list("dizzysolution","tiresolution","synthpax","tirizene","sulfonal","sodium_thiopental","cyanide","fentanyl") + reagent_ids = list("dizzysolution", "tiresolution", "synthpax", "tirizene", "sulfonal", "sodium_thiopental", "cyanide", "fentanyl") accepts_reagent_upgrades = FALSE /obj/item/reagent_containers/borghypo/epi - name = "epinephrine injector" + name = "Stabilizer injector" desc = "An advanced chemical synthesizer and injection system, designed to stabilize patients." - reagent_ids = list("epinephrine") + reagent_ids = list("epinephrine", "insulin") accepts_reagent_upgrades = FALSE diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index 75b705fc35..cd40f7aac3 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -152,6 +152,16 @@ category = list("Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL +/datum/design/telescopiciv + name = "Telescopic IV Drip" + desc = "An IV drip with an advanced infusion pump that can both drain blood into and inject liquids from attached containers. Blood packs are processed at an accelerated rate. This one is telescopic, and can be picked up and put down." + id = "telescopiciv" + build_type = PROTOLATHE + materials = list(MAT_METAL = 5000, MAT_GLASS = 3500, MAT_SILVER = 1000) + build_path = /obj/item/tele_iv + category = list("Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL + /datum/design/holobarrier_med name = "PENLITE holobarrier projector" desc = "PENLITE holobarriers, a device that halts individuals with malicious diseases." diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 1a3601beba..aff927c4f5 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -71,7 +71,7 @@ display_name = "Biological Technology" description = "What makes us tick." //the MC, silly! prereq_ids = list("base") - design_ids = list("medicalkit", "chem_heater", "chem_master", "chem_dispenser", "sleeper", "vr_sleeper", "pandemic", "defibmount", "operating", "soda_dispenser", "beer_dispenser", "healthanalyzer", "blood_bag", "bloodbankgen","genescanner") + design_ids = list("medicalkit", "chem_heater", "chem_master", "chem_dispenser", "sleeper", "vr_sleeper", "pandemic", "defibmount", "operating", "soda_dispenser", "beer_dispenser", "healthanalyzer", "blood_bag", "bloodbankgen", "telescopiciv","genescanner") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) export_price = 5000 diff --git a/code/modules/security_levels/security_levels.dm b/code/modules/security_levels/security_levels.dm index 70b06e6438..13d1543c92 100644 --- a/code/modules/security_levels/security_levels.dm +++ b/code/modules/security_levels/security_levels.dm @@ -49,7 +49,7 @@ GLOBAL_VAR_INIT(security_level, SEC_LEVEL_GREEN) else SSshuttle.emergency.modTimer(1.5) GLOB.security_level = SEC_LEVEL_BLUE - sound_to_playing_players('sound/misc/voybluealert.ogg') // Citadel change - Makes alerts play a sound + sound_to_playing_players('sound/misc/voybluealert.ogg', volume = 50) // Citadel change - Makes alerts play a sound for(var/obj/machinery/firealarm/FA in GLOB.machines) if(is_station_level(FA.z)) FA.update_icon() @@ -66,7 +66,7 @@ GLOBAL_VAR_INIT(security_level, SEC_LEVEL_GREEN) if(SSshuttle.emergency.mode == SHUTTLE_CALL || SSshuttle.emergency.mode == SHUTTLE_RECALL) SSshuttle.emergency.modTimer(1.6) GLOB.security_level = SEC_LEVEL_AMBER - sound_to_playing_players('sound/effects/alert.ogg') // Citadel change - Makes alerts play a sound + sound_to_playing_players('sound/effects/alert.ogg', volume = 50) // Citadel change - Makes alerts play a sound for(var/obj/machinery/firealarm/FA in GLOB.machines) if(is_station_level(FA.z)) FA.update_icon() @@ -83,7 +83,7 @@ GLOBAL_VAR_INIT(security_level, SEC_LEVEL_GREEN) else minor_announce(CONFIG_GET(string/alert_red_downto), "Attention! Code red!") GLOB.security_level = SEC_LEVEL_RED - sound_to_playing_players('sound/misc/voyalert.ogg') // Citadel change - Makes alerts play a sound + sound_to_playing_players('sound/misc/voyalert.ogg', volume = 50) // Citadel change - Makes alerts play a sound for(var/obj/machinery/firealarm/FA in GLOB.machines) if(is_station_level(FA.z)) diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm index dedff3ae04..161461d099 100644 --- a/code/modules/surgery/organs/vocal_cords.dm +++ b/code/modules/surgery/organs/vocal_cords.dm @@ -560,7 +560,7 @@ else if((findtext(message, honk_words))) cooldown = COOLDOWN_MEME addtimer(CALLBACK(GLOBAL_PROC, .proc/playsound, get_turf(user), 'sound/items/bikehorn.ogg', 300, 1), 25) - if(user.mind && user.mind.assigned_role == "Clown") + if(user.mind && HAS_TRAIT(user.mind, TRAIT_CLOWN_MENTALITY)) for(var/mob/living/carbon/C in listeners) C.slip(140 * power_multiplier) cooldown = COOLDOWN_MEME @@ -807,9 +807,8 @@ E.enthrallTally += (power_multiplier*(((length(message))/200) + 1)) //encourage players to say more than one word. else E.enthrallTally += power_multiplier*1.25 //thinking about it, I don't know how this can proc - if(L.canbearoused) - if(L.client?.prefs.lewdchem) - addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "[E.enthrallGender] is so nice to listen to."), 5) + if(L.canbearoused && E.lewd) + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "[E.enthrallGender] is so nice to listen to."), 5) E.cooldown += 1 //REWARD mixable works @@ -820,7 +819,7 @@ power_multiplier *= distancelist[get_dist(user, V)+1] if(L == user) continue - if (L.client?.prefs.lewdchem) + if (E.lewd) addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "[E.enthrallGender] has praised me!!"), 5) if(HAS_TRAIT(L, TRAIT_NYMPHO)) L.adjustArousalLoss(2*power_multiplier) @@ -832,7 +831,7 @@ addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "I've been praised for doing a good job!"), 5) E.resistanceTally -= power_multiplier E.enthrallTally += power_multiplier - var/descmessage = "[(L.client?.prefs.lewdchem?"I feel so happy! I'm a good pet who [E.enthrallGender] loves!":"I did a good job!")]" + var/descmessage = "[(E.lewd?"I feel so happy! I'm a good pet who [E.enthrallGender] loves!":"I did a good job!")]" SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "enthrallpraise", /datum/mood_event/enthrallpraise, descmessage) E.cooldown += 1 @@ -841,10 +840,10 @@ for(var/V in listeners) var/mob/living/L = V var/datum/status_effect/chem/enthrall/E = L.has_status_effect(/datum/status_effect/chem/enthrall) - var/descmessage = "[(L.client?.prefs.lewdchem?"I've failed [E.enthrallGender]... What a bad, bad pet!":"I did a bad job...")]" + var/descmessage = "[(E.lewd?"I've failed [E.enthrallGender]... What a bad, bad pet!":"I did a bad job...")]" if(L == user) continue - if (L.client?.prefs.lewdchem) + if (E.lewd) if(HAS_TRAIT(L, TRAIT_MASO)) L.adjustArousalLoss(3*power_multiplier) descmessage += "And yet, it feels so good..!" //I don't really understand masco, is this the right sort of thing they like? @@ -871,7 +870,7 @@ var/datum/status_effect/chem/enthrall/E = C.has_status_effect(/datum/status_effect/chem/enthrall) REMOVE_TRAIT(C, TRAIT_MUTE, "enthrall") C.silent = 0 - if(C.client?.prefs.lewdchem) + if(E.lewd) addtimer(CALLBACK(C, /atom/movable/proc/say, "[E.enthrallGender]"), 5) else addtimer(CALLBACK(C, /atom/movable/proc/say, "[E.master]"), 5) @@ -887,7 +886,7 @@ E.phase = 3 E.status = null user.emote("snap") - if(L.client?.prefs.lewdchem) + if(E.lewd) addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "The snapping of your [E.enthrallGender]'s fingers brings you back to your enthralled state, obedient and ready to serve."), 5) else addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "The snapping of [E.master]'s fingers brings you back to being under their influence."), 5) @@ -910,11 +909,11 @@ addtimer(CALLBACK(H, /atom/movable/proc/say, "I feel happy being with you."), 5) continue if(2) - speaktrigger += "[(H.client?.prefs.lewdchem?"I think I'm in love with you... ":"I find you really inspirational, ")]" //' + speaktrigger += "[(E.lewd?"I think I'm in love with you... ":"I find you really inspirational, ")]" //' if(3) - speaktrigger += "[(H.client?.prefs.lewdchem?"I'm devoted to being your pet":"I'm commited to following your cause!")]! " + speaktrigger += "[(E.lewd?"I'm devoted to being your pet":"I'm commited to following your cause!")]! " if(4) - speaktrigger += "[(H.client?.prefs.lewdchem?"You are my whole world and all of my being belongs to you, ":"I cannot think of anything else but aiding your cause, ")] "//Redflags!! + speaktrigger += "[(E.lewd?"You are my whole world and all of my being belongs to you, ":"I cannot think of anything else but aiding your cause, ")] "//Redflags!! //mood var/datum/component/mood/mood = H.GetComponent(/datum/component/mood) @@ -1003,7 +1002,7 @@ speaktrigger += "I feel like I'm on the brink of losing my mind, " //horny - if(HAS_TRAIT(H, TRAIT_NYMPHO) && H.canbearoused && H.client?.prefs.lewdchem) + if(HAS_TRAIT(H, TRAIT_NYMPHO) && H.canbearoused && E.lewd) switch(H.getArousalLoss()) if(40 to 60) speaktrigger += "I'm feeling a little horny, " @@ -1013,10 +1012,10 @@ speaktrigger += "I'm really, really horny, " //collar - if(istype(H.wear_neck, /obj/item/clothing/neck/petcollar) && H.client?.prefs.lewdchem) + if(istype(H.wear_neck, /obj/item/clothing/neck/petcollar) && E.lewd) speaktrigger += "I love the collar you gave me, " //End - if(H.client?.prefs.lewdchem) + if(E.lewd) speaktrigger += "[E.enthrallGender]!" else speaktrigger += "[user.first_name()]!" @@ -1044,7 +1043,7 @@ REMOVE_TRAIT(C, TRAIT_MUTE, "enthrall") C.silent = 0 E.cooldown += 3 - to_chat(user, "You [(C.client?.prefs.lewdchem?"allow [C] to speak again":"encourage [C] to speak again")].") + to_chat(user, "You [(E.lewd?"allow [C] to speak again":"encourage [C] to speak again")].") //Antiresist @@ -1074,7 +1073,7 @@ for(var/mob/living/carbon/C in listeners) var/datum/status_effect/chem/enthrall/E = C.has_status_effect(/datum/status_effect/chem/enthrall) if(E.phase == 4) - addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, C, "You're unable to forget about [(C.client?.prefs.lewdchem?"the dominating presence of [E.enthrallGender]":"[E.master]")]!"), 5) + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, C, "You're unable to forget about [(E.lewd?"the dominating presence of [E.enthrallGender]":"[E.master]")]!"), 5) continue addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, C, "You wake up, forgetting everything that just happened. You must've dozed off..? How embarassing!"), 5) C.Sleeping(50) @@ -1086,7 +1085,7 @@ if(3) E.phase = 0 E.cooldown = 0 - if(C.client?.prefs.lewdchem) + if(E.lewd) addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, C, "You revert to yourself before being enthralled by your [E.enthrallGender], with no memory of what happened."), 5) else addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, C, "You revert to who you were before, with no memory of what happened with [E.master]."), 5) @@ -1112,7 +1111,7 @@ var/mob/living/carbon/human/H = V var/datum/status_effect/chem/enthrall/E = H.has_status_effect(/datum/status_effect/chem/enthrall) if(E.phase > 1) - if(HAS_TRAIT(H, TRAIT_NYMPHO) && H.canbearoused && H.client?.prefs.lewdchem) // probably a redundant check but for good measure + if(HAS_TRAIT(H, TRAIT_NYMPHO) && H.canbearoused && E.lewd) // probably a redundant check but for good measure addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "Your [E.enthrallGender] pushes you over the limit, overwhelming your body with pleasure."), 5) H.mob_climax(forced_climax=TRUE) H.SetStun(20) @@ -1168,7 +1167,7 @@ for(var/obj/item/W in items) if(W == H.wear_suit) H.dropItemToGround(W, TRUE) - addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "Before you can even think about it, you quickly remove your clothes in response to [(H.client?.prefs.lewdchem?"your [E.enthrallGender]'s command'":"[E.master]'s directive'")]."), 5) + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "Before you can even think about it, you quickly remove your clothes in response to [(E.lewd?"your [E.enthrallGender]'s command'":"[E.master]'s directive'")]."), 5) E.cooldown += 10 //WALK @@ -1206,7 +1205,7 @@ if(2 to INFINITY) L.lay_down() E.cooldown += 10 - addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "[(L.client?.prefs.lewdchem?"You eagerly lie down!":"You suddenly lie down!")]"), 5) + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "[(E.lewd?"You eagerly lie down!":"You suddenly lie down!")]"), 5) to_chat(user, "You encourage [L] to lie down.") //KNOCKDOWN @@ -1237,7 +1236,7 @@ for (var/trigger in E.customTriggers) speaktrigger += "[trigger], " to_chat(user, "[C] whispers, \"[speaktrigger] are my triggers.\"")//So they don't trigger themselves! - addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, C, "You whisper your triggers to [(C.client?.prefs.lewdchem?"Your [E.enthrallGender]":"[E.master]")]."), 5) + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, C, "You whisper your triggers to [(E.lewd?"Your [E.enthrallGender]":"[E.master]")]."), 5) //CUSTOM TRIGGERS @@ -1249,7 +1248,7 @@ if (get_dist(user, H) > 1)//Requires user to be next to their pet. to_chat(user, "You need to be next to your pet to give them a new trigger!") continue - if(!H.client?.prefs.lewdchem) + if(!E.lewd) to_chat(user, "[H] seems incapable of being implanted with triggers.") continue else @@ -1272,7 +1271,7 @@ E.customTriggers[trigger] = trigger2 log_game("FERMICHEM: [H] has been implanted by [user] with [trigger], triggering [trigger2].") E.mental_capacity -= 5 - addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "[(H.client?.prefs.lewdchem?"your [E.enthrallGender]":"[E.master]")] whispers you a new trigger."), 5) + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "[(E.lewd?"your [E.enthrallGender]":"[E.master]")] whispers you a new trigger."), 5) to_chat(user, "You sucessfully set the trigger word [trigger] in [H]") else to_chat(user, "Your pet looks at you confused, it seems they don't understand that effect!") @@ -1290,7 +1289,7 @@ if (get_dist(user, H) > 1)//Requires user to be next to their pet. to_chat(user, "You need to be next to your pet to give them a new echophrase!") continue - if(!H.client?.prefs.lewdchem) + if(!E.lewd) to_chat(user, "[H] seems incapable of being implanted with an echoing phrase.") continue else @@ -1334,7 +1333,7 @@ objective = replacetext(lowertext(objective), "suicide", "self-love") message_admins("[H] has been implanted by [user] with the objective [objective].") log_game("FERMICHEM: [H] has been implanted by [user] with the objective [objective] via MKUltra.") - addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "[(H.client?.prefs.lewdchem?"Your [E.enthrallGender]":"[E.master]")] whispers you a new objective."), 5) + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "[(E.lewd?"Your [E.enthrallGender]":"[E.master]")] whispers you a new objective."), 5) brainwash(H, objective) E.mental_capacity -= 200 to_chat(user, "You sucessfully give an objective to [H]") @@ -1348,7 +1347,7 @@ for(var/V in listeners) var/mob/living/carbon/human/H = V var/datum/status_effect/chem/enthrall/E = H.has_status_effect(/datum/status_effect/chem/enthrall) - if(E.phase >= 3 && H.client?.prefs.lewdchem) + if(E.phase >= 3 && E.lewd) var/instill = stripped_input(user, "Instill an emotion in [H].", MAX_MESSAGE_LEN) to_chat(H, "[instill]") to_chat(user, "You sucessfully instill a feeling in [H]") @@ -1363,7 +1362,7 @@ if(E.phase > 1) if(user.ckey == E.enthrallID && user.real_name == E.master.real_name) E.master = user - addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "[(H.client?.prefs.lewdchem?"You hear the words of your [E.enthrallGender] again!! They're back!!":"You recognise the voice of [E.master].")]"), 5) + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "[(E.lewd?"You hear the words of your [E.enthrallGender] again!! They're back!!":"You recognise the voice of [E.master].")]"), 5) to_chat(user, "[H] looks at you with sparkling eyes, recognising you!") //I dunno how to do state objectives without them revealing they're an antag diff --git a/code/modules/vehicles/cars/clowncar.dm b/code/modules/vehicles/cars/clowncar.dm index a2a9c37cfd..1415604aff 100644 --- a/code/modules/vehicles/cars/clowncar.dm +++ b/code/modules/vehicles/cars/clowncar.dm @@ -21,7 +21,7 @@ /obj/vehicle/sealed/car/clowncar/auto_assign_occupant_flags(mob/M) if(ishuman(M)) var/mob/living/carbon/human/H = M - if(H.mind && H.mind.assigned_role == "Clown") //Ensures only clowns can drive the car. (Including more at once) + if(H.mind && HAS_TRAIT(H.mind, TRAIT_CLOWN_MENTALITY)) //Ensures only clowns can drive the car. (Including more at once) add_control_flags(M, VEHICLE_CONTROL_DRIVE|VEHICLE_CONTROL_PERMISSION) return add_control_flags(M, VEHICLE_CONTROL_KIDNAPPED) diff --git a/code/modules/vending/clothesmate.dm b/code/modules/vending/clothesmate.dm index 626abd51ef..6144f4c57a 100644 --- a/code/modules/vending/clothesmate.dm +++ b/code/modules/vending/clothesmate.dm @@ -70,14 +70,22 @@ /obj/item/clothing/under/skirt/red = 3, /obj/item/clothing/under/skirt/purple = 3, /obj/item/clothing/under/sundress = 4, + /obj/item/clothing/under/sundresswhite = 4, /obj/item/clothing/under/stripeddress = 3, /obj/item/clothing/under/sailordress = 3, + /obj/item/clothing/under/sweptskirt = 3, + /obj/item/clothing/under/greendress = 3, + /obj/item/clothing/under/pinkdress = 3, /obj/item/clothing/under/redeveninggown = 3, /obj/item/clothing/under/blacktango = 3, + /obj/item/clothing/under/westernbustle = 3, + /obj/item/clothing/under/flamenco = 3, + /obj/item/clothing/under/flowerdress = 3, /obj/item/clothing/under/plaid_skirt = 3, /obj/item/clothing/under/plaid_skirt/blue = 3, /obj/item/clothing/under/plaid_skirt/purple = 3, /obj/item/clothing/under/plaid_skirt/green = 3, + /obj/item/clothing/under/croptop = 3, /obj/item/clothing/glasses/regular = 2, /obj/item/clothing/glasses/regular/jamjar = 2, /obj/item/clothing/head/sombrero = 3, diff --git a/html/changelog.html b/html/changelog.html index 8eabba83df..21cade10d2 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -50,6 +50,328 @@ -->
+ 30 December 2019+AnturK updated:+
Arturlang updated:+
BlueWildrose updated:+
Commandersand updated:+
DeltaFire15 updated:+
Detective-Google updated:+
Fermis updated:+
Fikou updated:+
Ghommie updated:+
Ghommie (also porting PRs by AnturK and Arkatos) updated:+
Ghommie, Skogol updated:+
GrayRachnid updated:+
Hatterhat updated:+
ItzGabby updated:+
KeRSedChaplain updated:+
Linzolle updated:+
Mickyan, nemvar, RaveRadbury, AnturK, SpaceManiac updated:+
Narcissisko (ported by Hatterhat) updated:+
Nervere and subject217, Militaires, py01, nemvar updated:+
PersianXerxes updated:+
Putnam updated:+
Putnam3145 updated:+
Seris02 updated:+
ShizCalev updated:+
Sishen1542 updated:+
Toriate updated:+
Trilbyspaceclone updated:+
Useroth updated:+
Xantholne updated:+
kappa-sama updated:+
keronshb updated:+
kevinz000 updated:+
lolman360 updated:+
nemvar updated:+
nicbn, Kevinz000, ShizCalev updated:+
r4d6 updated:+
shellspeed1 updated:+
07 December 2019AffectedArc07 updated:
|