From dcebdfba1df879ffc1179c31a573077dc4fe2e72 Mon Sep 17 00:00:00 2001 From: MrMelbert Date: Wed, 15 Jan 2025 16:59:01 -0600 Subject: [PATCH 01/22] Skill rework/refactor, readds surgical skill, adds electrical skill --- code/controllers/subsystem/skills.dm | 10 +- code/datums/mind/skills.dm | 33 ++++--- code/datums/skills/_skill.dm | 99 ++++++++++++------- code/datums/skills/cleaning.dm | 17 +++- code/datums/skills/electrics.dm | 27 +++++ code/datums/skills/fishing.dm | 18 +++- code/datums/skills/fitness.dm | 26 ++++- code/datums/skills/gaming.dm | 33 +++++-- code/datums/skills/mining.dm | 26 ++++- code/datums/skills/surgery.dm | 31 ++++++ code/datums/wires/airalarm.dm | 2 +- code/datums/wires/airlock.dm | 15 ++- code/datums/wires/apc.dm | 4 +- code/datums/wires/autolathe.dm | 2 +- code/datums/wires/mecha.dm | 2 +- code/datums/wires/mod.dm | 2 +- code/datums/wires/robot.dm | 2 +- code/datums/wires/roulette.dm | 16 +-- code/datums/wires/suit_storage_unit.dm | 6 +- code/datums/wires/vending.dm | 5 +- code/game/objects/items.dm | 15 +-- code/modules/admin/skill_panel.dm | 2 +- code/modules/bitrunning/job.dm | 4 + code/modules/jobs/job_types/_job.dm | 6 ++ .../jobs/job_types/atmospheric_technician.dm | 4 + .../jobs/job_types/cargo_technician.dm | 3 + code/modules/jobs/job_types/chemist.dm | 3 + code/modules/jobs/job_types/chief_engineer.dm | 3 + .../jobs/job_types/chief_medical_officer.dm | 3 + code/modules/jobs/job_types/coroner.dm | 4 + code/modules/jobs/job_types/janitor.dm | 4 + code/modules/jobs/job_types/medical_doctor.dm | 3 + code/modules/jobs/job_types/paramedic.dm | 3 + .../jobs/job_types/research_director.dm | 4 + code/modules/jobs/job_types/roboticist.dm | 4 + code/modules/jobs/job_types/scientist.dm | 3 + code/modules/jobs/job_types/shaft_miner.dm | 3 + .../jobs/job_types/station_engineer.dm | 3 + code/modules/jobs/job_types/virologist.dm | 3 + .../file_system/programs/skill_tracker.dm | 7 +- code/modules/power/cable.dm | 6 +- code/modules/surgery/autopsy.dm | 23 +++-- code/modules/surgery/surgery_step.dm | 6 +- maplestation.dme | 2 + ...sSkillTracker.jsx => NtosSkillTracker.tsx} | 45 ++++++++- 45 files changed, 414 insertions(+), 128 deletions(-) create mode 100644 code/datums/skills/electrics.dm create mode 100644 code/datums/skills/surgery.dm rename tgui/packages/tgui/interfaces/{NtosSkillTracker.jsx => NtosSkillTracker.tsx} (73%) diff --git a/code/controllers/subsystem/skills.dm b/code/controllers/subsystem/skills.dm index fdf868cf1f7e..a14890e890cb 100644 --- a/code/controllers/subsystem/skills.dm +++ b/code/controllers/subsystem/skills.dm @@ -9,7 +9,15 @@ SUBSYSTEM_DEF(skills) ///Dictionary of skill.type || skill ref var/list/all_skills = list() ///List of level names with index corresponding to skill level - var/list/level_names = list("None", "Novice", "Apprentice", "Journeyman", "Expert", "Master", "Legendary") //List of skill level names. Note that indexes can be accessed like so: level_names[SKILL_LEVEL_NOVICE] + var/list/level_names = list( + SKILL_LEVEL_NONE = "None", + SKILL_LEVEL_NOVICE = "Novice", + SKILL_LEVEL_APPRENTICE = "Apprentice", + SKILL_LEVEL_JOURNEYMAN = "Journeyman", + SKILL_LEVEL_EXPERT = "Expert", + SKILL_LEVEL_MASTER = "Master", + SKILL_LEVEL_LEGENDARY = "Legendary", + ) /datum/controller/subsystem/skills/Initialize() InitializeSkills() diff --git a/code/datums/mind/skills.dm b/code/datums/mind/skills.dm index 474291d5ae0d..07086d77bcb5 100644 --- a/code/datums/mind/skills.dm +++ b/code/datums/mind/skills.dm @@ -1,6 +1,6 @@ /datum/mind/proc/init_known_skills() for (var/type in GLOB.skill_types) - known_skills[type] = list(SKILL_LEVEL_NONE, 0) + known_skills[type] = list(SKILL_LVL = SKILL_LEVEL_NONE, SKILL_EXP = 0) ///Return the amount of EXP needed to go to the next level. Returns 0 if max level /datum/mind/proc/exp_needed_to_level_up(skill) @@ -9,10 +9,18 @@ return 0 return SKILL_EXP_LIST[lvl+1] - known_skills[skill][SKILL_EXP] -///Adjust experience of a specific skill -/datum/mind/proc/adjust_experience(skill, amt, silent = FALSE, force_old_level = 0) +/// +/** + * Adjust experience of a specific skill + * + * * skill: The skill to adjust, typepath + * * amt: The amount to adjust the skill by + * * silent: If TRUE, don't send messages to the player + * * force_old_level: If set to any skill level, we will act as if the skill was at that level before the adjustment, rather than their current level + */ +/datum/mind/proc/adjust_experience(skill, amt, silent = FALSE, force_old_level) var/datum/skill/S = GetSkillRef(skill) - var/old_level = force_old_level ? force_old_level : known_skills[skill][SKILL_LVL] //Get current level of the S skill + var/old_level = force_old_level || known_skills[skill][SKILL_LVL] //Get current level of the S skill experience_multiplier = initial(experience_multiplier) for(var/key in experience_multiplier_reasons) experience_multiplier += experience_multiplier_reasons[key] @@ -58,21 +66,20 @@ /datum/mind/proc/get_skill_exp(skill) return known_skills[skill][SKILL_EXP] +/// Gets the what name the player's current level of the skill corresponds to /datum/mind/proc/get_skill_level_name(skill) - var/level = get_skill_level(skill) - return SSskills.level_names[level] + return SSskills.level_names[get_skill_level(skill)] /datum/mind/proc/print_levels(user) var/list/shown_skills = list() - for(var/i in known_skills) - if(known_skills[i][SKILL_LVL] > SKILL_LEVEL_NONE) //Do we actually have a level in this? - shown_skills += i + for(var/datum/skill/known_skill as anything in known_skills) + if(initial(known_skill.innate_skill) || known_skills[known_skill][SKILL_LVL] > SKILL_LEVEL_NONE) //Do we actually have a level in this? + shown_skills += known_skill if(!length(shown_skills)) to_chat(user, span_notice("You don't seem to have any particularly outstanding skills.")) return - var/msg = "[span_info("Your skills")]\n" - for(var/i in shown_skills) - var/datum/skill/the_skill = i - msg += "[initial(the_skill.name)] - [get_skill_level_name(the_skill)]\n" + var/msg = "[span_info("Your skills:")]
" + for(var/datum/skill/shown_skill as anything in shown_skills) + msg += "• [initial(shown_skill.name)] - [get_skill_level_name(shown_skill)]
" msg += "
" to_chat(user, examine_block(msg)) diff --git a/code/datums/skills/_skill.dm b/code/datums/skills/_skill.dm index b8438c67927c..61ed162ebcf0 100644 --- a/code/datums/skills/_skill.dm +++ b/code/datums/skills/_skill.dm @@ -1,41 +1,64 @@ GLOBAL_LIST_INIT(skill_types, subtypesof(/datum/skill)) /datum/skill - var/name = "Skilling" - var/title = "Skiller" - var/desc = "the art of doing things" - ///Dictionary of modifier type - list of modifiers (indexed by level). 7 entries in each list for all 7 skill levels. - var/modifiers = list(SKILL_SPEED_MODIFIER = list(1, 1, 1, 1, 1, 1, 1)) //Dictionary of modifier type - list of modifiers (indexed by level). 7 entries in each list for all 7 skill levels. - ///List Path pointing to the skill item reward that will appear when a user finishes leveling up a skill + /// String, required, the name of the skill + var/name + /// String, required, the title of the skill, e.g. "Surgeon" or "Miner" + var/title + /// String, required, Some flavor blurb relating to the skill + var/blurb + /// String, optional, how a user can be expected to earn this skill + var/earned_by + /// String, optional, what this skill generally does to improve the user's abilities + var/grants_you + /// String, optional, what this skill does to improve the user's abilities at higher levels + var/higher_levels_grant_you + /// Dictionary of modifier type - list of modifiers (indexed by level). + var/list/modifiers = list( + SKILL_SPEED_MODIFIER = list( + SKILL_LEVEL_NONE = 1, + SKILL_LEVEL_NOVICE = 1, + SKILL_LEVEL_APPRENTICE = 1, + SKILL_LEVEL_JOURNEYMAN = 1, + SKILL_LEVEL_EXPERT = 1, + SKILL_LEVEL_MASTER = 1, + SKILL_LEVEL_LEGENDARY = 1, + ), + ) + /// If TRUE, this skill is considered to be core or innate + /// This means the skill will always be visible to the user, even if at level 0 + var/innate_skill = FALSE + /// Typepath of skill item reward that will appear when a user finishes leveling up a skill var/skill_item_path - ///List associating different messages that appear on level up with different levels - var/list/levelUpMessages = list() - ///List associating different messages that appear on level up with different levels - var/list/levelDownMessages = list() + /// List associating different messages that appear on level up with different levels + var/list/level_up_messages + /// List associating different messages that appear on level up with different levels + var/list/level_down_messages +/// Getter for some modifier at a certain level /datum/skill/proc/get_skill_modifier(modifier, level) return modifiers[modifier][level] //Levels range from 1 (None) to 7 (Legendary) -/** - * new: sets up some lists. - * - *Can't happen in the datum's definition because these lists are not constant expressions - */ + /datum/skill/New() . = ..() - levelUpMessages = list(span_nicegreen("What the hell is [name]? Tell an admin if you see this message."), //This first index shouldn't ever really be used - span_nicegreen("I'm starting to figure out what [name] really is!"), - span_nicegreen("I'm getting a little better at [name]!"), - span_nicegreen("I'm getting much better at [name]!"), - span_nicegreen("I feel like I've become quite proficient at [name]!"), - span_nicegreen("After lots of practice, I've begun to truly understand the intricacies and surprising depth behind [name]. I now consider myself a master [title]."), - span_nicegreen("Through incredible determination and effort, I've reached the peak of my [name] abiltities. I'm finally able to consider myself a legendary [title]!") ) - levelDownMessages = list(span_nicegreen("I have somehow completely lost all understanding of [name]. Please tell an admin if you see this."), - span_nicegreen("I'm starting to forget what [name] really even is. I need more practice..."), - span_nicegreen("I'm getting a little worse at [name]. I'll need to keep practicing to get better at it..."), - span_nicegreen("I'm getting a little worse at [name]..."), - span_nicegreen("I'm losing my [name] expertise ...."), - span_nicegreen("I feel like I'm losing my mastery of [name]."), - span_nicegreen("I feel as though my legendary [name] skills have deteriorated. I'll need more intense training to recover my lost skills.") ) + level_up_messages = list( + SKILL_LEVEL_NONE = "", // Everyone starts at NONE, you can't go up to it + SKILL_LEVEL_NOVICE = span_nicegreen("I'm starting to figure out what [name] really is!"), + SKILL_LEVEL_APPRENTICE = span_nicegreen("I'm getting a little better at [name]!"), + SKILL_LEVEL_JOURNEYMAN = span_nicegreen("I'm getting much better at [name]!"), + SKILL_LEVEL_EXPERT = span_nicegreen("I feel like I've become quite proficient at [name]!"), + SKILL_LEVEL_MASTER = span_nicegreen("After lots of practice, I've begun to truly understand the intricacies and surprising depth behind [name]. I now consider myself a master [title]."), + SKILL_LEVEL_LEGENDARY = span_nicegreen("Through incredible determination and effort, I've reached the peak of my [name] abiltities. I'm finally able to consider myself a legendary [title]!"), + ) + level_down_messages = list( + SKILL_LEVEL_NONE = span_nicegreen("I have somehow completely lost all understanding of [name]."), + SKILL_LEVEL_NOVICE = span_nicegreen("I'm starting to forget what [name] really even is. I need more practice..."), + SKILL_LEVEL_APPRENTICE = span_nicegreen("I'm getting a little worse at [name]. I'll need to keep practicing to get better at it..."), + SKILL_LEVEL_JOURNEYMAN = span_nicegreen("I'm getting a little worse at [name]..."), + SKILL_LEVEL_EXPERT = span_nicegreen("I'm losing my [name] expertise ...."), + SKILL_LEVEL_MASTER = span_nicegreen("I feel like I'm losing my mastery of [name]."), + SKILL_LEVEL_LEGENDARY = span_nicegreen("I feel as though my legendary [name] skills have deteriorated. I'll need more intense training to recover my lost skills."), + ) /** * level_gained: Gives skill levelup messages to the user @@ -48,16 +71,18 @@ GLOBAL_LIST_INIT(skill_types, subtypesof(/datum/skill)) * * silent - Silences the announcement if TRUE */ /datum/skill/proc/level_gained(datum/mind/mind, new_level, old_level, silent) - if(silent) + if(new_level == SKILL_LEVEL_NONE) + CRASH("Someone tried to level up to NONE skill level, wtf") + if(silent || new_level == old_level) return - to_chat(mind.current, levelUpMessages[new_level]) //new_level will be a value from 1 to 6, so we get appropriate message from the 6-element levelUpMessages list + to_chat(mind.current, level_up_messages[new_level]) //new_level will be a value from 1 to 6, so we get appropriate message from the 6-element level_up_messages list /** * level_lost: See level_gained, same idea but fires on skill level-down */ /datum/skill/proc/level_lost(datum/mind/mind, new_level, old_level, silent) - if(silent) + if(silent || new_level == old_level) return - to_chat(mind.current, levelDownMessages[old_level]) //old_level will be a value from 1 to 6, so we get appropriate message from the 6-element levelUpMessages list + to_chat(mind.current, level_down_messages[old_level]) //old_level will be a value from 1 to 6, so we get appropriate message from the 6-element level_up_messages list /** * try_skill_reward: Checks to see if a user is eligable for a tangible reward for reaching a certain skill level @@ -71,9 +96,8 @@ GLOBAL_LIST_INIT(skill_types, subtypesof(/datum/skill)) if (new_level != SKILL_LEVEL_LEGENDARY) return if (!ispath(skill_item_path)) - to_chat(mind.current, span_nicegreen("My legendary [name] skill is quite impressive, though it seems the Professional [title] Association doesn't have any status symbols to commemorate my abilities with. I should let Centcom know of this travesty, maybe they can do something about it.")) return - if (LAZYFIND(mind.skills_rewarded, src.type)) + if (LAZYFIND(mind.skills_rewarded, type)) to_chat(mind.current, span_nicegreen("It seems the Professional [title] Association won't send me another status symbol.")) return podspawn(list( @@ -82,5 +106,6 @@ GLOBAL_LIST_INIT(skill_types, subtypesof(/datum/skill)) "spawn" = skill_item_path, "delays" = list(POD_TRANSIT = 150, POD_FALLING = 4, POD_OPENING = 30, POD_LEAVING = 30) )) - to_chat(mind.current, span_nicegreen("My legendary skill has attracted the attention of the Professional [title] Association. It seems they are sending me a status symbol to commemorate my abilities.")) - LAZYADD(mind.skills_rewarded, src.type) + to_chat(mind.current, span_nicegreen("My legendary skill has attracted the attention of the Professional [title] Association. \ + It seems they are sending me a status symbol to commemorate my abilities.")) + LAZYADD(mind.skills_rewarded, type) diff --git a/code/datums/skills/cleaning.dm b/code/datums/skills/cleaning.dm index b3ccad7eb4cb..9a6d7d749704 100644 --- a/code/datums/skills/cleaning.dm +++ b/code/datums/skills/cleaning.dm @@ -1,6 +1,19 @@ /datum/skill/cleaning name = "Cleaning" title = "Cleaner" - desc = "It’s not who I am underneath, but what I mop up that defines me." - modifiers = list(SKILL_SPEED_MODIFIER = list(1, 0.9, 0.8, 0.7, 0.6, 0.5, 0.36)) //speed also touches probability in using up a soap's charge + blurb = "It's not who I am underneath, but what I mop up that defines me." + earned_by = "cleaning grime and blood" + grants_you = "an improved proficiency with cleaning tools" + modifiers = list( + // speed also touches probability in using up a soap's charge + SKILL_SPEED_MODIFIER = list( + SKILL_LEVEL_NONE = 1.1, + SKILL_LEVEL_NOVICE = 1, + SKILL_LEVEL_APPRENTICE = 0.9, + SKILL_LEVEL_JOURNEYMAN = 0.8, + SKILL_LEVEL_EXPERT = 0.7, + SKILL_LEVEL_MASTER = 0.6, + SKILL_LEVEL_LEGENDARY = 0.5, + ), + ) skill_item_path = /obj/item/clothing/neck/cloak/skill_reward/cleaning diff --git a/code/datums/skills/electrics.dm b/code/datums/skills/electrics.dm new file mode 100644 index 000000000000..af1dc3ac139a --- /dev/null +++ b/code/datums/skills/electrics.dm @@ -0,0 +1,27 @@ +/datum/skill/electronics + name = "Electronics" + title = "Electrical Engineer" + blurb = "Hack the planet! Or, y'know, do your job." + grants_you = "reduced chance of being shocked when hacking or messing with cables" + higher_levels_grant_you = "innate knowledge of airlock and APC wiring" + modifiers = list( + SKILL_PROBS_MODIFIER = list( + SKILL_LEVEL_NONE = 0, + SKILL_LEVEL_NOVICE = 0, + SKILL_LEVEL_APPRENTICE = 10, + SKILL_LEVEL_JOURNEYMAN = 20, + SKILL_LEVEL_EXPERT = 30, + SKILL_LEVEL_MASTER = 40, + SKILL_LEVEL_LEGENDARY = 50, + ), + ) + +/datum/skill/electronics/level_gained(datum/mind/mind, new_level, old_level, silent) + . = ..() + if(new_level >= SKILL_LEVEL_MASTER) + ADD_TRAIT(mind, TRAIT_KNOW_ENGI_WIRES, type) + +/datum/skill/electronics/level_lost(datum/mind/mind, new_level, old_level, silent) + . = ..() + if(old_level >= SKILL_LEVEL_MASTER) + REMOVE_TRAIT(mind, TRAIT_KNOW_ENGI_WIRES, type) diff --git a/code/datums/skills/fishing.dm b/code/datums/skills/fishing.dm index ddf90e1a0a3a..f83064c71aa6 100644 --- a/code/datums/skills/fishing.dm +++ b/code/datums/skills/fishing.dm @@ -5,13 +5,25 @@ /datum/skill/fishing name = "Fishing" title = "Fisher" - desc = "How empty and alone you are on this barren Earth." - modifiers = list(SKILL_VALUE_MODIFIER = list(1, 1, 0, -1, -2, -4, -6)) + blurb = "How empty and alone you are on this barren Earth." + earned_by = "attempting a fishing challenge" + grants_you = "reduced difficulty in fishing challenges" + modifiers = list( + SKILL_VALUE_MODIFIER = list( + SKILL_LEVEL_NONE = 1, + SKILL_LEVEL_NOVICE = 1, + SKILL_LEVEL_APPRENTICE = 0, + SKILL_LEVEL_JOURNEYMAN = -1, + SKILL_LEVEL_EXPERT = -2, + SKILL_LEVEL_MASTER = -4, + SKILL_LEVEL_LEGENDARY = -6, + ), + ) skill_item_path = /obj/item/clothing/head/soft/fishing_hat /datum/skill/fishing/New() . = ..() - levelUpMessages[SKILL_LEVEL_MASTER] = span_nicegreen("After lots of practice, I've begun to truly understand the surprising depth behind [name]. As a master [title], I can take an easier guess of what I'm trying to catch now.") + level_up_messages[SKILL_LEVEL_MASTER] = span_nicegreen("After lots of practice, I've begun to truly understand the surprising depth behind [name]. As a master [title], I can take an easier guess of what I'm trying to catch now.") /datum/skill/fishing/level_gained(datum/mind/mind, new_level, old_level, silent) . = ..() diff --git a/code/datums/skills/fitness.dm b/code/datums/skills/fitness.dm index 64df8faa8d66..77b404a5c6f3 100644 --- a/code/datums/skills/fitness.dm +++ b/code/datums/skills/fitness.dm @@ -1,6 +1,24 @@ /datum/skill/fitness - name = "Fitness" + name = "Athletics" 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(1 MINUTES, 1.5 MINUTES, 2 MINUTES, 2.5 MINUTES, 3 MINUTES, 3.5 MINUTES, 5 MINUTES)) + blurb = "Twinkle twinkle little star, hit the gym and lift the bar." + earned_by = "exercising on the machines in the station's recreation area" + grants_you = "greater ease of grabbing, grappling, and carrying others" + higher_levels_grant_you = "the ability to exercise for longer periods of time" + // The skill value modifier effects the max duration that is possible for /datum/status_effect/exercised + modifiers = list( + SKILL_VALUE_MODIFIER = list( + SKILL_LEVEL_NONE = 1 MINUTES, + SKILL_LEVEL_NOVICE = 1.5 MINUTES, + SKILL_LEVEL_APPRENTICE = 2 MINUTES, + SKILL_LEVEL_JOURNEYMAN = 2.5 MINUTES, + SKILL_LEVEL_EXPERT = 3 MINUTES, + SKILL_LEVEL_MASTER = 3.5 MINUTES, + SKILL_LEVEL_LEGENDARY = 5 MINUTES, + ), + ) + +/datum/skill/fitness/New() + . = ..() + level_up_messages[SKILL_LEVEL_MASTER] = span_nicegreen("After lots of exercise, I've begun to truly understand the surprising depth behind [name].") + level_up_messages[SKILL_LEVEL_LEGENDARY] = span_nicegreen("Through incredible determination and effort, I've reached the peak of my Athletic abilities.") diff --git a/code/datums/skills/gaming.dm b/code/datums/skills/gaming.dm index 75d90f3d8c0d..34111cfc5c00 100644 --- a/code/datums/skills/gaming.dm +++ b/code/datums/skills/gaming.dm @@ -1,13 +1,34 @@ /datum/skill/gaming name = "Gaming" title = "Gamer" - desc = "My proficiency as a gamer. This helps me beat bosses with ease, powergame in Orion Trail, and makes me wanna slam some gamer fuel." - modifiers = list(SKILL_PROBS_MODIFIER = list(0, 5, 10, 15, 15, 20, 25), - SKILL_RANDS_MODIFIER = list(0, 1, 2, 3, 4, 5, 7)) + blurb = "I'm a gamer, I have lots of lives." + earned_by = "winning arcade games (earning achievements also helps)" + grants_you = "greater skill in arcade games" + higher_levels_grant_you = "a taste for gamer fuel" + modifiers = list( + SKILL_PROBS_MODIFIER = list( + SKILL_LEVEL_NONE = 0, + SKILL_LEVEL_NOVICE = 5, + SKILL_LEVEL_APPRENTICE = 10, + SKILL_LEVEL_JOURNEYMAN = 15, + SKILL_LEVEL_EXPERT = 15, + SKILL_LEVEL_MASTER = 20, + SKILL_LEVEL_LEGENDARY = 25, + ), + SKILL_RANDS_MODIFIER = list( + SKILL_LEVEL_NONE = 0, + SKILL_LEVEL_NOVICE = 1, + SKILL_LEVEL_APPRENTICE = 2, + SKILL_LEVEL_JOURNEYMAN = 3, + SKILL_LEVEL_EXPERT = 4, + SKILL_LEVEL_MASTER = 5, + SKILL_LEVEL_LEGENDARY = 7, + ), + ) skill_item_path = /obj/item/clothing/neck/cloak/skill_reward/gaming /datum/skill/gaming/New() . = ..() - levelUpMessages[1] = span_nicegreen("I'm starting to get a hang of the controls of these games...") - levelUpMessages[4] = span_nicegreen("I'm starting to pick up the meta of these arcade games. If I were to minmax the optimal strat and accentuate my playstyle around well-refined tech...") - levelUpMessages[6] = span_nicegreen("Through incredible determination and effort, I've reached the peak of my [name] abilities. I wonder how I can become any more powerful... Maybe gamer fuel would actually help me play better..?") + level_up_messages[SKILL_LEVEL_NOVICE] = span_nicegreen("I'm starting to get a hang of the controls of these games...") + level_up_messages[SKILL_LEVEL_JOURNEYMAN] = span_nicegreen("I'm starting to pick up the meta of these arcade games. If I were to minmax the optimal strat and accentuate my playstyle around well-refined tech...") + level_up_messages[SKILL_LEVEL_MASTER] = span_nicegreen("Through incredible determination and effort, I've reached the peak of my [name] abilities. I wonder how I can become any more powerful... Maybe gamer fuel would actually help me play better..?") diff --git a/code/datums/skills/mining.dm b/code/datums/skills/mining.dm index db79c2801a4c..d2212ce9babe 100644 --- a/code/datums/skills/mining.dm +++ b/code/datums/skills/mining.dm @@ -1,6 +1,28 @@ /datum/skill/mining name = "Mining" title = "Miner" - desc = "A dwarf's biggest skill, after drinking." - modifiers = list(SKILL_SPEED_MODIFIER = list(1, 0.95, 0.9, 0.85, 0.75, 0.6, 0.5),SKILL_PROBS_MODIFIER=list(10, 15, 20, 25, 30, 35, 40)) + blurb = "A dwarf's biggest skill, after drinking." + earned_by = "mining rare minerals" + grants_you = "an improved proficiency with mining tools" + higher_levels_grant_you = "the ability to see the contents of nearby rocks when mining" + modifiers = list( + SKILL_SPEED_MODIFIER = list( + SKILL_LEVEL_NONE = 1.1, + SKILL_LEVEL_NOVICE = 1, + SKILL_LEVEL_APPRENTICE = 0.9, + SKILL_LEVEL_JOURNEYMAN = 0.85, + SKILL_LEVEL_EXPERT = 0.75, + SKILL_LEVEL_MASTER = 0.6, + SKILL_LEVEL_LEGENDARY = 0.5, + ), + SKILL_PROBS_MODIFIER = list( + SKILL_LEVEL_NONE = 0, + SKILL_LEVEL_NOVICE = 0, + SKILL_LEVEL_APPRENTICE = 0, + SKILL_LEVEL_JOURNEYMAN = 20, + SKILL_LEVEL_EXPERT = 30, + SKILL_LEVEL_MASTER = 40, + SKILL_LEVEL_LEGENDARY = 50, + ), + ) skill_item_path = /obj/item/clothing/neck/cloak/skill_reward/mining diff --git a/code/datums/skills/surgery.dm b/code/datums/skills/surgery.dm new file mode 100644 index 000000000000..0728bfe97a7a --- /dev/null +++ b/code/datums/skills/surgery.dm @@ -0,0 +1,31 @@ +/datum/skill/surgery + name = "Surgery" + title = "Surgeon" + blurb = "Your capability to split someone's brain in two with a pen." + earned_by = "completing surgeries on members of the crew, or autopsies on any cadavers" + grants_you = "an improved proficiency with surgical tools" + higher_levels_grant_you = "the ability to perform more complex surgeries with worse (or improvised) tools" + modifiers = list( + // modifier to surgery speed + SKILL_SPEED_MODIFIER = list( + SKILL_LEVEL_NONE = 1.1, + SKILL_LEVEL_NOVICE = 1.1, + SKILL_LEVEL_APPRENTICE = 1, + SKILL_LEVEL_JOURNEYMAN = 0.9, + SKILL_LEVEL_EXPERT = 0.9, + SKILL_LEVEL_MASTER = 0.8, + SKILL_LEVEL_LEGENDARY = 0.75, + ), + // flat modifier on tool effectiveness used in surgery + // note that this also affects surgery speed (so +10 roughly corresponds to a 0.9x speed modifier), + // but only surgeries that use items (which in practice, only excludes surgeries like "stomach pump") + SKILL_VALUE_MODIFIER = list( + SKILL_LEVEL_NONE = -10, + SKILL_LEVEL_NOVICE = 0, + SKILL_LEVEL_APPRENTICE = 0, + SKILL_LEVEL_JOURNEYMAN = 0, + SKILL_LEVEL_EXPERT = 10, + SKILL_LEVEL_MASTER = 10, + SKILL_LEVEL_LEGENDARY = 25, + ), + ) diff --git a/code/datums/wires/airalarm.dm b/code/datums/wires/airalarm.dm index 2dc3244e9cac..7e7a6fff23fe 100644 --- a/code/datums/wires/airalarm.dm +++ b/code/datums/wires/airalarm.dm @@ -56,7 +56,7 @@ var/obj/machinery/airalarm/A = holder switch(wire) if(WIRE_POWER) // Short out forever. - A.shock(usr, 50) + A.shock(usr, 50 - usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) A.shorted = !mend A.update_appearance() if(WIRE_IDSCAN) diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm index 4672bd15b872..f4e8411949c0 100644 --- a/code/datums/wires/airlock.dm +++ b/code/datums/wires/airlock.dm @@ -139,7 +139,7 @@ if(WIRE_SHOCK) // Pulse to shock the door for 10 ticks. if(!A.secondsElectrified) A.set_electrified(MACHINE_DEFAULT_ELECTRIFY_TIME, usr) - A.shock(usr, 100) + A.shock(usr, 100- usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(WIRE_SAFETY) A.safe = !A.safe if(!A.density) @@ -169,15 +169,13 @@ A.regainMainPower() else A.loseMainPower() - if(isliving(usr)) - A.shock(usr, 50) + A.shock(usr, 50- usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(WIRE_BACKUP1, WIRE_BACKUP2) // Cut to lose backup power, repair all to gain backup power. if(mend && !is_cut(WIRE_BACKUP1) && !is_cut(WIRE_BACKUP2)) A.regainBackupPower() else A.loseBackupPower() - if(isliving(usr)) - A.shock(usr, 50) + A.shock(usr, 50 - usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(WIRE_BOLTS) // Cut to engage bolts, mend does nothing. if(!mend) A.bolt() @@ -201,7 +199,7 @@ else if(A.secondsElectrified != MACHINE_ELECTRIFIED_PERMANENT) A.set_electrified(MACHINE_ELECTRIFIED_PERMANENT, usr) - A.shock(usr, 100) + A.shock(usr, 100 - usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(WIRE_SAFETY) // Cut to disable safeties, mend to re-enable. A.safe = mend if (!isnull(source)) @@ -214,8 +212,7 @@ A.lights = mend A.update_appearance() if(WIRE_ZAP1, WIRE_ZAP2) // Ouch. - if(isliving(usr)) - A.shock(usr, 50) + A.shock(usr, 50 - usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(WIRE_UNRESTRICTED_EXIT) // If this wire is cut, the unrestricted helper goes away. If you mend it, it'll go "haywire" and pick a new direction at random. Might have to cut/mend a time or two to get the direction you want. if(!A.unres_sensor) //only works if the "sensor" is installed (a variable that we assign to the door either upon creation of a door with unrestricted directions, or if an unrestricted helper is added to a door in mapping) return @@ -228,7 +225,7 @@ /datum/wires/airlock/can_reveal_wires(mob/user) - if(HAS_TRAIT(user, TRAIT_KNOW_ENGI_WIRES)) + if(HAS_MIND_TRAIT(user, TRAIT_KNOW_ENGI_WIRES)) return TRUE return ..() diff --git a/code/datums/wires/apc.dm b/code/datums/wires/apc.dm index 54d179802a31..9c2a1124d51d 100644 --- a/code/datums/wires/apc.dm +++ b/code/datums/wires/apc.dm @@ -48,12 +48,12 @@ A.shorted = FALSE else A.shorted = TRUE - A.shock(usr, 50) + A.shock(usr, 50 - usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(WIRE_AI) // Disable AI control. A.aidisabled = !mend /datum/wires/apc/can_reveal_wires(mob/user) - if(HAS_TRAIT(user, TRAIT_KNOW_ENGI_WIRES)) + if(HAS_MIND_TRAIT(user, TRAIT_KNOW_ENGI_WIRES)) return TRUE return ..() diff --git a/code/datums/wires/autolathe.dm b/code/datums/wires/autolathe.dm index ca55dad954f6..02dfdecd3497 100644 --- a/code/datums/wires/autolathe.dm +++ b/code/datums/wires/autolathe.dm @@ -47,4 +47,4 @@ if(WIRE_DISABLE) A.disabled = !mend if(WIRE_ZAP) - A.shock(usr, 50) + A.shock(usr, 50 - usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) diff --git a/code/datums/wires/mecha.dm b/code/datums/wires/mecha.dm index 07bc11901481..76a7dea8f21a 100644 --- a/code/datums/wires/mecha.dm +++ b/code/datums/wires/mecha.dm @@ -73,6 +73,6 @@ return FALSE /datum/wires/mecha/can_reveal_wires(mob/user) - if(HAS_TRAIT(user, TRAIT_KNOW_ROBO_WIRES)) + if(HAS_MIND_TRAIT(user, TRAIT_KNOW_ROBO_WIRES)) return TRUE return ..() diff --git a/code/datums/wires/mod.dm b/code/datums/wires/mod.dm index 09274880367a..888a12a48871 100644 --- a/code/datums/wires/mod.dm +++ b/code/datums/wires/mod.dm @@ -57,6 +57,6 @@ return ..() /datum/wires/mod/can_reveal_wires(mob/user) - if(HAS_TRAIT(user, TRAIT_KNOW_ROBO_WIRES)) + if(HAS_MIND_TRAIT(user, TRAIT_KNOW_ROBO_WIRES)) return TRUE return ..() diff --git a/code/datums/wires/robot.dm b/code/datums/wires/robot.dm index 8e3870acb47c..cd2e99b8a903 100644 --- a/code/datums/wires/robot.dm +++ b/code/datums/wires/robot.dm @@ -105,7 +105,7 @@ log_silicon("[key_name(usr)] reset [key_name(R)]'s module via wire") /datum/wires/robot/can_reveal_wires(mob/user) - if(HAS_TRAIT(user, TRAIT_KNOW_ROBO_WIRES)) + if(HAS_MIND_TRAIT(user, TRAIT_KNOW_ROBO_WIRES)) return TRUE return ..() diff --git a/code/datums/wires/roulette.dm b/code/datums/wires/roulette.dm index f93bc3416999..5d1cbe91fd07 100644 --- a/code/datums/wires/roulette.dm +++ b/code/datums/wires/roulette.dm @@ -33,8 +33,7 @@ var/obj/machinery/roulette/R = holder switch(wire) if(WIRE_SHOCK) - if(isliving(usr)) - R.shock(usr, 50) + R.shock(usr, 50 - usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(WIRE_BOLTS) // Pulse to toggle bolts (but only raise if power is on). if(!R.on) return @@ -44,8 +43,7 @@ R.audible_message(span_warning("Owner reset!")) R.locked = FALSE if(WIRE_PRIZEVEND) - if(isliving(usr)) - R.shock(usr, 70) + R.shock(usr, 70- usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(R.locked) return R.audible_message(span_warning("Unauthorized prize vend detected! Locking down machine!")) @@ -55,8 +53,7 @@ var/obj/machinery/roulette/R = holder switch(wire) if(WIRE_SHOCK) - if(isliving(usr)) - R.shock(usr, 60) + R.shock(usr, 60- usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(mend) R.on = TRUE else @@ -66,13 +63,10 @@ return R.set_anchored(TRUE) if(WIRE_RESETOWNER) - if(isliving(usr)) - R.shock(usr, 70) + R.shock(usr, 70- usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(WIRE_PRIZEVEND) - if(isliving(usr)) - R.shock(usr, 75) + R.shock(usr, 75- usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(R.locked) return R.audible_message(span_warning("Unauthorized prize vend detected! Locking down machine!")) R.prize_theft(0.10) - diff --git a/code/datums/wires/suit_storage_unit.dm b/code/datums/wires/suit_storage_unit.dm index 26ab49763dd8..c8dacabbd9c9 100644 --- a/code/datums/wires/suit_storage_unit.dm +++ b/code/datums/wires/suit_storage_unit.dm @@ -32,8 +32,7 @@ if(WIRE_SAFETY) SSU.safeties = !SSU.safeties if(WIRE_ZAP) - if(usr) - SSU.shock(usr) + SSU.shock(usr, 100 - usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) /datum/wires/suit_storage_unit/on_cut(wire, mend, source) var/obj/machinery/suit_storage_unit/SSU = holder @@ -43,5 +42,4 @@ if(WIRE_SAFETY) SSU.safeties = mend if(WIRE_ZAP) - if(usr) - SSU.shock(usr) + SSU.shock(usr, 100 - usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) diff --git a/code/datums/wires/vending.dm b/code/datums/wires/vending.dm index 4e037f3e24b3..97121c7275d4 100644 --- a/code/datums/wires/vending.dm +++ b/code/datums/wires/vending.dm @@ -28,8 +28,9 @@ if(!..()) return FALSE var/obj/machinery/vending/vending_machine = holder - if(!issilicon(user) && vending_machine.seconds_electrified && vending_machine.shock(user, 100)) - return FALSE + if(vending_machine.seconds_electrified) + if(vending_machine.shock(user, 100 - user.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER))) + return FALSE if(vending_machine.panel_open) return TRUE diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 5505cde4b82e..829c3b0c56b3 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -1067,17 +1067,12 @@ if(!delay && !tool_start_check(user, amount)) return - var/skill_modifier = 1 - - if(tool_behaviour == TOOL_MINING && ishuman(user)) - if(user.mind) - skill_modifier = user.mind.get_skill_modifier(/datum/skill/mining, SKILL_SPEED_MODIFIER) - - if(user.mind.get_skill_level(/datum/skill/mining) >= SKILL_LEVEL_JOURNEYMAN && prob(user.mind.get_skill_modifier(/datum/skill/mining, SKILL_PROBS_MODIFIER))) // we check if the skill level is greater than Journeyman and then we check for the probality for that specific level. - mineral_scan_pulse(get_turf(user), SKILL_LEVEL_JOURNEYMAN - 2) //SKILL_LEVEL_JOURNEYMAN = 3 So to get range of 1+ we have to subtract 2 from it,. - - delay *= toolspeed * skill_modifier + if(tool_behaviour == TOOL_MINING && user.mind) + delay *= user.mind.get_skill_modifier(/datum/skill/mining, SKILL_SPEED_MODIFIER) + if(prob(user.mind.get_skill_modifier(/datum/skill/mining, SKILL_PROBS_MODIFIER))) + mineral_scan_pulse(get_turf(user), 2) + delay *= toolspeed // Play tool sound at the beginning of tool usage. play_tool_sound(target, volume) diff --git a/code/modules/admin/skill_panel.dm b/code/modules/admin/skill_panel.dm index ec80768276dc..79fdfcb78ad4 100644 --- a/code/modules/admin/skill_panel.dm +++ b/code/modules/admin/skill_panel.dm @@ -33,7 +33,7 @@ if (xp_prog_to_level)//is it even possible to level up? xp_req_to_level = SKILL_EXP_LIST[lvl_num+1] - SKILL_EXP_LIST[lvl_num] var/exp_percent = exp / SKILL_EXP_LIST[SKILL_LEVEL_LEGENDARY] - .["skills"] += list(list("playername" = targetmind.current, "path" = type, "name" = S.name, "desc" = S.desc, "lvlnum" = lvl_num, "lvl" = lvl_name, "exp" = exp, "exp_prog" = xp_req_to_level - xp_prog_to_level, "exp_req" = xp_req_to_level, "exp_percent" = exp_percent, "max_exp" = SKILL_EXP_LIST[length(SKILL_EXP_LIST)])) + .["skills"] += list(list("playername" = targetmind.current, "path" = type, "name" = S.name, "desc" = S.blurb, "lvlnum" = lvl_num, "lvl" = lvl_name, "exp" = exp, "exp_prog" = xp_req_to_level - xp_prog_to_level, "exp_req" = xp_req_to_level, "exp_percent" = exp_percent, "max_exp" = SKILL_EXP_LIST[length(SKILL_EXP_LIST)])) /datum/skill_panel/ui_act(action, params) . = ..() diff --git a/code/modules/bitrunning/job.dm b/code/modules/bitrunning/job.dm index 1e749a3c7a58..490654055027 100644 --- a/code/modules/bitrunning/job.dm +++ b/code/modules/bitrunning/job.dm @@ -31,6 +31,10 @@ rpg_title = "Recluse" job_flags = STATION_JOB_FLAGS + base_skills = list( + /datum/skill/electronics = SKILL_LEVEL_NOVICE, + ) + /datum/outfit/job/bitrunner name = "Bitrunner" jobtype = /datum/job/bitrunner diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm index 65b5d9a4100d..8ed88e83e1f9 100644 --- a/code/modules/jobs/job_types/_job.dm +++ b/code/modules/jobs/job_types/_job.dm @@ -133,6 +133,9 @@ /// Minimal character age for this job var/required_character_age + /// List of [typepath] to [base skill level] that this job starts with + var/list/base_skills + /datum/job/New() . = ..() @@ -154,6 +157,9 @@ if(liver && length(liver_traits)) liver.add_traits(liver_traits, JOB_TRAIT) + for(var/skill in base_skills) + spawned.mind.set_level(skill, base_skills[skill], silent = TRUE) + if(!ishuman(spawned)) return diff --git a/code/modules/jobs/job_types/atmospheric_technician.dm b/code/modules/jobs/job_types/atmospheric_technician.dm index d016688042a8..2260a388453a 100644 --- a/code/modules/jobs/job_types/atmospheric_technician.dm +++ b/code/modules/jobs/job_types/atmospheric_technician.dm @@ -38,6 +38,10 @@ job_flags = STATION_JOB_FLAGS rpg_title = "Aeromancer" + base_skills = list( + /datum/skill/electronics = SKILL_LEVEL_NOVICE, + ) + /datum/outfit/job/atmos name = "Atmospheric Technician" jobtype = /datum/job/atmospheric_technician diff --git a/code/modules/jobs/job_types/cargo_technician.dm b/code/modules/jobs/job_types/cargo_technician.dm index dd269bc7e373..8b2a0c09eac0 100644 --- a/code/modules/jobs/job_types/cargo_technician.dm +++ b/code/modules/jobs/job_types/cargo_technician.dm @@ -35,6 +35,9 @@ rpg_title = "Merchantman" job_flags = STATION_JOB_FLAGS + base_skills = list( + /datum/skill/electronics = SKILL_LEVEL_NOVICE, + ) /datum/outfit/job/cargo_tech name = "Cargo Technician" diff --git a/code/modules/jobs/job_types/chemist.dm b/code/modules/jobs/job_types/chemist.dm index bdb48c84f35d..23140c374620 100644 --- a/code/modules/jobs/job_types/chemist.dm +++ b/code/modules/jobs/job_types/chemist.dm @@ -37,6 +37,9 @@ rpg_title = "Alchemist" job_flags = STATION_JOB_FLAGS + base_skills = list( + /datum/skill/surgery = SKILL_LEVEL_NOVICE, + ) /datum/outfit/job/chemist name = "Chemist" diff --git a/code/modules/jobs/job_types/chief_engineer.dm b/code/modules/jobs/job_types/chief_engineer.dm index fd568464bb67..ed396cf7344a 100644 --- a/code/modules/jobs/job_types/chief_engineer.dm +++ b/code/modules/jobs/job_types/chief_engineer.dm @@ -48,6 +48,9 @@ voice_of_god_power = 1.4 //Command staff has authority + base_skills = list( + /datum/skill/electronics = SKILL_LEVEL_MASTER, + ) /datum/job/chief_engineer/after_spawn(mob/living/spawned, client/player_client) . = ..() diff --git a/code/modules/jobs/job_types/chief_medical_officer.dm b/code/modules/jobs/job_types/chief_medical_officer.dm index e20ef7c19edd..6c6b79f49733 100644 --- a/code/modules/jobs/job_types/chief_medical_officer.dm +++ b/code/modules/jobs/job_types/chief_medical_officer.dm @@ -45,6 +45,9 @@ voice_of_god_power = 1.4 //Command staff has authority + base_skills = list( + /datum/skill/surgery = SKILL_LEVEL_MASTER, + ) /datum/job/chief_medical_officer/get_captaincy_announcement(mob/living/captain) return "Due to staffing shortages, newly promoted Acting Captain [captain.real_name] on deck!" diff --git a/code/modules/jobs/job_types/coroner.dm b/code/modules/jobs/job_types/coroner.dm index 22f6c5e65db8..5129f5225aad 100644 --- a/code/modules/jobs/job_types/coroner.dm +++ b/code/modules/jobs/job_types/coroner.dm @@ -43,6 +43,10 @@ rpg_title = "Undertaker" + base_skills = list( + /datum/skill/surgery = SKILL_LEVEL_JOURNEYMAN, + ) + /datum/outfit/job/coroner name = "Coroner" jobtype = /datum/job/coroner diff --git a/code/modules/jobs/job_types/janitor.dm b/code/modules/jobs/job_types/janitor.dm index 2e926859d508..102092fb37ac 100644 --- a/code/modules/jobs/job_types/janitor.dm +++ b/code/modules/jobs/job_types/janitor.dm @@ -32,6 +32,10 @@ job_tone = "slip" + base_skills = list( + /datum/skill/cleaning = SKILL_LEVEL_NOVICE, // i'd make this higher, but i think grinding cleaning skill IS janitor's gameplay + ) + /datum/outfit/job/janitor name = "Janitor" jobtype = /datum/job/janitor diff --git a/code/modules/jobs/job_types/medical_doctor.dm b/code/modules/jobs/job_types/medical_doctor.dm index e3a396609eb2..80bbaa9d39d0 100644 --- a/code/modules/jobs/job_types/medical_doctor.dm +++ b/code/modules/jobs/job_types/medical_doctor.dm @@ -38,6 +38,9 @@ rpg_title = "Cleric" job_flags = STATION_JOB_FLAGS + base_skills = list( + /datum/skill/surgery = SKILL_LEVEL_EXPERT, + ) /datum/outfit/job/doctor name = "Medical Doctor" diff --git a/code/modules/jobs/job_types/paramedic.dm b/code/modules/jobs/job_types/paramedic.dm index 2fd4f3a93a6d..02694a1ed17f 100644 --- a/code/modules/jobs/job_types/paramedic.dm +++ b/code/modules/jobs/job_types/paramedic.dm @@ -38,6 +38,9 @@ rpg_title = "Corpse Runner" job_flags = STATION_JOB_FLAGS + base_skills = list( + /datum/skill/surgery = SKILL_LEVEL_APPRENTICE, + ) /datum/outfit/job/paramedic name = "Paramedic" diff --git a/code/modules/jobs/job_types/research_director.dm b/code/modules/jobs/job_types/research_director.dm index 1142ba033ff7..fc88c6c1573e 100644 --- a/code/modules/jobs/job_types/research_director.dm +++ b/code/modules/jobs/job_types/research_director.dm @@ -46,6 +46,10 @@ voice_of_god_power = 1.4 //Command staff has authority + base_skills = list( + /datum/skill/electronics = SKILL_LEVEL_JOURNEYMAN, + /datum/skill/surgery = SKILL_LEVEL_JOURNEYMAN, + ) /datum/job/research_director/get_captaincy_announcement(mob/living/captain) return "Due to staffing shortages, newly promoted Acting Captain [captain.real_name] on deck!" diff --git a/code/modules/jobs/job_types/roboticist.dm b/code/modules/jobs/job_types/roboticist.dm index e5ae78bdc6bc..f009c137e77b 100644 --- a/code/modules/jobs/job_types/roboticist.dm +++ b/code/modules/jobs/job_types/roboticist.dm @@ -33,6 +33,10 @@ rpg_title = "Necromancer" job_flags = STATION_JOB_FLAGS + base_skills = list( + /datum/skill/electronics = SKILL_LEVEL_JOURNEYMAN, + /datum/skill/surgery = SKILL_LEVEL_JOURNEYMAN, + ) /datum/job/roboticist/New() . = ..() diff --git a/code/modules/jobs/job_types/scientist.dm b/code/modules/jobs/job_types/scientist.dm index 878167f25483..c1c5aedd1d64 100644 --- a/code/modules/jobs/job_types/scientist.dm +++ b/code/modules/jobs/job_types/scientist.dm @@ -36,6 +36,9 @@ job_tone = "boom" + base_skills = list( + /datum/skill/surgery = SKILL_LEVEL_NOVICE, + ) /datum/outfit/job/scientist name = "Scientist" diff --git a/code/modules/jobs/job_types/shaft_miner.dm b/code/modules/jobs/job_types/shaft_miner.dm index 2c65ca3e05e7..5216b37af2e4 100644 --- a/code/modules/jobs/job_types/shaft_miner.dm +++ b/code/modules/jobs/job_types/shaft_miner.dm @@ -28,6 +28,9 @@ rpg_title = "Adventurer" job_flags = STATION_JOB_FLAGS + base_skills = list( + /datum/skill/mining = SKILL_LEVEL_NOVICE, // i'd make this higher, but i think grinding mining skill IS mining's gameplay + ) /datum/outfit/job/miner name = "Shaft Miner" diff --git a/code/modules/jobs/job_types/station_engineer.dm b/code/modules/jobs/job_types/station_engineer.dm index 8738389ab41d..acc8c406941e 100644 --- a/code/modules/jobs/job_types/station_engineer.dm +++ b/code/modules/jobs/job_types/station_engineer.dm @@ -38,6 +38,9 @@ rpg_title = "Crystallomancer" job_flags = STATION_JOB_FLAGS + base_skills = list( + /datum/skill/electronics = SKILL_LEVEL_EXPERT, + ) /datum/outfit/job/engineer name = "Station Engineer" diff --git a/code/modules/jobs/job_types/virologist.dm b/code/modules/jobs/job_types/virologist.dm index bdbfd7d687ca..6aa1410c2670 100644 --- a/code/modules/jobs/job_types/virologist.dm +++ b/code/modules/jobs/job_types/virologist.dm @@ -38,6 +38,9 @@ rpg_title = "Plague Doctor" job_flags = STATION_JOB_FLAGS + base_skills = list( + /datum/skill/surgery = SKILL_LEVEL_APPRENTICE, + ) /datum/outfit/job/virologist name = "Virologist" diff --git a/code/modules/modular_computers/file_system/programs/skill_tracker.dm b/code/modules/modular_computers/file_system/programs/skill_tracker.dm index 9063e3e239db..4b5750ac05d2 100644 --- a/code/modules/modular_computers/file_system/programs/skill_tracker.dm +++ b/code/modules/modular_computers/file_system/programs/skill_tracker.dm @@ -29,14 +29,17 @@ var/list/skilldata = list( "name" = skill.name, - "desc" = skill.desc, + "blurb" = skill.blurb, + "earned_by" = skill.earned_by, + "grants_you" = skill.grants_you, + "higher_levels_grant_you" = skill.higher_levels_grant_you, "title" = skill.title, "lvl_name" = lvl_name ) if (exp && xp_req_to_level) skilldata["progress_percent"] = (xp_req_to_level-xp_prog_to_level)/xp_req_to_level skilldata["overall_percent"] = exp / SKILL_EXP_LIST[length(SKILL_EXP_LIST)] - if (lvl_num >= length(SKILL_EXP_LIST) && !(type in targetmind.skills_rewarded)) + if (lvl_num >= length(SKILL_EXP_LIST) && !(type in targetmind.skills_rewarded) && ispath(skill.skill_item_path)) skilldata["reward"] = TRUE skills[++skills.len] = skilldata diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 30a1d406d095..11eab558d354 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -181,7 +181,7 @@ GLOBAL_LIST_INIT(wire_node_generating_types, typecacheof(list(/obj/structure/gri if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE) return if(W.tool_behaviour == TOOL_WIRECUTTER) - if (shock(user, 50)) + if (shock(user, 50 - user.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER))) return user.visible_message(span_notice("[user] cuts the cable."), span_notice("You cut the cable.")) investigate_log("was cut by [key_name(usr)] in [AREACOORD(src)]", INVESTIGATE_WIRES) @@ -190,7 +190,7 @@ GLOBAL_LIST_INIT(wire_node_generating_types, typecacheof(list(/obj/structure/gri else if(W.tool_behaviour == TOOL_MULTITOOL) to_chat(user, get_power_info()) - shock(user, 5, 0.2) + shock(user, 5 - user.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER), 0.2) add_fingerprint(user) @@ -624,7 +624,7 @@ GLOBAL_LIST_INIT(wire_node_generating_types, typecacheof(list(/obj/structure/gri use(1) - if(C.shock(user, 50)) + if(C.shock(user, 50 - user.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER))) if(prob(50)) //fail C.deconstruct() diff --git a/code/modules/surgery/autopsy.dm b/code/modules/surgery/autopsy.dm index bcf610e05fe9..fd89a1c7290b 100644 --- a/code/modules/surgery/autopsy.dm +++ b/code/modules/surgery/autopsy.dm @@ -33,17 +33,28 @@ ) display_pain(target, "You feel a burning sensation in your chest!", target_zone = target_zone) // NON-MODULE CHANGE -/datum/surgery_step/autopsy/success(mob/user, mob/living/carbon/target, target_zone, obj/item/autopsy_scanner/tool, datum/surgery/surgery, default_display_results = FALSE) +/datum/surgery_step/autopsy/success(mob/living/user, mob/living/carbon/target, target_zone, obj/item/autopsy_scanner/tool, datum/surgery/surgery, default_display_results = FALSE) + var/xp_given = 200 // some alien species + if(isalien(target)) + xp_given *= 2.5 // truly foreign + if(ishumanbasic(target) || isfelinid(target) || ismonkey(target)) + xp_given *= 0.25 // well documented + if(HAS_TRAIT(target, TRAIT_SURGICALLY_ANALYZED)) + xp_given *= 0 // this body has already been cut open! useless + ADD_TRAIT(target, TRAIT_DISSECTED, AUTOPSY_TRAIT) - if(!HAS_TRAIT(src, TRAIT_SURGICALLY_ANALYZED)) - ADD_TRAIT(target, TRAIT_SURGICALLY_ANALYZED, AUTOPSY_TRAIT) + ADD_TRAIT(target, TRAIT_SURGICALLY_ANALYZED, AUTOPSY_TRAIT) + tool.scan_cadaver(user, target) var/obj/machinery/computer/operating/operating_computer = surgery.locate_operating_computer(get_turf(target)) if (!isnull(operating_computer)) SEND_SIGNAL(operating_computer, COMSIG_OPERATING_COMPUTER_AUTOPSY_COMPLETE, target) - if(HAS_MIND_TRAIT(user, TRAIT_MORBID) && ishuman(user)) - var/mob/living/carbon/human/morbid_weirdo = user - morbid_weirdo.add_mood_event("morbid_dissection_success", /datum/mood_event/morbid_dissection_success) + + if(HAS_MIND_TRAIT(user, TRAIT_MORBID)) + user.add_mood_event("morbid_dissection_success", /datum/mood_event/morbid_dissection_success) + xp_given *= 1.5 // truly something worth seeing! + + user.mind?.adjust_experience(/datum/skill/surgery, xp_given) return ..() /datum/surgery_step/autopsy/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) diff --git a/code/modules/surgery/surgery_step.dm b/code/modules/surgery/surgery_step.dm index daf9e22ecd78..6b1aa0be53bd 100644 --- a/code/modules/surgery/surgery_step.dm +++ b/code/modules/surgery/surgery_step.dm @@ -95,7 +95,9 @@ var/implement_speed_mod = 1 if(implement_type) //this means it isn't a require hand or any item step. - implement_speed_mod = implements[implement_type] / 100.0 + implement_speed_mod = (implements[implement_type] + user.mind?.get_skill_modifier(/datum/skill/surgery, SKILL_VALUE_MODIFIER)) / 100.0 + + speed_mod *= (user.mind?.get_skill_modifier(/datum/skill/surgery, SKILL_SPEED_MODIFIER) || 1) speed_mod /= (get_location_modifier(target) * (1 + surgery.speed_modifier) * implement_speed_mod) * target.mob_surgery_speed_mod var/modded_time = time * speed_mod @@ -115,6 +117,8 @@ if((prob(100-fail_prob) || (iscyborg(user) && !silicons_obey_prob)) && chem_check_result && !try_to_fail) if(success(user, target, target_zone, tool, surgery)) + if(target.mind && !iscyborg(user)) // by default, you only gain surgery xp for operating on players. no monkey grinding + user.mind?.adjust_experience(/datum/skill/surgery, time * 0.5) // 1 xp per 2 second of surgery - 50 xp for brain surgery play_success_sound(user, target, target_zone, tool, surgery) advance = TRUE else diff --git a/maplestation.dme b/maplestation.dme index f073cbd17427..0b91880a1a96 100644 --- a/maplestation.dme +++ b/maplestation.dme @@ -1734,10 +1734,12 @@ #include "code\datums\shuttles\whiteship.dm" #include "code\datums\skills\_skill.dm" #include "code\datums\skills\cleaning.dm" +#include "code\datums\skills\electrics.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\skills\surgery.dm" #include "code\datums\station_traits\_station_trait.dm" #include "code\datums\station_traits\admin_panel.dm" #include "code\datums\station_traits\job_traits.dm" diff --git a/tgui/packages/tgui/interfaces/NtosSkillTracker.jsx b/tgui/packages/tgui/interfaces/NtosSkillTracker.tsx similarity index 73% rename from tgui/packages/tgui/interfaces/NtosSkillTracker.jsx rename to tgui/packages/tgui/interfaces/NtosSkillTracker.tsx index fd42d35ae746..fe7bf12bf22c 100644 --- a/tgui/packages/tgui/interfaces/NtosSkillTracker.jsx +++ b/tgui/packages/tgui/interfaces/NtosSkillTracker.tsx @@ -1,3 +1,4 @@ +import { BooleanLike } from '../../common/react'; import { useBackend } from '../backend'; import { AnimatedNumber, @@ -9,16 +10,52 @@ import { } from '../components'; import { NtosWindow } from '../layouts'; -export const NtosSkillTracker = (props) => { - const { act, data } = useBackend(); - const { skills = {} } = data; +type Data = { + skills: Skill[]; +}; + +type Skill = { + name: string; + title: string; + blurb: string; + earned_by?: string; + grants_you?: string; + higher_levels_grant_you?: string; + lvl_name: string; + progress_percent: number; + overall_percent: number; + reward: BooleanLike; +}; + +export const NtosSkillTracker = () => { + const { act, data } = useBackend(); + const { skills } = data; + return (
{skills.map((skill, idx) => (
-
{skill.desc}
+
+ {skill.blurb} +
+ {!!skill.earned_by && ( +
+ {'>'} Earned by {skill.earned_by}. +
+ )} + {!!skill.grants_you && ( +
+ {'>'} Grants you {skill.grants_you}. +
+ )} + {!!skill.higher_levels_grant_you && ( +
+ {'>'} At higher levels, you gain{' '} + {skill.higher_levels_grant_you}. +
+ )}
From e16b7759e72eec2526a09ea3134631a76c468d33 Mon Sep 17 00:00:00 2001 From: MrMelbert Date: Fri, 17 Jan 2025 23:03:31 -0600 Subject: [PATCH 02/22] Adds More Skills --- code/__DEFINES/living.dm | 2 + code/controllers/subsystem/skills.dm | 2 +- code/datums/mind/skills.dm | 9 +- code/datums/skills/cleaning.dm | 1 + code/datums/skills/cybernetic.dm | 19 ++ code/datums/skills/electrics.dm | 3 +- code/datums/skills/firearms.dm | 18 ++ code/datums/skills/hydroponics.dm | 8 + code/datums/skills/mechanics.dm | 6 + code/datums/skills/medical.dm | 29 +++ code/datums/skills/mining.dm | 1 + code/datums/skills/robotics.dm | 6 + code/datums/skills/surgery.dm | 4 +- code/datums/wires/airalarm.dm | 2 +- code/datums/wires/airlock.dm | 10 +- code/datums/wires/apc.dm | 2 +- code/datums/wires/autolathe.dm | 2 +- code/datums/wires/roulette.dm | 10 +- code/datums/wires/suit_storage_unit.dm | 4 +- code/game/objects/items/shooting_range.dm | 10 +- code/modules/admin/skill_panel.dm | 35 ++-- code/modules/admin/verbs/ert.dm | 4 + code/modules/bitrunning/job.dm | 1 + code/modules/hydroponics/beekeeping/beebox.dm | 12 +- code/modules/hydroponics/seeds.dm | 9 +- .../jobs/job_types/assistant/assistant.dm | 6 + .../jobs/job_types/atmospheric_technician.dm | 1 + code/modules/jobs/job_types/bartender.dm | 4 + code/modules/jobs/job_types/botanist.dm | 4 + code/modules/jobs/job_types/captain.dm | 4 + .../jobs/job_types/cargo_technician.dm | 2 + .../jobs/job_types/chaplain/chaplain.dm | 6 + code/modules/jobs/job_types/chemist.dm | 1 + code/modules/jobs/job_types/chief_engineer.dm | 2 + .../jobs/job_types/chief_medical_officer.dm | 4 + code/modules/jobs/job_types/cook.dm | 4 + code/modules/jobs/job_types/coroner.dm | 1 + code/modules/jobs/job_types/detective.dm | 4 + .../jobs/job_types/head_of_personnel.dm | 3 + .../jobs/job_types/head_of_security.dm | 4 + code/modules/jobs/job_types/janitor.dm | 1 + code/modules/jobs/job_types/medical_doctor.dm | 3 + code/modules/jobs/job_types/paramedic.dm | 1 + code/modules/jobs/job_types/prisoner.dm | 4 + code/modules/jobs/job_types/quartermaster.dm | 4 + .../jobs/job_types/research_director.dm | 4 + code/modules/jobs/job_types/roboticist.dm | 3 + code/modules/jobs/job_types/scientist.dm | 1 + .../jobs/job_types/security_officer.dm | 4 + code/modules/jobs/job_types/shaft_miner.dm | 2 + .../jobs/job_types/station_engineer.dm | 1 + .../station_trait/bridge_assistant.dm | 5 + code/modules/jobs/job_types/virologist.dm | 2 + code/modules/jobs/job_types/warden.dm | 5 + code/modules/mob/living/living_defense.dm | 1 + code/modules/projectiles/projectile.dm | 22 +++ .../modules/surgery/prosthetic_replacement.dm | 4 + code/modules/surgery/surgery_step.dm | 4 +- maplestation.dme | 6 + .../code/__DEFINES/_module_defines.dm | 2 - .../living/carbon/human/heart_rework/cpr.dm | 2 +- .../tgui/interfaces/NtosSkillTracker.tsx | 168 +++++++++--------- 62 files changed, 376 insertions(+), 132 deletions(-) create mode 100644 code/datums/skills/cybernetic.dm create mode 100644 code/datums/skills/firearms.dm create mode 100644 code/datums/skills/hydroponics.dm create mode 100644 code/datums/skills/mechanics.dm create mode 100644 code/datums/skills/medical.dm create mode 100644 code/datums/skills/robotics.dm diff --git a/code/__DEFINES/living.dm b/code/__DEFINES/living.dm index 1dbb96fb5fa6..9288890a5163 100644 --- a/code/__DEFINES/living.dm +++ b/code/__DEFINES/living.dm @@ -66,6 +66,8 @@ #define TRAIT_NO_GRAB_SPEED_PENALTY "no_grab_speed_penalty" /// Doesn't let a mob shift this atom around with move_pulled #define TRAIT_NO_MOVE_PULL "no_move_pull" +/// Does not harm patients when undergoing CPR +#define TRAIT_CPR_CERTIFIED "cpr_certified" /// The trait that determines if someone has the robotic limb reattachment quirk. #define TRAIT_ROBOTIC_LIMBATTACHMENT "trait_robotic_limbattachment" diff --git a/code/controllers/subsystem/skills.dm b/code/controllers/subsystem/skills.dm index a14890e890cb..96c130462fd8 100644 --- a/code/controllers/subsystem/skills.dm +++ b/code/controllers/subsystem/skills.dm @@ -10,7 +10,7 @@ SUBSYSTEM_DEF(skills) var/list/all_skills = list() ///List of level names with index corresponding to skill level var/list/level_names = list( - SKILL_LEVEL_NONE = "None", + SKILL_LEVEL_NONE = "Untrained", SKILL_LEVEL_NOVICE = "Novice", SKILL_LEVEL_APPRENTICE = "Apprentice", SKILL_LEVEL_JOURNEYMAN = "Journeyman", diff --git a/code/datums/mind/skills.dm b/code/datums/mind/skills.dm index 07086d77bcb5..d83a35b6d327 100644 --- a/code/datums/mind/skills.dm +++ b/code/datums/mind/skills.dm @@ -78,8 +78,9 @@ if(!length(shown_skills)) to_chat(user, span_notice("You don't seem to have any particularly outstanding skills.")) return - var/msg = "[span_info("Your skills:")]
" + var/list/skill_strings = list() for(var/datum/skill/shown_skill as anything in shown_skills) - msg += "• [initial(shown_skill.name)] - [get_skill_level_name(shown_skill)]
" - msg += "
" - to_chat(user, examine_block(msg)) + skill_strings += "• [initial(shown_skill.name)] - [get_skill_level_name(shown_skill)]" + + sortTim(skill_strings, GLOBAL_PROC_REF(cmp_text_asc)) + to_chat(user, examine_block("[span_info("Your skills:")]
[span_notice(jointext(skill_strings, "
"))]")) diff --git a/code/datums/skills/cleaning.dm b/code/datums/skills/cleaning.dm index 9a6d7d749704..bd47bee1a9cc 100644 --- a/code/datums/skills/cleaning.dm +++ b/code/datums/skills/cleaning.dm @@ -17,3 +17,4 @@ ), ) skill_item_path = /obj/item/clothing/neck/cloak/skill_reward/cleaning + innate_skill = TRUE diff --git a/code/datums/skills/cybernetic.dm b/code/datums/skills/cybernetic.dm new file mode 100644 index 000000000000..710ff029aacb --- /dev/null +++ b/code/datums/skills/cybernetic.dm @@ -0,0 +1,19 @@ +/datum/skill/cybernetics + name = "Cybernetics" + title = "Cyberneticist" + blurb = "You can build and repair cybernetic implants." + earned_by = "installing and repairing cybernetic implants" + grants_you = "less pain when installing cybernetic implants on yourself and others" + modifiers = list( + // amount of pain to reduce when installing cybernetic implants + SKILL_VALUE_MODIFIER = list( + SKILL_LEVEL_NONE = -10, + SKILL_LEVEL_NOVICE = 0, + SKILL_LEVEL_APPRENTICE = 0, + SKILL_LEVEL_JOURNEYMAN = 10, + SKILL_LEVEL_EXPERT = 20, + SKILL_LEVEL_MASTER = 30, + SKILL_LEVEL_LEGENDARY = 50, + ), + ) + innate_skill = TRUE diff --git a/code/datums/skills/electrics.dm b/code/datums/skills/electrics.dm index af1dc3ac139a..042d66636a86 100644 --- a/code/datums/skills/electrics.dm +++ b/code/datums/skills/electrics.dm @@ -15,6 +15,7 @@ SKILL_LEVEL_LEGENDARY = 50, ), ) + innate_skill = TRUE /datum/skill/electronics/level_gained(datum/mind/mind, new_level, old_level, silent) . = ..() @@ -23,5 +24,5 @@ /datum/skill/electronics/level_lost(datum/mind/mind, new_level, old_level, silent) . = ..() - if(old_level >= SKILL_LEVEL_MASTER) + if(old_level >= SKILL_LEVEL_MASTER && new_level < SKILL_LEVEL_MASTER) REMOVE_TRAIT(mind, TRAIT_KNOW_ENGI_WIRES, type) diff --git a/code/datums/skills/firearms.dm b/code/datums/skills/firearms.dm new file mode 100644 index 000000000000..8b010dbc73a6 --- /dev/null +++ b/code/datums/skills/firearms.dm @@ -0,0 +1,18 @@ +/datum/skill/firearms + name = "Firearms" + title = "Gunner" + blurb = "Don't shoot yourself in the foot." + earned_by = "training at the firing range (or shooting people)" + grants_you = "reduced accuracy penalties when using firearms while wounded" + modifiers = list( + SKILL_RANDS_MODIFIER = list( + SKILL_LEVEL_NONE = 5, + SKILL_LEVEL_NOVICE = 0, + SKILL_LEVEL_APPRENTICE = -5, + SKILL_LEVEL_JOURNEYMAN = -5, + SKILL_LEVEL_EXPERT = -10, + SKILL_LEVEL_MASTER = -10, + SKILL_LEVEL_LEGENDARY = -20, + ), + ) + innate_skill = TRUE diff --git a/code/datums/skills/hydroponics.dm b/code/datums/skills/hydroponics.dm new file mode 100644 index 000000000000..037e043b97f2 --- /dev/null +++ b/code/datums/skills/hydroponics.dm @@ -0,0 +1,8 @@ +/datum/skill/botany + name = "Botany" + title = "Botanist" + blurb = "You can grow plants." + earned_by = "growing plants" + higher_levels_grant_you = "guaranteed seed samples from plants with zero yield \ + and safety around bees without a suit" + innate_skill = TRUE diff --git a/code/datums/skills/mechanics.dm b/code/datums/skills/mechanics.dm new file mode 100644 index 000000000000..4a63d6dbc99d --- /dev/null +++ b/code/datums/skills/mechanics.dm @@ -0,0 +1,6 @@ +/datum/skill/mechanics + name = "Mechanics" + title = "Mechanical Engineer" + blurb = "I solve problems. Not problems like 'What is beauty?'... I solve practical problems." + earned_by = "repairing and building machines" + innate_skill = TRUE diff --git a/code/datums/skills/medical.dm b/code/datums/skills/medical.dm new file mode 100644 index 000000000000..87f20e5ddbcf --- /dev/null +++ b/code/datums/skills/medical.dm @@ -0,0 +1,29 @@ +/datum/skill/first_aid + name = "First Aid" + title = "Medic" + blurb = "You can stop the bleeding, but you can't fix the broken bones." + earned_by = "healing members of the crew with sutures or bandages" + grants_you = "an improved proficiency medical tools such as sutures or bandages" + higher_levels_grant_you = "the ability do CPR without harming the patient" + modifiers = list( + SKILL_SPEED_MODIFIER = list( + SKILL_LEVEL_NONE = 1.15, + SKILL_LEVEL_NOVICE = 1, + SKILL_LEVEL_APPRENTICE = 1, + SKILL_LEVEL_JOURNEYMAN = 0.9, + SKILL_LEVEL_EXPERT = 0.9, + SKILL_LEVEL_MASTER = 0.8, + SKILL_LEVEL_LEGENDARY = 0.75, + ), + ) + innate_skill = TRUE + +/datum/skill/first_aid/level_gained(datum/mind/mind, new_level, old_level, silent) + . = ..() + if(new_level >= SKILL_LEVEL_MASTER) + ADD_TRAIT(mind, TRAIT_CPR_CERTIFIED, type) + +/datum/skill/first_aid/level_lost(datum/mind/mind, new_level, old_level, silent) + . = ..() + if(old_level >= SKILL_LEVEL_MASTER && new_level < SKILL_LEVEL_MASTER) + REMOVE_TRAIT(mind, TRAIT_CPR_CERTIFIED, type) diff --git a/code/datums/skills/mining.dm b/code/datums/skills/mining.dm index d2212ce9babe..ffd33d809de4 100644 --- a/code/datums/skills/mining.dm +++ b/code/datums/skills/mining.dm @@ -26,3 +26,4 @@ ), ) skill_item_path = /obj/item/clothing/neck/cloak/skill_reward/mining + innate_skill = TRUE diff --git a/code/datums/skills/robotics.dm b/code/datums/skills/robotics.dm new file mode 100644 index 000000000000..6a3f356a018f --- /dev/null +++ b/code/datums/skills/robotics.dm @@ -0,0 +1,6 @@ +/datum/skill/robotics + name = "Robotics" + title = "Roboticist" + blurb = "You can build and repair robots." + earned_by = "building and repairing cyborgs and robots" + innate_skill = TRUE diff --git a/code/datums/skills/surgery.dm b/code/datums/skills/surgery.dm index 0728bfe97a7a..7455f2bdff93 100644 --- a/code/datums/skills/surgery.dm +++ b/code/datums/skills/surgery.dm @@ -2,7 +2,8 @@ name = "Surgery" title = "Surgeon" blurb = "Your capability to split someone's brain in two with a pen." - earned_by = "completing surgeries on members of the crew, or autopsies on any cadavers" + earned_by = "completing surgeries, though apprentices and above will only gain experience from operating on crewmembers. \ + Autopsies will also give training regardless of skill level (with a bonus for non-human, non-monkey species)" grants_you = "an improved proficiency with surgical tools" higher_levels_grant_you = "the ability to perform more complex surgeries with worse (or improvised) tools" modifiers = list( @@ -29,3 +30,4 @@ SKILL_LEVEL_LEGENDARY = 25, ), ) + innate_skill = TRUE diff --git a/code/datums/wires/airalarm.dm b/code/datums/wires/airalarm.dm index 7e7a6fff23fe..a1791223e88e 100644 --- a/code/datums/wires/airalarm.dm +++ b/code/datums/wires/airalarm.dm @@ -56,7 +56,7 @@ var/obj/machinery/airalarm/A = holder switch(wire) if(WIRE_POWER) // Short out forever. - A.shock(usr, 50 - usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) + A.shock(usr, 50 - usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) A.shorted = !mend A.update_appearance() if(WIRE_IDSCAN) diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm index f4e8411949c0..78165170b7dc 100644 --- a/code/datums/wires/airlock.dm +++ b/code/datums/wires/airlock.dm @@ -139,7 +139,7 @@ if(WIRE_SHOCK) // Pulse to shock the door for 10 ticks. if(!A.secondsElectrified) A.set_electrified(MACHINE_DEFAULT_ELECTRIFY_TIME, usr) - A.shock(usr, 100- usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) + A.shock(usr, 100- usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(WIRE_SAFETY) A.safe = !A.safe if(!A.density) @@ -169,13 +169,13 @@ A.regainMainPower() else A.loseMainPower() - A.shock(usr, 50- usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) + A.shock(usr, 50- usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(WIRE_BACKUP1, WIRE_BACKUP2) // Cut to lose backup power, repair all to gain backup power. if(mend && !is_cut(WIRE_BACKUP1) && !is_cut(WIRE_BACKUP2)) A.regainBackupPower() else A.loseBackupPower() - A.shock(usr, 50 - usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) + A.shock(usr, 50 - usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(WIRE_BOLTS) // Cut to engage bolts, mend does nothing. if(!mend) A.bolt() @@ -199,7 +199,7 @@ else if(A.secondsElectrified != MACHINE_ELECTRIFIED_PERMANENT) A.set_electrified(MACHINE_ELECTRIFIED_PERMANENT, usr) - A.shock(usr, 100 - usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) + A.shock(usr, 100 - usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(WIRE_SAFETY) // Cut to disable safeties, mend to re-enable. A.safe = mend if (!isnull(source)) @@ -212,7 +212,7 @@ A.lights = mend A.update_appearance() if(WIRE_ZAP1, WIRE_ZAP2) // Ouch. - A.shock(usr, 50 - usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) + A.shock(usr, 50 - usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(WIRE_UNRESTRICTED_EXIT) // If this wire is cut, the unrestricted helper goes away. If you mend it, it'll go "haywire" and pick a new direction at random. Might have to cut/mend a time or two to get the direction you want. if(!A.unres_sensor) //only works if the "sensor" is installed (a variable that we assign to the door either upon creation of a door with unrestricted directions, or if an unrestricted helper is added to a door in mapping) return diff --git a/code/datums/wires/apc.dm b/code/datums/wires/apc.dm index 9c2a1124d51d..f118f3b7c5fe 100644 --- a/code/datums/wires/apc.dm +++ b/code/datums/wires/apc.dm @@ -48,7 +48,7 @@ A.shorted = FALSE else A.shorted = TRUE - A.shock(usr, 50 - usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) + A.shock(usr, 50 - usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(WIRE_AI) // Disable AI control. A.aidisabled = !mend diff --git a/code/datums/wires/autolathe.dm b/code/datums/wires/autolathe.dm index 02dfdecd3497..bf30f790f703 100644 --- a/code/datums/wires/autolathe.dm +++ b/code/datums/wires/autolathe.dm @@ -47,4 +47,4 @@ if(WIRE_DISABLE) A.disabled = !mend if(WIRE_ZAP) - A.shock(usr, 50 - usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) + A.shock(usr, 50 - usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) diff --git a/code/datums/wires/roulette.dm b/code/datums/wires/roulette.dm index 5d1cbe91fd07..7a23fd0aef1a 100644 --- a/code/datums/wires/roulette.dm +++ b/code/datums/wires/roulette.dm @@ -33,7 +33,7 @@ var/obj/machinery/roulette/R = holder switch(wire) if(WIRE_SHOCK) - R.shock(usr, 50 - usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) + R.shock(usr, 50 - usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(WIRE_BOLTS) // Pulse to toggle bolts (but only raise if power is on). if(!R.on) return @@ -43,7 +43,7 @@ R.audible_message(span_warning("Owner reset!")) R.locked = FALSE if(WIRE_PRIZEVEND) - R.shock(usr, 70- usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) + R.shock(usr, 70- usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(R.locked) return R.audible_message(span_warning("Unauthorized prize vend detected! Locking down machine!")) @@ -53,7 +53,7 @@ var/obj/machinery/roulette/R = holder switch(wire) if(WIRE_SHOCK) - R.shock(usr, 60- usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) + R.shock(usr, 60- usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(mend) R.on = TRUE else @@ -63,9 +63,9 @@ return R.set_anchored(TRUE) if(WIRE_RESETOWNER) - R.shock(usr, 70- usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) + R.shock(usr, 70- usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(WIRE_PRIZEVEND) - R.shock(usr, 75- usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) + R.shock(usr, 75- usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(R.locked) return R.audible_message(span_warning("Unauthorized prize vend detected! Locking down machine!")) diff --git a/code/datums/wires/suit_storage_unit.dm b/code/datums/wires/suit_storage_unit.dm index c8dacabbd9c9..8f8e1a05e680 100644 --- a/code/datums/wires/suit_storage_unit.dm +++ b/code/datums/wires/suit_storage_unit.dm @@ -32,7 +32,7 @@ if(WIRE_SAFETY) SSU.safeties = !SSU.safeties if(WIRE_ZAP) - SSU.shock(usr, 100 - usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) + SSU.shock(usr, 100 - usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) /datum/wires/suit_storage_unit/on_cut(wire, mend, source) var/obj/machinery/suit_storage_unit/SSU = holder @@ -42,4 +42,4 @@ if(WIRE_SAFETY) SSU.safeties = mend if(WIRE_ZAP) - SSU.shock(usr, 100 - usr.mind?.get_skill_level(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) + SSU.shock(usr, 100 - usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) diff --git a/code/game/objects/items/shooting_range.dm b/code/game/objects/items/shooting_range.dm index ff08886e7d3e..151db84f84c8 100644 --- a/code/game/objects/items/shooting_range.dm +++ b/code/game/objects/items/shooting_range.dm @@ -21,11 +21,6 @@ . |= bullethole_overlays /obj/item/target/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit = FALSE) - if(prob(25)) - return ..() // RNG change to just not leave a mark, like walls - if(length(overlays) > 35) - return ..() // Too many bullets, we're done here - // Projectiles which do not deal damage will not leave dent / scorch mark graphics. // However we snowflake some projectiles to leave them anyway, because they're appropriate. var/static/list/always_leave_marks @@ -40,6 +35,11 @@ var/is_generic_projectile = !is_type_in_typecache(hitting_projectile, always_leave_marks) if(is_generic_projectile && (is_invalid_damage || is_safe)) return ..() // Don't bother unless it's real shit + hitting_projectile.award_firearms_exp(SKILL_LEVEL_JOURNEYMAN) + if(prob(25)) + return ..() // RNG change to just not leave a mark, like walls + if(length(overlays) > 35) + return ..() // Too many bullets, we're done here var/p_x = hitting_projectile.p_x + pick(0, 0, 0, 0, 0, -1, 1) // really ugly way of coding "sometimes offset p_x!" var/p_y = hitting_projectile.p_y + pick(0, 0, 0, 0, 0, -1, 1) diff --git a/code/modules/admin/skill_panel.dm b/code/modules/admin/skill_panel.dm index 79fdfcb78ad4..a3a2aa6b705c 100644 --- a/code/modules/admin/skill_panel.dm +++ b/code/modules/admin/skill_panel.dm @@ -22,18 +22,29 @@ /datum/skill_panel/ui_data(mob/user) //Sends info about the skills to UI . = list() - if(user?.mind) - for (var/type in GLOB.skill_types) - var/datum/skill/S = GetSkillRef(type) - var/lvl_num = targetmind.get_skill_level(type) - var/lvl_name = uppertext(targetmind.get_skill_level_name(type)) - var/exp = targetmind.get_skill_exp(type) - var/xp_prog_to_level = targetmind.exp_needed_to_level_up(type) - var/xp_req_to_level = 0 - if (xp_prog_to_level)//is it even possible to level up? - xp_req_to_level = SKILL_EXP_LIST[lvl_num+1] - SKILL_EXP_LIST[lvl_num] - var/exp_percent = exp / SKILL_EXP_LIST[SKILL_LEVEL_LEGENDARY] - .["skills"] += list(list("playername" = targetmind.current, "path" = type, "name" = S.name, "desc" = S.blurb, "lvlnum" = lvl_num, "lvl" = lvl_name, "exp" = exp, "exp_prog" = xp_req_to_level - xp_prog_to_level, "exp_req" = xp_req_to_level, "exp_percent" = exp_percent, "max_exp" = SKILL_EXP_LIST[length(SKILL_EXP_LIST)])) + for (var/type in GLOB.skill_types) + var/datum/skill/S = GetSkillRef(type) + var/lvl_num = targetmind.get_skill_level(type) + var/lvl_name = uppertext(targetmind.get_skill_level_name(type)) + var/exp = targetmind.get_skill_exp(type) + var/xp_prog_to_level = targetmind.exp_needed_to_level_up(type) + var/xp_req_to_level = 0 + if (xp_prog_to_level)//is it even possible to level up? + xp_req_to_level = SKILL_EXP_LIST[lvl_num+1] - SKILL_EXP_LIST[lvl_num] + var/exp_percent = exp / SKILL_EXP_LIST[SKILL_LEVEL_LEGENDARY] + .["skills"] += list(list( + "playername" = targetmind.current, + "path" = type, + "name" = S.name, + "desc" = S.blurb, + "lvlnum" = lvl_num, + "lvl" = lvl_name, + "exp" = exp, + "exp_prog" = xp_req_to_level - xp_prog_to_level, + "exp_req" = xp_req_to_level, + "exp_percent" = exp_percent, + "max_exp" = SKILL_EXP_LIST[length(SKILL_EXP_LIST)], + )) /datum/skill_panel/ui_act(action, params) . = ..() diff --git a/code/modules/admin/verbs/ert.dm b/code/modules/admin/verbs/ert.dm index 8b4c7e3c1b82..5448e5c1b5cb 100644 --- a/code/modules/admin/verbs/ert.dm +++ b/code/modules/admin/verbs/ert.dm @@ -243,6 +243,10 @@ ert_operative.mind.add_antag_datum(ert_antag,ert_team) ert_operative.mind.set_assigned_role(SSjob.GetJobType(ert_antag.ert_job_path)) + // future todo - tie to ert jobs, make ert jobs not one datum + ert_operative.mind.set_level(/datum/skill/firearms, SKILL_LEVEL_MASTER, silent = TRUE) + ert_operative.mind.set_level(/datum/skill/surgery, SKILL_LEVEL_MASTER, silent = TRUE) + ert_operative.mind.set_level(/datum/skill/first_aid, SKILL_LEVEL_MASTER, silent = TRUE) //Logging and cleanup ert_operative.log_message("has been selected as \a [ert_antag.name].", LOG_GAME) diff --git a/code/modules/bitrunning/job.dm b/code/modules/bitrunning/job.dm index 490654055027..1642fef4c34a 100644 --- a/code/modules/bitrunning/job.dm +++ b/code/modules/bitrunning/job.dm @@ -33,6 +33,7 @@ base_skills = list( /datum/skill/electronics = SKILL_LEVEL_NOVICE, + /datum/skill/gaming = SKILL_LEVEL_APPRENTICE, ) /datum/outfit/job/bitrunner diff --git a/code/modules/hydroponics/beekeeping/beebox.dm b/code/modules/hydroponics/beekeeping/beebox.dm index 6636fedd25ca..5df28f34dc49 100644 --- a/code/modules/hydroponics/beekeeping/beebox.dm +++ b/code/modules/hydroponics/beekeeping/beebox.dm @@ -13,14 +13,16 @@ /mob/living/carbon/human/bee_friendly() - if(dna && dna.species && dna.species.id == SPECIES_PODPERSON) //bees pollinate plants, duh. - return 1 - if (wear_suit && head && isclothing(wear_suit) && isclothing(head)) + if(ispodperson(src)) //bees pollinate plants, duh. + return TRUE + if(mind?.get_skill_level(/datum/skill/botany) >= SKILL_LEVEL_LEGENDARY) + return TRUE + if (isclothing(wear_suit) && isclothing(head)) var/obj/item/clothing/CS = wear_suit var/obj/item/clothing/CH = head if (CS.clothing_flags & CH.clothing_flags & THICKMATERIAL) - return 1 - return 0 + return TRUE + return FALSE /obj/structure/beebox diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm index 3642567e2b0f..eb688397e102 100644 --- a/code/modules/hydroponics/seeds.dm +++ b/code/modules/hydroponics/seeds.dm @@ -121,7 +121,8 @@ . += span_notice("- [reagent_gene.get_name()] -") /// Copy all the variables from one seed to a new instance of the same seed and return it. -/obj/item/seeds/proc/Copy() +/obj/item/seeds/proc/Copy() as /obj/item/seeds + RETURN_TYPE(/obj/item/seeds) var/obj/item/seeds/copy_seed = new type(null, TRUE) // Copy all the stats copy_seed.lifespan = lifespan @@ -247,8 +248,14 @@ return t_amount++ product_name = parent.myseed.plantname + if(product_count >= 1) SSblackbox.record_feedback("tally", "food_harvested", product_count, product_name) + user.mind?.adjust_experience(/datum/skill/botany, 2 * rarity * (yield / MAX_PLANT_YIELD) * (potency / MAX_PLANT_POTENCY)) + + else if(product_count == 0 && user.mind?.get_skill_level(/datum/skill/botany) >= SKILL_LEVEL_MASTER) + Copy().forceMove(output_loc) + parent.update_tray(user, product_count) return result diff --git a/code/modules/jobs/job_types/assistant/assistant.dm b/code/modules/jobs/job_types/assistant/assistant.dm index 89e837777020..50dd53d75741 100644 --- a/code/modules/jobs/job_types/assistant/assistant.dm +++ b/code/modules/jobs/job_types/assistant/assistant.dm @@ -37,6 +37,12 @@ Assistant rpg_title = "Lout" config_tag = "ASSISTANT" + base_skills = list( + /datum/skill/electronics = SKILL_LEVEL_NOVICE, + /datum/skill/mechanics = SKILL_LEVEL_NOVICE, + /datum/skill/botany = SKILL_LEVEL_NOVICE, + ) + /datum/job/assistant/get_outfit(consistent) if(consistent) return /datum/outfit/job/assistant/always_grey diff --git a/code/modules/jobs/job_types/atmospheric_technician.dm b/code/modules/jobs/job_types/atmospheric_technician.dm index 2260a388453a..9f80a4d8e2e7 100644 --- a/code/modules/jobs/job_types/atmospheric_technician.dm +++ b/code/modules/jobs/job_types/atmospheric_technician.dm @@ -40,6 +40,7 @@ base_skills = list( /datum/skill/electronics = SKILL_LEVEL_NOVICE, + /datum/skill/mechanics = SKILL_LEVEL_EXPERT, ) /datum/outfit/job/atmos diff --git a/code/modules/jobs/job_types/bartender.dm b/code/modules/jobs/job_types/bartender.dm index 13a4162ff3be..da70cbfc64ee 100644 --- a/code/modules/jobs/job_types/bartender.dm +++ b/code/modules/jobs/job_types/bartender.dm @@ -32,6 +32,10 @@ job_flags = STATION_JOB_FLAGS rpg_title = "Tavernkeeper" + base_skills = list( + /datum/skill/firearms = SKILL_LEVEL_JOURNEYMAN, + ) + /datum/job/bartender/award_service(client/winner, award) winner.give_award(award, winner.mob) diff --git a/code/modules/jobs/job_types/botanist.dm b/code/modules/jobs/job_types/botanist.dm index 7ccc4b31ceb7..8e6907a16812 100644 --- a/code/modules/jobs/job_types/botanist.dm +++ b/code/modules/jobs/job_types/botanist.dm @@ -39,6 +39,10 @@ job_flags = STATION_JOB_FLAGS rpg_title = "Gardener" + base_skills = list( + /datum/skill/botany = SKILL_LEVEL_EXPERT, + ) + /datum/outfit/job/botanist name = "Botanist" jobtype = /datum/job/botanist diff --git a/code/modules/jobs/job_types/captain.dm b/code/modules/jobs/job_types/captain.dm index 13e358bdcd52..5acb5134e1d8 100644 --- a/code/modules/jobs/job_types/captain.dm +++ b/code/modules/jobs/job_types/captain.dm @@ -48,6 +48,10 @@ voice_of_god_power = 1.4 //Command staff has authority + base_skills = list( + /datum/skill/firearms = SKILL_LEVEL_MASTER, + /datum/skill/first_aid = SKILL_LEVEL_NOVICE, + ) /datum/job/captain/get_captaincy_announcement(mob/living/captain) return "Captain [captain.real_name] on deck!" diff --git a/code/modules/jobs/job_types/cargo_technician.dm b/code/modules/jobs/job_types/cargo_technician.dm index 8b2a0c09eac0..672a7c02ae88 100644 --- a/code/modules/jobs/job_types/cargo_technician.dm +++ b/code/modules/jobs/job_types/cargo_technician.dm @@ -37,6 +37,8 @@ base_skills = list( /datum/skill/electronics = SKILL_LEVEL_NOVICE, + /datum/skill/firearms = SKILL_LEVEL_NOVICE, + /datum/skill/mechanics = SKILL_LEVEL_NOVICE, ) /datum/outfit/job/cargo_tech diff --git a/code/modules/jobs/job_types/chaplain/chaplain.dm b/code/modules/jobs/job_types/chaplain/chaplain.dm index 58821ec53587..2b5df95ee419 100644 --- a/code/modules/jobs/job_types/chaplain/chaplain.dm +++ b/code/modules/jobs/job_types/chaplain/chaplain.dm @@ -36,6 +36,12 @@ job_tone = "holy" + base_skills = list( + /datum/skill/firearms = SKILL_LEVEL_APPRENTICE, // chaplain gun + /datum/skill/first_aid = SKILL_LEVEL_APPRENTICE, + /datum/skill/cybernetics = SKILL_LEVEL_APPRENTICE, // robot sect + /datum/skill/botany = SKILL_LEVEL_APPRENTICE, + ) /datum/job/chaplain/after_spawn(mob/living/spawned, client/player_client) . = ..() diff --git a/code/modules/jobs/job_types/chemist.dm b/code/modules/jobs/job_types/chemist.dm index 23140c374620..d6a26bb67c06 100644 --- a/code/modules/jobs/job_types/chemist.dm +++ b/code/modules/jobs/job_types/chemist.dm @@ -39,6 +39,7 @@ base_skills = list( /datum/skill/surgery = SKILL_LEVEL_NOVICE, + /datum/skill/first_aid = SKILL_LEVEL_NOVICE, ) /datum/outfit/job/chemist diff --git a/code/modules/jobs/job_types/chief_engineer.dm b/code/modules/jobs/job_types/chief_engineer.dm index ed396cf7344a..19e6efbe0642 100644 --- a/code/modules/jobs/job_types/chief_engineer.dm +++ b/code/modules/jobs/job_types/chief_engineer.dm @@ -50,6 +50,8 @@ base_skills = list( /datum/skill/electronics = SKILL_LEVEL_MASTER, + /datum/skill/mechanics = SKILL_LEVEL_MASTER, + /datum/skill/firearms = SKILL_LEVEL_NOVICE, ) /datum/job/chief_engineer/after_spawn(mob/living/spawned, client/player_client) diff --git a/code/modules/jobs/job_types/chief_medical_officer.dm b/code/modules/jobs/job_types/chief_medical_officer.dm index 6c6b79f49733..c0e5e0cc2d19 100644 --- a/code/modules/jobs/job_types/chief_medical_officer.dm +++ b/code/modules/jobs/job_types/chief_medical_officer.dm @@ -46,6 +46,10 @@ voice_of_god_power = 1.4 //Command staff has authority base_skills = list( + /datum/skill/cleaning = SKILL_LEVEL_NOVICE, + /datum/skill/cybernetics = SKILL_LEVEL_EXPERT, + /datum/skill/firearms = SKILL_LEVEL_NOVICE, + /datum/skill/first_aid = SKILL_LEVEL_MASTER, /datum/skill/surgery = SKILL_LEVEL_MASTER, ) diff --git a/code/modules/jobs/job_types/cook.dm b/code/modules/jobs/job_types/cook.dm index e96bae827fa9..8bc51cc67e80 100644 --- a/code/modules/jobs/job_types/cook.dm +++ b/code/modules/jobs/job_types/cook.dm @@ -48,6 +48,10 @@ rpg_title = "Tavern Chef" job_flags = STATION_JOB_FLAGS + base_skills = list( + /datum/skill/botany = SKILL_LEVEL_JOURNEYMAN, + ) + /datum/job/cook/award_service(client/winner, award) winner.give_award(award, winner.mob) diff --git a/code/modules/jobs/job_types/coroner.dm b/code/modules/jobs/job_types/coroner.dm index 5129f5225aad..1de20b2d5b74 100644 --- a/code/modules/jobs/job_types/coroner.dm +++ b/code/modules/jobs/job_types/coroner.dm @@ -45,6 +45,7 @@ base_skills = list( /datum/skill/surgery = SKILL_LEVEL_JOURNEYMAN, + /datum/skill/first_aid = SKILL_LEVEL_NOVICE, ) /datum/outfit/job/coroner diff --git a/code/modules/jobs/job_types/detective.dm b/code/modules/jobs/job_types/detective.dm index b6984e24b422..61499eae6130 100644 --- a/code/modules/jobs/job_types/detective.dm +++ b/code/modules/jobs/job_types/detective.dm @@ -44,6 +44,10 @@ job_tone = "objection" + base_skills = list( + /datum/skill/firearms = SKILL_LEVEL_EXPERT, + /datum/skill/first_aid = SKILL_LEVEL_NOVICE, + ) /datum/outfit/job/detective name = "Detective" diff --git a/code/modules/jobs/job_types/head_of_personnel.dm b/code/modules/jobs/job_types/head_of_personnel.dm index e863a782d9b0..3684e2f27ffd 100644 --- a/code/modules/jobs/job_types/head_of_personnel.dm +++ b/code/modules/jobs/job_types/head_of_personnel.dm @@ -43,6 +43,9 @@ job_flags = STATION_JOB_FLAGS | HEAD_OF_STAFF_JOB_FLAGS voice_of_god_power = 1.4 //Command staff has authority + base_skills = list( + /datum/skill/firearms = SKILL_LEVEL_APPRENTICE, + ) /datum/job/head_of_personnel/get_captaincy_announcement(mob/living/captain) return "Due to staffing shortages, newly promoted Acting Captain [captain.real_name] on deck!" diff --git a/code/modules/jobs/job_types/head_of_security.dm b/code/modules/jobs/job_types/head_of_security.dm index 999117dc1be1..d7cff8c19ccd 100644 --- a/code/modules/jobs/job_types/head_of_security.dm +++ b/code/modules/jobs/job_types/head_of_security.dm @@ -39,6 +39,10 @@ voice_of_god_power = 1.4 //Command staff has authority + base_skills = list( + /datum/skill/firearms = SKILL_LEVEL_MASTER, + /datum/skill/first_aid = SKILL_LEVEL_JOURNEYMAN, + ) /datum/job/head_of_security/get_captaincy_announcement(mob/living/captain) return "Due to staffing shortages, newly promoted Acting Captain [captain.real_name] on deck!" diff --git a/code/modules/jobs/job_types/janitor.dm b/code/modules/jobs/job_types/janitor.dm index 102092fb37ac..f2a9dd68e45d 100644 --- a/code/modules/jobs/job_types/janitor.dm +++ b/code/modules/jobs/job_types/janitor.dm @@ -34,6 +34,7 @@ base_skills = list( /datum/skill/cleaning = SKILL_LEVEL_NOVICE, // i'd make this higher, but i think grinding cleaning skill IS janitor's gameplay + /datum/skill/firearms = SKILL_LEVEL_APPRENTICE, // garbage day ) /datum/outfit/job/janitor diff --git a/code/modules/jobs/job_types/medical_doctor.dm b/code/modules/jobs/job_types/medical_doctor.dm index 80bbaa9d39d0..c8a192edfcbe 100644 --- a/code/modules/jobs/job_types/medical_doctor.dm +++ b/code/modules/jobs/job_types/medical_doctor.dm @@ -39,6 +39,9 @@ job_flags = STATION_JOB_FLAGS base_skills = list( + /datum/skill/cleaning = SKILL_LEVEL_NOVICE, + /datum/skill/cybernetics = SKILL_LEVEL_JOURNEYMAN, + /datum/skill/first_aid = SKILL_LEVEL_EXPERT, /datum/skill/surgery = SKILL_LEVEL_EXPERT, ) diff --git a/code/modules/jobs/job_types/paramedic.dm b/code/modules/jobs/job_types/paramedic.dm index 02694a1ed17f..4d358e409a2c 100644 --- a/code/modules/jobs/job_types/paramedic.dm +++ b/code/modules/jobs/job_types/paramedic.dm @@ -40,6 +40,7 @@ base_skills = list( /datum/skill/surgery = SKILL_LEVEL_APPRENTICE, + /datum/skill/first_aid = SKILL_LEVEL_EXPERT, ) /datum/outfit/job/paramedic diff --git a/code/modules/jobs/job_types/prisoner.dm b/code/modules/jobs/job_types/prisoner.dm index fd6f0f939d68..037bcc4df817 100644 --- a/code/modules/jobs/job_types/prisoner.dm +++ b/code/modules/jobs/job_types/prisoner.dm @@ -25,6 +25,10 @@ rpg_title = "Defeated Miniboss" job_flags = STATION_JOB_FLAGS | JOB_CANNOT_OPEN_SLOTS & ~JOB_REOPEN_ON_ROUNDSTART_LOSS + base_skills = list( + /datum/skill/botany = SKILL_LEVEL_NOVICE, + ) + /datum/job/prisoner/New() . = ..() RegisterSignal(SSdcs, COMSIG_GLOB_CREWMEMBER_JOINED, PROC_REF(handle_prisoner_joining)) diff --git a/code/modules/jobs/job_types/quartermaster.dm b/code/modules/jobs/job_types/quartermaster.dm index 858ce8b64553..16f479b7e154 100644 --- a/code/modules/jobs/job_types/quartermaster.dm +++ b/code/modules/jobs/job_types/quartermaster.dm @@ -38,6 +38,10 @@ voice_of_god_power = 1.4 //Command staff has authority ignore_human_authority = TRUE + base_skills = list( + /datum/skill/firearms = SKILL_LEVEL_APPRENTICE, + ) + /datum/outfit/job/quartermaster name = "Quartermaster" jobtype = /datum/job/quartermaster diff --git a/code/modules/jobs/job_types/research_director.dm b/code/modules/jobs/job_types/research_director.dm index fc88c6c1573e..679cfb9ec02b 100644 --- a/code/modules/jobs/job_types/research_director.dm +++ b/code/modules/jobs/job_types/research_director.dm @@ -47,8 +47,12 @@ voice_of_god_power = 1.4 //Command staff has authority base_skills = list( + /datum/skill/cybernetics = SKILL_LEVEL_MASTER, /datum/skill/electronics = SKILL_LEVEL_JOURNEYMAN, + /datum/skill/firearms = SKILL_LEVEL_NOVICE, + /datum/skill/robotics = SKILL_LEVEL_EXPERT, /datum/skill/surgery = SKILL_LEVEL_JOURNEYMAN, + /datum/skill/mechanics = SKILL_LEVEL_NOVICE, ) /datum/job/research_director/get_captaincy_announcement(mob/living/captain) diff --git a/code/modules/jobs/job_types/roboticist.dm b/code/modules/jobs/job_types/roboticist.dm index f009c137e77b..bb8376a4eaa3 100644 --- a/code/modules/jobs/job_types/roboticist.dm +++ b/code/modules/jobs/job_types/roboticist.dm @@ -34,8 +34,11 @@ job_flags = STATION_JOB_FLAGS base_skills = list( + /datum/skill/cybernetics = SKILL_LEVEL_EXPERT, /datum/skill/electronics = SKILL_LEVEL_JOURNEYMAN, + /datum/skill/robotics = SKILL_LEVEL_EXPERT, /datum/skill/surgery = SKILL_LEVEL_JOURNEYMAN, + /datum/skill/mechanics = SKILL_LEVEL_NOVICE, ) /datum/job/roboticist/New() diff --git a/code/modules/jobs/job_types/scientist.dm b/code/modules/jobs/job_types/scientist.dm index c1c5aedd1d64..079ba155419b 100644 --- a/code/modules/jobs/job_types/scientist.dm +++ b/code/modules/jobs/job_types/scientist.dm @@ -38,6 +38,7 @@ base_skills = list( /datum/skill/surgery = SKILL_LEVEL_NOVICE, + /datum/skill/mechanics = SKILL_LEVEL_APPRENTICE, ) /datum/outfit/job/scientist diff --git a/code/modules/jobs/job_types/security_officer.dm b/code/modules/jobs/job_types/security_officer.dm index 25d76bf0156d..750fa9318d58 100644 --- a/code/modules/jobs/job_types/security_officer.dm +++ b/code/modules/jobs/job_types/security_officer.dm @@ -40,6 +40,10 @@ rpg_title = "Guard" job_flags = STATION_JOB_FLAGS + base_skills = list( + /datum/skill/firearms = SKILL_LEVEL_JOURNEYMAN, + /datum/skill/first_aid = SKILL_LEVEL_NOVICE, + ) GLOBAL_LIST_INIT(available_depts, list(SEC_DEPT_ENGINEERING, SEC_DEPT_MEDICAL, SEC_DEPT_SCIENCE, SEC_DEPT_SUPPLY)) diff --git a/code/modules/jobs/job_types/shaft_miner.dm b/code/modules/jobs/job_types/shaft_miner.dm index 5216b37af2e4..170e2423dc88 100644 --- a/code/modules/jobs/job_types/shaft_miner.dm +++ b/code/modules/jobs/job_types/shaft_miner.dm @@ -29,6 +29,8 @@ job_flags = STATION_JOB_FLAGS base_skills = list( + /datum/skill/firearms = SKILL_LEVEL_APPRENTICE, + /datum/skill/first_aid = SKILL_LEVEL_NOVICE, /datum/skill/mining = SKILL_LEVEL_NOVICE, // i'd make this higher, but i think grinding mining skill IS mining's gameplay ) diff --git a/code/modules/jobs/job_types/station_engineer.dm b/code/modules/jobs/job_types/station_engineer.dm index acc8c406941e..cba23757b86a 100644 --- a/code/modules/jobs/job_types/station_engineer.dm +++ b/code/modules/jobs/job_types/station_engineer.dm @@ -40,6 +40,7 @@ base_skills = list( /datum/skill/electronics = SKILL_LEVEL_EXPERT, + /datum/skill/mechanics = SKILL_LEVEL_EXPERT, ) /datum/outfit/job/engineer diff --git a/code/modules/jobs/job_types/station_trait/bridge_assistant.dm b/code/modules/jobs/job_types/station_trait/bridge_assistant.dm index b1ae57de1ffe..b93ae511ba66 100644 --- a/code/modules/jobs/job_types/station_trait/bridge_assistant.dm +++ b/code/modules/jobs/job_types/station_trait/bridge_assistant.dm @@ -35,6 +35,11 @@ job_flags = STATION_JOB_FLAGS | STATION_TRAIT_JOB_FLAGS ignore_human_authority = TRUE + base_skills = list( + /datum/skill/firearms = SKILL_LEVEL_NOVICE, + /datum/skill/first_aid = SKILL_LEVEL_NOVICE, + ) + /datum/job/bridge_assistant/after_spawn(mob/living/spawned, client/player_client) . = ..() ADD_TRAIT(spawned, TRAIT_NO_TWOHANDING, JOB_TRAIT) diff --git a/code/modules/jobs/job_types/virologist.dm b/code/modules/jobs/job_types/virologist.dm index 6aa1410c2670..5c3f44059f36 100644 --- a/code/modules/jobs/job_types/virologist.dm +++ b/code/modules/jobs/job_types/virologist.dm @@ -39,7 +39,9 @@ job_flags = STATION_JOB_FLAGS base_skills = list( + /datum/skill/cleaning = SKILL_LEVEL_NOVICE, /datum/skill/surgery = SKILL_LEVEL_APPRENTICE, + /datum/skill/first_aid = SKILL_LEVEL_NOVICE, ) /datum/outfit/job/virologist diff --git a/code/modules/jobs/job_types/warden.dm b/code/modules/jobs/job_types/warden.dm index 643611201c8c..7a43bca06a2f 100644 --- a/code/modules/jobs/job_types/warden.dm +++ b/code/modules/jobs/job_types/warden.dm @@ -42,6 +42,11 @@ rpg_title = "Jailor" job_flags = STATION_JOB_FLAGS | JOB_BOLD_SELECT_TEXT + base_skills = list( + /datum/skill/firearms = SKILL_LEVEL_EXPERT, + /datum/skill/first_aid = SKILL_LEVEL_APPRENTICE, + ) + /datum/outfit/job/warden name = "Warden" jobtype = /datum/job/warden diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 92ecda67f82b..979ea55e69ae 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -105,6 +105,7 @@ if(!hitting_projectile.is_hostile_projectile()) return BULLET_ACT_HIT + hitting_projectile.award_firearms_exp(isnull(mind) ? SKILL_LEVEL_JOURNEYMAN : SKILL_LEVEL_LEGENDARY) // we need a second, silent armor check to actually know how much to reduce damage taken, as opposed to // on [/atom/proc/bullet_act] where it's just to pass it to the projectile's on_hit(). var/armor_check = check_projectile_armor(def_zone, hitting_projectile, is_silent = TRUE) diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index bb6c0ab512d1..c7f4a224671e 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -1186,3 +1186,25 @@ bullet.preparePixelProjectile(target, src) bullet.fire() return bullet + +/// Awards firearms XP to the firer of a projectile. +/// +/// * max_skill_level - If the firer's skill level is beyond this, no XP is awarded (equal is fine) +/obj/projectile/proc/award_firearms_exp(max_skill_level = SKILL_LEVEL_LEGENDARY) + if(!isliving(firer)) + return + var/mob/living/firer_mob = firer + if(isnull(firer_mob.mind) || firer_mob.mind.get_skill_level(/datum/skill/firearms) > max_skill_level) + return + var/xp_gain = 0 + if(istype(fired_from, /obj/item/gun/energy)) + var/obj/item/gun/energy/lasgun = fired_from + var/obj/item/ammo_casing/energy/lasgun_ammo = lasgun.ammo_type[lasgun.select] + xp_gain = istype(lasgun_ammo) ? clamp(lasgun_ammo.e_cost * 0.34, 0, 100) : 30 + else if(istype(fired_from, /obj/item/gun/ballistic)) + var/obj/item/gun/ballistic/balgun = fired_from + xp_gain = clamp(200 / (balgun.magazine?.max_ammo || 10), 0, 100) + if(xp_gain <= 0) + return + // closer hits give less xp, encourage actually aiming and not standing right by the target + firer_mob.mind.adjust_experience(/datum/skill/firearms, xp_gain * clamp(get_dist(firer, src) / 10, 0.2, 1.2)) diff --git a/code/modules/surgery/prosthetic_replacement.dm b/code/modules/surgery/prosthetic_replacement.dm index 8515ddd94aaa..68ee6df451fe 100644 --- a/code/modules/surgery/prosthetic_replacement.dm +++ b/code/modules/surgery/prosthetic_replacement.dm @@ -108,6 +108,9 @@ span_notice("[user] successfully replaces [target]'s [parse_zone(target_zone)]!"), ) display_pain(target, "You feel synthetic sensation wash from your [parse_zone(target_zone)], which you can feel again!", TRUE, target_zone = target_zone) // NON-MODULE CHANGE + target.cause_pain(bodypart_to_attach.body_zone, -1 * user.mind?.get_skill_modifier(/datum/skill/cybernetics, SKILL_VALUE_MODIFIER)) + if(IS_ROBOTIC_LIMB(bodypart_to_attach)) + user.mind?.adjust_experience(/datum/skill/cybernetics, 100) return else var/obj/item/bodypart/bodypart_to_attach = target.newBodyPart(target_zone, FALSE, FALSE) @@ -122,6 +125,7 @@ span_notice("[user] finishes the attachment procedure!"), ) display_pain(target, "You feel a strange sensation from your new [parse_zone(target_zone)].", TRUE, target_zone = target_zone) // NON-MODULE CHANGE + user.mind?.adjust_experience(/datum/skill/cybernetics, 200) if(istype(tool, /obj/item/chainsaw)) qdel(tool) var/obj/item/chainsaw/mounted_chainsaw/new_arm = new(target) diff --git a/code/modules/surgery/surgery_step.dm b/code/modules/surgery/surgery_step.dm index 6b1aa0be53bd..47b64263dd9b 100644 --- a/code/modules/surgery/surgery_step.dm +++ b/code/modules/surgery/surgery_step.dm @@ -117,8 +117,8 @@ if((prob(100-fail_prob) || (iscyborg(user) && !silicons_obey_prob)) && chem_check_result && !try_to_fail) if(success(user, target, target_zone, tool, surgery)) - if(target.mind && !iscyborg(user)) // by default, you only gain surgery xp for operating on players. no monkey grinding - user.mind?.adjust_experience(/datum/skill/surgery, time * 0.5) // 1 xp per 2 second of surgery - 50 xp for brain surgery + if(user.mind && (target.mind || user.mind.get_skill_level(/datum/skill/surgery) <= SKILL_LEVEL_NOVICE) && !iscyborg(user)) // by default, you only gain surgery xp for operating on players. no monkey grinding + user.mind.adjust_experience(/datum/skill/surgery, time * 0.5) // 1 xp per 2 second of surgery - 50 xp for brain surgery play_success_sound(user, target, target_zone, tool, surgery) advance = TRUE else diff --git a/maplestation.dme b/maplestation.dme index 0b91880a1a96..e06302fed26e 100644 --- a/maplestation.dme +++ b/maplestation.dme @@ -1734,11 +1734,17 @@ #include "code\datums\shuttles\whiteship.dm" #include "code\datums\skills\_skill.dm" #include "code\datums\skills\cleaning.dm" +#include "code\datums\skills\cybernetic.dm" #include "code\datums\skills\electrics.dm" +#include "code\datums\skills\firearms.dm" #include "code\datums\skills\fishing.dm" #include "code\datums\skills\fitness.dm" #include "code\datums\skills\gaming.dm" +#include "code\datums\skills\hydroponics.dm" +#include "code\datums\skills\mechanics.dm" +#include "code\datums\skills\medical.dm" #include "code\datums\skills\mining.dm" +#include "code\datums\skills\robotics.dm" #include "code\datums\skills\surgery.dm" #include "code\datums\station_traits\_station_trait.dm" #include "code\datums\station_traits\admin_panel.dm" diff --git a/maplestation_modules/code/__DEFINES/_module_defines.dm b/maplestation_modules/code/__DEFINES/_module_defines.dm index 34266b33578b..4fb2560091e2 100644 --- a/maplestation_modules/code/__DEFINES/_module_defines.dm +++ b/maplestation_modules/code/__DEFINES/_module_defines.dm @@ -14,8 +14,6 @@ /// Essentially a buffed version of TRAIT_VIRUS_RESISTANCE, but not as strong as TRAIT_VIRUS_IMMUNE. /// Outright prevents contraction of disease, but if you do get sick, you're not immune to it. #define TRAIT_VIRUS_CONTACT_IMMUNE "virus_contact_immune" -/// Does not harm patients when undergoing CPR -#define TRAIT_CPR_CERTIFIED "cpr_certified" /// Defines for speech sounds #define SOUND_NORMAL "normal" diff --git a/maplestation_modules/code/modules/mob/living/carbon/human/heart_rework/cpr.dm b/maplestation_modules/code/modules/mob/living/carbon/human/heart_rework/cpr.dm index 712a4a649532..6674315daf0c 100644 --- a/maplestation_modules/code/modules/mob/living/carbon/human/heart_rework/cpr.dm +++ b/maplestation_modules/code/modules/mob/living/carbon/human/heart_rework/cpr.dm @@ -22,7 +22,7 @@ to_chat(src, span_warning("[target.name] is dead!")) return - var/cpr_certified = HAS_TRAIT(src, TRAIT_CPR_CERTIFIED) + var/cpr_certified = HAS_MIND_TRAIT(src, TRAIT_CPR_CERTIFIED) if(!panicking && target.stat != CONSCIOUS && beat >= BEATS_PER_CPR_CYCLE + 1) to_chat(src, span_warning("[target] still isn't up[cpr_certified ? " - you pick up the pace." : "! You try harder!"]")) panicking = TRUE diff --git a/tgui/packages/tgui/interfaces/NtosSkillTracker.tsx b/tgui/packages/tgui/interfaces/NtosSkillTracker.tsx index fe7bf12bf22c..448251def4a5 100644 --- a/tgui/packages/tgui/interfaces/NtosSkillTracker.tsx +++ b/tgui/packages/tgui/interfaces/NtosSkillTracker.tsx @@ -35,94 +35,98 @@ export const NtosSkillTracker = () => {
- {skills.map((skill, idx) => ( -
-
- {skill.blurb} -
- {!!skill.earned_by && ( + {skills + .sort((a, b) => (a.name > b.name ? 1 : -1)) + .map((skill, idx) => ( +
- {'>'} Earned by {skill.earned_by}. + {skill.blurb}
- )} - {!!skill.grants_you && ( -
- {'>'} Grants you {skill.grants_you}. -
- )} - {!!skill.higher_levels_grant_you && ( -
- {'>'} At higher levels, you gain{' '} - {skill.higher_levels_grant_you}. -
- )} -
-
- - - Level - - Level Progress - Overall Progress - - - - {skill.lvl_name} - - - {skill.progress_percent ? ( - - - % - - ) : ( - '—' - )} - - - {skill.overall_percent ? ( - - - % - - ) : ( - '—' - )} - - - {!!skill.reward && ( + {!!skill.earned_by && ( +
+ {'>'} Earned by {skill.earned_by}. +
+ )} + {!!skill.grants_you && ( +
+ {'>'} Grants you {skill.grants_you}. +
+ )} + {!!skill.higher_levels_grant_you && ( +
+ {'>'} At higher levels, you gain{' '} + {skill.higher_levels_grant_you}. +
+ )} +
+
+ + + Level + + Level Progress + + Overall Progress + + - - + + {skill.lvl_name} + + + {skill.progress_percent ? ( + + + % + + ) : ( + '—' + )} + + + {skill.overall_percent ? ( + + + % + + ) : ( + '—' + )} - )} -
+ {!!skill.reward && ( + + + + + + )} + +
-
- ))} + ))}
From 2286948e36b593b82726da76398f09ac34cef572 Mon Sep 17 00:00:00 2001 From: MrMelbert Date: Thu, 13 Feb 2025 12:27:56 -0600 Subject: [PATCH 03/22] Update --- code/game/objects/items/stacks/medical.dm | 7 ++++--- maplestation_modules/code/datums/pain/pain.dm | 5 +++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index af4f194fec2b..b4b67cf07dac 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -95,7 +95,7 @@ ) if(!do_after( user, - self_delay, + self_delay * (user.mind?.get_skill_modifier(/datum/skill/first_aid, SKILL_SPEED_MODIFIER) || 1), patient, extra_checks = CALLBACK(src, PROC_REF(can_heal), patient, user), )) @@ -109,7 +109,7 @@ ) if(!do_after( user, - other_delay, + other_delay * (user.mind?.get_skill_modifier(/datum/skill/first_aid, SKILL_SPEED_MODIFIER) || 1), patient, extra_checks = CALLBACK(src, PROC_REF(can_heal), patient, user), )) @@ -126,6 +126,7 @@ else CRASH("Stack medical item healing a non-carbon, non-animal mob [patient] ([patient.type])") + user.mind?.adjust_experience(/datum/skill/first_aid, 50) log_combat(user, patient, "healed", name) if(!use(1) || !repeating || amount <= 0) return @@ -309,7 +310,7 @@ if(!try_heal_checks(patient, user, 0, 0)) return - var/treatment_delay = (user == patient ? self_delay : other_delay) + var/treatment_delay = (user == patient ? self_delay : other_delay) * (user.mind?.get_skill_modifier(/datum/skill/first_aid, SKILL_SPEED_MODIFIER) || 1) var/obj/item/bodypart/limb = patient.get_bodypart(check_zone(user.zone_selected)) var/boosted = FALSE diff --git a/maplestation_modules/code/datums/pain/pain.dm b/maplestation_modules/code/datums/pain/pain.dm index 11a992b7ffc7..25cc5106327f 100644 --- a/maplestation_modules/code/datums/pain/pain.dm +++ b/maplestation_modules/code/datums/pain/pain.dm @@ -638,6 +638,11 @@ penalty += chest.get_modified_pain() * 0.5 penalty += head?.get_modified_pain() * 0.5 // HARS guard penalty /= 3 + // Factor in firearms skill + if(penalty > 0) + penalty += user.mind?.get_skill_modifier(/datum/skill/firearms, SKILL_RANDS_MODIFIER) + if(penalty <= 0) + return // Applying min and max bonus_spread_values[MIN_BONUS_SPREAD_INDEX] += floor(penalty / 3) bonus_spread_values[MAX_BONUS_SPREAD_INDEX] += floor(penalty) From 4f9c30c90ba05f4c0e74eebc53c4aad761e5980d Mon Sep 17 00:00:00 2001 From: MrMelbert Date: Wed, 26 Mar 2025 14:52:14 -0500 Subject: [PATCH 04/22] Docs --- code/__DEFINES/skills.dm | 3 +++ code/datums/mind/skills.dm | 2 +- code/datums/skills/_skill.dm | 5 ++--- code/datums/skills/cleaning.dm | 2 +- code/datums/skills/cybernetic.dm | 2 +- code/datums/skills/electrics.dm | 2 +- code/datums/skills/firearms.dm | 2 +- code/datums/skills/hydroponics.dm | 2 +- code/datums/skills/mechanics.dm | 2 +- code/datums/skills/medical.dm | 2 +- code/datums/skills/mining.dm | 2 +- code/datums/skills/robotics.dm | 2 +- code/datums/skills/surgery.dm | 2 +- code/datums/wires/airalarm.dm | 1 + code/datums/wires/airlock.dm | 4 ++++ code/datums/wires/apc.dm | 1 + code/datums/wires/autolathe.dm | 1 + code/datums/wires/roulette.dm | 5 +++++ code/datums/wires/suit_storage_unit.dm | 2 ++ code/datums/wires/vending.dm | 1 + code/game/objects/items.dm | 1 + code/game/objects/items/stacks/medical.dm | 3 +++ code/modules/power/cable.dm | 3 +++ code/modules/surgery/autopsy.dm | 1 + code/modules/surgery/prosthetic_replacement.dm | 1 + code/modules/surgery/surgery_step.dm | 3 +++ 26 files changed, 43 insertions(+), 14 deletions(-) diff --git a/code/__DEFINES/skills.dm b/code/__DEFINES/skills.dm index d00eb55eb868..b3ff2ceea597 100644 --- a/code/__DEFINES/skills.dm +++ b/code/__DEFINES/skills.dm @@ -49,3 +49,6 @@ //while using the SKILLCHIP_RESTRICTED_CATEGORIES flag /// General related skillchip category #define SKILLCHIP_CATEGORY_GENERAL "general" + +/// Always print this skill in print_skills +#define SKILL_ALWAYS_PRINT (1<<0) diff --git a/code/datums/mind/skills.dm b/code/datums/mind/skills.dm index d83a35b6d327..ad5eb34f9206 100644 --- a/code/datums/mind/skills.dm +++ b/code/datums/mind/skills.dm @@ -73,7 +73,7 @@ /datum/mind/proc/print_levels(user) var/list/shown_skills = list() for(var/datum/skill/known_skill as anything in known_skills) - if(initial(known_skill.innate_skill) || known_skills[known_skill][SKILL_LVL] > SKILL_LEVEL_NONE) //Do we actually have a level in this? + if((initial(known_skill.skill_flags) & SKILL_ALWAYS_PRINT) || known_skills[known_skill][SKILL_LVL] > SKILL_LEVEL_NONE) //Do we actually have a level in this? shown_skills += known_skill if(!length(shown_skills)) to_chat(user, span_notice("You don't seem to have any particularly outstanding skills.")) diff --git a/code/datums/skills/_skill.dm b/code/datums/skills/_skill.dm index 61ed162ebcf0..d5a2124e8bd1 100644 --- a/code/datums/skills/_skill.dm +++ b/code/datums/skills/_skill.dm @@ -25,9 +25,8 @@ GLOBAL_LIST_INIT(skill_types, subtypesof(/datum/skill)) SKILL_LEVEL_LEGENDARY = 1, ), ) - /// If TRUE, this skill is considered to be core or innate - /// This means the skill will always be visible to the user, even if at level 0 - var/innate_skill = FALSE + /// Flags relating to this skill + var/skill_flags = NONE /// Typepath of skill item reward that will appear when a user finishes leveling up a skill var/skill_item_path /// List associating different messages that appear on level up with different levels diff --git a/code/datums/skills/cleaning.dm b/code/datums/skills/cleaning.dm index bd47bee1a9cc..752a832d95da 100644 --- a/code/datums/skills/cleaning.dm +++ b/code/datums/skills/cleaning.dm @@ -17,4 +17,4 @@ ), ) skill_item_path = /obj/item/clothing/neck/cloak/skill_reward/cleaning - innate_skill = TRUE + skill_flags = SKILL_ALWAYS_PRINT diff --git a/code/datums/skills/cybernetic.dm b/code/datums/skills/cybernetic.dm index 710ff029aacb..5d07ad200f27 100644 --- a/code/datums/skills/cybernetic.dm +++ b/code/datums/skills/cybernetic.dm @@ -16,4 +16,4 @@ SKILL_LEVEL_LEGENDARY = 50, ), ) - innate_skill = TRUE + skill_flags = SKILL_ALWAYS_PRINT diff --git a/code/datums/skills/electrics.dm b/code/datums/skills/electrics.dm index 042d66636a86..b5564193725f 100644 --- a/code/datums/skills/electrics.dm +++ b/code/datums/skills/electrics.dm @@ -15,7 +15,7 @@ SKILL_LEVEL_LEGENDARY = 50, ), ) - innate_skill = TRUE + skill_flags = SKILL_ALWAYS_PRINT /datum/skill/electronics/level_gained(datum/mind/mind, new_level, old_level, silent) . = ..() diff --git a/code/datums/skills/firearms.dm b/code/datums/skills/firearms.dm index 8b010dbc73a6..77f7a42e22b0 100644 --- a/code/datums/skills/firearms.dm +++ b/code/datums/skills/firearms.dm @@ -15,4 +15,4 @@ SKILL_LEVEL_LEGENDARY = -20, ), ) - innate_skill = TRUE + skill_flags = SKILL_ALWAYS_PRINT diff --git a/code/datums/skills/hydroponics.dm b/code/datums/skills/hydroponics.dm index 037e043b97f2..14bd3922375c 100644 --- a/code/datums/skills/hydroponics.dm +++ b/code/datums/skills/hydroponics.dm @@ -5,4 +5,4 @@ earned_by = "growing plants" higher_levels_grant_you = "guaranteed seed samples from plants with zero yield \ and safety around bees without a suit" - innate_skill = TRUE + skill_flags = SKILL_ALWAYS_PRINT diff --git a/code/datums/skills/mechanics.dm b/code/datums/skills/mechanics.dm index 4a63d6dbc99d..ca7b7d1be349 100644 --- a/code/datums/skills/mechanics.dm +++ b/code/datums/skills/mechanics.dm @@ -3,4 +3,4 @@ title = "Mechanical Engineer" blurb = "I solve problems. Not problems like 'What is beauty?'... I solve practical problems." earned_by = "repairing and building machines" - innate_skill = TRUE + skill_flags = SKILL_ALWAYS_PRINT diff --git a/code/datums/skills/medical.dm b/code/datums/skills/medical.dm index 87f20e5ddbcf..7f3b8c11c8fc 100644 --- a/code/datums/skills/medical.dm +++ b/code/datums/skills/medical.dm @@ -16,7 +16,7 @@ SKILL_LEVEL_LEGENDARY = 0.75, ), ) - innate_skill = TRUE + skill_flags = SKILL_ALWAYS_PRINT /datum/skill/first_aid/level_gained(datum/mind/mind, new_level, old_level, silent) . = ..() diff --git a/code/datums/skills/mining.dm b/code/datums/skills/mining.dm index ffd33d809de4..950b40a784aa 100644 --- a/code/datums/skills/mining.dm +++ b/code/datums/skills/mining.dm @@ -26,4 +26,4 @@ ), ) skill_item_path = /obj/item/clothing/neck/cloak/skill_reward/mining - innate_skill = TRUE + skill_flags = SKILL_ALWAYS_PRINT diff --git a/code/datums/skills/robotics.dm b/code/datums/skills/robotics.dm index 6a3f356a018f..7fa8412576bc 100644 --- a/code/datums/skills/robotics.dm +++ b/code/datums/skills/robotics.dm @@ -3,4 +3,4 @@ title = "Roboticist" blurb = "You can build and repair robots." earned_by = "building and repairing cyborgs and robots" - innate_skill = TRUE + skill_flags = SKILL_ALWAYS_PRINT diff --git a/code/datums/skills/surgery.dm b/code/datums/skills/surgery.dm index 7455f2bdff93..5dd0b29802e6 100644 --- a/code/datums/skills/surgery.dm +++ b/code/datums/skills/surgery.dm @@ -30,4 +30,4 @@ SKILL_LEVEL_LEGENDARY = 25, ), ) - innate_skill = TRUE + skill_flags = SKILL_ALWAYS_PRINT diff --git a/code/datums/wires/airalarm.dm b/code/datums/wires/airalarm.dm index a1791223e88e..67d5ec16555d 100644 --- a/code/datums/wires/airalarm.dm +++ b/code/datums/wires/airalarm.dm @@ -56,6 +56,7 @@ var/obj/machinery/airalarm/A = holder switch(wire) if(WIRE_POWER) // Short out forever. + // NON-MODULE CHANGE A.shock(usr, 50 - usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) A.shorted = !mend A.update_appearance() diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm index 78165170b7dc..1952596ddd79 100644 --- a/code/datums/wires/airlock.dm +++ b/code/datums/wires/airlock.dm @@ -169,12 +169,14 @@ A.regainMainPower() else A.loseMainPower() + // NON-MODULE CHANGE A.shock(usr, 50- usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(WIRE_BACKUP1, WIRE_BACKUP2) // Cut to lose backup power, repair all to gain backup power. if(mend && !is_cut(WIRE_BACKUP1) && !is_cut(WIRE_BACKUP2)) A.regainBackupPower() else A.loseBackupPower() + // NON-MODULE CHANGE A.shock(usr, 50 - usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(WIRE_BOLTS) // Cut to engage bolts, mend does nothing. if(!mend) @@ -199,6 +201,7 @@ else if(A.secondsElectrified != MACHINE_ELECTRIFIED_PERMANENT) A.set_electrified(MACHINE_ELECTRIFIED_PERMANENT, usr) + // NON-MODULE CHANGE A.shock(usr, 100 - usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(WIRE_SAFETY) // Cut to disable safeties, mend to re-enable. A.safe = mend @@ -212,6 +215,7 @@ A.lights = mend A.update_appearance() if(WIRE_ZAP1, WIRE_ZAP2) // Ouch. + // NON-MODULE CHANGE A.shock(usr, 50 - usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(WIRE_UNRESTRICTED_EXIT) // If this wire is cut, the unrestricted helper goes away. If you mend it, it'll go "haywire" and pick a new direction at random. Might have to cut/mend a time or two to get the direction you want. if(!A.unres_sensor) //only works if the "sensor" is installed (a variable that we assign to the door either upon creation of a door with unrestricted directions, or if an unrestricted helper is added to a door in mapping) diff --git a/code/datums/wires/apc.dm b/code/datums/wires/apc.dm index f118f3b7c5fe..aff69db143e4 100644 --- a/code/datums/wires/apc.dm +++ b/code/datums/wires/apc.dm @@ -48,6 +48,7 @@ A.shorted = FALSE else A.shorted = TRUE + // NON-MODULE CHANGE A.shock(usr, 50 - usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(WIRE_AI) // Disable AI control. A.aidisabled = !mend diff --git a/code/datums/wires/autolathe.dm b/code/datums/wires/autolathe.dm index bf30f790f703..1c8c4c9d2f05 100644 --- a/code/datums/wires/autolathe.dm +++ b/code/datums/wires/autolathe.dm @@ -47,4 +47,5 @@ if(WIRE_DISABLE) A.disabled = !mend if(WIRE_ZAP) + // NON-MODULE CHANGE A.shock(usr, 50 - usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) diff --git a/code/datums/wires/roulette.dm b/code/datums/wires/roulette.dm index 7a23fd0aef1a..1c22ff5a32f5 100644 --- a/code/datums/wires/roulette.dm +++ b/code/datums/wires/roulette.dm @@ -33,6 +33,7 @@ var/obj/machinery/roulette/R = holder switch(wire) if(WIRE_SHOCK) + // NON-MODULE CHANGE R.shock(usr, 50 - usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(WIRE_BOLTS) // Pulse to toggle bolts (but only raise if power is on). if(!R.on) @@ -43,6 +44,7 @@ R.audible_message(span_warning("Owner reset!")) R.locked = FALSE if(WIRE_PRIZEVEND) + // NON-MODULE CHANGE R.shock(usr, 70- usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(R.locked) return @@ -53,6 +55,7 @@ var/obj/machinery/roulette/R = holder switch(wire) if(WIRE_SHOCK) + // NON-MODULE CHANGE R.shock(usr, 60- usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(mend) R.on = TRUE @@ -63,8 +66,10 @@ return R.set_anchored(TRUE) if(WIRE_RESETOWNER) + // NON-MODULE CHANGE R.shock(usr, 70- usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(WIRE_PRIZEVEND) + // NON-MODULE CHANGE R.shock(usr, 75- usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(R.locked) return diff --git a/code/datums/wires/suit_storage_unit.dm b/code/datums/wires/suit_storage_unit.dm index 8f8e1a05e680..de3e812c29ef 100644 --- a/code/datums/wires/suit_storage_unit.dm +++ b/code/datums/wires/suit_storage_unit.dm @@ -32,6 +32,7 @@ if(WIRE_SAFETY) SSU.safeties = !SSU.safeties if(WIRE_ZAP) + // NON-MODULE CHANGE SSU.shock(usr, 100 - usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) /datum/wires/suit_storage_unit/on_cut(wire, mend, source) @@ -42,4 +43,5 @@ if(WIRE_SAFETY) SSU.safeties = mend if(WIRE_ZAP) + // NON-MODULE CHANGE SSU.shock(usr, 100 - usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) diff --git a/code/datums/wires/vending.dm b/code/datums/wires/vending.dm index 97121c7275d4..ce973507b84c 100644 --- a/code/datums/wires/vending.dm +++ b/code/datums/wires/vending.dm @@ -29,6 +29,7 @@ return FALSE var/obj/machinery/vending/vending_machine = holder if(vending_machine.seconds_electrified) + // NON-MODULE CHANGE if(vending_machine.shock(user, 100 - user.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER))) return FALSE if(vending_machine.panel_open) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index c3d1fec590ff..a67147b7a7de 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -1069,6 +1069,7 @@ if(!delay && !tool_start_check(user, amount)) return + // NON-MODULE CHANGE if(tool_behaviour == TOOL_MINING && user.mind) delay *= user.mind.get_skill_modifier(/datum/skill/mining, SKILL_SPEED_MODIFIER) if(prob(user.mind.get_skill_modifier(/datum/skill/mining, SKILL_PROBS_MODIFIER))) diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index b4b67cf07dac..a7cbfe015c68 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -93,6 +93,7 @@ span_notice("[user] starts to apply [src] on [user.p_them()]self..."), span_notice("You begin applying [src] on yourself..."), ) + // NON-MODULE CHANGE if(!do_after( user, self_delay * (user.mind?.get_skill_modifier(/datum/skill/first_aid, SKILL_SPEED_MODIFIER) || 1), @@ -107,6 +108,7 @@ span_notice("[user] starts to apply [src] on [patient]."), span_notice("You begin applying [src] on [patient]..."), ) + // NON-MODULE CHANGE if(!do_after( user, other_delay * (user.mind?.get_skill_modifier(/datum/skill/first_aid, SKILL_SPEED_MODIFIER) || 1), @@ -310,6 +312,7 @@ if(!try_heal_checks(patient, user, 0, 0)) return + // NON-MODULE CHANGE var/treatment_delay = (user == patient ? self_delay : other_delay) * (user.mind?.get_skill_modifier(/datum/skill/first_aid, SKILL_SPEED_MODIFIER) || 1) var/obj/item/bodypart/limb = patient.get_bodypart(check_zone(user.zone_selected)) diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 11eab558d354..cf3a70262c01 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -181,6 +181,7 @@ GLOBAL_LIST_INIT(wire_node_generating_types, typecacheof(list(/obj/structure/gri if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE) return if(W.tool_behaviour == TOOL_WIRECUTTER) + // NON-MODULE CHANGE if (shock(user, 50 - user.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER))) return user.visible_message(span_notice("[user] cuts the cable."), span_notice("You cut the cable.")) @@ -190,6 +191,7 @@ GLOBAL_LIST_INIT(wire_node_generating_types, typecacheof(list(/obj/structure/gri else if(W.tool_behaviour == TOOL_MULTITOOL) to_chat(user, get_power_info()) + // NON-MODULE CHANGE shock(user, 5 - user.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER), 0.2) add_fingerprint(user) @@ -624,6 +626,7 @@ GLOBAL_LIST_INIT(wire_node_generating_types, typecacheof(list(/obj/structure/gri use(1) + // NON-MODULE CHANGE if(C.shock(user, 50 - user.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER))) if(prob(50)) //fail C.deconstruct() diff --git a/code/modules/surgery/autopsy.dm b/code/modules/surgery/autopsy.dm index fd4ac0cac416..f5e1a3b793cb 100644 --- a/code/modules/surgery/autopsy.dm +++ b/code/modules/surgery/autopsy.dm @@ -33,6 +33,7 @@ ) /datum/surgery_step/autopsy/success(mob/living/user, mob/living/carbon/target, target_zone, obj/item/autopsy_scanner/tool, datum/surgery/surgery, default_display_results = FALSE) + // NON-MODULE CHANGE var/xp_given = 200 // some alien species if(isalien(target)) xp_given *= 2.5 // truly foreign diff --git a/code/modules/surgery/prosthetic_replacement.dm b/code/modules/surgery/prosthetic_replacement.dm index de1fc98c8b55..0733a350fba6 100644 --- a/code/modules/surgery/prosthetic_replacement.dm +++ b/code/modules/surgery/prosthetic_replacement.dm @@ -113,6 +113,7 @@ pain_message = "You feel synthetic sensation wash from your [parse_zone(target_zone)], which you can feel again!", mechanical_surgery = TRUE, ) + // NON-MODULE CHANGE target.cause_pain(bodypart_to_attach.body_zone, -1 * user.mind?.get_skill_modifier(/datum/skill/cybernetics, SKILL_VALUE_MODIFIER)) if(IS_ROBOTIC_LIMB(bodypart_to_attach)) user.mind?.adjust_experience(/datum/skill/cybernetics, 100) diff --git a/code/modules/surgery/surgery_step.dm b/code/modules/surgery/surgery_step.dm index 8936fad04e1c..0cadce821f11 100644 --- a/code/modules/surgery/surgery_step.dm +++ b/code/modules/surgery/surgery_step.dm @@ -93,9 +93,11 @@ if(check_morbid_curiosity(user, tool, surgery)) speed_mod *= SURGERY_SPEED_MORBID_CURIOSITY + // NON-MODULE CHANGE if(implement_type && (implements[implement_type] > 0)) //this means it isn't a require hand or any item step. speed_mod *= (1 / ((implements[implement_type] + user.mind?.get_skill_modifier(/datum/skill/surgery, SKILL_VALUE_MODIFIER)) / 100.0)) + // NON-MODULE CHANGE speed_mod *= (user.mind?.get_skill_modifier(/datum/skill/surgery, SKILL_SPEED_MODIFIER) || 1) speed_mod *= surgery.speed_modifier @@ -121,6 +123,7 @@ if((prob(100-fail_prob) || (iscyborg(user) && !silicons_obey_prob)) && chem_check_result && !try_to_fail) if(success(user, target, target_zone, tool, surgery)) + // NON-MODULE CHANGE if(user.mind && (target.mind || user.mind.get_skill_level(/datum/skill/surgery) <= SKILL_LEVEL_NOVICE) && !iscyborg(user)) // by default, you only gain surgery xp for operating on players. no monkey grinding user.mind.adjust_experience(/datum/skill/surgery, time * 0.5) // 1 xp per 2 second of surgery - 50 xp for brain surgery play_success_sound(user, target, target_zone, tool, surgery) From 98a909dab4edb75368fd0766df41918a5ba1040f Mon Sep 17 00:00:00 2001 From: MrMelbert Date: Wed, 26 Mar 2025 15:00:40 -0500 Subject: [PATCH 05/22] Get ahead --- tgstation.dme | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tgstation.dme b/tgstation.dme index 0784eba69b71..53f21513ef66 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1750,10 +1750,18 @@ #include "code\datums\shuttles\whiteship.dm" #include "code\datums\skills\_skill.dm" #include "code\datums\skills\cleaning.dm" +#include "code\datums\skills\cybernetic.dm" +#include "code\datums\skills\electrics.dm" +#include "code\datums\skills\firearms.dm" #include "code\datums\skills\fishing.dm" #include "code\datums\skills\fitness.dm" #include "code\datums\skills\gaming.dm" +#include "code\datums\skills\hydroponics.dm" +#include "code\datums\skills\mechanics.dm" +#include "code\datums\skills\medical.dm" #include "code\datums\skills\mining.dm" +#include "code\datums\skills\robotics.dm" +#include "code\datums\skills\surgery.dm" #include "code\datums\station_traits\_station_trait.dm" #include "code\datums\station_traits\admin_panel.dm" #include "code\datums\station_traits\job_traits.dm" From c60c1321a3f8477c9a30992d3cd834ec396cf947 Mon Sep 17 00:00:00 2001 From: MrMelbert Date: Wed, 26 Mar 2025 15:22:04 -0500 Subject: [PATCH 06/22] Missed some --- code/datums/wires/airlock.dm | 2 ++ code/datums/wires/apc.dm | 1 + code/datums/wires/mecha.dm | 1 + code/datums/wires/mod.dm | 1 + code/datums/wires/robot.dm | 1 + code/modules/hydroponics/beekeeping/beebox.dm | 3 +-- code/modules/hydroponics/seeds.dm | 2 ++ 7 files changed, 9 insertions(+), 2 deletions(-) diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm index 1952596ddd79..e18195e0e94b 100644 --- a/code/datums/wires/airlock.dm +++ b/code/datums/wires/airlock.dm @@ -139,6 +139,7 @@ if(WIRE_SHOCK) // Pulse to shock the door for 10 ticks. if(!A.secondsElectrified) A.set_electrified(MACHINE_DEFAULT_ELECTRIFY_TIME, usr) + // NON-MODULE CHANGE A.shock(usr, 100- usr.mind?.get_skill_modifier(/datum/skill/electronics, SKILL_PROBS_MODIFIER)) if(WIRE_SAFETY) A.safe = !A.safe @@ -229,6 +230,7 @@ /datum/wires/airlock/can_reveal_wires(mob/user) + // NON-MODULE CHANGE if(HAS_MIND_TRAIT(user, TRAIT_KNOW_ENGI_WIRES)) return TRUE diff --git a/code/datums/wires/apc.dm b/code/datums/wires/apc.dm index aff69db143e4..098e08f4d401 100644 --- a/code/datums/wires/apc.dm +++ b/code/datums/wires/apc.dm @@ -54,6 +54,7 @@ A.aidisabled = !mend /datum/wires/apc/can_reveal_wires(mob/user) + // NON-MODULE CHANGE if(HAS_MIND_TRAIT(user, TRAIT_KNOW_ENGI_WIRES)) return TRUE diff --git a/code/datums/wires/mecha.dm b/code/datums/wires/mecha.dm index 76a7dea8f21a..633c79706be8 100644 --- a/code/datums/wires/mecha.dm +++ b/code/datums/wires/mecha.dm @@ -73,6 +73,7 @@ return FALSE /datum/wires/mecha/can_reveal_wires(mob/user) + // NON-MODULE CHANGE if(HAS_MIND_TRAIT(user, TRAIT_KNOW_ROBO_WIRES)) return TRUE return ..() diff --git a/code/datums/wires/mod.dm b/code/datums/wires/mod.dm index 888a12a48871..30b34e6952e2 100644 --- a/code/datums/wires/mod.dm +++ b/code/datums/wires/mod.dm @@ -57,6 +57,7 @@ return ..() /datum/wires/mod/can_reveal_wires(mob/user) + // NON-MODULE CHANGE if(HAS_MIND_TRAIT(user, TRAIT_KNOW_ROBO_WIRES)) return TRUE return ..() diff --git a/code/datums/wires/robot.dm b/code/datums/wires/robot.dm index cd2e99b8a903..3564c3d15056 100644 --- a/code/datums/wires/robot.dm +++ b/code/datums/wires/robot.dm @@ -105,6 +105,7 @@ log_silicon("[key_name(usr)] reset [key_name(R)]'s module via wire") /datum/wires/robot/can_reveal_wires(mob/user) + // NON-MODULE CHANGE if(HAS_MIND_TRAIT(user, TRAIT_KNOW_ROBO_WIRES)) return TRUE diff --git a/code/modules/hydroponics/beekeeping/beebox.dm b/code/modules/hydroponics/beekeeping/beebox.dm index 5df28f34dc49..531af9871833 100644 --- a/code/modules/hydroponics/beekeeping/beebox.dm +++ b/code/modules/hydroponics/beekeeping/beebox.dm @@ -10,8 +10,7 @@ /mob/proc/bee_friendly() return 0 - - +// NON-MODULE CHANGE /mob/living/carbon/human/bee_friendly() if(ispodperson(src)) //bees pollinate plants, duh. return TRUE diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm index eb688397e102..0c803532252d 100644 --- a/code/modules/hydroponics/seeds.dm +++ b/code/modules/hydroponics/seeds.dm @@ -121,6 +121,7 @@ . += span_notice("- [reagent_gene.get_name()] -") /// Copy all the variables from one seed to a new instance of the same seed and return it. +// NON-MODULE CHANGE /obj/item/seeds/proc/Copy() as /obj/item/seeds RETURN_TYPE(/obj/item/seeds) var/obj/item/seeds/copy_seed = new type(null, TRUE) @@ -249,6 +250,7 @@ t_amount++ product_name = parent.myseed.plantname + // NON-MODULE CHANGE if(product_count >= 1) SSblackbox.record_feedback("tally", "food_harvested", product_count, product_name) user.mind?.adjust_experience(/datum/skill/botany, 2 * rarity * (yield / MAX_PLANT_YIELD) * (potency / MAX_PLANT_POTENCY)) From 86016c685b0e087c14a5c80e7b50dd6fb4551fa9 Mon Sep 17 00:00:00 2001 From: MrMelbert Date: Thu, 27 Mar 2025 16:14:42 -0500 Subject: [PATCH 07/22] Food changes --- code/__DEFINES/food.dm | 6 +- code/__DEFINES/traits/declarations.dm | 2 + code/_globalvars/traits/_traits.dm | 1 + code/datums/components/bakeable.dm | 13 ++-- code/datums/components/food/edible.dm | 69 ++++++++++++++----- code/datums/components/grillable.dm | 13 ++-- code/datums/elements/dryable.dm | 20 +++--- code/datums/elements/food/microwavable.dm | 3 +- code/datums/mood_events/food_events.dm | 38 ++++++++-- code/datums/skills/cooking.dm | 57 +++++++++++++++ code/game/atom/_atom.dm | 3 +- code/game/objects/items/food/donkpocket.dm | 5 ++ code/game/objects/items/food/misc.dm | 12 ++++ code/game/objects/items/food/packaged.dm | 5 ++ .../food_and_drinks/machinery/deep_fryer.dm | 4 +- .../food_and_drinks/recipes/food_mixtures.dm | 5 +- code/modules/jobs/job_types/bartender.dm | 1 + code/modules/jobs/job_types/botanist.dm | 1 + code/modules/jobs/job_types/cook.dm | 1 + code/modules/jobs/job_types/detective.dm | 1 + maplestation.dme | 1 + 21 files changed, 208 insertions(+), 53 deletions(-) create mode 100644 code/datums/skills/cooking.dm diff --git a/code/__DEFINES/food.dm b/code/__DEFINES/food.dm index 60f417691aa0..3cd51e6e918f 100644 --- a/code/__DEFINES/food.dm +++ b/code/__DEFINES/food.dm @@ -160,8 +160,10 @@ GLOBAL_LIST_INIT(food_buffs, list( )) /// Food quality change according to species diet -#define DISLIKED_FOOD_QUALITY_CHANGE -2 -#define LIKED_FOOD_QUALITY_CHANGE 2 +#define DISLIKED_FOOD_QUALITY_CHANGE -1.5 +#define LIKED_FOOD_QUALITY_CHANGE 1.5 +/// Threshold for food to be considered gross +#define GROSS_FOOD_QUALITY_THRESHOLD -2 /// Threshold for food to give a toxic reaction #define TOXIC_FOOD_QUALITY_THRESHOLD -8 /// Food is dangerous to consume diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index a32f6a41c1af..e106fd14f298 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -654,6 +654,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_FOOD_SILVER "food_silver" /// If this item's been made by a chef instead of being map-spawned or admin-spawned or such #define TRAIT_FOOD_CHEF_MADE "food_made_by_chef" +/// If this item is microwaved or cooked, it won't gain TRAIT_FOOD_CHEF_MADE unless it already had it +#define TRAIT_FOOD_MUST_INHERIT_CHEF_MADE "food_must_inherit_chef_made" /// The items needs two hands to be carried #define TRAIT_NEEDS_TWO_HANDS "needstwohands" /// Can't be catched when thrown diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index e5d3edf8fa2b..bb4edba481a7 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -19,6 +19,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_FOOD_CHEF_MADE" = TRAIT_FOOD_CHEF_MADE, "TRAIT_FOOD_FRIED" = TRAIT_FOOD_FRIED, "TRAIT_FOOD_GRILLED" = TRAIT_FOOD_GRILLED, + "TRAIT_FOOD_MUST_INHERIT_CHEF_MADE" = TRAIT_FOOD_MUST_INHERIT_CHEF_MADE, "TRAIT_FOOD_SILVER" = TRAIT_FOOD_SILVER, "TRAIT_KEEP_TOGETHER" = TRAIT_KEEP_TOGETHER, "TRAIT_LIGHTING_DEBUGGED" = TRAIT_LIGHTING_DEBUGGED, diff --git a/code/datums/components/bakeable.dm b/code/datums/components/bakeable.dm index a745be2b1a57..4be4a29dc918 100644 --- a/code/datums/components/bakeable.dm +++ b/code/datums/components/bakeable.dm @@ -11,8 +11,9 @@ ///Time spent baking so far var/current_bake_time = 0 - /// REF() to the mind which placed us in an oven - var/who_baked_us + // NON-MODULE CHANGE + /// WEAKREF() to the mind which placed us in an oven + var/datum/weakref/who_baked_us /// Reagents that should be added to the result var/list/added_reagents @@ -53,8 +54,8 @@ /datum/component/bakeable/proc/on_baking_start(datum/source, atom/used_oven, mob/baker) SIGNAL_HANDLER - if(baker && baker.mind) - who_baked_us = REF(baker.mind) + // NON-MODULE CHANGE + who_baked_us = WEAKREF(baker?.mind) ///Ran every time an item is baked by something /datum/component/bakeable/proc/on_bake(datum/source, atom/used_oven, seconds_per_tick = 1) @@ -80,8 +81,8 @@ if(added_reagents) // Add any new reagents that should be added baked_result.reagents.add_reagent_list(added_reagents) - if(who_baked_us) - ADD_TRAIT(baked_result, TRAIT_FOOD_CHEF_MADE, who_baked_us) + // NON-MODULE CHANGE + handle_chef_made_food(baked_result, original_object, who_baked_us?.resolve()) if(original_object.custom_materials) baked_result.set_custom_materials(original_object.custom_materials, 1) diff --git a/code/datums/components/food/edible.dm b/code/datums/components/food/edible.dm index 7d78cb3bccd1..aa2532df37b4 100644 --- a/code/datums/components/food/edible.dm +++ b/code/datums/components/food/edible.dm @@ -227,22 +227,29 @@ Behavior that's still missing from this component that original food items had t examine_list += span_warning("You may die from eating this meal.") else if (quality <= TOXIC_FOOD_QUALITY_THRESHOLD) examine_list += span_warning("You find this meal disgusting!") - else + // NON-MODULE CHANGE + else if (quality <= GROSS_FOOD_QUALITY_THRESHOLD) examine_list += span_warning("You find this meal inedible.") + else + examine_list += span_notice("You find this meal shoddy.") if(owner.reagents.total_volume > 0) var/purity = owner.reagents.get_average_purity(/datum/reagent/consumable) switch(purity) if(0 to 0.2) examine_list += span_warning("It is made of terrible ingredients shortening the effect...") + // NON-MODULE CHANGE if(0.2 to 0.4) - examine_list += span_warning("It is made of synthetic ingredients shortening the effect.") + examine_list += span_warning("It is made of poor ingredients shortening the effect.") if(0.4 to 0.6) examine_list += span_notice("It is made of average quality ingredients.") if(0.6 to 0.8) examine_list += span_green("It is made of organic ingredients prolonging the effect.") if(0.8 to 1) examine_list += span_green("It is made of finest ingredients prolonging the effect!") + // NON-MODULE CHANGE + if(1 to 1.5) + examine_list += span_green("A master chef using the finest ingredients to make this meal, prolonging the effect!") var/datum/mind/mind = user.mind if(mind && HAS_TRAIT_FROM(owner, TRAIT_FOOD_CHEF_MADE, REF(mind))) @@ -568,25 +575,33 @@ Behavior that's still missing from this component that original food items had t gourmand.add_mood_event("toxic_food", /datum/mood_event/disgusting_food) return - if(food_quality < 0) - to_chat(gourmand,span_notice("That didn't taste very good...")) + // NON-MODULE CHANGE + if(food_quality <= GROSS_FOOD_QUALITY_THRESHOLD) + to_chat(gourmand, span_notice("That didn't taste very good...")) gourmand.adjust_disgust(11 + 15 * fraction) gourmand.add_mood_event("gross_food", /datum/mood_event/gross_food) return - + // NON-MODULE CHANGE + if(food_quality < 0) + to_chat(gourmand, span_notice("That could've been better.")) + gourmand.add_mood_event("gross_food", /datum/mood_event/bad_food) + return + // NON-MODULE CHANGE if(food_quality == 0) + to_chat(gourmand, span_notice("That's a mediocre meal.")) + gourmand.add_mood_event("mid_food", /datum/mood_event/mid_food) return // meh - food_quality = min(food_quality, FOOD_QUALITY_TOP) + // NON-MODULE CHANGES var/atom/owner = parent - var/timeout_mod = owner.reagents.get_average_purity(/datum/reagent/consumable) * 2 // mood event duration is 100% at average purity of 50% + var/timeout_mod = owner.reagents.get_average_purity(/datum/reagent/consumable) * 1.5 // mood event duration is 100% at average purity of 50% var/datum/mood_event/event = GLOB.food_quality_events[food_quality] event = new event.type event.timeout *= timeout_mod gourmand.add_mood_event("quality_food", event) gourmand.adjust_disgust(-5 + -2 * food_quality * fraction) var/quality_label = GLOB.food_quality_description[food_quality] - to_chat(gourmand, span_notice("That's \an [quality_label] meal.")) + to_chat(gourmand, span_notice("That's \an [quality_label] meal.")) /// Get the complexity of the crafted food /datum/component/edible/proc/get_recipe_complexity() @@ -599,6 +614,13 @@ Behavior that's still missing from this component that original food items had t /datum/component/edible/proc/get_perceived_food_quality(mob/living/carbon/human/eater) var/food_quality = get_recipe_complexity() + // NON-MODULE CHANGE + if(HAS_MIND_TRAIT(eater, TRAIT_SNOB)) + if(food_quality <= FOOD_QUALITY_VERYGOOD) + food_quality -= 0.5 + else + food_quality += 0.5 + if(HAS_TRAIT(parent, TRAIT_FOOD_SILVER)) // it's not real food if(!isjellyperson(eater)) //if you aren't a jellyperson, it makes you sick no matter how nice it looks return TOXIC_FOOD_QUALITY_THRESHOLD @@ -616,17 +638,26 @@ Behavior that's still missing from this component that original food items had t if(FOOD_ALLERGIC) return FOOD_QUALITY_DANGEROUS - if(ishuman(eater)) - if(foodtypes & eater.get_allergic_foodtypes()) - return FOOD_QUALITY_DANGEROUS - if(count_matching_foodtypes(foodtypes, eater.get_toxic_foodtypes())) //if the food is toxic, we don't care about anything else - return TOXIC_FOOD_QUALITY_THRESHOLD - if(HAS_TRAIT(eater, TRAIT_AGEUSIA)) //if you can't taste it, it doesn't taste good - return 0 - food_quality += DISLIKED_FOOD_QUALITY_CHANGE * count_matching_foodtypes(foodtypes, eater.get_disliked_foodtypes()) - food_quality += LIKED_FOOD_QUALITY_CHANGE * count_matching_foodtypes(foodtypes, eater.get_liked_foodtypes()) - - return food_quality + // NON-MODULE CHANGES + if(HAS_TRAIT(eater, TRAIT_AGEUSIA)) //if you can't taste it, it doesn't taste good + return 0 + if(foodtypes & eater.get_allergic_foodtypes()) + return FOOD_QUALITY_DANGEROUS + if(count_matching_foodtypes(foodtypes, eater.get_toxic_foodtypes())) //if the food is toxic, we don't care about anything else + return TOXIC_FOOD_QUALITY_THRESHOLD + food_quality += DISLIKED_FOOD_QUALITY_CHANGE * count_matching_foodtypes(foodtypes, eater.get_disliked_foodtypes()) + food_quality += LIKED_FOOD_QUALITY_CHANGE * count_matching_foodtypes(foodtypes, eater.get_liked_foodtypes()) + + // NON-MODULE CHANGES + var/obj/item/food = parent + var/reagent_quality_mod = INFINITY + for(var/datum/reagent/consumable/nutri in food.reagents?.reagent_list) + reagent_quality_mod = min(reagent_quality_mod, nutri.data?["quality_modifier"] || 0) + + if(reagent_quality_mod != INFINITY) + food_quality += reagent_quality_mod + + return min(floor(food_quality), FOOD_QUALITY_TOP) /// Get the number of matching food types in provided bitfields /datum/component/edible/proc/count_matching_foodtypes(bitfield_one, bitfield_two) diff --git a/code/datums/components/grillable.dm b/code/datums/components/grillable.dm index f584808a1f3b..14ca7ff48cb3 100644 --- a/code/datums/components/grillable.dm +++ b/code/datums/components/grillable.dm @@ -10,8 +10,9 @@ var/current_cook_time = 0 ///Do we use the large steam sprite? var/use_large_steam_sprite = FALSE - /// REF() to the mind which placed us on the griddle - var/who_placed_us + // NON-MODULE CHANGE + /// WEAKREF() to the mind which placed us on the griddle + var/datum/weakref/who_placed_us /// Reagents that should be added to the result var/list/added_reagents @@ -59,8 +60,8 @@ /datum/component/grillable/proc/on_grill_placed(datum/source, mob/griller) SIGNAL_HANDLER - if(griller && griller.mind) - who_placed_us = REF(griller.mind) + // NON-MODULE CHANGE + who_placed_us = WEAKREF(griller?.mind) RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved)) @@ -110,8 +111,8 @@ grilled_result.reagents.add_reagent_list(added_reagents) SEND_SIGNAL(parent, COMSIG_ITEM_GRILLED, grilled_result) - if(who_placed_us) - ADD_TRAIT(grilled_result, TRAIT_FOOD_CHEF_MADE, who_placed_us) + // NON-MODULE CHANGE + handle_chef_made_food(grilled_result, parent, who_placed_us?.resolve()) grill_source.visible_message("[parent] turns into \a [grilled_result]!") grilled_result.pixel_x = original_object.pixel_x diff --git a/code/datums/elements/dryable.dm b/code/datums/elements/dryable.dm index d66ea96d8c1f..51f77eb23e7a 100644 --- a/code/datums/elements/dryable.dm +++ b/code/datums/elements/dryable.dm @@ -26,13 +26,15 @@ if(dry_result == dried_atom.type)//if the dried type is the same as our currrent state, don't bother creating a whole new item, just re-color it. var/atom/movable/resulting_atom = dried_atom resulting_atom.add_atom_colour(COLOR_DRIED_TAN, FIXED_COLOUR_PRIORITY) - apply_dried_status(resulting_atom, drying_user) + // NON-MODULE CHANGE + apply_dried_status(resulting_atom, drying_user?.resolve(), source) return else if(isstack(source)) //Check if its a sheet var/obj/item/stack/itemstack = dried_atom for(var/i in 1 to itemstack.amount) var/atom/movable/resulting_atom = new dry_result(source.loc) - apply_dried_status(resulting_atom, drying_user) + // NON-MODULE CHANGE + apply_dried_status(resulting_atom, drying_user?.resolve(), source) qdel(source) return else if(istype(source, /obj/item/food) && ispath(dry_result, /obj/item/food)) @@ -40,16 +42,18 @@ var/obj/item/food/resulting_food = new dry_result(source.loc) resulting_food.reagents.clear_reagents() source_food.reagents.trans_to(resulting_food, source_food.reagents.total_volume) - apply_dried_status(resulting_food, drying_user) + // NON-MODULE CHANGE + apply_dried_status(resulting_food, drying_user?.resolve(), source) qdel(source) return else var/atom/movable/resulting_atom = new dry_result(source.loc) - apply_dried_status(resulting_atom, drying_user) + // NON-MODULE CHANGE + apply_dried_status(resulting_atom, drying_user?.resolve(), source) qdel(source) -/datum/element/dryable/proc/apply_dried_status(atom/target, datum/weakref/drying_user) +/datum/element/dryable/proc/apply_dried_status(atom/target, datum/mind/chef, atom/source) ADD_TRAIT(target, TRAIT_DRIED, ELEMENT_TRAIT(type)) - var/datum/mind/user_mind = drying_user?.resolve() - if(drying_user && istype(target, /obj/item/food)) - ADD_TRAIT(target, TRAIT_FOOD_CHEF_MADE, REF(user_mind)) + // NON-MODULE CHANGE + if(istype(chef) && istype(target, /obj/item/food)) + handle_chef_made_food(target, source, chef) diff --git a/code/datums/elements/food/microwavable.dm b/code/datums/elements/food/microwavable.dm index 8e7305545c0b..3232b97be8a6 100644 --- a/code/datums/elements/food/microwavable.dm +++ b/code/datums/elements/food/microwavable.dm @@ -52,8 +52,7 @@ if(added_reagents) // Add any new reagents that should be added result.reagents.add_reagent_list(added_reagents) - if(microwaver && microwaver.mind) - ADD_TRAIT(result, TRAIT_FOOD_CHEF_MADE, REF(microwaver.mind)) + handle_chef_made_food(result, source, microwaver?.mind) qdel(source) diff --git a/code/datums/mood_events/food_events.dm b/code/datums/mood_events/food_events.dm index 7d33e7e57ce0..a0bb563530b3 100644 --- a/code/datums/mood_events/food_events.dm +++ b/code/datums/mood_events/food_events.dm @@ -27,10 +27,18 @@ timeout = 5 MINUTES var/quality = FOOD_QUALITY_NORMAL -/datum/mood_event/food/New(mob/M, ...) - . = ..() - mood_change = 2 + 2 * quality - description = "That food was [GLOB.food_quality_description[quality]]." +// NON-MODULE CHANGE +/datum/mood_event/food/add_effects(param) + mood_change = floor(quality * 1.34) + if(HAS_MIND_TRAIT(owner, TRAIT_SNOB)) + if(quality <= FOOD_QUALITY_VERYGOOD) + mood_change -= 1 + description = "That food was [GLOB.food_quality_description[quality]], but I expect better." + else + mood_change += 1 + description = "That food was [GLOB.food_quality_description[quality]]. Perfection!" + else + description = "That food was [GLOB.food_quality_description[quality]]." /datum/mood_event/food/nice quality = FOOD_QUALITY_NICE @@ -49,3 +57,25 @@ /datum/mood_event/food/top quality = FOOD_QUALITY_TOP + +// NON-MODULE CHANGE +/datum/mood_event/mid_food + timeout = 5 MINUTES + description = "That's some shockingly mediocre food." + mood_change = 0 + +/datum/mood_event/mid_food/add_effects() + if(HAS_MIND_TRAIT(owner, TRAIT_SNOB)) + mood_change = -2 + description = "That's some shockingly mediocre food - I expect better!" + +// NON-MODULE CHANGE +/datum/mood_event/bad_food + timeout = 5 MINUTES + description = "That food wasn't very good, but at least it didn't make me sick." + mood_change = -2 + +/datum/mood_event/bad_food/add_effects() + if(HAS_MIND_TRAIT(owner, TRAIT_SNOB)) + mood_change = -4 + description = "That food wasn't very good. I expect better!" diff --git a/code/datums/skills/cooking.dm b/code/datums/skills/cooking.dm new file mode 100644 index 000000000000..676987df0e5b --- /dev/null +++ b/code/datums/skills/cooking.dm @@ -0,0 +1,57 @@ +/datum/skill/cooking + name = "Cooking" + title = "Chef" + blurb = "Everyone can cook." + earned_by = "cooking food" + grants_you = "tastier food" + modifiers = list( + // modifiers food reagent purity in cooked products + // with poor skill, you make fantastic ingredients good, and mediocre ingredients bad + // but with high skill, you can make bad ingredients good, and the best is even better + SKILL_VALUE_MODIFIER = list( + SKILL_LEVEL_NONE = 0.75, + SKILL_LEVEL_NOVICE = 0.9, + SKILL_LEVEL_APPRENTICE = 1, + SKILL_LEVEL_JOURNEYMAN = 1, + SKILL_LEVEL_EXPERT = 1.1, + SKILL_LEVEL_MASTER = 1.2, + SKILL_LEVEL_LEGENDARY = 1.3, + ), + // flat addition to food quality + // with poor skill "nice" food becomes "normal" + // but with high skill "nice" food becomes "very nice" or even "fantastic" + SKILL_RANDS_MODIFIER = list( + SKILL_LEVEL_NONE = -1, + SKILL_LEVEL_NOVICE = 0, + SKILL_LEVEL_APPRENTICE = 0, + SKILL_LEVEL_JOURNEYMAN = 0.5, + SKILL_LEVEL_EXPERT = 1, + SKILL_LEVEL_MASTER = 1.5, + SKILL_LEVEL_LEGENDARY = 2, + ), + ) + +/// Mark a food item as "made by a chef", modify its quality +/proc/handle_chef_made_food(obj/item/food, obj/item/source, datum/mind/chef) + modify_food_quality(food, chef) + if(isnull(chef)) + return + if(HAS_TRAIT(source, TRAIT_FOOD_MUST_INHERIT_CHEF_MADE) && !HAS_TRAIT(source, TRAIT_FOOD_CHEF_MADE)) + return + ADD_TRAIT(food, TRAIT_FOOD_CHEF_MADE, REF(chef)) + +/// When given some item with reagents (normally food), +/// modifies the quality of the reagents according to the passed chef's mind's cooking skill +/proc/modify_food_quality(obj/item/food, datum/mind/chef) + if(isnull(food?.reagents)) + return + + var/purity_modifier = chef?.get_skill_modifier(/datum/skill/cooking, SKILL_VALUE_MODIFIER) || 1 + var/quality_modifier = chef?.get_skill_modifier(/datum/skill/cooking, SKILL_RANDS_MODIFIER) || -1 + + for(var/datum/reagent/consumable/nutri in food.reagents.reagent_list) + // purity in food models how quality the ingredient is + // we reduce the purtiy based on the chef's skill to model wasting quality parts of the ingredients + nutri.purity *= purity_modifier + // we store this in the reagent data to read it later + LAZYSET(nutri.data, "quality_modifier", quality_modifier) diff --git a/code/game/atom/_atom.dm b/code/game/atom/_atom.dm index 9259ad07dd3d..bc2422f3a7e0 100644 --- a/code/game/atom/_atom.dm +++ b/code/game/atom/_atom.dm @@ -679,8 +679,7 @@ SHOULD_CALL_PARENT(TRUE) SEND_SIGNAL(src, COMSIG_ATOM_CREATEDBY_PROCESSING, original_atom, chosen_option) - if(user.mind) - ADD_TRAIT(src, TRAIT_FOOD_CHEF_MADE, REF(user.mind)) + handle_chef_made_food(src, original_atom, user.mind) ///Connect this atom to a shuttle /atom/proc/connect_to_shuttle(mapload, obj/docking_port/mobile/port, obj/docking_port/stationary/dock) diff --git a/code/game/objects/items/food/donkpocket.dm b/code/game/objects/items/food/donkpocket.dm index d4b4636f15c9..1e3b1d037a1c 100644 --- a/code/game/objects/items/food/donkpocket.dm +++ b/code/game/objects/items/food/donkpocket.dm @@ -25,6 +25,11 @@ /// The reagents that most child types add when microwaved. Needed because you can't override static lists. var/static/list/child_added_reagents = list(/datum/reagent/medicine/omnizine = 2) +// NON-MODULE CHANGE +/obj/item/food/donkpocket/Initialize(mapload) + . = ..() + ADD_TRAIT(src, TRAIT_FOOD_MUST_INHERIT_CHEF_MADE, INNATE_TRAIT) + /obj/item/food/donkpocket/make_bakeable() AddComponent(/datum/component/bakeable, warm_type, rand(baking_time_short, baking_time_long), TRUE, TRUE, added_reagents) diff --git a/code/game/objects/items/food/misc.dm b/code/game/objects/items/food/misc.dm index 840d431bfa55..d4ea8b1551b7 100644 --- a/code/game/objects/items/food/misc.dm +++ b/code/game/objects/items/food/misc.dm @@ -119,9 +119,21 @@ // We override the parent procs here to prevent burned messes from cooking into burned messes. /obj/item/food/badrecipe/make_grillable() return + /obj/item/food/badrecipe/make_bakeable() return +// Everyone thinks bad recipes are toxic unless you like gross food. +/obj/item/food/badrecipe/make_edible() + . = ..() + AddComponent(/datum/component/edible, check_liked = CALLBACK(src, PROC_REF(check_liked))) + +/obj/item/food/badrecipe/proc/check_liked(mob/living/carbon/human/consumer) + if(consumer.get_liked_foodtypes() & GROSS) + return null + // ignores Ageusia + return FOOD_TOXIC + /obj/item/food/badrecipe/moldy name = "moldy mess" desc = "A rancid, disgusting culture of mold and ants. Somewhere under there, at some point, there was food." diff --git a/code/game/objects/items/food/packaged.dm b/code/game/objects/items/food/packaged.dm index 3ef9606485ad..407c4db97671 100644 --- a/code/game/objects/items/food/packaged.dm +++ b/code/game/objects/items/food/packaged.dm @@ -215,6 +215,11 @@ /// What reagents should be added when this item is warmed? var/static/list/added_reagents = list(/datum/reagent/medicine/omnizine = 3) +// NON-MODULE CHANGE +/obj/item/food/ready_donk/Initialize(mapload) + . = ..() + ADD_TRAIT(src, TRAIT_FOOD_MUST_INHERIT_CHEF_MADE, INNATE_TRAIT) + /obj/item/food/ready_donk/make_bakeable() AddComponent(/datum/component/bakeable, warm_type, rand(15 SECONDS, 20 SECONDS), TRUE, TRUE, added_reagents) diff --git a/code/modules/food_and_drinks/machinery/deep_fryer.dm b/code/modules/food_and_drinks/machinery/deep_fryer.dm index 23423161835d..6ee74c43b13c 100644 --- a/code/modules/food_and_drinks/machinery/deep_fryer.dm +++ b/code/modules/food_and_drinks/machinery/deep_fryer.dm @@ -181,8 +181,8 @@ GLOBAL_LIST_INIT(oilfry_blacklisted_items, typecacheof(list( // Give them reagents to put frying oil in if(isnull(frying.reagents)) frying.create_reagents(50, INJECTABLE) - if(user.mind) - ADD_TRAIT(frying, TRAIT_FOOD_CHEF_MADE, REF(user.mind)) + // NON-MODULE CHANGE + handle_chef_made_food(frying, frying, user.mind) SEND_SIGNAL(frying, COMSIG_ITEM_ENTERED_FRYER) flick("fryer_start", src) // NON-MODULE CHANGE diff --git a/code/modules/food_and_drinks/recipes/food_mixtures.dm b/code/modules/food_and_drinks/recipes/food_mixtures.dm index cf174e89817e..8523f2ebae7f 100644 --- a/code/modules/food_and_drinks/recipes/food_mixtures.dm +++ b/code/modules/food_and_drinks/recipes/food_mixtures.dm @@ -4,8 +4,9 @@ /datum/crafting_recipe/food/on_craft_completion(mob/user, atom/result) SHOULD_CALL_PARENT(TRUE) . = ..() - if(istype(result) && !isnull(user.mind)) - ADD_TRAIT(result, TRAIT_FOOD_CHEF_MADE, REF(user.mind)) + // NON-MODULE CHANGE + if(istype(result)) + handle_chef_made_food(result, result, user.mind) /datum/crafting_recipe/food/New() . = ..() diff --git a/code/modules/jobs/job_types/bartender.dm b/code/modules/jobs/job_types/bartender.dm index be619502a003..5ab31d9a9a46 100644 --- a/code/modules/jobs/job_types/bartender.dm +++ b/code/modules/jobs/job_types/bartender.dm @@ -37,6 +37,7 @@ base_skills = list( /datum/skill/firearms = SKILL_LEVEL_JOURNEYMAN, + /datum/skill/cooking = SKILL_LEVEL_NOVICE, ) /datum/job/bartender/award_service(client/winner, award) diff --git a/code/modules/jobs/job_types/botanist.dm b/code/modules/jobs/job_types/botanist.dm index 253ba2fe0363..92dde32b1b48 100644 --- a/code/modules/jobs/job_types/botanist.dm +++ b/code/modules/jobs/job_types/botanist.dm @@ -41,6 +41,7 @@ base_skills = list( /datum/skill/botany = SKILL_LEVEL_EXPERT, + /datum/skill/cooking = SKILL_LEVEL_NOVICE, ) /datum/outfit/job/botanist diff --git a/code/modules/jobs/job_types/cook.dm b/code/modules/jobs/job_types/cook.dm index 3519660c489d..d5fa958ca8bf 100644 --- a/code/modules/jobs/job_types/cook.dm +++ b/code/modules/jobs/job_types/cook.dm @@ -50,6 +50,7 @@ base_skills = list( /datum/skill/botany = SKILL_LEVEL_JOURNEYMAN, + /datum/skill/cooking = SKILL_LEVEL_EXPERT, // not all NT chefs are gordon ramsay ) /datum/job/cook/award_service(client/winner, award) diff --git a/code/modules/jobs/job_types/detective.dm b/code/modules/jobs/job_types/detective.dm index 6cb536445c82..d5726b3536ca 100644 --- a/code/modules/jobs/job_types/detective.dm +++ b/code/modules/jobs/job_types/detective.dm @@ -51,6 +51,7 @@ base_skills = list( /datum/skill/firearms = SKILL_LEVEL_EXPERT, /datum/skill/first_aid = SKILL_LEVEL_NOVICE, + /datum/skill/surgery = SKILL_LEVEL_NOVICE, ) /datum/outfit/job/detective diff --git a/maplestation.dme b/maplestation.dme index 7d641f446bb6..f31af5f26780 100644 --- a/maplestation.dme +++ b/maplestation.dme @@ -1748,6 +1748,7 @@ #include "code\datums\shuttles\whiteship.dm" #include "code\datums\skills\_skill.dm" #include "code\datums\skills\cleaning.dm" +#include "code\datums\skills\cooking.dm" #include "code\datums\skills\cybernetic.dm" #include "code\datums\skills\electrics.dm" #include "code\datums\skills\firearms.dm" From e9686ce43cdca0a790216f39814201a4a42c185c Mon Sep 17 00:00:00 2001 From: MrMelbert Date: Thu, 27 Mar 2025 16:24:23 -0500 Subject: [PATCH 08/22] E --- code/datums/components/food/edible.dm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/datums/components/food/edible.dm b/code/datums/components/food/edible.dm index aa2532df37b4..b0ad1c6061bd 100644 --- a/code/datums/components/food/edible.dm +++ b/code/datums/components/food/edible.dm @@ -630,9 +630,11 @@ Behavior that's still missing from this component that original food items had t var/special_reaction = check_liked.Invoke(eater) switch(special_reaction) //return early for special foods if(FOOD_LIKED) - return LIKED_FOOD_QUALITY_CHANGE + // NON-MODULE CHANGE + return round(LIKED_FOOD_QUALITY_CHANGE * 1.25) if(FOOD_DISLIKED) - return DISLIKED_FOOD_QUALITY_CHANGE + // NON-MODULE CHANGE + return round(DISLIKED_FOOD_QUALITY_CHANGE * 1.25) if(FOOD_TOXIC) return TOXIC_FOOD_QUALITY_THRESHOLD if(FOOD_ALLERGIC) From b2e67cfd6bc5f204e01a692065512d2aa3543bfb Mon Sep 17 00:00:00 2001 From: MrMelbert Date: Sun, 30 Mar 2025 17:26:24 -0500 Subject: [PATCH 09/22] Fix --- code/datums/components/food/edible.dm | 5 +---- code/datums/mood_events/food_events.dm | 3 ++- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/code/datums/components/food/edible.dm b/code/datums/components/food/edible.dm index b0ad1c6061bd..030bb50669b4 100644 --- a/code/datums/components/food/edible.dm +++ b/code/datums/components/food/edible.dm @@ -595,10 +595,7 @@ Behavior that's still missing from this component that original food items had t // NON-MODULE CHANGES var/atom/owner = parent var/timeout_mod = owner.reagents.get_average_purity(/datum/reagent/consumable) * 1.5 // mood event duration is 100% at average purity of 50% - var/datum/mood_event/event = GLOB.food_quality_events[food_quality] - event = new event.type - event.timeout *= timeout_mod - gourmand.add_mood_event("quality_food", event) + gourmand.add_mood_event("quality_food", GLOB.food_quality_events[food_quality], timeout_mod) gourmand.adjust_disgust(-5 + -2 * food_quality * fraction) var/quality_label = GLOB.food_quality_description[food_quality] to_chat(gourmand, span_notice("That's \an [quality_label] meal.")) diff --git a/code/datums/mood_events/food_events.dm b/code/datums/mood_events/food_events.dm index a0bb563530b3..5180f962e76d 100644 --- a/code/datums/mood_events/food_events.dm +++ b/code/datums/mood_events/food_events.dm @@ -28,7 +28,8 @@ var/quality = FOOD_QUALITY_NORMAL // NON-MODULE CHANGE -/datum/mood_event/food/add_effects(param) +/datum/mood_event/food/add_effects(timeout_mod = 1) + timeout *= timeout_mod mood_change = floor(quality * 1.34) if(HAS_MIND_TRAIT(owner, TRAIT_SNOB)) if(quality <= FOOD_QUALITY_VERYGOOD) From 93b254420b0d4b135bc92ebebcb19e9092346fd7 Mon Sep 17 00:00:00 2001 From: MrMelbert Date: Sun, 30 Mar 2025 23:39:29 -0500 Subject: [PATCH 10/22] Lint --- tgui/packages/tgui/interfaces/NtosSkillTracker.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tgui/packages/tgui/interfaces/NtosSkillTracker.tsx b/tgui/packages/tgui/interfaces/NtosSkillTracker.tsx index 61e105834361..5468af5f1b08 100644 --- a/tgui/packages/tgui/interfaces/NtosSkillTracker.tsx +++ b/tgui/packages/tgui/interfaces/NtosSkillTracker.tsx @@ -111,7 +111,7 @@ export const NtosSkillTracker = () => { {!!skill.reward && ( - +