From 001109cfcd745589ac06c032b88a5ba2f869f193 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Tue, 5 May 2020 20:58:44 +0200 Subject: [PATCH] About ready. --- code/__DEFINES/combat.dm | 9 +++++ code/__DEFINES/skills/defines.dm | 3 ++ code/__DEFINES/skills/helpers.dm | 40 ++++++++++--------- code/_onclick/item_attack.dm | 50 ++++++++++++++---------- code/datums/skills/_skill.dm | 34 ++++++++-------- code/datums/skills/_skill_holder.dm | 19 +++++---- code/datums/wires/_wires.dm | 10 +++-- code/game/objects/items.dm | 18 ++++----- code/game/objects/items/melee/misc.dm | 2 +- code/game/objects/items/stunbaton.dm | 2 +- code/game/objects/items/toys.dm | 5 +-- code/modules/mob/living/carbon/carbon.dm | 2 +- code/modules/power/cable.dm | 3 +- 13 files changed, 111 insertions(+), 86 deletions(-) diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index 7de162207d..74ce8519a2 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -248,6 +248,15 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list( #define TOTAL_MASS_MEDIEVAL_WEAPON 3.6 //very, very generic average sword/warpick/etc. weight in pounds. #define TOTAL_MASS_TOY_SWORD 1.5 +//stamina cost defines. +#define STAM_COST_ATTACK_OBJ_MULT 1.2 +#define STAM_COST_ATTACK_MOB_MULT 0.8 +#define STAM_COST_BATON_MOB_MULT 1 +#define STAM_COST_NO_COMBAT_MULT 1.25 +#define STAM_COST_W_CLASS_MULT 1.25 +#define STAM_COST_THROW_MULT 2 + + //bullet_act() return values #define BULLET_ACT_HIT "HIT" //It's a successful hit, whatever that means in the context of the thing it's hitting. #define BULLET_ACT_BLOCK "BLOCK" //It's a blocked hit, whatever that means in the context of the thing it's hitting. diff --git a/code/__DEFINES/skills/defines.dm b/code/__DEFINES/skills/defines.dm index 00859bbd40..58b51b88e7 100644 --- a/code/__DEFINES/skills/defines.dm +++ b/code/__DEFINES/skills/defines.dm @@ -36,6 +36,9 @@ #define SKILL_TRAIN_ATTACK_MOB (1<<3) #define SKILL_ATTACK_OBJ (1<<4) #define SKILL_TRAIN_ATTACK_OBJ (1<<5) +#define SKILL_STAMINA_COST (1<<6) //Influences the stamina cost from weapon usage. +#define SKILL_THROW_STAM_COST (1<<7) +#define SKILL_COMBAT_MODE (1<<8) //The user must have combat mode on. ///competency_threshold index defines #define THRESHOLD_COMPETENT 1 diff --git a/code/__DEFINES/skills/helpers.dm b/code/__DEFINES/skills/helpers.dm index 165b9091ae..88ad481e87 100644 --- a/code/__DEFINES/skills/helpers.dm +++ b/code/__DEFINES/skills/helpers.dm @@ -13,26 +13,28 @@ }\ 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])\ +/// This is the one that accepts typepaths and lists. if flags are enabled, an associative value check will be done. +#define LIST_SKILL_MODIFIER(list, holder, target, threshold, flags, bad_flags) \ + var/___sum = 0;\ + var/___divisor = 0;\ + for(var/_S in list){\ + if((flags && !(list[_S] & (flags))) || (bad_flags && list[_S] & (bad_flags))){\ + continue\ }\ - target /= (___sum/length(___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]);\ + ___divisor++\ + }\ + if(___divisor){\ + target /= (___sum/___divisor)\ } //How experience levels are calculated. diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 36a718b4b5..cdbab52d15 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -91,7 +91,7 @@ log_combat(user, M, "attacked", src.name, "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])") add_fingerprint(user) - user.adjustStaminaLossBuffered(getweight()*0.8)//CIT CHANGE - makes attacking things cause stamina loss + user.adjustStaminaLossBuffered(getweight(user, STAM_COST_ATTACK_MOB_MULT))//CIT CHANGE - makes attacking things cause stamina loss //the equivalent of the standard version of attack() but for object targets. /obj/item/proc/attack_obj(obj/O, mob/living/user) @@ -102,7 +102,7 @@ if(IS_STAMCRIT(user)) // CIT CHANGE - makes it impossible to attack in stamina softcrit to_chat(user, "You're too exhausted.") // CIT CHANGE - ditto return // CIT CHANGE - ditto - user.adjustStaminaLossBuffered(getweight()*1.2)//CIT CHANGE - makes attacking things cause stamina loss + user.adjustStaminaLossBuffered(getweight(user, STAM_COST_ATTACK_OBJ_MULT))//CIT CHANGE - makes attacking things cause stamina loss user.changeNext_move(CLICK_CD_MELEE) user.do_attack_animation(O) O.attacked_by(src, user) @@ -112,15 +112,17 @@ /obj/attacked_by(obj/item/I, mob/living/user) var/totitemdamage = I.force + var/bad_flag = NONE + if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) && iscarbon(user)) + totitemdamage *= 0.5 + bad_flag |= SKILL_COMBAT_MODE //blacklist combat skills. if(I.used_skills && user.mind) - if(I.skill_flags & SKILL_ATTACK_OBJ) - LIST_SKILL_MODIFIER(I.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(I.used_skills, I.skill_gain) - else - for(var/skill in I.used_skills) - user.mind.skill_holder.boost_skill_value_to(skill, I.skill_gain) + if(totitemdamage) + LIST_SKILL_MODIFIER(I.used_skills, user.mind.skill_holder, totitemdamage, I.skill_difficulty, SKILL_ATTACK_OBJ, bad_flag) + for(var/skill in I.used_skills) + if(!(I.used_skills[skill] & SKILL_TRAIN_ATTACK_OBJ)) + continue + user.mind.skill_holder.auto_gain_experience(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. @@ -152,20 +154,20 @@ /mob/living/proc/pre_attacked_by(obj/item/I, mob/living/user) . = I.force - if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) + var/bad_flag = NONE + if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) && iscarbon(user)) . *= 0.5 + bad_flag |= SKILL_COMBAT_MODE //blacklist combat skills. if(!CHECK_MOBILITY(user, MOBILITY_STAND)) . *= 0.5 if(!user.mind || !I.used_skills) return - if(. && I.skill_flags & SKILL_ATTACK_MOB) - LIST_SKILL_MODIFIER(I.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(I.used_skills, I.skill_gain) - else - for(var/skill in I.used_skills) - user.mind.skill_holder.boost_skill_value_to(skill, I.skill_gain) + if(.) + LIST_SKILL_MODIFIER(I.used_skills, user.mind.skill_holder, ., I.skill_difficulty, SKILL_ATTACK_MOB, bad_flag) + for(var/skill in I.used_skills) + if(!(I.used_skills[skill] & SKILL_TRAIN_ATTACK_MOB)) + continue + user.mind.skill_holder.auto_gain_experience(skill, I.skill_gain) /mob/living/carbon/pre_attacked_by(obj/item/I, mob/living/user) . = ..() @@ -205,8 +207,14 @@ return 1 /// How much stamina this takes to swing this is not for realism purposes hecc off. -/obj/item/proc/getweight() - return total_mass || w_class * 1.25 +/obj/item/proc/getweight(mob/living/user, multiplier = 1, flags = NONE) + . = (total_mass || w_class * STAM_COST_W_CLASS_MULT) * multiplier + var/bad_flag = NONE + if(iscarbon(user) && !(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) + . *= STAM_COST_NO_COMBAT_MULT + bad_flag |= SKILL_COMBAT_MODE + if(used_skills && user.mind) + LIST_SKILL_MODIFIER(used_skills, user.mind.skill_holder, ., skill_difficulty, SKILL_STAMINA_COST|flags, bad_flag) /// How long this staggers for. 0 and negatives supported. /obj/item/proc/melee_stagger_duration(force_override) diff --git a/code/datums/skills/_skill.dm b/code/datums/skills/_skill.dm index 039afacfa5..acfa44389e 100644 --- a/code/datums/skills/_skill.dm +++ b/code/datums/skills/_skill.dm @@ -28,7 +28,7 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums()) /// Our description var/desc /// Color of the name as shown in the html readout - var/name_color = "#000000" + var/name_color = "#FFFFFF" /// Our progression type var/progression_type /// Abstract type @@ -62,7 +62,7 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums()) /** * Standard value "render" */ -/datum/skill/proc/standard_render_value(value) +/datum/skill/proc/standard_render_value(value, level) return value // Just saying, the choice to use different sub-parent-types is to force coders to resolve issues as I won't be implementing custom procs to grab skill levels in a certain context. @@ -77,7 +77,7 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums()) /datum/skill/binary/sanitize_value(new_value) return new_value? TRUE : FALSE -/datum/skill/binary/standard_render_value(value) +/datum/skill/binary/standard_render_value(value, level) return value? "Yes" : "No" /datum/skill/numerical @@ -93,7 +93,7 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums()) /datum/skill/numerical/sanitize_value(new_value) return clamp(new_value, min_value, max_value) -/datum/skill/numerical/standard_render_value(value) +/datum/skill/numerical/standard_render_value(value, level) return display_as_percent? "[round(value/max_value/100, 0.01)]%" : "[value] / [max_value]" /datum/skill/enum @@ -113,7 +113,7 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums()) 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/xp_lvl_multiplier = STD_XP_LVL_MULTI //standard required level up exp multiplier. def: 2 (100, 200, 400, 800 etc.) 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" @@ -132,7 +132,7 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums()) value = XP_LEVEL(standard_xp_lvl_up, xp_lvl_multiplier, lvl) if(DWARFY_LEVEL_UP) value = DORF_XP_LEVEL(standard_xp_lvl_up, xp_lvl_multiplier, lvl) - value = round(value) + value = round(value, 1) if(!associative) levels += value continue @@ -142,7 +142,7 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums()) var/key = LAZYACCESS(levels, lvl) if(!key) if(lvl == 1) //You dun goof it. - stack_trace("Skill datum [src] was set to have an associative levels list despite the latted having no key.") + stack_trace("Skill datum [src] was set to have an associative levels list despite the latter having no key value.") associative = FALSE levels += value continue @@ -170,18 +170,18 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums()) else if(. < 0) to_chat(M.current, "I feel like I've become worse at [name]!") -/datum/skill/level/standard_render_value(value) - var/current_lvl = associative ? unskilled_tier : 0 +/datum/skill/level/standard_render_value(value, level) + var/current_lvl = associative ? (!level ? unskilled_tier : levels[level]) : level var/current_lvl_xp_sum = 0 - var/next_lvl_xp_sum - 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] : lvl+1 + if(level) + current_lvl_xp_sum = associative ? levels[levels[level]] : levels[level] + var/next_index = max(max_levels, level+1) + var/next_lvl_xp = associative ? levels[levels[next_index]] : levels[next_index] + if(next_lvl_xp > current_lvl_xp_sum) + next_lvl_xp -= current_lvl_xp_sum - return "[associative ? current_lvl : "Lvl. [current_lvl]"] ([value - current_lvl_xp_sum]/[next_lvl_xp_sum])[value > next_lvl_xp_sum ? " \[MAX!\]" : ""]" + + return "[associative ? current_lvl : "Lvl. [current_lvl]"] ([value - current_lvl_xp_sum]/[next_lvl_xp])[level == max_levels ? " \[MAX!\]" : ""]" /datum/skill/level/job levels = list("Basic", "Trained", "Experienced", "Master") diff --git a/code/datums/skills/_skill_holder.dm b/code/datums/skills/_skill_holder.dm index db9a84bb05..8b72b5c96d 100644 --- a/code/datums/skills/_skill_holder.dm +++ b/code/datums/skills/_skill_holder.dm @@ -29,8 +29,8 @@ * 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(!ispath(skill, /datum/skill)) + CRASH("Invalid get_skill_value call. Use skill 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] @@ -39,8 +39,8 @@ * Grabs our affinity for a skill. !!This is a multiplier!! */ /datum/skill_holder/proc/get_skill_affinity(skill) - if(!ispath(skill)) - CRASH("Invalid get_skill_affinity call. Use typepaths.") //until a time when we somehow need text ids for dynamic skills, I'm enforcing this. + if(!ispath(skill, /datum/skill)) + CRASH("Invalid get_skill_affinity call. Use skill typepaths.") //until a time when we somehow need text ids for dynamic skills, I'm enforcing this. var/affinity = LAZYACCESS(skill_affinities, skill) if(isnull(affinity)) return 1 @@ -51,7 +51,7 @@ */ /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. + CRASH("Invalid set_skill_value call. Use skill typepaths.") //until a time when we somehow need text ids for dynamic skills, I'm enforcing this. var/datum/skill/S = GLOB.skill_datums[skill] value = S.sanitize_value(value) if(!isnull(value)) @@ -75,8 +75,11 @@ * Only works if skill is numerical. */ /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!") + if(!ispath(skill, /datum/skill)) + CRASH("Invalid set_skill_value call. Use skill typepaths.") + var/datum/skill/S = GLOB.skill_datums[skill] + if(S.progression_type != SKILL_PROGRESSION_NUMERICAL && S.progression_type != SKILL_PROGRESSION_LEVEL) + CRASH("You cannot auto increment a non numerical(experience skill!") var/current = get_skill_value(skill) var/affinity = get_skill_affinity(skill) var/target_value = current + (value * affinity) @@ -95,6 +98,6 @@ out += "
| Skill | Value |
|---|---|
| [S.name] | [S.standard_render_value(skills[path])] |
| [S.name] | [S.standard_render_value(skills[path], LAZYACCESS(skill_levels, path) || 0)] |