Skip to content
This repository was archived by the owner on May 22, 2025. It is now read-only.

Commit 827e14b

Browse files
skill update part 2 (#22956)
* skill issue * more stuff * not so much
1 parent 1d8e4c9 commit 827e14b

File tree

19 files changed

+206
-46
lines changed

19 files changed

+206
-46
lines changed

code/__DEFINES/skills.dm

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,6 @@
2525

2626
/// Experience required to increase your skills by one level. Increases exponentially the higher your level already is.
2727
#define EXPERIENCE_PER_LEVEL 500
28+
29+
/// Calculates how much experience is required to reach a given level.
30+
#define EXP_REQ_CALC(level) (EXPERIENCE_PER_LEVEL * (((2**(level + 1)) / 2) - 1))

code/_onclick/hud/screen_objects.dm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@
155155
data["skills"] = skill_data
156156
data["skill_points"] = user.mind.skill_points
157157
data["allocated_points"] = allocated_points
158-
data["exceptional_skill"] = HAS_MIND_TRAIT(user, TRAIT_EXCEPTIONAL_SKILL)
158+
data["skill_cap"] = EXP_MASTER + HAS_MIND_TRAIT(user, TRAIT_EXCEPTIONAL_SKILL)
159159
return data
160160

161161
/atom/movable/screen/skill_menu/ui_static_data(mob/user)
@@ -199,7 +199,7 @@
199199
return TRUE
200200
if(allocated_points + params["amount"] < 0)
201201
return TRUE
202-
if(allocated_skills[params["skill"]] + params["amount"] + user.get_skill(params["skill"]) > (4 + HAS_MIND_TRAIT(user, TRAIT_EXCEPTIONAL_SKILL)))
202+
if(allocated_skills[params["skill"]] + params["amount"] + user.get_skill(params["skill"]) > (EXP_MASTER + HAS_MIND_TRAIT(user, TRAIT_EXCEPTIONAL_SKILL)))
203203
return TRUE
204204
if(allocated_skills[params["skill"]] + params["amount"] < 0)
205205
return TRUE

code/datums/mind.dm

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
SKILL_FITNESS = EXP_NONE,
6060
)
6161

62-
/// Progress towards increasing their skill level
62+
/// Progress towards increasing their skill level.
6363
var/list/exp_progress = list(
6464
SKILL_PHYSIOLOGY = 0,
6565
SKILL_MECHANICAL = 0,
@@ -68,6 +68,9 @@
6868
SKILL_FITNESS = 0,
6969
)
7070

71+
/// One-time experience gains that have already been acquired.
72+
var/list/exp_sources = list()
73+
7174
/// Free skill points to allocate
7275
var/skill_points = 0
7376

@@ -118,6 +121,7 @@
118121
key = _key
119122
soulOwner = src
120123
martial_art = default_martial_art
124+
RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_EXCEPTIONAL_SKILL), PROC_REF(update_skills))
121125

122126
/datum/mind/Destroy()
123127
SSticker.minds -= src
@@ -804,25 +808,47 @@
804808
return FALSE
805809
return (mind.skills[skill] >= amount)
806810

807-
/// Adds progress towards increasing skill level. Returns TRUE if it improved the skill.
808-
/mob/proc/add_exp(skill, amount)
811+
/// Adds progress towards increasing skill level. Returns TRUE if it added progress. Adding a source prevents gaining exp from that source again.
812+
/mob/proc/add_exp(skill, amount, source)
809813
if(!mind)
810814
return FALSE
811-
if(mind.skill_points > 0)
815+
if(!amount)
812816
return FALSE
813-
var/exp_required = EXPERIENCE_PER_LEVEL * (2**mind.skills[skill]) // exp required scales exponentially
814-
if(mind.exp_progress[skill] + amount >= exp_required)
815-
var/levels_gained = round(log(2, 1 + (mind.exp_progress[skill] + amount) / exp_required)) // in case you gained so much you go up more than one level
816-
var/levels_allocated = hud_used?.skill_menu ? hud_used.skill_menu.allocated_skills[skill] : 0
817-
if(levels_allocated > 0) // adjust any already allocated skills to prevent shenanigans (you know who you are)
818-
hud_used.skill_menu.allocated_points -= min(levels_gained, levels_allocated)
819-
hud_used.skill_menu.allocated_skills[skill] -= min(levels_gained, levels_allocated)
820-
mind.exp_progress[skill] += amount - exp_required * (2**(levels_gained - 1))
821-
adjust_skill(skill, levels_gained)
822-
to_chat(src, span_boldnotice("Your [skill] skill is now level [get_skill(skill)]!"))
823-
return TRUE
817+
if(source && (source in mind.exp_sources))
818+
return FALSE
819+
mind.exp_sources.Add(source)
824820
mind.exp_progress[skill] += amount
825-
return FALSE
821+
var/levels_gained = check_exp(skill)
822+
if(levels_gained) // remove an equal amount of unallocated skill points to prevent exploits
823+
mind.skill_points = max(mind.skill_points - levels_gained, 0)
824+
return TRUE
825+
826+
/// Levels up a skill if it has enough experience to do so.
827+
/mob/proc/check_exp(skill)
828+
if(!mind)
829+
return FALSE
830+
var/current_level = get_skill(skill)
831+
var/exp_required = EXPERIENCE_PER_LEVEL * (2**current_level) // exp required scales exponentially
832+
if(mind.exp_progress[skill] < exp_required)
833+
return FALSE
834+
var/skill_cap = EXP_MASTER + HAS_MIND_TRAIT(src, TRAIT_EXCEPTIONAL_SKILL)
835+
var/levels_gained = min(round(log(2, 1 + (mind.exp_progress[skill] / exp_required))), max(skill_cap - current_level)) // in case you gained so much you go up more than one level
836+
if(levels_gained < 1)
837+
return FALSE
838+
var/levels_allocated = hud_used?.skill_menu ? hud_used.skill_menu.allocated_skills[skill] : 0
839+
if(levels_allocated > 0) // adjust any already allocated skills to prevent shenanigans (you know who you are)
840+
hud_used.skill_menu.allocated_points -= min(levels_gained, levels_allocated)
841+
hud_used.skill_menu.allocated_skills[skill] -= min(levels_gained, levels_allocated)
842+
mind.exp_progress[skill] -= exp_required * (((2**round(levels_gained + 1)) / 2) - 1)
843+
adjust_skill(skill, levels_gained, max_skill = skill_cap)
844+
to_chat(src, span_boldnotice("Your [skill] skill is now level [get_skill(skill)]!"))
845+
return levels_gained
846+
847+
/// Returns whether experience has been gained from a given source.
848+
/mob/proc/has_exp(source)
849+
if(!mind)
850+
return FALSE
851+
return (source in mind.exp_sources) ? TRUE : FALSE
826852

827853
/// Adds skill points to be allocated at will.
828854
/mob/proc/add_skill_points(amount)
@@ -831,6 +857,14 @@
831857
mind.skill_points += amount
832858
throw_alert("skill points", /atom/movable/screen/alert/skill_up)
833859

860+
/// Called when [TRAIT_EXCEPTIONAL_SKILL] is added to the mob.
861+
/datum/mind/proc/update_skills(datum/source)
862+
SIGNAL_HANDLER
863+
if(!current)
864+
return
865+
for(var/skill in skills)
866+
current.check_exp(skill)
867+
834868
/datum/mind/proc/has_martialart(string)
835869
if(martial_art && martial_art.id == string)
836870
return martial_art

code/datums/wires/_wires.dm

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,13 +184,15 @@
184184
return TRUE
185185
return FALSE
186186

187-
/datum/wires/proc/cut(wire)
187+
/datum/wires/proc/cut(wire, mob/user)
188188
if(is_cut(wire))
189189
cut_wires -= wire
190190
on_cut(wire, mend = TRUE)
191191
else
192192
cut_wires += wire
193193
on_cut(wire, mend = FALSE)
194+
if(user)
195+
user.add_exp(SKILL_TECHNICAL, 50, "[wire]_[type]")
194196

195197
/datum/wires/proc/cut_color(color)
196198
cut(get_wire(color))
@@ -202,10 +204,12 @@
202204
for(var/wire in wires)
203205
cut(wire)
204206

205-
/datum/wires/proc/pulse(wire, user)
207+
/datum/wires/proc/pulse(wire, mob/user)
206208
if(is_cut(wire))
207209
return
208210
on_pulse(wire, user)
211+
if(user)
212+
user.add_exp(SKILL_TECHNICAL, 50, "[wire]_[type]")
209213

210214
/datum/wires/proc/pulse_color(color, mob/living/user)
211215
pulse(get_wire(color), user)

code/game/mecha/mecha.dm

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1380,6 +1380,6 @@ GLOBAL_VAR_INIT(year_integer, text2num(year)) // = 2013???
13801380
if(!pilot)
13811381
pilot = occupant
13821382
var/effective_skill = pilot.get_skill(SKILL_TECHNICAL)
1383-
if(effective_skill < EXP_MASTER && HAS_TRAIT(pilot, TRAIT_SKILLED_PILOT))
1384-
effective_skill += EXP_LOW // mech pilot suit adds extra pilot skill, up to EXP_MASTER
1385-
return (12 - effective_skill) / 10
1383+
if(HAS_TRAIT(pilot, TRAIT_SKILLED_PILOT) || HAS_MIND_TRAIT(pilot, TRAIT_SKILLED_PILOT))
1384+
effective_skill += EXP_LOW
1385+
return 1 + (2 - effective_skill) * 0.075

code/game/objects/items/granters/_granters.dm

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
unique = 1
99
/// Flavor messages displayed to mobs reading the granter
1010
var/list/remarks = list()
11+
/// Whether to display the remarks in order.
12+
var/ordered_remarks = FALSE
1113
/// Controls how long a mob must keep the book in his hand to actually successfully learn
1214
var/pages_to_mastery = 3
1315
/// Sanity, whether it's currently being read
@@ -40,7 +42,7 @@
4042
on_reading_start(user)
4143
reading = TRUE
4244
for(var/i in 1 to pages_to_mastery)
43-
if(!turn_page(user))
45+
if(!turn_page(user, i))
4446
on_reading_stopped()
4547
reading = FALSE
4648
return
@@ -64,13 +66,13 @@
6466
to_chat(user, span_notice("You finish reading [name]!"))
6567

6668
/// The actual "turning over of the page" flavor bit that happens while someone is reading the granter.
67-
/obj/item/book/granter/proc/turn_page(mob/living/user)
69+
/obj/item/book/granter/proc/turn_page(mob/living/user, current_page = 1)
6870
playsound(user, pick(book_sounds), 30, TRUE)
6971

7072
if(!do_after(user, 5 SECONDS, src))
7173
return FALSE
7274

73-
to_chat(user, span_notice("[length(remarks) ? pick_n_take(remarks) : "You keep reading..."]"))
75+
to_chat(user, span_notice("[ordered_remarks ? "[remarks[current_page]]" : (length(remarks) ? pick_n_take(remarks) : "You keep reading...")]"))
7476
return TRUE
7577

7678
/// Effects that occur whenever the book is read when it has no uses left.

code/game/objects/items/granters/martial_arts/racial.dm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
icon = 'icons/obj/module.dmi'
102102
icon_state = "cyborg_upgrade"
103103
remarks = list("MANKIND IS DEAD.", "BLOOD IS FUEL.", "HELL IS FULL.")
104+
ordered_remarks = TRUE
104105

105106
/obj/item/book/granter/martial/ultra_violence/on_reading_start(mob/user)
106107
to_chat(user, span_notice("You plug \the [src] in and begin loading PRG$[martial_name]."))

code/game/objects/items/granters/mech_piloting.dm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@
1414

1515
/obj/item/book/granter/mechpiloting/on_reading_finished(mob/user)
1616
. = ..()
17-
user.adjust_skill(SKILL_TECHNICAL, EXP_MID, max_skill = EXP_GENIUS)
17+
ADD_TRAIT(user.mind, TRAIT_SKILLED_PILOT, type)
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/// Grants experience to the reader.
2+
/obj/item/book/granter/skill
3+
name = "skill guide"
4+
desc = "A guide to getting good, whatever that means."
5+
remarks = list(
6+
"Skill issue...?",
7+
)
8+
/// Experience gains from reading this book.
9+
var/list/exp_gain = list(
10+
SKILL_PHYSIOLOGY = EXPERIENCE_PER_LEVEL,
11+
SKILL_MECHANICAL = EXPERIENCE_PER_LEVEL,
12+
SKILL_TECHNICAL = EXPERIENCE_PER_LEVEL,
13+
SKILL_SCIENCE = EXPERIENCE_PER_LEVEL,
14+
SKILL_PHYSIOLOGY = EXPERIENCE_PER_LEVEL,
15+
)
16+
17+
/obj/item/book/granter/skill/can_learn(mob/living/user)
18+
return !user.has_exp("[type]_[exp_gain[1]]")
19+
20+
/obj/item/book/granter/skill/on_reading_finished(mob/living/user)
21+
. = ..()
22+
if(!user.mind)
23+
CRASH("[user.type] somehow read [type] without a mind!")
24+
for(var/skill in exp_gain)
25+
user.add_exp(skill, exp_gain[skill], "[type]_[skill]")
26+
27+
/obj/item/book/granter/skill/physiology
28+
name = "\improper Guide to First Aid"
29+
desc = "This book teaches basic first aid information."
30+
remarks = list(
31+
"Dying is bad..?",
32+
"Suture or cauterize open wounds to prevent bleeding out...",
33+
"Apply ointment or regenerative mesh to sterilize infected burns...",
34+
"Move critical patients on rolling beds or over your shoulder..."
35+
)
36+
exp_gain = list(
37+
SKILL_PHYSIOLOGY = EXP_REQ_CALC(EXP_HIGH),
38+
)
39+
40+
/obj/item/book/granter/skill/mechanics
41+
name = "Nuclear Engineering for Dummies"
42+
desc = "A step-by-step guide to operating a nuclear reactor."
43+
remarks = list(
44+
"Wear radiation protection during maintenance...",
45+
"Adjust control rods to moderate the temperature...",
46+
"High temperatures generate more power...",
47+
"Don't press AZ-5..?",
48+
)
49+
exp_gain = list(
50+
SKILL_MECHANICAL = EXP_REQ_CALC(EXP_HIGH),
51+
)
52+
53+
/obj/item/book/granter/skill/technical
54+
name = "Hacking 101"
55+
desc = "Contains detailed information on airlock maintenance."
56+
remarks = list(
57+
"Wear insulated gloves for protection...",
58+
"Pulse wires twice to avoid changing settings...",
59+
"Pry open unpowered doors with a crowbar...",
60+
"Bolt an open door to prevent it closing behind you...",
61+
)
62+
exp_gain = list(
63+
SKILL_TECHNICAL = EXP_REQ_CALC(EXP_HIGH),
64+
)
65+
66+
/obj/item/book/granter/skill/science
67+
name = "Statistical Mechanics and Thermodynamics"
68+
desc = "Perhaps it will be wise to approach this subject cautiously."
69+
remarks = list(
70+
"Ludwig Boltzmann, who spent much of his life studying statistical mechanics, died in 1906, by his own hand...",
71+
"Paul Ehrenfest, carrying on the work, died similarly in 1933...",
72+
"Now it is our turn to study statistical mechanics...",
73+
)
74+
ordered_remarks = TRUE
75+
exp_gain = list(
76+
SKILL_SCIENCE = EXP_REQ_CALC(EXP_HIGH),
77+
)

code/game/objects/items/storage/bags.dm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@
284284
if(usr.incapacitated())
285285
return
286286
for(var/obj/item/O in contents)
287-
seedify(O, 1)
287+
seedify(O, 1, null, usr)
288288

289289
// -----------------------------
290290
// Stack Snatcher

0 commit comments

Comments
 (0)