[Ready] Skillcapes II: Revenge of the broken github: A Skill Menu Special: New Sprites Edition (#50656)

* 10K hours

60,000 minutes
hahah


sure if you want a trailing newline i can do that


default cloak gets default skill


lazy list and no equip good


necessary ig


Update code/datums/skills/_skill.dm

Co-Authored-By: nemvar <47324920+nemvar@users.noreply.github.com>
Update code/datums/skills/gaming.dm

Co-Authored-By: Angust <46400996+Angustmeta@users.noreply.github.com>
WIP PDA skill monitor program


hacky fixes till i refactor skills


refactors skills a bit, adds admin skill edit menu


If you have a failing, it's that you're always demanding perfection

...IF you have a failing
i think that's it for the admin skill manger


appeases lord flord


bruh


level names


FUCK!!


unga


Update code/modules/vehicles/vehicle_key.dm

Co-authored-by: Rohesie <rohesie@gmail.com>
Update code/modules/admin/topic.dm

Co-authored-by: Rohesie <rohesie@gmail.com>
Update code/modules/admin/skill_panel.dm

Co-authored-by: Rohesie <rohesie@gmail.com>
Update code/modules/admin/skill_panel.dm

Co-authored-by: Rohesie <rohesie@gmail.com>
Apply suggestions from code review

frick

Co-authored-by: Rohesie <rohesie@gmail.com>
EOL and dumb spaces


more rohsie bait


tgui: Query Windows Registry for BYOND cache directory

hell yeah brother


update tgui and dmi


CLRF and bat file


typo ig

* tgui and new janicloak that i accdiently changed on another branch

* jani

* gamer cloak

* trim trailing whitespace

* tgui

* bruh

* variable renaming
This commit is contained in:
MrDoomBringer
2020-05-25 20:46:22 -04:00
committed by GitHub
parent 06bd70eb14
commit ceea9b6793
29 changed files with 452 additions and 99 deletions
+2 -1
View File
@@ -48,6 +48,7 @@
#define ADMIN_VV(atom) "(<a href='?_src_=vars;[HrefToken(TRUE)];Vars=[REF(atom)]'>VV</a>)"
#define ADMIN_SM(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];subtlemessage=[REF(user)]'>SM</a>)"
#define ADMIN_TP(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];traitor=[REF(user)]'>TP</a>)"
#define ADMIN_SP(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];skillpanel=[REF(user)]'>TP</a>)"
#define ADMIN_KICK(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];boot2=[REF(user)]'>KICK</a>)"
#define ADMIN_CENTCOM_REPLY(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];CentComReply=[REF(user)]'>RPLY</a>)"
#define ADMIN_SYNDICATE_REPLY(user) "(<a href='?_src_=holder;[HrefToken(TRUE)];SyndicateReply=[REF(user)]'>RPLY</a>)"
@@ -56,7 +57,7 @@
#define ADMIN_LOOKUP(user) "[key_name_admin(user)][ADMIN_QUE(user)]"
#define ADMIN_LOOKUPFLW(user) "[key_name_admin(user)][ADMIN_QUE(user)] [ADMIN_FLW(user)]"
#define ADMIN_SET_SD_CODE "(<a href='?_src_=holder;[HrefToken(TRUE)];set_selfdestruct_code=1'>SETCODE</a>)"
#define ADMIN_FULLMONTY_NONAME(user) "[ADMIN_QUE(user)] [ADMIN_PP(user)] [ADMIN_VV(user)] [ADMIN_SM(user)] [ADMIN_FLW(user)] [ADMIN_TP(user)] [ADMIN_INDIVIDUALLOG(user)] [ADMIN_SMITE(user)]"
#define ADMIN_FULLMONTY_NONAME(user) "[ADMIN_QUE(user)] [ADMIN_PP(user)] [ADMIN_VV(user)] [ADMIN_SM(user)] [ADMIN_FLW(user)] [ADMIN_SP(user)] [ADMIN_TP(user)] [ADMIN_INDIVIDUALLOG(user)] [ADMIN_SMITE(user)]"
#define ADMIN_FULLMONTY(user) "[key_name_admin(user)] [ADMIN_FULLMONTY_NONAME(user)]"
#define ADMIN_JMP(src) "(<a href='?_src_=holder;[HrefToken(TRUE)];adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>)"
#define COORD(src) "[src ? "([src.x],[src.y],[src.z])" : "nonexistent location"]"
+12 -15
View File
@@ -1,27 +1,24 @@
// Skill levels
#define SKILL_LEVEL_NONE 0
#define SKILL_LEVEL_NOVICE 1
#define SKILL_LEVEL_APPRENTICE 2
#define SKILL_LEVEL_JOURNEYMAN 3
#define SKILL_LEVEL_EXPERT 4
#define SKILL_LEVEL_MASTER 5
#define SKILL_LEVEL_LEGENDARY 6
#define SKILL_LEVEL_NONE 1
#define SKILL_LEVEL_NOVICE 2
#define SKILL_LEVEL_APPRENTICE 3
#define SKILL_LEVEL_JOURNEYMAN 4
#define SKILL_LEVEL_EXPERT 5
#define SKILL_LEVEL_MASTER 6
#define SKILL_LEVEL_LEGENDARY 7
//Skill experience thresholds
#define SKILL_EXP_NOVICE 100
#define SKILL_EXP_APPRENTICE 250
#define SKILL_EXP_JOURNEYMAN 500
#define SKILL_EXP_EXPERT 900
#define SKILL_EXP_MASTER 1500
#define SKILL_EXP_LEGENDARY 2500
#define SKILL_LVL 1
#define SKILL_EXP 2
//Allows us to get EXP from level, or level from EXP
#define SKILL_EXP_LIST list(0, 100, 250, 500, 900, 1500, 2500)
//Skill modifier types
#define SKILL_SPEED_MODIFIER "skill_speed_modifier"//ideally added/subtracted in speed calculations to make you do stuff faster
#define SKILL_PROBS_MODIFIER "skill_probability_modifier"//ideally added/subtracted where beneficial in prob(x) calls
#define SKILL_RANDS_MODIFIER "skill_randomness_modifier"//ideally added/subtracted where beneficial in rand(x,y) calls
// Gets the reference for the skill type that was given
#define GetSkillRef(A) (SSskills.all_skills[A])
+9 -8
View File
@@ -822,11 +822,12 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
catch
return
/proc/num2loadingbar(percent as num, var/numSquares = 20)
var/loadstring = ""
for (var/i in 1 to numSquares)
if (i <= numSquares - percent*numSquares)
loadstring += "▮"
else
loadstring += "▯"
return "\[" + loadstring + "]"
/proc/num2loadingbar(percent as num, var/numSquares = 20, var/reverse = FALSE)
var/loadstring = ""
for (var/i in 1 to numSquares)
var/limit = reverse ? numSquares - percent*numSquares : percent*numSquares
if (i <= limit)
loadstring += "█"
else
loadstring += "░"
return "\[" + loadstring + "]"
+3 -4
View File
@@ -8,9 +8,8 @@ SUBSYSTEM_DEF(skills)
init_order = INIT_ORDER_SKILLS
///Dictionary of skill.type || skill ref
var/list/all_skills = list()
///Static assoc list of levels (ints) - strings
var/list/level_names = list("Novice", "Apprentice", "Journeyman", "Expert", "Master", "Legendary")//This list is already in the right order, due to indexing
///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]
/datum/controller/subsystem/skills/Initialize(timeofday)
InitializeSkills()
@@ -18,6 +17,6 @@ SUBSYSTEM_DEF(skills)
///Ran on initialize, populates the skills dictionary
/datum/controller/subsystem/skills/proc/InitializeSkills(timeofday)
for(var/type in subtypesof(/datum/skill))
for(var/type in GLOB.skill_types)
var/datum/skill/ref = new type
all_skills[type] = ref
+58 -36
View File
@@ -67,15 +67,16 @@
var/list/learned_recipes //List of learned recipe TYPES.
///Assoc list of skills - level
///List of skills the user has recieved a reward for. Should not be used to keep track of currently known skills. Lazy list because it shouldnt be filled often
var/list/skills_rewarded
///Assoc list of skills. Use SKILL_LVL to access level, and SKILL_EXP to access skill's exp.
var/list/known_skills = list()
///Assoc list of skills - exp
var/list/skill_experience = list()
/datum/mind/New(key)
src.key = key
soulOwner = src
martial_art = default_martial_art
init_known_skills()
/datum/mind/Destroy()
SSticker.minds -= src
@@ -123,62 +124,83 @@
new_character.key = key //now transfer the key to link the client to our new body
current.update_atom_languages()
/datum/mind/proc/init_known_skills()
for (var/type in GLOB.skill_types)
known_skills[type] = list(SKILL_LEVEL_NONE, 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)
var/lvl = update_skill_level(skill)
if (lvl >= length(SKILL_EXP_LIST)) //If we're already past the last exp threshold
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)
/datum/mind/proc/adjust_experience(skill, amt, silent = FALSE, force_old_level = 0)
var/datum/skill/S = GetSkillRef(skill)
skill_experience[S] = max(0, skill_experience[S] + amt) //Prevent going below 0
var/old_level = known_skills[S]
switch(skill_experience[S])
if(SKILL_EXP_LEGENDARY to INFINITY)
known_skills[S] = SKILL_LEVEL_LEGENDARY
if(SKILL_EXP_MASTER to SKILL_EXP_LEGENDARY)
known_skills[S] = SKILL_LEVEL_MASTER
if(SKILL_EXP_EXPERT to SKILL_EXP_MASTER)
known_skills[S] = SKILL_LEVEL_EXPERT
if(SKILL_EXP_JOURNEYMAN to SKILL_EXP_EXPERT)
known_skills[S] = SKILL_LEVEL_JOURNEYMAN
if(SKILL_EXP_APPRENTICE to SKILL_EXP_JOURNEYMAN)
known_skills[S] = SKILL_LEVEL_APPRENTICE
if(SKILL_EXP_NOVICE to SKILL_EXP_APPRENTICE)
known_skills[S] = SKILL_LEVEL_NOVICE
if(0 to SKILL_EXP_NOVICE)
known_skills[S] = SKILL_LEVEL_NONE
if(isnull(old_level) || known_skills[S] == old_level)
return //same level or we just started earning xp towards the first level.
var/old_level = force_old_level ? force_old_level : known_skills[skill][SKILL_LVL] //Get current level of the S skill
known_skills[skill][SKILL_EXP] = max(0, known_skills[skill][SKILL_EXP] + amt) //Update exp. Prevent going below 0
known_skills[skill][SKILL_LVL] = update_skill_level(skill)//Check what the current skill level is based on that skill's exp
if(silent)
return
if(known_skills[S] >= old_level)
S.level_gained(src, known_skills[S], old_level)
else
S.level_lost(src, known_skills[S], old_level)
if(known_skills[skill][SKILL_LVL] > old_level)
S.level_gained(src, known_skills[skill][SKILL_LVL], old_level)
else if(known_skills[skill][SKILL_LVL] < old_level)
S.level_lost(src, known_skills[skill][SKILL_LVL], old_level)
///Set experience of a specific skill to a number
/datum/mind/proc/set_experience(skill, amt, silent = FALSE)
var/old_level = known_skills[skill][SKILL_EXP]
known_skills[skill][SKILL_EXP] = amt
adjust_experience(skill, 0, silent, old_level) //Make a call to adjust_experience to handle updating level
///Set level of a specific skill
/datum/mind/proc/set_level(skill, newlevel, silent = FALSE)
var/oldlevel = get_skill_level(skill)
var/difference = SKILL_EXP_LIST[newlevel] - SKILL_EXP_LIST[oldlevel]
adjust_experience(skill, difference, silent)
///Check what the current skill level is based on that skill's exp
/datum/mind/proc/update_skill_level(skill)
var/i = 0
for (var/exp in SKILL_EXP_LIST)
i ++
if (known_skills[skill][SKILL_EXP] >= SKILL_EXP_LIST[i])
continue
return i - 1 //Return level based on the last exp requirement that we were greater than
return i //If we had greater EXP than even the last exp threshold, we return the last level
///Gets the skill's singleton and returns the result of its get_skill_modifier
/datum/mind/proc/get_skill_modifier(skill, modifier)
var/datum/skill/S = GetSkillRef(skill)
return S.get_skill_modifier(modifier, known_skills[S] || SKILL_LEVEL_NONE)
return S.get_skill_modifier(modifier, known_skills[skill][SKILL_LVL])
///Gets the player's current level number from the relevant skill
/datum/mind/proc/get_skill_level(skill)
var/datum/skill/S = GetSkillRef(skill)
return known_skills[S] || SKILL_LEVEL_NONE
return known_skills[skill][SKILL_LVL]
///Gets the player's current exp from the relevant skill
/datum/mind/proc/get_skill_exp(skill)
return known_skills[skill][SKILL_EXP]
/datum/mind/proc/get_skill_level_name(skill)
var/level = get_skill_level(skill)
return SSskills.level_names[level]
/datum/mind/proc/print_levels(user)
var/list/shown_skills = list()
for(var/i in known_skills)
if(known_skills[i]) //Do we actually have a level in this?
if(known_skills[i][SKILL_LVL] > SKILL_LEVEL_NONE) //Do we actually have a level in this?
shown_skills += i
if(!length(shown_skills))
to_chat(user, "<span class='notice'>You don't seem to have any particularly outstanding skills.</span>")
return
var/msg = ""
msg += "<span class='info'>*---------*\n<EM>Your skills</EM></span>\n<span class='notice'>"
var/msg = "<span class='info'>*---------*\n<EM>Your skills</EM></span>\n<span class='notice'>"
for(var/i in shown_skills)
var/datum/skill/S = i
msg += "[i] - [SSskills.level_names[known_skills[S]]]\n"
msg += "[i] - [get_skill_level_name(i)]\n"
msg += "</span>"
to_chat(user, msg)
/datum/mind/proc/set_death_time()
last_death = world.time
+61 -5
View File
@@ -1,10 +1,42 @@
GLOBAL_LIST_INIT(skill_types, subtypesof(/datum/skill))
/datum/skill
var/name = "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 cape reward that will appear when a user finishes leveling up a skill
var/skill_cape_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()
/datum/skill/proc/get_skill_modifier(modifier, level)
return modifiers[modifier][level+1] //+1 because lists start at 1
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 class='nicegreen'>What the hell is [name]? Tell an admin if you see this message.</span>", //This first index shouldn't ever really be used
"<span class='nicegreen'>I'm starting to figure out what [name] really is!</span>",
"<span class='nicegreen'>I'm getting a little better at [name]!</span>",
"<span class='nicegreen'>I'm getting much better at [name]!</span>",
"<span class='nicegreen'>I feel like I've become quite proficient at [name]!</span>",
"<span class='nicegreen'>After lots of practice, I've begun to truly understand the intricies \
and surprising depth behind [name]. I now condsider myself a master [title].</span>",
"<span class='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]!</span>" )
levelDownMessages = list("<span class='nicegreen'>I have somehow completely lost all understanding of [name]. Please tell an admin if you see this.</span>",
"<span class='nicegreen'>I'm starting to forget what [name] really even is. I need more practice...</span>",
"<span class='nicegreen'>I'm getting a little worse at [name]. I'll need to keep practicing to get better at it...</span>",
"<span class='nicegreen'>I'm getting a little worse at [name]...</span>",
"<span class='nicegreen'>I'm losing my [name] expertise ....</span>",
"<span class='nicegreen'>I feel like I'm losing my mastery of [name].</span>",
"<span class='nicegreen'>I feel as though my legendary [name] skills have deteriorated. I'll need more intense training to recover my lost skills.</span>" )
/**
* level_gained: Gives skill levelup messages to the user
@@ -16,10 +48,34 @@
* * old_level - Similar to the above, but the level you had before levelling up.
*/
/datum/skill/proc/level_gained(var/datum/mind/mind, new_level, old_level)//just for announcements (doesn't go off if the xp gain is silent)
to_chat(mind.current, "<span class='nicegreen'>I feel like I've become more proficient at [name]!</span>")
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
/**
* level_lost: See level_gained, same idea but fires on skill level-down
*/
/datum/skill/proc/level_lost(var/datum/mind/mind, new_level, old_level)
to_chat(mind.current, "<span class='warning'>I feel like I've become worse at [name]!</span>")
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
/**
* try_skill_reward: Checks to see if a user is eligable for a tangible reward for reaching a certain skill level
*
* Currently gives the user a special cloak when they reach a legendary level at any given skill
* Arguments:
* * mind - The mind that you'll want to send messages and rewards to
* * new_level - The current level of the user. Used to check if it meets the requirements for a reward
*/
/datum/skill/proc/try_skill_reward(var/datum/mind/mind, new_level)
if (new_level != SKILL_LEVEL_LEGENDARY)
return
if (!ispath(skill_cape_path))
to_chat(mind.current, "<span class='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.</span>")
return
if (LAZYFIND(mind.skills_rewarded, src.type))
to_chat(mind.current, "<span class='nicegreen'>It seems the Professional [title] Association won't send me another status symbol.</span>")
return
var/obj/structure/closet/supplypod/bluespacepod/pod = new()
pod.landingDelay = 150
pod.explosionSize = list(0,0,0,0)
to_chat(mind.current, "<span class='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.</span>")
var/turf/T = get_turf(mind.current)
new /obj/effect/DPtarget(T, pod , new skill_cape_path(T))
LAZYADD(mind.skills_rewarded, src.type)
+3 -1
View File
@@ -1,4 +1,6 @@
/datum/skill/cleaning
name = "Scrubbing"
name = "Cleaning"
title = "Cleaner"
desc = "Its 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
skill_cape_path = /obj/item/clothing/neck/cloak/skill_reward/cleaning
+7 -9
View File
@@ -1,15 +1,13 @@
/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))
skill_cape_path = /obj/item/clothing/neck/cloak/skill_reward/gaming
/datum/skill/gaming/level_gained(var/datum/mind/mind, new_level, old_level)
switch(new_level)
if(SKILL_LEVEL_JOURNEYMAN)//gives slight extra perks outside roll modifiers
to_chat(mind.current, "<span class='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...</span>")
if(SKILL_LEVEL_LEGENDARY)//leads to a mysterious power...
to_chat(mind.current, "<span class='nicegreen'>Maybe gamerfuel actually would help me play better...</span>")
else
to_chat(mind.current, "<span class='nicegreen'>I'm getting better at these arcade games!</span>")
/datum/skill/gaming/New()
. = ..()
levelUpMessages[1] = "<span class='nicegreen'>I'm starting to get a hang of the controls of these games...</span>"
levelUpMessages[4] = "<span class='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...</span>"
levelUpMessages[6] = "<span class='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..?</span>"
+4 -2
View File
@@ -1,4 +1,6 @@
/datum/skill/medical
name = "Medical"
/datum/skill/healing
name = "Healing"
title = "Healer"
desc = "From Bandaids to biopsies, this improves your ability to get people back up both in the field and on the operating table."
modifiers = list(SKILL_SPEED_MODIFIER = list(1, 0.95, 0.9, 0.85, 0.75, 0.6, 0.5))
skill_cape_path = /obj/item/clothing/neck/cloak/skill_reward/healing
+2
View File
@@ -1,4 +1,6 @@
/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))
skill_cape_path = /obj/item/clothing/neck/cloak/skill_reward/mining
+38 -1
View File
@@ -251,6 +251,7 @@ GLOBAL_LIST_EMPTY(PDAs)
dat += "<ul>"
dat += "<li><a href='byond://?src=[REF(src)];choice=1'>[PDAIMG(notes)]Notekeeper</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=2'>[PDAIMG(mail)]Messenger</a></li>"
dat += "<li><a href='byond://?src=[REF(src)];choice=6'>[PDAIMG(skills)]Skill Tracker</a></li>"
if (cartridge)
if (cartridge.access & CART_CLOWN)
@@ -356,7 +357,33 @@ GLOBAL_LIST_EMPTY(PDAs)
dat += "None detected.<br>"
else if(cartridge && cartridge.spam_enabled)
dat += "<a href='byond://?src=[REF(src)];choice=MessageAll'>Send To All</a>"
if(6)
dat += "<h4>[PDAIMG(mail)] ExperTrak® Skill Tracker V4.26.2</h4>"
dat += "<i>Thank you for choosing ExperTrak® brand software! ExperTrak® inc. is proud to be a NanoTrasen employee expertise and effectiveness department subsidary!</i>"
dat += "<br><br>This software is designed to track and monitor your skill development as a NanoTrasen employee. Your job performance across different fields has been quantified and categorized below.<br>"
var/datum/mind/targetmind = 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]
dat += "<HR><b>[S.name]</b>"
dat += "<br><i>[S.desc]</i>"
dat += "<ul><li>EMPLOYEE SKILL LEVEL: <b>[lvl_name]</b>"
if (exp && xp_req_to_level)
var/progress_percent = (xp_req_to_level-xp_prog_to_level)/xp_req_to_level
var/overall_percent = exp / SKILL_EXP_LIST[length(SKILL_EXP_LIST)]
dat += "<br>PROGRESS TO NEXT SKILL LEVEL:"
dat += "<br>" + num2loadingbar(progress_percent) + "([progress_percent*100])%"
dat += "<br>OVERALL DEVELOPMENT PROGRESS:"
dat += "<br>" + num2loadingbar(overall_percent) + "([overall_percent*100])%"
if (lvl_num >= length(SKILL_EXP_LIST) && !(type in targetmind.skills_rewarded))
dat += "<br><a href='byond://?src=[REF(src)];choice=SkillReward;skill=[type]'>Contact the Professional [S.title] Association</a>"
dat += "</li></ul>"
if(21)
dat += "<h4>[PDAIMG(mail)] SpaceMessenger V3.9.6</h4>"
dat += "<a href='byond://?src=[REF(src)];choice=Clear'>[PDAIMG(blank)]Clear Messages</a>"
@@ -571,6 +598,7 @@ GLOBAL_LIST_EMPTY(PDAs)
M.close()
//pAI FUNCTIONS===================================
if("pai")
switch(href_list["option"])
if("1") // Configure pAI device
@@ -579,6 +607,15 @@ GLOBAL_LIST_EMPTY(PDAs)
usr.put_in_hands(pai)
to_chat(usr, "<span class='notice'>You remove the pAI from the [name].</span>")
//SKILL FUNCTIONS===================================
if("SkillReward")
var/type = text2path(href_list["skill"])
var/datum/skill/S = GetSkillRef(type)
var/datum/mind/mind = U.mind
var/new_level = mind.get_skill_level(type)
S.try_skill_reward(mind, new_level)
//LINK FUNCTIONS===================================
else//Cartridge menu linking
+2 -2
View File
@@ -37,7 +37,7 @@
return
if(heal(M, user))
user?.mind.adjust_experience(/datum/skill/medical, experience_given)
user?.mind.adjust_experience(/datum/skill/healing, experience_given)
log_combat(user, M, "healed", src.name)
use(1)
if(repeating && amount > 0)
@@ -58,7 +58,7 @@
user.visible_message("<span class='green'>[user] applies \the [src] on [C]'s [affecting.name].</span>", "<span class='green'>You apply \the [src] on [C]'s [affecting.name].</span>")
var/brute2heal = brute
var/burn2heal = burn
var/skill_mod = user?.mind?.get_skill_modifier(/datum/skill/medical, SKILL_SPEED_MODIFIER)
var/skill_mod = user?.mind?.get_skill_modifier(/datum/skill/healing, SKILL_SPEED_MODIFIER)
if(skill_mod)
brute2heal *= (2-skill_mod)
burn2heal *= (2-skill_mod)
+23 -9
View File
@@ -60,6 +60,7 @@
body += "<a href='?_src_=vars;[HrefToken()];Vars=[REF(M)]'>VV</a> - "
if(M.mind)
body += "<a href='?_src_=holder;[HrefToken()];traitor=[REF(M)]'>TP</a> - "
body += "<a href='?_src_=holder;[HrefToken()];skill=[REF(M)]'>SKILLS</a> - "
else
body += "<a href='?_src_=holder;[HrefToken()];initmind=[REF(M)]'>Init Mind</a> - "
if (iscyborg(M))
@@ -739,22 +740,35 @@
log_admin("[key_name(usr)] spawned cargo pack [chosen] at [AREACOORD(usr)]")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Spawn Cargo") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/admins/proc/show_traitor_panel(mob/M in GLOB.mob_list)
/datum/admins/proc/show_traitor_panel(mob/target_mob in GLOB.mob_list)
set category = "Admin - Game"
set desc = "Edit mobs's memory and role"
set name = "Show Traitor Panel"
if(!istype(M))
to_chat(usr, "This can only be used on instances of type /mob", confidential = TRUE)
return
if(!M.mind)
var/datum/mind/target_mind = target_mob.mind
if(!target_mind)
to_chat(usr, "This mob has no mind!", confidential = TRUE)
return
M.mind.traitor_panel()
if(!istype(target_mob) && !istype(target_mind))
to_chat(usr, "This can only be used on instances of type /mob and /mind", confidential = TRUE)
return
target_mind.traitor_panel()
SSblackbox.record_feedback("tally", "admin_verb", 1, "Traitor Panel") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/admins/proc/show_skill_panel(var/target)
set category = "Admin - Game"
set desc = "Edit mobs's experience and skill levels"
set name = "Show Skill Panel"
var/datum/mind/target_mind
if(ismob(target))
var/mob/target_mob = target
target_mind = target_mob.mind
else if (istype(target, /datum/mind))
target_mind = target
else
to_chat(usr, "This can only be used on instances of type /mob and /mind", confidential = TRUE)
return
var/datum/skill_panel/SP = new(usr, target_mind)
SP.ui_interact(usr)
/datum/admins/proc/toggletintedweldhelmets()
set category = "Debug"
+1
View File
@@ -180,6 +180,7 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
/client/proc/reset_ooc,
/client/proc/deadmin,
/datum/admins/proc/show_traitor_panel,
/datum/admins/proc/show_skill_panel,
/datum/admins/proc/toggleenter,
/datum/admins/proc/toggleguests,
/datum/admins/proc/announce,
+1
View File
@@ -83,6 +83,7 @@
body += "<a href='?_src_=holder;[HrefToken()];adminplayeropts="+ref+"'>PP</a> - "
body += "<a href='?_src_=holder;[HrefToken()];showmessageckey="+ckey+"'>N</a> - "
body += "<a href='?_src_=vars;[HrefToken()];Vars="+ref+"'>VV</a> - "
body += "<a href='?_src_=vars;[HrefToken()];skill="+ref+"'>SP</a> - "
body += "<a href='?_src_=holder;[HrefToken()];traitor="+ref+"'>TP</a> - "
if (job == "Cyborg")
body += "<a href='?_src_=holder;[HrefToken()];borgpanel="+ref+"'>BP</a> - "
+55
View File
@@ -0,0 +1,55 @@
/datum/skill_panel
var/datum/mind/targetmind
var/client/holder //client of whoever is using this datum
/datum/skill_panel/New(user, datum/mind/mind)//H can either be a client or a mob due to byondcode(tm)
targetmind = mind
if (istype(user,/client))
var/client/userClient = user
holder = userClient //if its a client, assign it to holder
else
var/mob/userMob = user
holder = userMob.client //if its a mob, assign the mob's client to holder
/datum/skill_panel/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, \
force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.admin_state)//ui_interact is called when the client verb is called.
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "SkillPanel", "Manage Skills", 600, 500, master_ui, state)
ui.open()
/datum/skill_panel/ui_data(mob/user) //Sends info about the skills to UI
. = 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.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)]))
/datum/skill_panel/ui_act(action, params)
. = ..()
if(.)
return
switch (action)
if ("adj_exp")
var/skill = text2path(params["skill"])
var/number = input("Please insert the amount of experience you'd like to add/subtract:") as num|null
if (number)
targetmind.adjust_experience(skill, number)
if ("set_exp")
var/skill = text2path(params["skill"])
var/number = input("Please insert the number you want to set the player's exp to:") as num|null
if (number)
targetmind.set_experience(skill, number)
if ("set_lvl")
var/skill = text2path(params["skill"])
var/max_skill = length(SKILL_EXP_LIST)
var/number = input("Please insert a whole number between 1 (NONE) and [max_skill] (LEGENDARY) corresponding to the level you'd like to set the player to.") as num|null
if (number > 0 && number <= max_skill )
targetmind.set_level(skill, number)
+20
View File
@@ -1545,6 +1545,26 @@
else
show_traitor_panel(M)
else if(href_list["skill"])
if(!check_rights(R_ADMIN))
return
if(!SSticker.HasRoundStarted())
alert("The game hasn't started yet!")
return
var/target = locate(href_list["skill"])
var/datum/mind/target_mind
if(ismob(target))
var/mob/target_mob = target
target_mind = target_mob.mind
else if (istype(target, /datum/mind))
target_mind = target
else
to_chat(usr, "This can only be used on instances of type /mob and /mind", confidential = TRUE)
return
show_skill_panel(target_mind)
else if(href_list["borgpanel"])
if(!check_rights(R_ADMIN))
return
@@ -71,6 +71,7 @@
"refresh" = 'icons/pda_icons/pda_refresh.png',
"scanner" = 'icons/pda_icons/pda_scanner.png',
"signaler" = 'icons/pda_icons/pda_signaler.png',
"skills" = 'icons/pda_icons/pda_skills.png',
"status" = 'icons/pda_icons/pda_status.png',
"dronephone" = 'icons/pda_icons/pda_dronephone.png',
"emoji" = 'icons/pda_icons/pda_emoji.png'
+45
View File
@@ -89,3 +89,48 @@
heat_protection = HEAD
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
resistance_flags = FIRE_PROOF | ACID_PROOF
/obj/item/clothing/neck/cloak/skill_reward
var/associated_skill_path = /datum/skill
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE
/obj/item/clothing/neck/cloak/skill_reward/examine(mob/user)
. = ..()
. += "<span class='notice'>You notice a powerful aura about this cloak, suggesting that only the truly experienced may wield it.</span>"
/obj/item/clothing/neck/cloak/skill_reward/equipped(mob/user, slot)
if (user.mind?.get_skill_level(associated_skill_path) < SKILL_LEVEL_LEGENDARY)
to_chat(user, "<span class = 'notice'>You feel completely and utterly unworthy to even touch \the [src].</span>")
user.dropItemToGround(src, TRUE)
return FALSE
return ..()
/obj/item/clothing/neck/cloak/skill_reward/attack_hand(mob/user)
if (user.mind?.get_skill_level(associated_skill_path) < SKILL_LEVEL_LEGENDARY)
to_chat(user, "<span class = 'notice'>You feel completely and utterly unworthy to even touch \the [src]!</span>")
return FALSE
return ..()
/obj/item/clothing/neck/cloak/skill_reward/gaming
name = "legendary gamer's cloak"
desc = "Worn by the most skilled professional gamers on the station, this legendary cloak is only attainable by achieving true gaming enlightenment. This status symbol represents the awesome might of a being of focus, commitment, and sheer fucking will. Something casual gamers will never begin to understand."
icon_state = "gamercloak"
associated_skill_path = /datum/skill/gaming
/obj/item/clothing/neck/cloak/skill_reward/cleaning
name = "legendary cleaner's cloak"
desc = "Worn by the most skilled of custodians, this legendary cloak is only attainable by achieving janitorial enlightenment. This status symbol represents a being not only extensively trained in grime combat, but one who is willing to use an entire aresenal of cleaning supplies to its full extent to wipe grime's miserable ass off the face of the station."
icon_state = "cleanercloak"
associated_skill_path = /datum/skill/cleaning
/obj/item/clothing/neck/cloak/skill_reward/healing
name = "legendary healer's cloak"
desc = "Worn by the most skilled healers, this legendary cloak is only attainable by achieving true medical enlightenment. This status symbol represents a being who has saved enough lives to repopulate a small country, a being who could transplant a monkey's brain into your skull faster than you could yell ;HELP SEC."
icon_state = "healercloak"
associated_skill_path = /datum/skill/healing
/obj/item/clothing/neck/cloak/skill_reward/mining
name = "legendary miner's cloak"
desc = "Worn by the most skilled miners, this legendary cloak is only attainable by achieving true mineral enlightenment. This status symbol represents a being who has forgotten more about rocks than most miners will ever know, a being who has moved mountains and filled valleys."
icon_state = "minercloak"
associated_skill_path = /datum/skill/mining
@@ -223,7 +223,7 @@
/mob/living/simple_animal/cow/wisdom/attack_hand(mob/living/carbon/M)
if(!stat && M.a_intent == INTENT_HELP)
to_chat(M, "<span class='nicegreen'>[src] whispers you some intense wisdoms and then disappears!</span>")
M.mind?.adjust_experience(pick(subtypesof(/datum/skill)), 500)
M.mind?.adjust_experience(pick(GLOB.skill_types), 500)
do_smoke(1, get_turf(src))
qdel(src)
return
+1 -1
View File
@@ -27,5 +27,5 @@
var/obj/item/bodypart/target_limb = surgery.operated_bodypart
target_limb.drop_limb()
if(user.mind)
user.mind.adjust_experience(/datum/skill/medical, experience_given)
user.mind.adjust_experience(/datum/skill/healing, experience_given)
return ..()
+1 -1
View File
@@ -36,7 +36,7 @@
"<span class='notice'>[user] begins to <i>carefully</i> make an incision in [target]'s [parse_zone(target_zone)].</span>")
/datum/surgery_step/incise/nobleed/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results)
user?.mind.adjust_experience(/datum/skill/medical, experience_given)
user?.mind.adjust_experience(/datum/skill/healing, experience_given)
return TRUE
//clamp bleeders
+2 -2
View File
@@ -78,7 +78,7 @@
implement_speed_mod = implements[implement_type] / 100.0
speed_mod /= (get_location_modifier(target) * (1 + surgery.speed_modifier) * implement_speed_mod)
var/modded_time = time * speed_mod * user.mind.get_skill_modifier(/datum/skill/medical, SKILL_SPEED_MODIFIER)
var/modded_time = time * speed_mod * user.mind.get_skill_modifier(/datum/skill/healing, SKILL_SPEED_MODIFIER)
fail_prob = min(max(0, modded_time - (time * SURGERY_SLOWDOWN_CAP_MULTIPLIER)),99)//if modded_time > time * modifier, then fail_prob = modded_time - time*modifier. starts at 0, caps at 99
@@ -122,7 +122,7 @@
display_results(user, target, "<span class='notice'>You succeed.</span>",
"<span class='notice'>[user] succeeds!</span>",
"<span class='notice'>[user] finishes.</span>")
user?.mind.adjust_experience(/datum/skill/medical, round(experience_given))
user?.mind.adjust_experience(/datum/skill/healing, round(experience_given))
return TRUE
/datum/surgery_step/proc/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, var/fail_prob = 0)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

+1
View File
@@ -1291,6 +1291,7 @@
#include "code\modules\admin\player_panel.dm"
#include "code\modules\admin\poll_management.dm"
#include "code\modules\admin\secrets.dm"
#include "code\modules\admin\skill_panel.dm"
#include "code\modules\admin\sound_emitter.dm"
#include "code\modules\admin\sql_ban_system.dm"
#include "code\modules\admin\sql_message_system.dm"
@@ -0,0 +1,98 @@
import { useBackend } from '../backend';
import { Box, Button, LabeledList, ProgressBar, Section } from '../components';
import { Window } from '../layouts';
const skillgreen = {
color: 'lightgreen',
fontWeight: 'bold',
};
const skillyellow = {
color: '#FFDB58',
fontWeight: 'bold',
};
export const SkillPanel = (props, context) => {
const { act, data } = useBackend(context);
const skills = data.skills || [];
return (
<Window resizable>
<Window.Content scrollable>
<Section title={skills.playername}>
<LabeledList>
{skills.map(skill => (
<LabeledList.Item key={skill.name} label={skill.name}>
<span style={skillyellow}>
{skill.desc}
</span>
<br />
<Level skill_lvl_num={skill.lvlnum} skill_lvl={skill.lvl} />
<br />
Total Experience: [{skill.exp} XP]
<br />
XP To Next Level: 
{skill.exp_req !== 0 ? (
<span>
[{skill.exp_prog} / {skill.exp_req}]
</span>
) : (
<span style={skillgreen}>
[MAXXED]
</span>
)}
<br />
Overall Skill Progress: [{skill.exp} / {skill.max_exp}]
<ProgressBar
value={skill.exp_percent}
color="good" />
<br />
<Button
content="Adjust Exp"
onClick={() => act('adj_exp', {
skill: skill.path,
})} />
<Button
content="Set Exp"
onClick={() => act('set_exp', {
skill: skill.path,
})} />
<Button
content="Set Level"
onClick={() => act('set_lvl', {
skill: skill.path,
})} />
<br />
<br />
</LabeledList.Item>
))}
</LabeledList>
</Section>
</Window.Content>
</Window>
);
};
const Level = (props, context) => {
const { act, data } = useBackend(context);
const {
skill_lvl_num,
skill_lvl,
} = props;
let textstyle="font-weight:bold; color:hsl("+skill_lvl_num*50+", 50%, 50%)";
return (
<span>Level: [<span style={textstyle}>{skill_lvl}</span>]</span>
);
};
const XPToNextLevel = (props, context) => {
const { act, data } = useBackend(context);
const {
xp_req,
xp_prog,
} = props;
if (xp_req === 0) {
return (
<span style={skillgreen}>
to next level: MAXXED
</span>
);
}
return (
<span>XP to next level: [{xp_prog} / {xp_req}]</span>
);
};
File diff suppressed because one or more lines are too long