Skip to content

Commit

Permalink
Merge branch 'upstream-master' into merge-upstream
Browse files Browse the repository at this point in the history
  • Loading branch information
larentoun committed Nov 30, 2024
2 parents 25a2530 + bc12a4d commit e133800
Show file tree
Hide file tree
Showing 42 changed files with 272 additions and 124 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/generate_documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
touch dmdoc/.nojekyll
echo codedocs.tgstation13.org > dmdoc/CNAME
- name: Deploy
uses: JamesIves/github-pages-deploy-action@v4.6.9
uses: JamesIves/github-pages-deploy-action@v4.7.1
with:
branch: gh-pages
clean: true
Expand Down
2 changes: 1 addition & 1 deletion code/__DEFINES/dcs/signals/signals_reagent.dm
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#define COMSIG_ATOM_EXPOSE_REAGENT "atom_expose_reagent"
///from base of [/datum/reagent/proc/expose_atom]: (/atom, reac_volume)
#define COMSIG_REAGENT_EXPOSE_ATOM "reagent_expose_atom"
///from base of [/datum/reagent/proc/expose_atom]: (/obj, reac_volume)
///from base of [/datum/reagent/proc/expose_atom]: (/obj, reac_volume, methods, show_message)
#define COMSIG_REAGENT_EXPOSE_OBJ "reagent_expose_obj"
///from base of [/datum/reagent/proc/expose_atom]: (/mob/living, reac_volume, methods, show_message, touch_protection, /mob/eye/blob) // ovemind arg is only used by blob reagents.
#define COMSIG_REAGENT_EXPOSE_MOB "reagent_expose_mob"
Expand Down
8 changes: 4 additions & 4 deletions code/datums/mood_events/_mood_event.dm
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@
/// if false, it will be an overlay instead
var/special_screen_replace = TRUE
/// Owner of this mood event
var/mob/owner
var/mob/living/owner
/// List of required jobs for this mood event
var/list/required_job = list()

/datum/mood_event/New(mob/M, ...)
owner = M
/datum/mood_event/New(mob/living/emotional_mob, ...)
owner = emotional_mob
var/list/params = args.Copy(2)
if ((length(required_job) > 0) && M.mind && !(M.mind.assigned_role.type in required_job))
if ((length(required_job) > 0) && owner.mind && !(owner.mind.assigned_role.type in required_job))
qdel(src)
return
add_effects(arglist(params))
Expand Down
26 changes: 21 additions & 5 deletions code/datums/mood_events/needs_events.dm
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,31 @@
timeout = 4 MINUTES

//Generic needs events
/datum/mood_event/nice_shower
/datum/mood_event/shower
description = "I have recently had a nice shower."
mood_change = 4
timeout = 5 MINUTES

/datum/mood_event/shower_hater
description = "I hate being wet!"
mood_change = -2
timeout = 3 MINUTES
/datum/mood_event/shower/add_effects(shower_reagent)
if(istype(shower_reagent, /datum/reagent/blood))
if(HAS_TRAIT(owner, TRAIT_MORBID) || HAS_TRAIT(owner, TRAIT_EVIL) || (owner.mob_biotypes & MOB_UNDEAD))
description = "The sensation of a lovely blood shower felt good."
mood_change = 6 // you sicko
else
description = "I have recently had a horrible shower raining blood!"
mood_change = -4
timeout = 3 MINUTES
else if(istype(shower_reagent, /datum/reagent/water))
if(HAS_TRAIT(owner, TRAIT_WATER_HATER) && !HAS_TRAIT(owner, TRAIT_WATER_ADAPTATION))
description = "I hate being wet!"
mood_change = -2
timeout = 3 MINUTES
else
return // just normal clean shower
else // it's dirty ass water
description = "I have recently had a dirty shower!"
mood_change = -3
timeout = 3 MINUTES

/datum/mood_event/hot_spring
description = "It's so relaxing to bathe in steamy water..."
Expand Down
97 changes: 72 additions & 25 deletions code/datums/status_effects/neutral.dm
Original file line number Diff line number Diff line change
Expand Up @@ -619,40 +619,67 @@
duration = STATUS_EFFECT_PERMANENT
status_type = STATUS_EFFECT_UNIQUE
alert_type = /atom/movable/screen/alert/status_effect/washing_regen
///The screen alert shown if you hate water
var/hater_alert = /atom/movable/screen/alert/status_effect/washing_regen/hater
/// How much stamina we regain from washing
var/stamina_heal_per_tick = -4
/// How much brute, tox and fie damage we heal from this
var/heal_per_tick = 0
/// The main reagent used for the shower (if no reagent is at least 70% of volume then it's null)
var/datum/reagent/shower_reagent

/datum/status_effect/washing_regen/on_creation(mob/living/new_owner, shower_reagent)
if(!src.shower_reagent)
src.shower_reagent = shower_reagent
return ..()

/datum/status_effect/washing_regen/on_apply()
. = ..()
if(HAS_TRAIT(owner, TRAIT_WATER_HATER) && !HAS_TRAIT(owner, TRAIT_WATER_ADAPTATION))
alert_type = hater_alert
if(istype(shower_reagent, /datum/reagent/blood))
if(HAS_TRAIT(owner, TRAIT_MORBID) || HAS_TRAIT(owner, TRAIT_EVIL) || (owner.mob_biotypes & MOB_UNDEAD))
alert_type = /atom/movable/screen/alert/status_effect/washing_regen/bloody_like
else
alert_type = /atom/movable/screen/alert/status_effect/washing_regen/bloody_dislike
else if(istype(shower_reagent, /datum/reagent/water))
if(HAS_TRAIT(owner, TRAIT_WATER_HATER) && !HAS_TRAIT(owner, TRAIT_WATER_ADAPTATION))
alert_type = /atom/movable/screen/alert/status_effect/washing_regen/hater
else
alert_type = /atom/movable/screen/alert/status_effect/washing_regen
else if(!shower_reagent) // dirty shower
alert_type = /atom/movable/screen/alert/status_effect/washing_regen/dislike

/datum/status_effect/washing_regen/tick(seconds_between_ticks)
. = ..()
var/water_adaptation = HAS_TRAIT(owner, TRAIT_WATER_ADAPTATION)
var/water_hater = HAS_TRAIT(owner, TRAIT_WATER_HATER)
var/stam_recovery = (water_hater && !water_adaptation ? -stamina_heal_per_tick : stamina_heal_per_tick) * seconds_between_ticks
var/recovery = heal_per_tick
if(water_adaptation)
recovery -= 1
stam_recovery *= 1.5
else if(water_hater)
recovery *= 0
recovery *= seconds_between_ticks

var/healed = 0
if(recovery) //very mild healing for those with the water adaptation trait (fish infusion)
healed += owner.adjustOxyLoss(recovery * (water_adaptation ? 1.5 : 1), updating_health = FALSE, required_biotype = MOB_ORGANIC)
healed += owner.adjustFireLoss(recovery, updating_health = FALSE, required_bodytype = BODYTYPE_ORGANIC)
healed += owner.adjustToxLoss(recovery, updating_health = FALSE, required_biotype = MOB_ORGANIC)
healed += owner.adjustBruteLoss(recovery, updating_health = FALSE, required_bodytype = BODYTYPE_ORGANIC)
healed += owner.adjustStaminaLoss(stam_recovery, updating_stamina = FALSE)
if(healed)
owner.updatehealth()

var/is_disgusted = FALSE

if(istype(shower_reagent, /datum/reagent/water))
var/water_adaptation = HAS_TRAIT(owner, TRAIT_WATER_ADAPTATION)
var/water_hater = HAS_TRAIT(owner, TRAIT_WATER_HATER)
var/stam_recovery = (water_hater && !water_adaptation ? -stamina_heal_per_tick : stamina_heal_per_tick) * seconds_between_ticks
var/recovery = heal_per_tick
if(water_adaptation)
recovery -= 1
stam_recovery *= 1.5
else if(water_hater)
recovery *= 0
recovery *= seconds_between_ticks

var/healed = 0
if(recovery) //very mild healing for those with the water adaptation trait (fish infusion)
healed += owner.adjustOxyLoss(recovery * (water_adaptation ? 1.5 : 1), updating_health = FALSE, required_biotype = MOB_ORGANIC)
healed += owner.adjustFireLoss(recovery, updating_health = FALSE, required_bodytype = BODYTYPE_ORGANIC)
healed += owner.adjustToxLoss(recovery, updating_health = FALSE, required_biotype = MOB_ORGANIC)
healed += owner.adjustBruteLoss(recovery, updating_health = FALSE, required_bodytype = BODYTYPE_ORGANIC)
healed += owner.adjustStaminaLoss(stam_recovery, updating_stamina = FALSE)
if(healed)
owner.updatehealth()
else if(istype(shower_reagent, /datum/reagent/blood))
var/enjoy_bloody_showers = HAS_TRAIT(owner, TRAIT_MORBID) || HAS_TRAIT(owner, TRAIT_EVIL) || (owner.mob_biotypes & MOB_UNDEAD)
is_disgusted = !enjoy_bloody_showers
else if(!shower_reagent) // dirty shower
is_disgusted = TRUE

if(is_disgusted)
owner.adjust_disgust(2)

/atom/movable/screen/alert/status_effect/washing_regen
name = "Washing"
Expand All @@ -663,11 +690,31 @@
desc = "Waaater... Fuck this WATER!!"
icon_state = "shower_regen_catgirl"

/atom/movable/screen/alert/status_effect/washing_regen/dislike
name = "Washing"
desc = "This water feels dirty..."
icon_state = "shower_regen_dirty"

/atom/movable/screen/alert/status_effect/washing_regen/bloody_like
name = "Washing"
desc = "Mhhhmmmm... the crimson red drops of life. How delightful."
icon_state = "shower_regen_blood_happy"

/atom/movable/screen/alert/status_effect/washing_regen/bloody_dislike
name = "Washing"
desc = "Is that... blood? What the fuck!"
icon_state = "shower_regen_blood_bad"

/datum/status_effect/washing_regen/hot_spring
alert_type = /atom/movable/screen/alert/status_effect/washing_regen/hotspring
hater_alert = /atom/movable/screen/alert/status_effect/washing_regen/hotspring/hater
stamina_heal_per_tick = -4.5
heal_per_tick = -0.4
shower_reagent = /datum/reagent/water

/datum/status_effect/washing_regen/hot_spring/on_apply()
. = ..()
if(HAS_TRAIT(owner, TRAIT_WATER_HATER) && !HAS_TRAIT(owner, TRAIT_WATER_ADAPTATION))
alert_type = /atom/movable/screen/alert/status_effect/washing_regen/hotspring/hater

/datum/status_effect/washing_regen/hot_spring/tick(seconds_between_ticks)
. = ..()
Expand Down
6 changes: 3 additions & 3 deletions code/game/objects/objs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -218,9 +218,9 @@ GLOBAL_LIST_EMPTY(objects_by_id_tag)
return

SEND_SIGNAL(source, COMSIG_REAGENTS_EXPOSE_OBJ, src, reagents, methods, volume_modifier, show_message)
for(var/reagent in reagents)
var/datum/reagent/R = reagent
. |= R.expose_obj(src, reagents[R])
for(var/datum/reagent/reagent as anything in reagents)
var/reac_volume = reagents[reagent]
. |= reagent.expose_obj(src, reac_volume, methods, show_message)

/// Attempt to freeze this obj if possible. returns TRUE if it succeeded, FALSE otherwise.
/obj/proc/freeze()
Expand Down
33 changes: 26 additions & 7 deletions code/game/objects/structures/shower.dm
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,6 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/shower, (-16))
if(mist && !(actually_on && current_temperature != SHOWER_FREEZING))
qdel(mist)


/obj/machinery/shower/proc/on_entered(datum/source, atom/movable/enterer)
SIGNAL_HANDLER

Expand All @@ -253,17 +252,37 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/shower, (-16))
take_his_status_effect.remove_status_effect(/datum/status_effect/washing_regen)

/obj/machinery/shower/proc/wash_atom(atom/target)
target.wash(CLEAN_RAD | CLEAN_WASH)
var/purity_volume = reagents.total_volume*0.70 // need 70% of total reagents
var/datum/reagent/blood/bloody_shower = reagents.has_reagent(/datum/reagent/blood, amount=purity_volume)
var/datum/reagent/water/clean_shower = reagents.has_reagent(/datum/reagent/water, amount=purity_volume)

// radiation my beloved
var/rad_purity_volume = reagents.total_volume*0.20 // need 20% of total reagents
var/radium_volume = reagents.get_reagent_amount(/datum/reagent/uranium/radium)
var/uranium_volume = reagents.get_reagent_amount(/datum/reagent/uranium)
var/polonium_volume = reagents.get_reagent_amount(/datum/reagent/toxin/polonium) * 3 // highly radioactive
var/total_radiation_volume = (radium_volume + uranium_volume + polonium_volume)
var/radioactive_shower = total_radiation_volume >= rad_purity_volume

// we only care about blood and h20 for mood/status effect
var/datum/reagent/shower_reagent = bloody_shower || clean_shower || null

var/wash_flags = NONE
if(clean_shower)
wash_flags |= CLEAN_WASH
if(!radioactive_shower)
// note it is possible to have a clean_shower that is radioactive (+70% water mixed with +20% radiation)
wash_flags |= CLEAN_RAD
target.wash(wash_flags)

reagents.expose(target, (TOUCH), SHOWER_EXPOSURE_MULTIPLIER * SHOWER_SPRAY_VOLUME / max(reagents.total_volume, SHOWER_SPRAY_VOLUME))
if(!isliving(target))
return
var/mob/living/living_target = target
check_heat(living_target)
living_target.apply_status_effect(/datum/status_effect/washing_regen)
if(!HAS_TRAIT(target, TRAIT_WATER_HATER) || HAS_TRAIT(target, TRAIT_WATER_ADAPTATION))
living_target.add_mood_event("shower", /datum/mood_event/nice_shower)
else
living_target.add_mood_event("shower", /datum/mood_event/shower_hater)

living_target.apply_status_effect(/datum/status_effect/washing_regen, shower_reagent)
living_target.add_mood_event("shower", /datum/mood_event/shower, shower_reagent)

/**
* Toggle whether shower is actually on and outputting water.
Expand Down
6 changes: 3 additions & 3 deletions code/game/turfs/turf.dm
Original file line number Diff line number Diff line change
Expand Up @@ -698,9 +698,9 @@ GLOBAL_LIST_EMPTY(station_turfs)
return

SEND_SIGNAL(source, COMSIG_REAGENTS_EXPOSE_TURF, src, reagents, methods, volume_modifier, show_message)
for(var/reagent in reagents)
var/datum/reagent/R = reagent
. |= R.expose_turf(src, reagents[R])
for(var/datum/reagent/reagent as anything in reagents)
var/reac_volume = reagents[reagent]
. |= reagent.expose_turf(src, reac_volume)

/**
* Called when this turf is being washed. Washing a turf will also wash any mopable floor decals
Expand Down
6 changes: 5 additions & 1 deletion code/modules/atmospherics/machinery/components/tank.dm
Original file line number Diff line number Diff line change
Expand Up @@ -268,10 +268,14 @@

window = image(icon, icon_state = "window-bg", layer = FLOAT_LAYER)

var/static/alpha_filter
if(!alpha_filter) // Gotta do this separate since the icon may not be correct at world init
alpha_filter = filter(type="alpha", icon = icon('icons/obj/pipes_n_cables/stationary_canisters.dmi', "window-bg"))

var/list/new_underlays = list()
for(var/obj/effect/overlay/gas/gas as anything in air_contents.return_visuals(get_turf(src)))
var/image/new_underlay = image(gas.icon, icon_state = gas.icon_state, layer = FLOAT_LAYER)
new_underlay.filters = alpha_mask_filter(icon = icon(icon, icon_state = "window-bg"))
new_underlay.filters = alpha_filter
new_underlays += new_underlay

var/image/foreground = image(icon, icon_state = "window-fg", layer = FLOAT_LAYER)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@

/obj/item/clothing/under/plasmaman/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if (!istype(tool, /obj/item/extinguisher_refill))
return
return ..()

if (extinguishes_left == 5)
to_chat(user, span_notice("The inbuilt extinguisher is full."))
Expand Down
4 changes: 2 additions & 2 deletions code/modules/explorer_drone/loot.dm
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ GLOBAL_LIST_INIT(adventure_loot_generator_index,generate_generator_index())
var/datum/adventure_loot_generator/simple/cash/replacement = new
return replacement.generate()
var/chosen_pack_type = pick(still_locked_packs)
return new /obj/item/trade_chip(null,chosen_pack_type)
return list(new /obj/item/trade_chip(null, chosen_pack_type))

/// Just picks and instatiates the path from the list
/datum/adventure_loot_generator/simple
Expand Down Expand Up @@ -107,7 +107,7 @@ GLOBAL_LIST_INIT(adventure_loot_generator_index,generate_generator_index())
var/chosen_pet_type = pick(possible_pets)
var/mob/living/basic/pet/pet = new chosen_pet_type()
carrier.add_occupant(pet)
return carrier
return list(carrier)

/obj/item/antique
name = "antique"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@
desc = "Twists and corrupts the nearby area as well as dispelling holy auras on floors."
button_icon_state = "defile"
cooldown_time = 15 SECONDS

aoe_radius = 4
unlock_amount = 10
cast_amount = 30
Expand All @@ -169,6 +168,14 @@
if(victim.type == /turf/closed/wall/r_wall && prob(10) && !HAS_TRAIT(victim, TRAIT_RUSTY))
new /obj/effect/temp_visual/revenant(victim)
victim.AddElement(/datum/element/rust)
for(var/obj/machinery/shower/cursed_shower in victim)
new /obj/effect/temp_visual/revenant(victim)
cursed_shower.has_water_reclaimer = FALSE
cursed_shower.reagents.remove_all(1, relative=TRUE)
cursed_shower.reagents.add_reagent(/datum/reagent/blood, initial(cursed_shower.reagent_capacity))
if(prob(50))
cursed_shower.intended_on = TRUE
cursed_shower.update_actually_on(TRUE)
for(var/obj/effect/decal/cleanable/food/salt/salt in victim)
new /obj/effect/temp_visual/revenant(victim)
qdel(salt)
Expand Down
6 changes: 3 additions & 3 deletions code/modules/mob/living/living_defense.dm
Original file line number Diff line number Diff line change
Expand Up @@ -677,9 +677,9 @@

var/touch_protection = (methods & VAPOR) ? getarmor(null, BIO) * 0.01 : 0
SEND_SIGNAL(source, COMSIG_REAGENTS_EXPOSE_MOB, src, reagents, methods, volume_modifier, show_message, touch_protection)
for(var/reagent in reagents)
var/datum/reagent/R = reagent
. |= R.expose_mob(src, methods, reagents[R], show_message, touch_protection)
for(var/datum/reagent/reagent as anything in reagents)
var/reac_volume = reagents[reagent]
. |= reagent.expose_mob(src, methods, reac_volume, show_message, touch_protection)

/// Simplified ricochet angle calculation for mobs (also the base version doesn't work on mobs)
/mob/living/handle_ricochet(obj/projectile/ricocheting_projectile)
Expand Down
4 changes: 2 additions & 2 deletions code/modules/reagents/chemistry/reagents.dm
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,10 @@
exposed_mob.reagents.add_reagent(type, amount, added_purity = purity)

/// Applies this reagent to an [/obj]
/datum/reagent/proc/expose_obj(obj/exposed_obj, reac_volume)
/datum/reagent/proc/expose_obj(obj/exposed_obj, reac_volume, methods=TOUCH, show_message=TRUE)
SHOULD_CALL_PARENT(TRUE)

return SEND_SIGNAL(src, COMSIG_REAGENT_EXPOSE_OBJ, exposed_obj, reac_volume)
return SEND_SIGNAL(src, COMSIG_REAGENT_EXPOSE_OBJ, exposed_obj, reac_volume, methods, show_message)

/// Applies this reagent to a [/turf]
/datum/reagent/proc/expose_turf(turf/exposed_turf, reac_volume)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
if(liver.apply_organ_damage(((max(sqrt(volume) * (boozepwr ** ALCOHOL_EXPONENT) * liver.alcohol_tolerance * heavy_drinker_multiplier * seconds_per_tick, 0))/150)))
return UPDATE_MOB_HEALTH

/datum/reagent/consumable/ethanol/expose_obj(obj/exposed_obj, reac_volume)
/datum/reagent/consumable/ethanol/expose_obj(obj/exposed_obj, reac_volume, methods=TOUCH, show_message=TRUE)
if(istype(exposed_obj, /obj/item/paper))
var/obj/item/paper/paperaffected = exposed_obj
paperaffected.clear_paper()
Expand Down
2 changes: 1 addition & 1 deletion code/modules/reagents/chemistry/reagents/food_reagents.dm
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
var/fry_temperature = 450 //Around ~350 F (117 C) which deep fryers operate around in the real world

/datum/reagent/consumable/nutriment/fat/expose_obj(obj/exposed_obj, reac_volume)
/datum/reagent/consumable/nutriment/fat/expose_obj(obj/exposed_obj, reac_volume, methods=TOUCH, show_message=TRUE)
. = ..()
if(!holder || (holder.chem_temp <= fry_temperature))
return
Expand Down
Loading

0 comments on commit e133800

Please sign in to comment.