Skip to content

Commit

Permalink
[MIRROR] Add new fitness skill and mechanics [MDB IGNORE] (#24448) (#185
Browse files Browse the repository at this point in the history
)

* Add new fitness skill and mechanics

* Modular changes

* No size increase

* Update fitness.dm

---------

Co-authored-by: SkyratBot <[email protected]>
Co-authored-by: Tim <[email protected]>
Co-authored-by: Giz <[email protected]>
  • Loading branch information
4 people authored Oct 20, 2023
1 parent 8e64254 commit a64e90c
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 23 deletions.
22 changes: 22 additions & 0 deletions code/datums/skills/fitness.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/datum/skill/fitness
name = "Fitness"
title = "Fitness"
desc = "Twinkle twinkle little star, hit the gym and lift the bar."
/// The skill value modifier effects the max duration that is possible for /datum/status_effect/exercised
modifiers = list(SKILL_VALUE_MODIFIER = list(2 MINUTES, 3 MINUTES, 4 MINUTES, 5 MINUTES, 6 MINUTES, 7 MINUTES, 10 MINUTES))
// skill_item_path - your mob sprite gets bigger to showoff so we don't get a special item

/* SKYRAT EDIT REMOVAL START - NO SIZE INCREASE
/datum/skill/fitness/level_gained(datum/mind/mind, new_level, old_level, silent)
. = ..()
var/size_boost = (new_level == SKILL_LEVEL_LEGENDARY) ? 0.25 : 0.05
var/gym_size = RESIZE_DEFAULT_SIZE + size_boost
mind.current.update_transform(gym_size)
/datum/skill/fitness/level_lost(datum/mind/mind, new_level, old_level, silent)
. = ..()
var/size_boost = (new_level == SKILL_LEVEL_LEGENDARY) ? 0.25 : 0.05
var/gym_size = RESIZE_DEFAULT_SIZE + size_boost
mind.current.update_transform(RESIZE_DEFAULT_SIZE / gym_size)
SKYRAT EDIT REMOVAL END */
66 changes: 65 additions & 1 deletion code/datums/status_effects/buffs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,73 @@

/datum/status_effect/exercised
id = "Exercised"
duration = 1200
duration = 30 SECONDS
status_type = STATUS_EFFECT_REFRESH // New effects will add to total duration
alert_type = null
processing_speed = STATUS_EFFECT_NORMAL_PROCESS
alert_type = /atom/movable/screen/alert/status_effect/exercised
/// Having any of these reagents in your system extends the duration
var/static/list/supplementary_reagents_bonus = list(
/datum/reagent/consumable/ethanol/protein_blend = 30 SECONDS, // protein shakes are very robust
/datum/reagent/consumable/eggwhite = 20 SECONDS,
/datum/reagent/consumable/eggyolk = 15 SECONDS,
/datum/reagent/consumable/nutriment/protein = 15 SECONDS,
/datum/reagent/consumable/nutriment/vitamin = 10 SECONDS,
/datum/reagent/consumable/rice = 10 SECONDS,
/datum/reagent/consumable/milk = 10 SECONDS,
/datum/reagent/consumable/soymilk = 5 SECONDS, // darn vegans!
/datum/reagent/consumable/nutraslop = 5 SECONDS, // prison food to bulk up with
// time for the bad stuff
/datum/reagent/consumable/sugar = -5 SECONDS,
/datum/reagent/consumable/monkey_energy = -5 SECONDS,
/datum/reagent/consumable/nutriment/fat = -5 SECONDS,
)

/datum/status_effect/exercised/proc/workout_duration(mob/living/new_owner, bonus_time)
if(!bonus_time || !new_owner.mind)
return 0 SECONDS

var/modifier = 1
if(HAS_TRAIT(new_owner, TRAIT_HULK))
modifier += 0.5

if(HAS_TRAIT(new_owner, TRAIT_FAT)) // less xp until you get into shape
modifier -= 0.5

if(new_owner.reagents.has_reagent(/datum/reagent/drug/pumpup)) // steriods? yes please!
modifier += 3

var/food_boost = 0
for(var/datum/reagent/workout_reagent in supplementary_reagents_bonus)
if(new_owner.reagents.has_reagent(workout_reagent))
food_boost += supplementary_reagents_bonus[workout_reagent]

var/skill_level_boost = (new_owner.mind.get_skill_level(/datum/skill/fitness) - 1) * 5 SECONDS
bonus_time = (bonus_time + food_boost + skill_level_boost) * modifier

var/exhaustion_limit = new_owner.mind.get_skill_modifier(/datum/skill/fitness, SKILL_VALUE_MODIFIER) + world.time
if(duration + bonus_time >= exhaustion_limit)
duration = exhaustion_limit
to_chat(new_owner, span_userdanger("Your muscles are exhausted! Might be a good idea to sleep..."))
new_owner.emote("scream")
return // exhaustion_limit

return bonus_time

/datum/status_effect/exercised/tick(seconds_between_ticks)
owner.reagents.metabolize(owner, seconds_between_ticks * SSMOBS_DT, 0) // doubles the metabolization rate

/datum/status_effect/exercised/on_creation(mob/living/new_owner, bonus_time)
duration += workout_duration(new_owner, bonus_time)
return ..()

/datum/status_effect/exercised/refresh(mob/living/new_owner, bonus_time)
duration += workout_duration(new_owner, bonus_time)

/atom/movable/screen/alert/status_effect/exercised
name = "Exercise"
desc = "You feel well exercised! Sleeping will improve your fitness."
icon_state = "exercised"

//Hippocratic Oath: Applied when the Rod of Asclepius is activated.
/datum/status_effect/hippocratic_oath
Expand Down
51 changes: 31 additions & 20 deletions code/datums/status_effects/debuffs/debuffs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#define HEALING_SLEEP_DEFAULT 0.2
/// The sleep healing multipler for organ passive healing (since organs heal slowly)
#define HEALING_SLEEP_ORGAN_MULTIPLIER 5
/// The sleep multipler for fitness xp conversion
#define SLEEP_QUALITY_WORKOUT_MULTIPLER 10

//Largely negative status effects go here, even if they have small benificial effects
//STUN EFFECTS
Expand Down Expand Up @@ -163,51 +165,51 @@
/datum/status_effect/incapacitating/sleeping/tick(seconds_between_ticks)
if(owner.maxHealth)
var/health_ratio = owner.health / owner.maxHealth
var/healing = HEALING_SLEEP_DEFAULT
var/sleep_quality = HEALING_SLEEP_DEFAULT

// having high spirits helps us recover
if(owner.mob_mood)
switch(owner.mob_mood.sanity_level)
if(SANITY_LEVEL_GREAT)
healing = 0.2
sleep_quality = 0.2
if(SANITY_LEVEL_NEUTRAL)
healing = 0.1
sleep_quality = 0.1
if(SANITY_LEVEL_DISTURBED)
healing = 0
sleep_quality = 0
if(SANITY_LEVEL_UNSTABLE)
healing = 0
sleep_quality = 0
if(SANITY_LEVEL_CRAZY)
healing = -0.1
sleep_quality = -0.1
if(SANITY_LEVEL_INSANE)
healing = -0.2
sleep_quality = -0.2

var/turf/rest_turf = get_turf(owner)
var/is_sleeping_in_darkness = rest_turf.get_lumcount() <= LIGHTING_TILE_IS_DARK

// sleeping with a blindfold or in the dark helps us rest
if(owner.is_blind_from(EYES_COVERED) || is_sleeping_in_darkness)
healing += 0.1
sleep_quality += 0.1

// sleeping in silence is always better
if(HAS_TRAIT(src, TRAIT_DEAF))
healing += 0.1
if(HAS_TRAIT(owner, TRAIT_DEAF))
sleep_quality += 0.1

// check for beds
if((locate(/obj/structure/bed) in owner.loc))
healing += 0.2
sleep_quality += 0.2
else if((locate(/obj/structure/table) in owner.loc))
healing += 0.1
sleep_quality += 0.1

// don't forget the bedsheet
if(locate(/obj/item/bedsheet) in owner.loc)
healing += 0.1
sleep_quality += 0.1

// you forgot the pillow
if(locate(/obj/item/pillow) in owner.loc)
healing += 0.1
sleep_quality += 0.1

var/need_mob_update = FALSE
if(healing > 0)
if(sleep_quality > 0)
if(iscarbon(owner))
var/mob/living/carbon/carbon_owner = owner
for(var/obj/item/organ/target_organ as anything in carbon_owner.organs)
Expand All @@ -216,14 +218,22 @@
continue

// organ regeneration is very low so we crank up the healing rate to give a good bonus
var/healing_bonus = target_organ.healing_factor * healing * HEALING_SLEEP_ORGAN_MULTIPLIER
var/healing_bonus = target_organ.healing_factor * sleep_quality * HEALING_SLEEP_ORGAN_MULTIPLIER
target_organ.apply_organ_damage(-healing_bonus * target_organ.maxHealth)

var/datum/status_effect/exercised/exercised = carbon_owner.has_status_effect(/datum/status_effect/exercised)
if(exercised && carbon_owner.mind)
// the better you sleep, the more xp you gain
carbon_owner.mind.adjust_experience(/datum/skill/fitness, seconds_between_ticks * sleep_quality * SLEEP_QUALITY_WORKOUT_MULTIPLER)
carbon_owner.adjust_timed_status_effect(-1 * seconds_between_ticks * sleep_quality * SLEEP_QUALITY_WORKOUT_MULTIPLER, /datum/status_effect/exercised)
if(prob(2))
to_chat(carbon_owner, span_notice("You feel your fitness improving!"))

if(health_ratio > 0.8) // only heals minor physical damage
need_mob_update += owner.adjustBruteLoss(-0.4 * healing * seconds_between_ticks, updating_health = FALSE, required_bodytype = BODYTYPE_ORGANIC)
need_mob_update += owner.adjustFireLoss(-0.4 * healing * seconds_between_ticks, updating_health = FALSE, required_bodytype = BODYTYPE_ORGANIC)
need_mob_update += owner.adjustToxLoss(-0.2 * healing * seconds_between_ticks, updating_health = FALSE, forced = TRUE, required_biotype = MOB_ORGANIC)
need_mob_update += owner.adjustStaminaLoss(min(-0.4 * healing * seconds_between_ticks, -0.4 * HEALING_SLEEP_DEFAULT * seconds_between_ticks), updating_stamina = FALSE)
need_mob_update += owner.adjustBruteLoss(-0.4 * sleep_quality * seconds_between_ticks, updating_health = FALSE, required_bodytype = BODYTYPE_ORGANIC)
need_mob_update += owner.adjustFireLoss(-0.4 * sleep_quality * seconds_between_ticks, updating_health = FALSE, required_bodytype = BODYTYPE_ORGANIC)
need_mob_update += owner.adjustToxLoss(-0.2 * sleep_quality * seconds_between_ticks, updating_health = FALSE, forced = TRUE, required_biotype = MOB_ORGANIC)
need_mob_update += owner.adjustStaminaLoss(min(-0.4 * sleep_quality * seconds_between_ticks, -0.4 * HEALING_SLEEP_DEFAULT * seconds_between_ticks), updating_stamina = FALSE)
if(need_mob_update)
owner.updatehealth()
// Drunkenness gets reduced by 0.3% per tick (6% per 2 seconds)
Expand Down Expand Up @@ -1034,3 +1044,4 @@

#undef HEALING_SLEEP_DEFAULT
#undef HEALING_SLEEP_ORGAN_MULTIPLIER
#undef SLEEP_QUALITY_WORKOUT_MULTIPLER
10 changes: 10 additions & 0 deletions code/game/objects/structures/gym/punching_bag.dm
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,17 @@
return
flick("[icon_state]-punch", src)
playsound(loc, pick(hit_sounds), 25, TRUE, -1)

var/stamina_exhaustion = 3
if(ishuman(user))
var/mob/living/carbon/human/boxer = user
var/obj/item/clothing/gloves/boxing/boxing_gloves = boxer.get_item_by_slot(ITEM_SLOT_GLOVES)
if(istype(boxing_gloves))
stamina_exhaustion = 2

user.adjustStaminaLoss(stamina_exhaustion)
user.add_mood_event("exercise", /datum/mood_event/exercise)
user.mind?.adjust_experience(/datum/skill/fitness, 0.1)
user.apply_status_effect(/datum/status_effect/exercised)

/obj/structure/punching_bag/wrench_act_secondary(mob/living/user, obj/item/tool)
Expand Down
32 changes: 30 additions & 2 deletions code/game/objects/structures/gym/weight_machine.dm
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#define WORKOUT_XP 5
#define EXERCISE_STATUS_DURATION 20 SECONDS

/obj/structure/weightmachine
name = "chest press machine"
desc = "Just looking at this thing makes you feel tired."
Expand Down Expand Up @@ -90,16 +93,35 @@
return TRUE

/obj/structure/weightmachine/proc/perform_workout(mob/living/user)
if(user.nutrition <= NUTRITION_LEVEL_STARVING)
user.balloon_alert(user, "too hungry to workout!")
return

user.balloon_alert_to_viewers("[pick(more_weight)]")
START_PROCESSING(SSobj, src)

if(do_after(user, 8 SECONDS, src) && user.has_gravity())
user.Stun(2 SECONDS)
// with enough dedication, even clowns can overcome their handicaps
var/clumsy_chance = 30 - (user.mind.get_skill_level(/datum/skill/fitness) * 5)
if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(clumsy_chance))
playsound(src, 'sound/effects/bang.ogg', 50, TRUE)
to_chat(user, span_warning("Your hand slips, causing the [name] to smash you!"))
user.take_bodypart_damage(rand(2, 5))
end_workout()
return

if(issilicon(user))
user.balloon_alert(user, pick(finished_silicon_message))
else
user.balloon_alert(user, pick(finished_message))

user.adjust_nutrition(-3) // feel the burn
user.add_mood_event("exercise", /datum/mood_event/exercise)
user.apply_status_effect(/datum/status_effect/exercised)

// remember the real xp gain is from sleeping after working out
user.mind.adjust_experience(/datum/skill/fitness, WORKOUT_XP)
user.apply_status_effect(/datum/status_effect/exercised, EXERCISE_STATUS_DURATION)

end_workout()

/obj/structure/weightmachine/proc/end_workout()
Expand All @@ -119,6 +141,10 @@
animate(user, pixel_y = pixel_shift_y, time = 4)
playsound(user, 'sound/machines/creak.ogg', 60, TRUE)
animate(pixel_y = user.base_pixel_y, time = 4)

var/stamina_exhaustion = 5 - (user.mind.get_skill_level(/datum/skill/fitness) * 0.5)
user.adjustStaminaLoss(stamina_exhaustion * seconds_per_tick)

return TRUE

/**
Expand All @@ -131,3 +157,5 @@

pixel_shift_y = 5

#undef WORKOUT_XP
#undef EXERCISE_STATUS_DURATION
Binary file modified icons/hud/screen_alert.dmi
Binary file not shown.
1 change: 1 addition & 0 deletions tgstation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -1756,6 +1756,7 @@
#include "code\datums\skills\_skill.dm"
#include "code\datums\skills\cleaning.dm"
#include "code\datums\skills\fishing.dm"
#include "code\datums\skills\fitness.dm"
#include "code\datums\skills\gaming.dm"
#include "code\datums\skills\mining.dm"
#include "code\datums\station_traits\_station_trait.dm"
Expand Down

0 comments on commit a64e90c

Please sign in to comment.