From 643ef48f0e66e52138b62844059133214f34b762 Mon Sep 17 00:00:00 2001
From: Ghommie <42542238+Ghommie@users.noreply.github.com>
Date: Tue, 5 May 2020 04:42:34 +0200
Subject: [PATCH] Macros, generic skill implementations.
---
.../skills/{skills.dm => defines.dm} | 62 +++++++++++------
code/__DEFINES/skills/helpers.dm | 44 ++++++++++++
code/_onclick/item_attack.dm | 56 +++++++++++----
code/datums/mind.dm | 3 +-
code/datums/skills/_skill.dm | 69 ++++++++++++-------
code/datums/skills/_skill_holder.dm | 37 ++++++++--
code/datums/skills/engineering.dm | 3 +-
code/datums/skills/medical.dm | 1 +
code/datums/wires/_wires.dm | 37 ++++++++--
code/datums/wires/airalarm.dm | 1 +
code/datums/wires/airlock.dm | 5 +-
code/datums/wires/apc.dm | 1 +
code/datums/wires/autolathe.dm | 1 +
code/datums/wires/emitter.dm | 2 +
code/datums/wires/explosive.dm | 2 +
code/datums/wires/microwave.dm | 2 +
code/datums/wires/mulebot.dm | 1 +
code/datums/wires/particle_accelerator.dm | 2 +
code/datums/wires/r_n_d.dm | 1 +
code/datums/wires/radio.dm | 2 +
code/datums/wires/robot.dm | 2 +
code/datums/wires/suit_storage_unit.dm | 2 +
code/datums/wires/syndicatebomb.dm | 2 +
code/datums/wires/tesla_coil.dm | 1 +
code/datums/wires/vending.dm | 1 +
code/game/machinery/camera/camera_assembly.dm | 3 +-
code/game/machinery/constructable_frame.dm | 1 -
code/game/machinery/doors/firedoor.dm | 3 +-
code/game/machinery/firealarm.dm | 4 +-
code/game/machinery/shieldgen.dm | 5 +-
code/game/mecha/mecha_defense.dm | 3 +-
code/game/objects/items.dm | 18 ++++-
.../objects/items/grenades/chem_grenade.dm | 3 +-
.../game/objects/items/stacks/sheets/glass.dm | 2 +-
code/game/objects/structures/ai_core.dm | 2 +-
code/game/objects/structures/barsigns.dm | 3 +-
.../objects/structures/windoor_assembly.dm | 3 +-
.../atmospherics/machinery/airalarm.dm | 5 +-
code/modules/clothing/under/_under.dm | 2 +-
code/modules/hydroponics/plant_genes.dm | 3 +-
code/modules/jobs/job_types/_job.dm | 2 +-
code/modules/jobs/job_types/ai.dm | 2 +
.../jobs/job_types/atmospheric_technician.dm | 4 ++
code/modules/jobs/job_types/chief_engineer.dm | 3 +
code/modules/jobs/job_types/cyborg.dm | 2 +
code/modules/jobs/job_types/roboticist.dm | 4 ++
.../jobs/job_types/station_engineer.dm | 3 +
code/modules/mining/ores_coins.dm | 3 +-
.../mob/living/carbon/carbon_defense.dm | 6 +-
.../mob/living/carbon/human/species.dm | 15 +---
.../modules/mob/living/silicon/robot/robot.dm | 13 ++--
.../living/simple_animal/bot/construction.dm | 5 +-
.../modular_computers/hardware/_hardware.dm | 3 +-
code/modules/power/apc.dm | 20 +++---
code/modules/power/cable.dm | 4 +-
code/modules/power/floodlight.dm | 3 +-
code/modules/power/lighting.dm | 3 +-
.../particle_accelerator.dm | 3 +-
.../particle_accelerator/particle_control.dm | 3 +-
code/modules/power/smes.dm | 5 +-
.../projectiles/guns/ballistic/revolver.dm | 3 +-
.../surgery/bodyparts/robot_bodyparts.dm | 15 ++--
code/modules/surgery/surgery_step.dm | 9 ++-
tgstation.dme | 3 +-
64 files changed, 358 insertions(+), 178 deletions(-)
rename code/__DEFINES/skills/{skills.dm => defines.dm} (51%)
create mode 100644 code/__DEFINES/skills/helpers.dm
diff --git a/code/__DEFINES/skills/skills.dm b/code/__DEFINES/skills/defines.dm
similarity index 51%
rename from code/__DEFINES/skills/skills.dm
rename to code/__DEFINES/skills/defines.dm
index d8c37bec59..00859bbd40 100644
--- a/code/__DEFINES/skills/skills.dm
+++ b/code/__DEFINES/skills/defines.dm
@@ -1,4 +1,3 @@
-#define GET_SKILL_DATUM(path) GLOB.skill_datums[path]
/// true/false
#define SKILL_PROGRESSION_BINARY 1
@@ -6,6 +5,8 @@
#define SKILL_PROGRESSION_NUMERICAL 2
/// Enum
#define SKILL_PROGRESSION_ENUM 3
+/// Levels
+#define SKILL_PROGRESSION_LEVEL 4
/// Max value of skill for numerical skills
@@ -13,7 +14,35 @@
/// Min value of skill for numerical skills
#define SKILL_NUMERICAL_MIN 0
-// Values for experience skills
+// Standard values for job starting skills
+
+#define STARTING_SKILL_SURGERY_MEDICAL 35 //out of SKILL_NUMERICAL_MAX
+
+// Standard values for job starting skill affinities
+
+#define STARTING_SKILL_AFFINITY_SURGERY_MEDICAL 1.2
+
+#define STARTING_SKILL_AFFINITY_WIRING_ENGI_ROBO 1.2
+
+// Standard values for skill gain (this is multiplied by affinity)
+
+#define DEF_SKILL_GAIN 1
+#define SKILL_GAIN_SURGERY_PER_STEP 0.25
+
+///Items skill_flags and other defines
+#define SKILL_USE_TOOL (1<<0)
+#define SKILL_TRAINING_TOOL (1<<1)
+#define SKILL_ATTACK_MOB (1<<2)
+#define SKILL_TRAIN_ATTACK_MOB (1<<3)
+#define SKILL_ATTACK_OBJ (1<<4)
+#define SKILL_TRAIN_ATTACK_OBJ (1<<5)
+
+///competency_threshold index defines
+#define THRESHOLD_COMPETENT 1
+#define THRESHOLD_EXPERT 2
+#define THRESHOLD_MASTER 3
+
+/// Level/Experience skills defines.
#define STD_XP_LVL_UP 100
#define STD_XP_LVL_MULTI 2
#define STD_MAX_LVL 4
@@ -24,27 +53,18 @@
#define DORF_XP_LVL_MULTI 100
#define DORF_MAX_LVL 20 // Dabbling, novice, adequate, [...], legendary +3, legendary +4, legendary +5
-//How experience levels are calculated.
-#define XP_LEVEL(std, multi, lvl) (std * (multi**lvl))
-#define DORF_XP_LEVEL(std, extra, lvl) (std*lvl+extra*(lvl*(lvl/2+0.5)))
-
//level up methods defines
#define STANDARD_LEVEL_UP "standard_level_up"
#define DWARFY_LEVEL_UP "dwarfy_level_up"
-// Standard values for job starting skills
+//job skill level defines
+#define JOB_SKILL_UNTRAINED 0
+#define JOB_SKILL_BASIC 1
+#define JOB_SKILL_TRAINED 2
+#define JOB_SKILL_EXPERT 3
+#define JOB_SKILL_MASTER 4
-#define STARTING_SKILL_SURGERY_MEDICAL 35 //out of SKILL_NUMERICAL_MAX
-
-// Standard values for job starting skill affinities
-
-#define STARTING_SKILL_AFFINITY_SURGERY_MEDICAL 1.2
-
-// Standard values for skill gain (this is multiplied by affinity)
-
-#define SKILL_GAIN_SURGERY_PER_STEP 0.25
-
-// Misc
-
-/// 40% speedup at 100 skill
-#define SURGERY_SKILL_SPEEDUP_NUMERICAL_SCALE(number) clamp(number / 250, 1, 2)
+//other skill level defines, not an exhaustive catalogue, only contains be most relevant ones.
+#define DORF_SKILL_COMPETENT 3
+#define DORF_SKILL_EXPERT 8
+#define DORF_SKILL_MASTER 12
diff --git a/code/__DEFINES/skills/helpers.dm b/code/__DEFINES/skills/helpers.dm
new file mode 100644
index 0000000000..165b9091ae
--- /dev/null
+++ b/code/__DEFINES/skills/helpers.dm
@@ -0,0 +1,44 @@
+/**
+ *Generic delay calculation macro for various delayed actions.
+ *The skill to check must be an instance, not a path or list.
+ */
+#define SKILL_MODIFIER(to_check, holder, target, threshold) \
+ var/___value;\
+ switch(to_check.progression_type){\
+ if(SKILL_PROGRESSION_LEVEL){\
+ ___value = LAZYACCESS(holder.skill_levels, to_check.type)\
+ } else {\
+ ___value = LAZYACCESS(holder.skills, to_check.type)\
+ }\
+ }\
+ target /= (1+(___value-to_check.competency_thresholds[threshold])*to_check.competency_mults[threshold])
+
+/// This is the one that accepts typepaths and lists.
+#define LIST_SKILL_MODIFIER(to_check, holder, target, threshold) \
+ if(!islist(to_check)){\
+ SKILL_MODIFIER(GLOB.skill_datums[to_check], holder, target, threshold)\
+ } else {\
+ var/___sum = 0;\
+ var/list/___L = to_check;\
+ for(var/_S in ___L){\
+ var/___value;\
+ var/datum/skill/___S = GLOB.skill_datums[_S];\
+ switch(___S.progression_type){\
+ if(SKILL_PROGRESSION_LEVEL){\
+ ___value = LAZYACCESS(holder.skill_levels, ___S.type)\
+ } else {\
+ ___value = LAZYACCESS(holder.skills, ___S.type)\
+ }\
+ }\
+ ___sum += (1+(___value - ___S.competency_thresholds[threshold])*___S.competency_mults[threshold])\
+ }\
+ target /= (___sum/length(___L))\
+ }
+
+//How experience levels are calculated.
+#define XP_LEVEL(std, multi, lvl) (std*((multi**lvl)/(multi-1))-std/(multi-1)) //don't use 1 as multi, you'll get division by zero errors
+#define DORF_XP_LEVEL(std, extra, lvl) (std*lvl+extra*(lvl*(lvl/2+0.5)))
+
+//More experience value getter macros
+#define GET_STANDARD_LVL(lvl) XP_LEVEL(STD_XP_LVL_UP, STD_XP_LVL_MULTI, lvl)
+#define GET_DORF_LVL(lvl) DORF_XP_LEVEL(DORF_XP_LVL_UP, DORF_XP_LVL_MULTI, lvl)
diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index 98db89a100..dbcf171663 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -111,26 +111,30 @@
return
/obj/attacked_by(obj/item/I, mob/living/user)
- if(I.force)
+ var/totitemdamage = I.force
+ if(I.used_skills && user.mind)
+ if(I.skill_flags & SKILL_ATTACK_OBJ)
+ LIST_SKILL_MODIFIER(used_skills, user.mind.skill_holder, totitemdamage, I.skill_difficulty)
+ if(I.skill_flags & SKILL_TRAIN_ATTACK_OBJ)
+ if(!islist(I.used_skills))
+ user.mind.skill_holder.boost_skill_value_to(used_skills, I.skill_gain)
+ else
+ for(var/skill in used_skills)
+ user.mind.skill_holder.boost_skill_value_to(skill, I.skill_gain)
+ if(totitemdamage)
visible_message("[user] has hit [src] with [I]!", null, null, COMBAT_MESSAGE_RANGE)
//only witnesses close by and the victim see a hit message.
log_combat(user, src, "attacked", I)
- take_damage(I.force, I.damtype, "melee", 1)
+ take_damage(totitemdamage, I.damtype, "melee", 1)
/mob/living/attacked_by(obj/item/I, mob/living/user)
- //CIT CHANGES START HERE - combatmode and resting checks
- var/totitemdamage = I.force
- if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
- totitemdamage *= 0.5
- if(!CHECK_MOBILITY(user, MOBILITY_STAND))
- totitemdamage *= 0.5
- //CIT CHANGES END HERE
+ var/totitemdamage = calculate_item_force(I, user, TRUE)
if((user != src) && run_block(I, totitemdamage, "the [I.name]", ATTACK_TYPE_MELEE, I.armour_penetration, user) & BLOCK_SUCCESS)
return FALSE
send_item_attack_message(I, user)
- I.do_stagger_action(src, user)
+ I.do_stagger_action(src, user, totitemdamage)
if(I.force)
- apply_damage(totitemdamage, I.damtype) //CIT CHANGE - replaces I.force with totitemdamage
+ apply_damage(totitemdamage, I.damtype)
if(I.damtype == BRUTE)
if(prob(33))
I.add_mob_blood(src)
@@ -146,6 +150,28 @@
else
return ..()
+/mob/living/proc/pre_attacked_by(obj/item/I, mob/living/user, pre_attack = FALSE)
+ . = I.force
+ if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
+ . *= 0.5
+ if(!CHECK_MOBILITY(user, MOBILITY_STAND))
+ . *= 0.5
+ if(!pre_attack || !user.mind || !I.used_skills)
+ return
+ if(. && I.skill_flags & SKILL_ATTACK_MOB)
+ LIST_SKILL_MODIFIER(used_skills, user.mind.skill_holder, ., I.skill_difficulty)
+ if(I.skill_flags & SKILL_TRAIN_ATTACK_MOB)
+ if(!islist(I.used_skills))
+ user.mind.skill_holder.boost_skill_value_to(used_skills, I.skill_gain)
+ else
+ for(var/skill in used_skills)
+ user.mind.skill_holder.boost_skill_value_to(skill, I.skill_gain)
+
+/mob/living/carbon/proc/pre_attacked_by(obj/item/I, mob/living/user, pre_attack = FALSE)
+ . = ..()
+ if(!(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
+ . *= 1.5
+
// Proximity_flag is 1 if this afterattack was called on something adjacent, in your square, or on your person.
// Click parameters is the params string from byond Click() code, see that documentation.
/obj/item/proc/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
@@ -183,18 +209,18 @@
return total_mass || w_class * 1.25
/// How long this staggers for. 0 and negatives supported.
-/obj/item/proc/melee_stagger_duration()
+/obj/item/proc/melee_stagger_duration(force_override)
if(!isnull(stagger_force))
return stagger_force
/// totally not an untested, arbitrary equation.
- return clamp((1.5 + (w_class/7.5)) * (force / 2), 0, 10 SECONDS)
+ return clamp((1.5 + (w_class/7.5)) * ((force_override || force) / 2), 0, 10 SECONDS)
-/obj/item/proc/do_stagger_action(mob/living/target, mob/living/user)
+/obj/item/proc/do_stagger_action(mob/living/target, mob/living/user, force_override)
if(!CHECK_BITFIELD(target.status_flags, CANSTAGGER))
return FALSE
if(target.combat_flags & COMBAT_FLAG_SPRINT_ACTIVE)
target.do_staggered_animation()
- var/duration = melee_stagger_duration()
+ var/duration = melee_stagger_duration(force_override)
if(!duration) //0
return FALSE
else if(duration > 0)
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 728c4fb51b..54fcbbc6aa 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -67,7 +67,7 @@
var/datum/skill_holder/skill_holder
/datum/mind/New(var/key)
- skill_holder = new
+ skill_holder = new(src)
src.key = key
soulOwner = src
martial_art = default_martial_art
@@ -80,6 +80,7 @@
if(antag_datum.delete_on_mind_deletion)
qdel(i)
antag_datums = null
+ QDEL_NULL(skill_holder)
return ..()
/datum/mind/proc/get_language_holder()
diff --git a/code/datums/skills/_skill.dm b/code/datums/skills/_skill.dm
index f7225283cd..039afacfa5 100644
--- a/code/datums/skills/_skill.dm
+++ b/code/datums/skills/_skill.dm
@@ -1,4 +1,4 @@
-GLOBAL_LIST_INIT(skill_datums, init_skill_datums())
+GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums())
/proc/init_skill_datums()
. = list()
@@ -10,12 +10,12 @@ GLOBAL_LIST_INIT(skill_datums, init_skill_datums())
.[S.type] = S
/proc/sanitize_skill_value(path, value)
- var/datum/skill/S = GET_SKILL_DATUM(path)
+ var/datum/skill/S = GLOB.skill_datums[path]
// don't check, if we runtime let it happen.
return S.sanitize_value(value)
/proc/is_skill_value_greater(path, existing, new_value)
- var/datum/skill/S = GET_SKILL_DATUM(path)
+ var/datum/skill/S = GLOB.skill_datums[path]
// don't check, if we runtime let it happen.
return S.is_value_greater(existing, new_value)
@@ -33,6 +33,10 @@ GLOBAL_LIST_INIT(skill_datums, init_skill_datums())
var/progression_type
/// Abstract type
var/abstract_type = /datum/skill
+ /// skill threshold used in generic skill modifiers calculations.
+ var/list/competency_thresholds = list(0, 0, 0)
+ /// Multiplier of the difference of the holder skill value and the selected threshold.
+ var/list/competency_mults = list(0, 0, 0)
/**
* Ensures what someone's setting as a value for this skill is valid.
@@ -44,7 +48,7 @@ GLOBAL_LIST_INIT(skill_datums, init_skill_datums())
* Sets the new value of this skill in the holder skills list.
* As well as possible feedback messages or secondary effects on value change, that's on you.
*/
-/datum/skill/proc/set_skill(datum/skill_holder/H, value, mob/owner)
+/datum/skill/proc/set_skill_value(datum/skill_holder/H, value, mob/owner)
H.skills[type] = value
/**
@@ -67,6 +71,8 @@ GLOBAL_LIST_INIT(skill_datums, init_skill_datums())
/datum/skill/binary
abstract_type = /datum/skill/binary
progression_type = SKILL_PROGRESSION_BINARY
+ competency_thresholds = list(FALSE, TRUE, TRUE)
+ competency_mults = list(0.5, 0.5, 0.5)
/datum/skill/binary/sanitize_value(new_value)
return new_value? TRUE : FALSE
@@ -103,22 +109,23 @@ GLOBAL_LIST_INIT(skill_datums, init_skill_datums())
/**
* Classing r p g styled skills, tiered by lvl, and current/nextlvl experience.
*/
-/datum/skill/experience
- abstract_type = /datum/skill/experience
+/datum/skill/level
+ abstract_type = /datum/skill/level
+ progression_type = SKILL_PROGRESSION_LEVEL
var/standard_xp_lvl_up = STD_XP_LVL_UP //the standard required to level up. def: 100
var/xp_lvl_multiplier = STD_XP_LVL_UP //standard required level up exp multiplier. def: 2 (100, 200, 400, 800 etc.)
- var/max_lvl = STD_MAX_LVL
+ var/max_levels = STD_MAX_LVL
var/level_up_method = STANDARD_LEVEL_UP //how levels are calculated.
var/list/levels = list() //level thresholds, if associative, these will be preceded by tiers such as "novice" or "trained"
var/associative = FALSE //See above.
var/unskilled_tier = "Unskilled" //Only relevant for associative experience levels
//Builds the levels list.
-/datum/skill/experience/New()
+/datum/skill/level/New()
. = ..()
var/max_assoc = ""
var/max_assoc_start = 1
- for(var/lvl in 1 to max_lvl)
+ for(var/lvl in 1 to max_levels)
var/value
switch(level_up_method)
if(STANDARD_LEVEL_UP)
@@ -143,41 +150,57 @@ GLOBAL_LIST_INIT(skill_datums, init_skill_datums())
levels["[max_assoc] +[max_assoc_start++]"] = value
levels[key] = value
+/datum/skill/level/sanitize_value(new_value)
+ return max(new_value, 0)
-/datum/skill/experience/sanitize_value(new_value)
- return round(max(new_value, 0))
-
-/datum/skill/experience/set_skill(datum/skill_holder/H, value, mob/owner)
- var/old_value = H.skills[type]
+/datum/skill/level/set_skill_value(datum/skill_holder/H, value, datum/mind/M, silent = FALSE)
H.skills[type] = value
- if(value > old_value)
+ var/new_level
+ for(var/k in levels)
+ if(value < (associative ? levels[k] : k))
+ break
+ new_level++
+ var/old_level = LAZYACCESS(H.skill_levels, type)
+ LAZYSET(H.skill_levels, type, new_level)
+ . = new_level - old_level
+ if(silent || !(M?.current))
+ return
+ if(. > 0)
+ to_chat(M.current, "I feel like I've become more proficient at [name]!")
+ else if(. < 0)
+ to_chat(M.current, "I feel like I've become worse at [name]!")
-/datum/skill/experience/standard_render_value(value)
+/datum/skill/level/standard_render_value(value)
var/current_lvl = associative ? unskilled_tier : 0
var/current_lvl_xp_sum = 0
var/next_lvl_xp_sum
- for(var/lvl in 1 to max_lvl)
+ for(var/lvl in 1 to max_levels)
next_lvl_xp_sum = associative ? levels[levels[lvl]] : levels[lvl]
if(value < next_lvl_xp_sum)
break
current_lvl_xp_sum = next_lvl_xp_sum
- current_lvl = associative ? levels[lvl] : current_lvl+1
+ current_lvl = associative ? levels[lvl] : lvl+1
return "[associative ? current_lvl : "Lvl. [current_lvl]"] ([value - current_lvl_xp_sum]/[next_lvl_xp_sum])[value > next_lvl_xp_sum ? " \[MAX!\]" : ""]"
-/datum/skill/experience/job
- levels = ("Basic", "Trained", "Experienced", "Master")
+/datum/skill/level/job
+ levels = list("Basic", "Trained", "Experienced", "Master")
+ competency_thresholds = list(JOB_SKILL_TRAINED, JOB_SKILL_EXPERT, JOB_SKILL_MASTER)
+ competency_mults = list(0.15, 0.1, 0.1)
associative = TRUE
//quite the reference, no?
-/datum/skill/experience/dwarfy
- abstract_type = /datum/skill/experience/dwarfy
+/datum/skill/level/dwarfy
+ abstract_type = /datum/skill/level/dwarfy
standard_xp_lvl_up = DORF_XP_LVL_UP
xp_lvl_multiplier = DORF_XP_LVL_MULTI
- max_lvl = DORF_MAX_LVL
+ max_levels = DORF_MAX_LVL
+ level_up_method = DWARFY_LEVEL_UP
levels = list("Novice", "Adequate", "Competent", "Skilled",
"Proficient", "Talented", "Adept", "Expert",
"Professional", "Accomplished", "Great", "Master",
"High Master", "Grand Master", "Legendary")
+ competency_thresholds = list(DORF_SKILL_COMPETENT, DORF_SKILL_EXPERT, DORF_SKILL_MASTER)
+ competency_mults = list(0.15, 0.1, 0.08)
associative = TRUE
unskilled_tier = "Dabbling"
diff --git a/code/datums/skills/_skill_holder.dm b/code/datums/skills/_skill_holder.dm
index 71744b7d43..d1b6b8bd0d 100644
--- a/code/datums/skills/_skill_holder.dm
+++ b/code/datums/skills/_skill_holder.dm
@@ -2,10 +2,18 @@
* Skill holder datums
*/
/datum/skill_holder
+ var/datum/mind/owner
/// Our list of skills and values. Lazylist. Associative. Keys are datum typepaths to the skill.
var/list/skills
/// Same as [skills] but affinities, which are multiplied to increase amount when gaining skills.
var/list/skill_affinities
+ /// Let's say we want to get a specific skill "level" without looping through a proc everytime.
+ /// Only supported by skills with tiers or levels.
+ var/list/skill_levels
+
+/datum/skill_holder/New(datum/mind/M)
+ . = ..()
+ owner = M
/**
* Grabs the value of a skill.
@@ -17,6 +25,16 @@
return null
return skills[skill]
+/**
+ * Grabs the level of a skill. Only supported by skills with tiers or levels.
+ */
+/datum/skill_holder/proc/get_skill_level(skill)
+ if(!ispath(skill))
+ CRASH("Invalid get_skill_value call. Use typepaths.") //until a time when we somehow need text ids for dynamic skills, I'm enforcing this.
+ if(!skill_levels)
+ return 0
+ return skill_levels[skill]
+
/**
* Grabs our affinity for a skill. !!This is a multiplier!!
*/
@@ -33,37 +51,42 @@
/**
* Sets the value of a skill.
*/
-/datum/skill_holder/proc/set_skill_value(skill, value, owner)
+/datum/skill_holder/proc/set_skill_value(skill, value, silent = FALSE)
if(!ispath(skill, /datum/skill))
CRASH("Invalid set_skill_value call. Use typepaths.") //until a time when we somehow need text ids for dynamic skills, I'm enforcing this.
- var/datum/skill/S = GET_SKILL_DATUM(path)
+ var/datum/skill/S = GLOB.skill_datums[skill]
value = S.sanitize_value(value)
if(!isnull(value))
LAZYINITLIST(skills)
- S.set_skill(src, value, owner)
+ S.set_skill_value(src, value, owner, silent)
return TRUE
return FALSE
/**
* Boosts a skill to a value if not aobve
*/
-/datum/skill_holder/proc/boost_skill_value_to(skill, value, mob/owner)
+/datum/skill_holder/proc/boost_skill_value_to(skill, value, silent = FALSE)
var/current = get_skill_value(skill)
if(!is_skill_value_greater(skill, current, value))
return FALSE
- set_skill_value(skill, value, owner)
+ set_skill_value(skill, value, silent)
return TRUE
/**
* Automatic skill increase, multiplied by skill affinity if existing.
* Only works if skill is numerical.
*/
-/datum/skill_holder/proc/auto_gain_experience(skill, value, mob/owner)
+/datum/skill_holder/proc/auto_gain_experience(skill, value, maximum, silent = FALSE)
if(!ispath(skill, /datum/skill/numerical))
CRASH("You cannot auto increment a non numerical skill!")
var/current = get_skill_value(skill)
var/affinity = get_skill_affinity(skill)
- boost_skill_value_to(skill, current + (value * affinity), owner)
+ var/target_value = current + (value * affinity)
+ if(maximum)
+ target_value = max(target_value, maximum)
+ if(target_value == maximum) //no more experience to gain, early return.
+ return
+ boost_skill_value_to(skill, target_value, silent)
/**
* Generates a HTML readout of our skills.
diff --git a/code/datums/skills/engineering.dm b/code/datums/skills/engineering.dm
index c06accea77..b3eeb9d57d 100644
--- a/code/datums/skills/engineering.dm
+++ b/code/datums/skills/engineering.dm
@@ -1,3 +1,4 @@
-/datum/skill/experience/job/wiring
+/datum/skill/level/job/wiring
name = "Wiring"
desc = "How proficient and knowledged you are at wiring beyond laying cables on the floor."
+ competency_thresholds = list(JOB_SKILL_BASIC, JOB_SKILL_EXPERT, JOB_SKILL_MASTER)
diff --git a/code/datums/skills/medical.dm b/code/datums/skills/medical.dm
index 3b67cacb04..1b0774b0ce 100644
--- a/code/datums/skills/medical.dm
+++ b/code/datums/skills/medical.dm
@@ -1,3 +1,4 @@
/datum/skill/numerical/surgery
name = "Surgery"
desc = "How proficient you are at doing surgery."
+ competency_mults = list(0.025, 0.025, 0.025) // 60% surgery speed up at max value of 100.
diff --git a/code/datums/wires/_wires.dm b/code/datums/wires/_wires.dm
index ad24126e45..fc31cb9286 100644
--- a/code/datums/wires/_wires.dm
+++ b/code/datums/wires/_wires.dm
@@ -33,6 +33,9 @@
var/list/assemblies = list() // List of attached assemblies.
var/randomize = 0 // If every instance of these wires should be random.
// Prevents wires from showing up in station blueprints
+ var/req_knowledge = INFINITY //wiring skill level on which the functions are revealed.
+ var/req_skill = JOB_SKILL_BASIC //used in user's cutting/pulsing/mending speed calculations.
+ var/list/current_users //list of untrained people currently interacting with this set of wires.
/datum/wires/New(atom/holder)
..()
@@ -130,8 +133,20 @@
cut_wires += wire
on_cut(wire, mend = FALSE)
-/datum/wires/proc/cut_color(color)
+/datum/wires/proc/cut_color(color, mob/living/user)
+ LAZYINITLIST(current_users)
+ if(current_users[user])
+ return FALSE
+ if(req_skill && user?.mind)
+ var/level_diff = req_skill - user.mind.skill_holder.get_skill_level(/datum/skill/level/job/wiring)
+ if(level_diff > 0)
+ to_chat(user, "You begin cutting [holder]'s [color] wire...")
+ if(!do_after(user, 1.5 SECONDS * level_diff, target = holder) || !interactable(user))
+ return FALSE
+ user.mind?.skill_holder.auto_gain_experience(/datum/skill/level/job/wiring, DEF_SKILL_GAIN*level_diff)
+ to_chat(user, "You cut [holder]'s [color] wire.")
cut(get_wire(color))
+ return TRUE
/datum/wires/proc/cut_random()
cut(wires[rand(1, wires.len)])
@@ -146,7 +161,19 @@
on_pulse(wire, user)
/datum/wires/proc/pulse_color(color, mob/living/user)
+ LAZYINITLIST(current_users)
+ if(current_users[user])
+ return FALSE
+ if(req_skill && user?.mind)
+ var/level_diff = req_skill - user.mind.skill_holder.get_skill_level(/datum/skill/level/job/wiring)
+ if(level_diff > 0)
+ to_chat(user, "You begin pulsing [holder]'s [color] wire...")
+ if(!do_after(user, 1.5 SECONDS * level_diff, target = holder) || !interactable(user))
+ return FALSE
+ user.mind?.skill_holder.auto_gain_experience(/datum/skill/level/job/wiring, DEF_SKILL_GAIN*level_diff)
+ to_chat(user, "You pulse [holder]'s [color] wire.")
pulse(get_wire(color), user)
+ return TRUE
/datum/wires/proc/pulse_assembly(obj/item/assembly/S)
for(var/color in assemblies)
@@ -224,7 +251,7 @@
var/reveal_wires = FALSE
// Admin ghost can see a purpose of each wire.
- if(IsAdminGhost(user))
+ if(IsAdminGhost(user) || user.mind.skill_holder.get_skill_level(/datum/skill/level/job/wiring) >= req_knowledge)
reveal_wires = TRUE
// Same for anyone with an abductor multitool.
@@ -259,18 +286,16 @@
if("cut")
I = L.is_holding_tool_quality(TOOL_WIRECUTTER)
if(I || IsAdminGhost(usr))
- if(I && holder)
+ if(cut_color(target_wire) && I && holder)
I.play_tool_sound(holder, 20)
- cut_color(target_wire)
. = TRUE
else
to_chat(L, "You need wirecutters!")
if("pulse")
I = L.is_holding_tool_quality(TOOL_MULTITOOL)
if(I || IsAdminGhost(usr))
- if(I && holder)
+ if(pulse_color(target_wire, L) && I && holder)
I.play_tool_sound(holder, 20)
- pulse_color(target_wire, L)
. = TRUE
else
to_chat(L, "You need a multitool!")
diff --git a/code/datums/wires/airalarm.dm b/code/datums/wires/airalarm.dm
index 0c4715e27e..dae92d3c42 100644
--- a/code/datums/wires/airalarm.dm
+++ b/code/datums/wires/airalarm.dm
@@ -1,6 +1,7 @@
/datum/wires/airalarm
holder_type = /obj/machinery/airalarm
proper_name = "Air Alarm"
+ req_knowledge = JOB_SKILL_MASTER
/datum/wires/airalarm/New(atom/holder)
wires = list(
diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm
index b6699540c3..c2b5db9540 100644
--- a/code/datums/wires/airlock.dm
+++ b/code/datums/wires/airlock.dm
@@ -52,10 +52,11 @@
/datum/wires/airlock/interactable(mob/user)
var/obj/machinery/door/airlock/A = holder
+ if(!A.panel_open)
+ return FALSE
if(!A.hasSiliconAccessInArea(user) && A.isElectrified() && A.shock(user, 100))
return FALSE
- if(A.panel_open)
- return TRUE
+ return TRUE
/datum/wires/airlock/get_status()
var/obj/machinery/door/airlock/A = holder
diff --git a/code/datums/wires/apc.dm b/code/datums/wires/apc.dm
index dc126f612e..997c77aa51 100644
--- a/code/datums/wires/apc.dm
+++ b/code/datums/wires/apc.dm
@@ -1,6 +1,7 @@
/datum/wires/apc
holder_type = /obj/machinery/power/apc
proper_name = "APC"
+ req_knowledge = JOB_SKILL_MASTER
/datum/wires/apc/New(atom/holder)
wires = list(
diff --git a/code/datums/wires/autolathe.dm b/code/datums/wires/autolathe.dm
index f83bab5910..01e87228d4 100644
--- a/code/datums/wires/autolathe.dm
+++ b/code/datums/wires/autolathe.dm
@@ -1,6 +1,7 @@
/datum/wires/autolathe
holder_type = /obj/machinery/autolathe
proper_name = "Autolathe"
+ req_knowledge = JOB_SKILL_EXPERT
/datum/wires/autolathe/New(atom/holder)
wires = list(
diff --git a/code/datums/wires/emitter.dm b/code/datums/wires/emitter.dm
index d0e1352c0e..6d82a7db5a 100644
--- a/code/datums/wires/emitter.dm
+++ b/code/datums/wires/emitter.dm
@@ -1,6 +1,8 @@
/datum/wires/emitter
holder_type = /obj/machinery/power/emitter
+ req_knowledge = JOB_SKILL_TRAINED
+ req_skill = JOB_SKILL_UNTRAINED
/datum/wires/emitter/New(atom/holder)
wires = list(WIRE_ZAP,WIRE_HACK)
diff --git a/code/datums/wires/explosive.dm b/code/datums/wires/explosive.dm
index 3d1ed8b746..dc4db9e85d 100644
--- a/code/datums/wires/explosive.dm
+++ b/code/datums/wires/explosive.dm
@@ -15,6 +15,7 @@
/datum/wires/explosive/c4
holder_type = /obj/item/grenade/plastic/c4
randomize = TRUE //Same behaviour since no wire actually disarms it
+ req_skill = JOB_SKILL_UNTRAINED
/datum/wires/explosive/c4/interactable(mob/user)
var/obj/item/grenade/plastic/c4/P = holder
@@ -29,6 +30,7 @@
/datum/wires/explosive/pizza
holder_type = /obj/item/pizzabox
randomize = TRUE
+ req_skill = JOB_SKILL_MASTER
/datum/wires/explosive/pizza/New(atom/holder)
wires = list(
diff --git a/code/datums/wires/microwave.dm b/code/datums/wires/microwave.dm
index 8c74abfa46..c6e6aa13b5 100644
--- a/code/datums/wires/microwave.dm
+++ b/code/datums/wires/microwave.dm
@@ -1,6 +1,8 @@
/datum/wires/microwave
holder_type = /obj/machinery/microwave
proper_name = "Microwave"
+ req_knowledge = JOB_SKILL_TRAINED
+ req_skill = JOB_SKILL_UNTRAINED
/datum/wires/microwave/New(atom/holder)
wires = list(
diff --git a/code/datums/wires/mulebot.dm b/code/datums/wires/mulebot.dm
index a452b46830..988487727b 100644
--- a/code/datums/wires/mulebot.dm
+++ b/code/datums/wires/mulebot.dm
@@ -1,6 +1,7 @@
/datum/wires/mulebot
holder_type = /mob/living/simple_animal/bot/mulebot
randomize = TRUE
+ req_knowledge = JOB_SKILL_MASTER
/datum/wires/mulebot/New(atom/holder)
wires = list(
diff --git a/code/datums/wires/particle_accelerator.dm b/code/datums/wires/particle_accelerator.dm
index af89f0d6f1..b782e589dd 100644
--- a/code/datums/wires/particle_accelerator.dm
+++ b/code/datums/wires/particle_accelerator.dm
@@ -1,6 +1,8 @@
/datum/wires/particle_accelerator/control_box
holder_type = /obj/machinery/particle_accelerator/control_box
proper_name = "Particle Accelerator"
+ req_knowledge = JOB_SKILL_EXPERT
+ req_skill = JOB_SKILL_TRAINED
/datum/wires/particle_accelerator/control_box/New(atom/holder)
wires = list(
diff --git a/code/datums/wires/r_n_d.dm b/code/datums/wires/r_n_d.dm
index ea61c1779e..25d3b73fe0 100644
--- a/code/datums/wires/r_n_d.dm
+++ b/code/datums/wires/r_n_d.dm
@@ -1,6 +1,7 @@
/datum/wires/rnd
holder_type = /obj/machinery/rnd
randomize = TRUE
+ req_knowledge = JOB_SKILL_EXPERT
/datum/wires/rnd/New(atom/holder)
wires = list(
diff --git a/code/datums/wires/radio.dm b/code/datums/wires/radio.dm
index a1118da6d7..5db6ddd186 100644
--- a/code/datums/wires/radio.dm
+++ b/code/datums/wires/radio.dm
@@ -1,6 +1,8 @@
/datum/wires/radio
holder_type = /obj/item/radio
proper_name = "Radio"
+ req_knowledge = JOB_SKILL_TRAINED
+ req_skill = JOB_SKILL_UNTRAINED
/datum/wires/radio/New(atom/holder)
wires = list(
diff --git a/code/datums/wires/robot.dm b/code/datums/wires/robot.dm
index aa7c3cc4c3..6ede0415da 100644
--- a/code/datums/wires/robot.dm
+++ b/code/datums/wires/robot.dm
@@ -1,6 +1,8 @@
/datum/wires/robot
holder_type = /mob/living/silicon/robot
randomize = TRUE
+ req_knowledge = JOB_SKILL_MASTER
+ req_skill = JOB_SKILL_TRAINED
/datum/wires/robot/New(atom/holder)
wires = list(
diff --git a/code/datums/wires/suit_storage_unit.dm b/code/datums/wires/suit_storage_unit.dm
index eb7781203b..4387d0dc76 100644
--- a/code/datums/wires/suit_storage_unit.dm
+++ b/code/datums/wires/suit_storage_unit.dm
@@ -1,6 +1,8 @@
/datum/wires/suit_storage_unit
holder_type = /obj/machinery/suit_storage_unit
proper_name = "Suit Storage Unit"
+ req_knowledge = JOB_SKILL_TRAINED
+ req_skill = JOB_SKILL_UNTRAINED
/datum/wires/suit_storage_unit/New(atom/holder)
wires = list(
diff --git a/code/datums/wires/syndicatebomb.dm b/code/datums/wires/syndicatebomb.dm
index 53c1a1b9bc..8e1cf5002f 100644
--- a/code/datums/wires/syndicatebomb.dm
+++ b/code/datums/wires/syndicatebomb.dm
@@ -1,6 +1,8 @@
/datum/wires/syndicatebomb
holder_type = /obj/machinery/syndicatebomb
randomize = TRUE
+ req_skill = JOB_SKILL_EXPERT //good luck, wannabe hero.
+
/datum/wires/syndicatebomb/New(atom/holder)
wires = list(
diff --git a/code/datums/wires/tesla_coil.dm b/code/datums/wires/tesla_coil.dm
index fa858a9a8f..68fe8e72fc 100644
--- a/code/datums/wires/tesla_coil.dm
+++ b/code/datums/wires/tesla_coil.dm
@@ -2,6 +2,7 @@
/datum/wires/tesla_coil
randomize = 1 //Only one wire don't need blueprints
holder_type = /obj/machinery/power/tesla_coil
+ req_knowledge = JOB_SKILL_TRAINED
/datum/wires/tesla_coil/New(atom/holder)
wires = list(WIRE_ZAP)
diff --git a/code/datums/wires/vending.dm b/code/datums/wires/vending.dm
index 114791e873..6c7e59c24c 100644
--- a/code/datums/wires/vending.dm
+++ b/code/datums/wires/vending.dm
@@ -1,6 +1,7 @@
/datum/wires/vending
holder_type = /obj/machinery/vending
proper_name = "Vending Unit"
+ req_knowledge = JOB_SKILL_EXPERT
/datum/wires/vending/New(atom/holder)
wires = list(
diff --git a/code/game/machinery/camera/camera_assembly.dm b/code/game/machinery/camera/camera_assembly.dm
index 1766391709..b6af0600e4 100644
--- a/code/game/machinery/camera/camera_assembly.dm
+++ b/code/game/machinery/camera/camera_assembly.dm
@@ -48,8 +48,7 @@
if(2)
// State 2
if(istype(W, /obj/item/stack/cable_coil))
- var/obj/item/stack/cable_coil/C = W
- if(C.use(2))
+ if(W.use_tool(src, user, 0, 2))
to_chat(user, "You add wires to the assembly.")
state = 3
else
diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm
index b007bc0161..5ee8223625 100644
--- a/code/game/machinery/constructable_frame.dm
+++ b/code/game/machinery/constructable_frame.dm
@@ -83,7 +83,6 @@
if(istype(P, /obj/item/stack/cable_coil))
if(!P.tool_start_check(user, amount=5))
return
-
to_chat(user, "You start to add cables to the frame...")
if(P.use_tool(src, user, 20, volume=50, amount=5))
to_chat(user, "You add cables to the frame.")
diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm
index 1b83bb4b96..28b9796bb6 100644
--- a/code/game/machinery/doors/firedoor.dm
+++ b/code/game/machinery/doors/firedoor.dm
@@ -400,12 +400,11 @@
"You begin adding wires to [src]...")
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
if(do_after(user, 60, target = src))
- if(constructionStep != CONSTRUCTION_GUTTED || B.get_amount() < 5 || !B)
+ if(constructionStep != CONSTRUCTION_GUTTED || !B.use_tool(src, user, 0, 5))
return
user.visible_message("[user] adds wires to [src].", \
"You wire [src].")
playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1)
- B.use(5)
constructionStep = CONSTRUCTION_WIRES_EXPOSED
update_icon()
return
diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm
index f4f308c490..4a0042e1da 100644
--- a/code/game/machinery/firealarm.dm
+++ b/code/game/machinery/firealarm.dm
@@ -205,11 +205,9 @@
return
if(1)
if(istype(W, /obj/item/stack/cable_coil))
- var/obj/item/stack/cable_coil/coil = W
- if(coil.get_amount() < 5)
+ if(!W.use_tool(src, user, 0, 5))
to_chat(user, "You need more cable for this!")
else
- coil.use(5)
buildstage = 2
to_chat(user, "You wire \the [src].")
update_icon()
diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm
index 34db7b0e08..6793d361b5 100644
--- a/code/game/machinery/shieldgen.dm
+++ b/code/game/machinery/shieldgen.dm
@@ -160,10 +160,7 @@
to_chat(user, "You need one length of cable to repair [src]!")
return
to_chat(user, "You begin to replace the wires...")
- if(do_after(user, 30, target = src))
- if(coil.get_amount() < 1)
- return
- coil.use(1)
+ if(W.use_tool(src, user, 30, 1))
obj_integrity = max_integrity
stat &= ~BROKEN
to_chat(user, "You repair \the [src].")
diff --git a/code/game/mecha/mecha_defense.dm b/code/game/mecha/mecha_defense.dm
index 581283d339..53768fe9a9 100644
--- a/code/game/mecha/mecha_defense.dm
+++ b/code/game/mecha/mecha_defense.dm
@@ -220,8 +220,7 @@
return
else if(istype(W, /obj/item/stack/cable_coil))
if(state == 3 && (internal_damage & MECHA_INT_SHORT_CIRCUIT))
- var/obj/item/stack/cable_coil/CC = W
- if(CC.use(2))
+ if(W.use_tool(src, user, 0, 2))
clearInternalDamage(MECHA_INT_SHORT_CIRCUIT)
to_chat(user, "You replace the fused wires.")
else
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index c8e5b15f72..9d3cc8293b 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -132,6 +132,12 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
var/list/grind_results //A reagent list containing the reagents this item produces when ground up in a grinder - this can be an empty list to allow for reagent transferring only
var/list/juice_results //A reagent list containing blah blah... but when JUICED in a grinder!
+ ///Skills vars
+ var/used_skills //path/s of skill/s exercised when using this item.
+ var/skill_flags = NONE //better defines which tasks the the skill/s is/are exercised on.
+ var/skill_difficulty = THRESHOLD_COMPETENT //how difficult it's to use this item in general.
+ var/skill_gain = DEF_SKILL_GAIN //base skill value gain from using this item.
+
/obj/item/Initialize()
if (attack_verb)
@@ -783,7 +789,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
// Called when a mob tries to use the item as a tool.
// Handles most checks.
-/obj/item/proc/use_tool(atom/target, mob/living/user, delay, amount=0, volume=0, datum/callback/extra_checks)
+/obj/item/proc/use_tool(atom/target, mob/living/user, delay, amount=0, volume=0, datum/callback/extra_checks, skill_gain_mult = 1, max_level = INFINITY)
// No delay means there is no start message, and no reason to call tool_start_check before use_tool.
// Run the start check here so we wouldn't have to call it manually.
if(!delay && !tool_start_check(user, amount))
@@ -795,6 +801,9 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
play_tool_sound(target, volume)
if(delay)
+ if(user.mind && used_skills && skill_flags & SKILL_USE_TOOL)
+ LIST_SKILL_MODIFIER(used_skills, user.mind.skill_holder, delay, skill_difficulty)
+
// Create a callback with checks that would be called every tick by do_after.
var/datum/callback/tool_check = CALLBACK(src, .proc/tool_check_callback, user, amount, extra_checks)
@@ -819,6 +828,13 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
if(delay >= MIN_TOOL_SOUND_DELAY)
play_tool_sound(target, volume)
+ if(user.mind && used_skills && skill_flags & SKILL_TRAINING_TOOL && skill_gain_mult)
+ if(!islist(used_skills))
+ user.mind.skill_holder.boost_skill_value_to(used_skills, skill_gain*skill_gain_mult, GET_STANDARD_LVL(max_level))
+ else
+ for(var/skill in used_skills)
+ user.mind.skill_holder.boost_skill_value_to(skill, skill_gain*skill_gain_mult, GET_STANDARD_LVL(max_level))
+
return TRUE
// Called before use_tool if there is a delay, or by use_tool if there isn't.
diff --git a/code/game/objects/items/grenades/chem_grenade.dm b/code/game/objects/items/grenades/chem_grenade.dm
index acd71c57ac..91dde2899d 100644
--- a/code/game/objects/items/grenades/chem_grenade.dm
+++ b/code/game/objects/items/grenades/chem_grenade.dm
@@ -97,8 +97,7 @@
to_chat(user, "You add [A] to the [initial(name)] assembly.")
else if(stage == EMPTY && istype(I, /obj/item/stack/cable_coil))
- var/obj/item/stack/cable_coil/C = I
- if (C.use(1))
+ if (I.use_tool(src, user, 0, 1, max_level = JOB_SKILL_BASIC))
det_time = 50 // In case the cable_coil was removed and readded.
stage_change(WIRED)
to_chat(user, "You rig the [initial(name)] assembly.")
diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm
index c8ee6b05c7..1648598c4e 100644
--- a/code/game/objects/items/stacks/sheets/glass.dm
+++ b/code/game/objects/items/stacks/sheets/glass.dm
@@ -69,7 +69,7 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
if (get_amount() < 1 || CC.get_amount() < 5)
to_chat(user, "You attach wire to the [name].")
var/obj/item/stack/light_w/new_tile = new(user.loc)
diff --git a/code/game/objects/structures/ai_core.dm b/code/game/objects/structures/ai_core.dm
index 3e35c12314..1090bae9f8 100644
--- a/code/game/objects/structures/ai_core.dm
+++ b/code/game/objects/structures/ai_core.dm
@@ -131,7 +131,7 @@
if(C.get_amount() >= 5)
playsound(loc, 'sound/items/deconstruct.ogg', 50, 1)
to_chat(user, "You start to add cables to the frame...")
- if(do_after(user, 20, target = src) && state == SCREWED_CORE && C.use(5))
+ if(do_after(user, 20, target = src) && state == SCREWED_CORE && C.use_tool(src, user, 0, 5))
to_chat(user, "You add cables to the frame.")
state = CABLED_CORE
update_icon()
diff --git a/code/game/objects/structures/barsigns.dm b/code/game/objects/structures/barsigns.dm
index d2fff9649d..821409c26b 100644
--- a/code/game/objects/structures/barsigns.dm
+++ b/code/game/objects/structures/barsigns.dm
@@ -84,7 +84,6 @@
panel_open = FALSE
else if(istype(I, /obj/item/stack/cable_coil) && panel_open)
- var/obj/item/stack/cable_coil/C = I
if(obj_flags & EMAGGED) //Emagged, not broken by EMP
to_chat(user, "Sign has been damaged beyond repair!")
return
@@ -92,7 +91,7 @@
to_chat(user, "This sign is functioning properly!")
return
- if(C.use(2))
+ if(I.use_tool(src, user, 0, 2))
to_chat(user, "You replace the burnt wiring.")
broken = FALSE
else
diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm
index 04c3909696..4544cab3da 100644
--- a/code/game/objects/structures/windoor_assembly.dm
+++ b/code/game/objects/structures/windoor_assembly.dm
@@ -169,8 +169,7 @@
if(do_after(user, 40, target = src))
if(!src || !anchored || src.state != "01")
return
- var/obj/item/stack/cable_coil/CC = W
- if(!CC.use(1))
+ if(!W.use_tool(src, user, 0, 1))
to_chat(user, "You need more cable to do this!")
return
to_chat(user, "You wire the windoor.")
diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm
index a4617462fe..0838c7b091 100644
--- a/code/modules/atmospherics/machinery/airalarm.dm
+++ b/code/modules/atmospherics/machinery/airalarm.dm
@@ -786,9 +786,8 @@
return
user.visible_message("[user.name] wires the air alarm.", \
"You start wiring the air alarm...")
- if (do_after(user, 20, target = src))
- if (cable.get_amount() >= 5 && buildstage == 1)
- cable.use(5)
+ if (W.use_tool(src, user, 20, 5))
+ if (buildstage == 1)
to_chat(user, "You wire the air alarm.")
wires.repair()
aidisabled = 0
diff --git a/code/modules/clothing/under/_under.dm b/code/modules/clothing/under/_under.dm
index 0d08b59be9..11fdb47eb6 100644
--- a/code/modules/clothing/under/_under.dm
+++ b/code/modules/clothing/under/_under.dm
@@ -32,7 +32,7 @@
/obj/item/clothing/under/attackby(obj/item/I, mob/user, params)
if((has_sensor == BROKEN_SENSORS) && istype(I, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = I
- C.use(1)
+ I.use_tool(src, user, 0, 1)
has_sensor = HAS_SENSORS
to_chat(user,"You repair the suit sensors on [src] with [C].")
return 1
diff --git a/code/modules/hydroponics/plant_genes.dm b/code/modules/hydroponics/plant_genes.dm
index ef2eff707f..b18f4396d6 100644
--- a/code/modules/hydroponics/plant_genes.dm
+++ b/code/modules/hydroponics/plant_genes.dm
@@ -392,8 +392,7 @@
/datum/plant_gene/trait/battery/on_attackby(obj/item/reagent_containers/food/snacks/grown/G, obj/item/I, mob/user)
if(istype(I, /obj/item/stack/cable_coil))
- var/obj/item/stack/cable_coil/C = I
- if(C.use(5))
+ if(I.use_tool(src, user, 0, 5, max_level = JOB_SKILL_EXPERT))
to_chat(user, "You add some cable to [G] and slide it inside the battery encasing.")
var/obj/item/stock_parts/cell/potato/pocell = new /obj/item/stock_parts/cell/potato(user.loc)
pocell.icon_state = G.icon_state
diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm
index e40c278e92..e10f009cec 100644
--- a/code/modules/jobs/job_types/_job.dm
+++ b/code/modules/jobs/job_types/_job.dm
@@ -174,7 +174,7 @@
if(!starting_skills)
return
for(var/skill in starting_skills)
- M.skill_holder.boost_skill_value_to(skill, starting_skills[skill])
+ M.skill_holder.boost_skill_value_to(skill, starting_skills[skill], TRUE) //silent
// do wipe affinities though
M.skill_holder.skill_affinities = list()
for(var/skill in skill_affinities)
diff --git a/code/modules/jobs/job_types/ai.dm b/code/modules/jobs/job_types/ai.dm
index efe574ab66..1395b90b39 100644
--- a/code/modules/jobs/job_types/ai.dm
+++ b/code/modules/jobs/job_types/ai.dm
@@ -17,6 +17,8 @@
var/do_special_check = TRUE
threat = 5
+ starting_skills = list(/datum/skill/level/job/wiring = GET_STANDARD_LVL(JOB_SKILL_BASIC))
+
/datum/job/ai/equip(mob/living/carbon/human/H, visualsOnly, announce, latejoin, datum/outfit/outfit_override, client/preference_source = null)
if(visualsOnly)
CRASH("dynamic preview is unsupported")
diff --git a/code/modules/jobs/job_types/atmospheric_technician.dm b/code/modules/jobs/job_types/atmospheric_technician.dm
index 019e50799e..770cbe3bda 100644
--- a/code/modules/jobs/job_types/atmospheric_technician.dm
+++ b/code/modules/jobs/job_types/atmospheric_technician.dm
@@ -17,6 +17,10 @@
ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION, ACCESS_ATMOSPHERICS, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_ATMOSPHERICS, ACCESS_MAINT_TUNNELS, ACCESS_EXTERNAL_AIRLOCKS, ACCESS_ENGINE,
ACCESS_ENGINE_EQUIP, ACCESS_EMERGENCY_STORAGE, ACCESS_CONSTRUCTION, ACCESS_MINERAL_STOREROOM)
+
+ starting_skills = list(/datum/skill/level/job/wiring = GET_STANDARD_LVL(JOB_SKILL_BASIC))
+ skill_affinities = list(/datum/skill/level/job/wiring = STARTING_SKILL_AFFINITY_WIRING_ENGI_ROBO)
+
display_order = JOB_DISPLAY_ORDER_ATMOSPHERIC_TECHNICIAN
threat = 0.5
diff --git a/code/modules/jobs/job_types/chief_engineer.dm b/code/modules/jobs/job_types/chief_engineer.dm
index 0d70e872ac..bd4732f3c3 100644
--- a/code/modules/jobs/job_types/chief_engineer.dm
+++ b/code/modules/jobs/job_types/chief_engineer.dm
@@ -27,6 +27,9 @@
ACCESS_HEADS, ACCESS_CONSTRUCTION, ACCESS_SEC_DOORS, ACCESS_MINISAT,
ACCESS_CE, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_TCOMSAT, ACCESS_MINERAL_STOREROOM)
+ starting_skills = list(/datum/skill/level/job/wiring = GET_STANDARD_LVL(JOB_SKILL_TRAINED))
+ skill_affinities = list(/datum/skill/level/job/wiring = STARTING_SKILL_AFFINITY_WIRING_ENGI_ROBO)
+
display_order = JOB_DISPLAY_ORDER_CHIEF_ENGINEER
blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/paraplegic, /datum/quirk/insanity)
threat = 2
diff --git a/code/modules/jobs/job_types/cyborg.dm b/code/modules/jobs/job_types/cyborg.dm
index f84bd0d8d6..d88d888aec 100644
--- a/code/modules/jobs/job_types/cyborg.dm
+++ b/code/modules/jobs/job_types/cyborg.dm
@@ -12,6 +12,8 @@
exp_requirements = 120
exp_type = EXP_TYPE_CREW
+ starting_skills = list(/datum/skill/level/job/wiring = GET_STANDARD_LVL(JOB_SKILL_BASIC))
+
display_order = JOB_DISPLAY_ORDER_CYBORG
/datum/job/cyborg/equip(mob/living/carbon/human/H, visualsOnly = FALSE, announce = TRUE, latejoin = FALSE, datum/outfit/outfit_override = null, client/preference_source = null)
diff --git a/code/modules/jobs/job_types/roboticist.dm b/code/modules/jobs/job_types/roboticist.dm
index f9f1d20d3b..d9e891f057 100644
--- a/code/modules/jobs/job_types/roboticist.dm
+++ b/code/modules/jobs/job_types/roboticist.dm
@@ -16,6 +16,10 @@
access = list(ACCESS_ROBOTICS, ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_TECH_STORAGE, ACCESS_MORGUE, ACCESS_RESEARCH, ACCESS_MINERAL_STOREROOM, ACCESS_XENOBIOLOGY, ACCESS_GENETICS)
minimal_access = list(ACCESS_ROBOTICS, ACCESS_TECH_STORAGE, ACCESS_MORGUE, ACCESS_RESEARCH, ACCESS_MINERAL_STOREROOM)
+ starting_skills = list(/datum/skill/level/job/wiring = GET_STANDARD_LVL(JOB_SKILL_TRAINED))
+ skill_affinities = list(/datum/skill/level/job/wiring = STARTING_SKILL_AFFINITY_WIRING_ENGI_ROBO)
+
+
display_order = JOB_DISPLAY_ORDER_ROBOTICIST
threat = 1
diff --git a/code/modules/jobs/job_types/station_engineer.dm b/code/modules/jobs/job_types/station_engineer.dm
index 66ddc90e9b..c5280d72db 100644
--- a/code/modules/jobs/job_types/station_engineer.dm
+++ b/code/modules/jobs/job_types/station_engineer.dm
@@ -18,6 +18,9 @@
minimal_access = list(ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_TECH_STORAGE, ACCESS_MAINT_TUNNELS,
ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION, ACCESS_TCOMSAT, ACCESS_MINERAL_STOREROOM)
+ starting_skills = list(/datum/skill/level/job/wiring = GET_STANDARD_LVL(JOB_SKILL_TRAINED))
+ skill_affinities = list(/datum/skill/level/job/wiring = STARTING_SKILL_AFFINITY_WIRING_ENGI_ROBO)
+
display_order = JOB_DISPLAY_ORDER_STATION_ENGINEER
threat = 1
diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm
index c7c34b0389..a0c2cc73e8 100644
--- a/code/modules/mining/ores_coins.dm
+++ b/code/modules/mining/ores_coins.dm
@@ -364,12 +364,11 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
/obj/item/coin/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/stack/cable_coil))
- var/obj/item/stack/cable_coil/CC = W
if(string_attached)
to_chat(user, "There already is a string attached to this coin!")
return
- if (CC.use(1))
+ if (W.use_tool(src, user, 0, 1, max_level = JOB_SKILL_BASIC))
add_overlay("coin_string_overlay")
string_attached = 1
to_chat(user, "You attach a string to the coin.")
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index 9c4f0316b7..42e702c5d9 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -9,7 +9,7 @@
if(istype(src.glasses, /obj/item/clothing/glasses)) //glasses
var/obj/item/clothing/glasses/GFP = src.glasses
number += GFP.flash_protect
-
+
if(istype(src.wear_mask, /obj/item/clothing/mask)) //mask
var/obj/item/clothing/mask/MFP = src.wear_mask
number += MFP.flash_protect
@@ -77,15 +77,13 @@
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded)
/mob/living/carbon/attacked_by(obj/item/I, mob/living/user)
- //CIT CHANGES START HERE - combatmode and resting checks
- var/totitemdamage = I.force
+ var/totitemdamage = pre_attacked_by(I, user, TRUE)
if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
totitemdamage *= 0.5
if(!CHECK_MOBILITY(user, MOBILITY_STAND))
totitemdamage *= 0.5
if(!(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
totitemdamage *= 1.5
- //CIT CHANGES END HERE
var/impacting_zone = (user == src)? check_zone(user.zone_selected) : ran_zone(user.zone_selected)
if((user != src) && (run_block(I, totitemdamage, "the [I]", ATTACK_TYPE_MELEE, I.armour_penetration, user, impacting_zone) & BLOCK_SUCCESS))
return FALSE
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 683c3e18fd..124f862244 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -1712,9 +1712,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
disarm(M, H, attacker_style)
/datum/species/proc/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H)
+ var/totitemdamage = H.pre_attacked_by(I, user, TRUE)
// Allows you to put in item-specific reactions based on species
if(user != H)
- if(H.run_block(I, I.force, "the [I.name]", ATTACK_TYPE_MELEE, I.armour_penetration, user, affecting.body_zone) & BLOCK_SUCCESS)
+ if(H.run_block(I, totitemdamage, "the [I.name]", ATTACK_TYPE_MELEE, I.armour_penetration, user, affecting.body_zone) & BLOCK_SUCCESS)
return 0
if(H.check_martial_melee_block())
H.visible_message("[H] blocks [I]!")
@@ -1730,16 +1731,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/armor_block = H.run_armor_check(affecting, "melee", "Your armor has protected your [hit_area].", "Your armor has softened a hit to your [hit_area].",I.armour_penetration)
armor_block = min(90,armor_block) //cap damage reduction at 90%
var/Iforce = I.force //to avoid runtimes on the forcesay checks at the bottom. Some items might delete themselves if you drop them. (stunning yourself, ninja swords)
- //CIT CHANGES START HERE - combatmode and resting checks
- var/totitemdamage = I.force
- if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
- totitemdamage *= 0.5
- if(!CHECK_MOBILITY(user, MOBILITY_STAND))
- totitemdamage *= 0.5
- if(istype(H))
- if(!(H.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
- totitemdamage *= 1.5
- //CIT CHANGES END HERE
var/weakness = H.check_weakness(I, user)
apply_damage(totitemdamage * weakness, I.damtype, def_zone, armor_block, H) //CIT CHANGE - replaces I.force with totitemdamage
@@ -1747,7 +1738,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
I.do_stagger_action(H, user)
- if(!I.force)
+ if(!totitemdamage)
return 0 //item force is zero
//dismemberment
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index b389e386d4..508dc67dd7 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -427,24 +427,23 @@
else if(istype(W, /obj/item/stack/cable_coil) && wiresexposed)
user.changeNext_move(CLICK_CD_MELEE)
- var/obj/item/stack/cable_coil/coil = W
if (getFireLoss() > 0 || getToxLoss() > 0)
- if(src == user && coil.use(1))
+ if(src == user)
to_chat(user, "You start fixing yourself...")
- if(!do_after(user, 50, target = src))
+ if(!W.use_tool(src, user, 50, 1, max_level = JOB_SKILL_TRAINED))
+ to_chat(user, "You need more cable to repair [src]!")
return
adjustFireLoss(-10)
adjustToxLoss(-10)
- if (coil.use(1))
+ else
to_chat(user, "You start fixing [src]...")
- if(!do_after(user, 30, target = src))
+ if(!W.use_tool(src, user, 30, 1))
+ to_chat(user, "You need more cable to repair [src]!")
return
adjustFireLoss(-30)
adjustToxLoss(-30)
updatehealth()
user.visible_message("[user] has fixed some of the burnt wires on [src].", "You fix some of the burnt wires on [src].")
- else
- to_chat(user, "You need more cable to repair [src]!")
else
to_chat(user, "The wires seem fine, there's no need to fix them.")
diff --git a/code/modules/mob/living/simple_animal/bot/construction.dm b/code/modules/mob/living/simple_animal/bot/construction.dm
index 6c4680a477..08fffc2cf8 100644
--- a/code/modules/mob/living/simple_animal/bot/construction.dm
+++ b/code/modules/mob/living/simple_animal/bot/construction.dm
@@ -147,9 +147,8 @@
to_chat(user, "You need one length of cable to wire the ED-209!")
return
to_chat(user, "You start to wire [src]...")
- if(do_after(user, 40, target = src))
- if(coil.get_amount() >= 1 && build_step == 6)
- coil.use(1)
+ if(coil.use_tool(src, user, 40, 1))
+ if(build_step == 6)
to_chat(user, "You wire [src].")
name = "wired ED-209 assembly"
build_step++
diff --git a/code/modules/modular_computers/hardware/_hardware.dm b/code/modules/modular_computers/hardware/_hardware.dm
index 744db1572f..37f3fc434e 100644
--- a/code/modules/modular_computers/hardware/_hardware.dm
+++ b/code/modules/modular_computers/hardware/_hardware.dm
@@ -41,11 +41,10 @@
// Cable coil. Works as repair method, but will probably require multiple applications and more cable.
if(istype(I, /obj/item/stack/cable_coil))
- var/obj/item/stack/S = I
if(obj_integrity == max_integrity)
to_chat(user, "\The [src] doesn't seem to require repairs.")
return 1
- if(S.use(1))
+ if(I.use_tool(src, user, 0, 1))
to_chat(user, "You patch up \the [src] with a bit of \the [I].")
obj_integrity = min(obj_integrity + 10, max_integrity)
return 1
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 7eabeafcb1..977a6484b7 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -593,19 +593,15 @@
user.visible_message("[user.name] adds cables to the APC frame.", \
"You start adding cables to the APC frame...")
playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1)
- if(do_after(user, 20, target = src))
- if (C.get_amount() < 10 || !C)
+ if(C.use_tool(src, user, 20, 10) && !terminal && opened && has_electronics)
+ var/turf/T = get_turf(src)
+ var/obj/structure/cable/N = T.get_cable_node()
+ if (prob(50) && electrocute_mob(usr, N, N, 1, TRUE))
+ do_sparks(5, TRUE, src)
return
- if (C.get_amount() >= 10 && !terminal && opened && has_electronics)
- var/turf/T = get_turf(src)
- var/obj/structure/cable/N = T.get_cable_node()
- if (prob(50) && electrocute_mob(usr, N, N, 1, TRUE))
- do_sparks(5, TRUE, src)
- return
- C.use(10)
- to_chat(user, "You add cables to the APC frame.")
- make_terminal()
- terminal.connect_to_network()
+ to_chat(user, "You add cables to the APC frame.")
+ make_terminal()
+ terminal.connect_to_network()
else if (istype(W, /obj/item/electronics/apc) && opened)
if (has_electronics)
to_chat(user, "There is already a board inside the [src]!")
diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm
index eecc1394de..1e2650d17f 100644
--- a/code/modules/power/cable.dm
+++ b/code/modules/power/cable.dm
@@ -495,6 +495,8 @@ By design, d1 is the smallest direction and d2 is the highest
full_w_class = WEIGHT_CLASS_SMALL
grind_results = list(/datum/reagent/copper = 2) //2 copper per cable in the coil
usesound = 'sound/items/deconstruct.ogg'
+ used_skills = /datum/skill/level/job/wiring
+ skill_flags = SKILL_USE_TOOL|SKILL_TRAINING_TOOL
/obj/item/stack/cable_coil/cyborg
is_cyborg = 1
@@ -576,8 +578,6 @@ By design, d1 is the smallest direction and d2 is the highest
amount += extra
update_icon()
-
-
///////////////////////////////////////////////
// Cable laying procedures
//////////////////////////////////////////////
diff --git a/code/modules/power/floodlight.dm b/code/modules/power/floodlight.dm
index 9fb1a1ce7d..e0b3f5f316 100644
--- a/code/modules/power/floodlight.dm
+++ b/code/modules/power/floodlight.dm
@@ -15,8 +15,7 @@
state = FLOODLIGHT_NEEDS_WIRES
desc = "A bare metal frame looking vaguely like a floodlight. Requires wiring."
else if(istype(O, /obj/item/stack/cable_coil) && (state == FLOODLIGHT_NEEDS_WIRES))
- var/obj/item/stack/S = O
- if(S.use(5))
+ if(O.use_tool(src, user, 0, 5))
to_chat(user, "You wire [src].")
name = "wired [name]"
desc = "A bare metal frame looking vaguely like a floodlight. Requires securing with a screwdriver."
diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm
index 7ad9f3a6ce..2f7f9ad729 100644
--- a/code/modules/power/lighting.dm
+++ b/code/modules/power/lighting.dm
@@ -118,8 +118,7 @@
return
if(istype(W, /obj/item/stack/cable_coil))
- var/obj/item/stack/cable_coil/coil = W
- if(coil.use(1))
+ if(W.use_tool(src, user, 0, 1, max_level = JOB_SKILL_TRAINED))
icon_state = "[fixture_type]-construct-stage2"
stage = 2
user.visible_message("[user.name] adds wires to [src].", \
diff --git a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm
index 59792b6539..e33116b02c 100644
--- a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm
+++ b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm
@@ -79,8 +79,7 @@
construction_state = PA_CONSTRUCTION_UNSECURED
did_something = TRUE
else if(istype(W, /obj/item/stack/cable_coil))
- var/obj/item/stack/cable_coil/CC = W
- if(CC.use(1))
+ if(W.use_tool(src, user, 0, 1))
user.visible_message("[user.name] adds wires to the [name].", \
"You add some wires.")
construction_state = PA_CONSTRUCTION_PANEL_OPEN
diff --git a/code/modules/power/singularity/particle_accelerator/particle_control.dm b/code/modules/power/singularity/particle_accelerator/particle_control.dm
index af83f7ebca..957ceb986f 100644
--- a/code/modules/power/singularity/particle_accelerator/particle_control.dm
+++ b/code/modules/power/singularity/particle_accelerator/particle_control.dm
@@ -288,8 +288,7 @@
construction_state = PA_CONSTRUCTION_UNSECURED
did_something = TRUE
else if(istype(W, /obj/item/stack/cable_coil))
- var/obj/item/stack/cable_coil/CC = W
- if(CC.use(1))
+ if(W.use_tool(src, user, 0, 1))
user.visible_message("[user.name] adds wires to the [name].", \
"You add some wires.")
construction_state = PA_CONSTRUCTION_PANEL_OPEN
diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm
index 41ed28f0a5..85999707a2 100644
--- a/code/modules/power/smes.dm
+++ b/code/modules/power/smes.dm
@@ -125,15 +125,12 @@
to_chat(user, "You start building the power terminal...")
playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1)
- if(do_after(user, 20, target = src) && C.get_amount() >= 10)
- if(C.get_amount() < 10 || !C)
- return
+ if(C.use_tool(src, user, 20, 10))
var/obj/structure/cable/N = T.get_cable_node() //get the connecting node cable, if there's one
if (prob(50) && electrocute_mob(usr, N, N, 1, TRUE)) //animate the electrocution if uncautious and unlucky
do_sparks(5, TRUE, src)
return
- C.use(10)
user.visible_message(\
"[user.name] has built a power terminal.",\
"You build the power terminal.")
diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm
index b43ac3057a..afe2b9ca3e 100644
--- a/code/modules/projectiles/guns/ballistic/revolver.dm
+++ b/code/modules/projectiles/guns/ballistic/revolver.dm
@@ -331,8 +331,7 @@
/obj/item/gun/ballistic/revolver/doublebarrel/improvised/attackby(obj/item/A, mob/user, params)
..()
if(istype(A, /obj/item/stack/cable_coil) && !sawn_off)
- var/obj/item/stack/cable_coil/C = A
- if(C.use(10))
+ if(A.use_tool(src, user, 0, 10, max_level = JOB_SKILL_BASIC))
slot_flags = ITEM_SLOT_BACK
to_chat(user, "You tie the lengths of cable to the shotgun, making a sling.")
slung = TRUE
diff --git a/code/modules/surgery/bodyparts/robot_bodyparts.dm b/code/modules/surgery/bodyparts/robot_bodyparts.dm
index a3f8b883b4..39e660203e 100644
--- a/code/modules/surgery/bodyparts/robot_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/robot_bodyparts.dm
@@ -19,7 +19,7 @@
flags_1 = CONDUCT_1
icon_state = "borg_l_arm"
status = BODYPART_ROBOTIC
-
+
brute_reduction = 2
burn_reduction = 1
@@ -40,7 +40,7 @@
flags_1 = CONDUCT_1
icon_state = "borg_r_arm"
status = BODYPART_ROBOTIC
-
+
brute_reduction = 2
burn_reduction = 1
@@ -61,7 +61,7 @@
flags_1 = CONDUCT_1
icon_state = "borg_l_leg"
status = BODYPART_ROBOTIC
-
+
brute_reduction = 2
burn_reduction = 1
@@ -82,7 +82,7 @@
flags_1 = CONDUCT_1
icon_state = "borg_r_leg"
status = BODYPART_ROBOTIC
-
+
brute_reduction = 2
burn_reduction = 1
@@ -102,7 +102,7 @@
flags_1 = CONDUCT_1
icon_state = "borg_chest"
status = BODYPART_ROBOTIC
-
+
brute_reduction = 2
burn_reduction = 1
@@ -131,8 +131,7 @@
if(src.wired)
to_chat(user, "You have already inserted wire!")
return
- var/obj/item/stack/cable_coil/coil = W
- if (coil.use(1))
+ if (W.use_tool(src, user, 0, 1))
src.wired = 1
to_chat(user, "You insert the wire.")
else
@@ -164,7 +163,7 @@
flags_1 = CONDUCT_1
icon_state = "borg_head"
status = BODYPART_ROBOTIC
-
+
brute_reduction = 5
burn_reduction = 4
diff --git a/code/modules/surgery/surgery_step.dm b/code/modules/surgery/surgery_step.dm
index 7127b41ee3..23dffdea87 100644
--- a/code/modules/surgery/surgery_step.dm
+++ b/code/modules/surgery/surgery_step.dm
@@ -58,10 +58,9 @@
return FALSE
if(tool)
speed_mod = tool.toolspeed
- var/skill_mod = 1
- if(user?.mind?.skill_holder)
- skill_mod = SURGERY_SKILL_SPEEDUP_NUMERICAL_SCALE(user.mind.skill_holder.get_skill_value(/datum/skill/numerical/surgery))
- if(do_after(user, time * speed_mod * skill_mod, target = target))
+ if(user.mind)
+ SKILL_MODIFIER(GLOB.skill_datums[/datum/skill/numerical/surgery], user.mind.skill_holder, speed_mod, THRESHOLD_COMPETENT)
+ if(do_after(user, time * speed_mod, target = target))
var/prob_chance = 100
if(implement_type) //this means it isn't a require hand or any item step.
prob_chance = implements[implement_type]
@@ -69,7 +68,7 @@
if((prob(prob_chance) || (iscyborg(user) && !silicons_obey_prob)) && chem_check(target) && !try_to_fail)
if(success(user, target, target_zone, tool, surgery))
- user?.mind?.skill_holder?.auto_gain_experience(/datum/skill/numerical/surgery, SKILL_GAIN_SURGERY_PER_STEP)
+ user.mind?.skill_holder.auto_gain_experience(/datum/skill/numerical/surgery, SKILL_GAIN_SURGERY_PER_STEP)
advance = TRUE
else
if(failure(user, target, target_zone, tool, surgery))
diff --git a/tgstation.dme b/tgstation.dme
index 68ae7669f3..8245ef02f4 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -125,7 +125,8 @@
#include "code\__DEFINES\dcs\signals.dm"
#include "code\__DEFINES\flags\shields.dm"
#include "code\__DEFINES\misc\return_values.dm"
-#include "code\__DEFINES\skills\skills.dm"
+#include "code\__DEFINES\skills\defines.dm"
+#include "code\__DEFINES\skills\helpers.dm"
#include "code\__HELPERS\_cit_helpers.dm"
#include "code\__HELPERS\_lists.dm"
#include "code\__HELPERS\_logging.dm"