About ready.

This commit is contained in:
Ghommie
2020-05-05 20:58:44 +02:00
parent 791b05871f
commit 001109cfcd
13 changed files with 111 additions and 86 deletions
+9
View File
@@ -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.
+3
View File
@@ -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
+21 -19
View File
@@ -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.
+29 -21
View File
@@ -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, "<span class='warning'>You're too exhausted.</span>") // 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("<span class='danger'>[user] has hit [src] with [I]!</span>", 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)
+17 -17
View File
@@ -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, "<span class='warning'>I feel like I've become worse at [name]!</span>")
/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")
+11 -8
View File
@@ -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 += "<table style=\"width:100%\"><tr><th><b>Skill</b><th><b>Value</b></tr>"
for(var/path in skills)
var/datum/skill/S = GLOB.skill_datums[path]
out += "<tr><td><font color='[S.name_color]'>[S.name]</font></td><td>[S.standard_render_value(skills[path])]</td></tr>"
out += "<tr><td><font color='[S.name_color]'>[S.name]</font></td><td>[S.standard_render_value(skills[path], LAZYACCESS(skill_levels, path) || 0)]</td></tr>"
out += "</table>"
return out.Join("")
+7 -3
View File
@@ -140,10 +140,12 @@
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)
LAZYSET(current_users, user, TRUE)
to_chat(user, "<span class='notice'>You begin cutting [holder]'s [color] wire...</span>")
if(!do_after(user, 1.5 SECONDS * level_diff, target = holder) || !interactable(user))
LAZYREMOVE(current_users, user)
return FALSE
user.mind?.skill_holder.auto_gain_experience(/datum/skill/level/job/wiring, DEF_SKILL_GAIN*level_diff)
LAZYREMOVE(current_users, user)
to_chat(user, "<span class='notice'>You cut [holder]'s [color] wire.</span>")
cut(get_wire(color))
return TRUE
@@ -167,10 +169,12 @@
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)
LAZYSET(current_users, user, TRUE)
to_chat(user, "<span class='notice'>You begin pulsing [holder]'s [color] wire...</span>")
if(!do_after(user, 1.5 SECONDS * level_diff, target = holder) || !interactable(user))
LAZYREMOVE(current_users, user)
return FALSE
user.mind?.skill_holder.auto_gain_experience(/datum/skill/level/job/wiring, DEF_SKILL_GAIN*level_diff)
LAZYREMOVE(current_users, user)
to_chat(user, "<span class='notice'>You pulse [holder]'s [color] wire.</span>")
pulse(get_wire(color), user)
return TRUE
@@ -286,7 +290,7 @@
if("cut")
I = L.is_holding_tool_quality(TOOL_WIRECUTTER)
if(I || IsAdminGhost(usr))
if(cut_color(target_wire) && I && holder)
if(cut_color(target_wire, L) && I && holder)
I.play_tool_sound(holder, 20)
. = TRUE
else
+8 -10
View File
@@ -133,8 +133,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
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/list/used_skills //list of skills exercised when using this item. An associated bitfield indicates how the skill is exercised.
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.
@@ -801,8 +800,8 @@ 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)
if(user.mind && used_skills)
LIST_SKILL_MODIFIER(used_skills, user.mind.skill_holder, delay, skill_difficulty, SKILL_USE_TOOL, NONE)
// 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)
@@ -828,12 +827,11 @@ 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))
if(user.mind && used_skills && skill_gain_mult)
for(var/skill in used_skills)
if(!(used_skills[skill] & SKILL_TRAINING_TOOL))
continue
user.mind.skill_holder.auto_gain_experience(skill, skill_gain*skill_gain_mult, GET_STANDARD_LVL(max_level))
return TRUE
+1 -1
View File
@@ -325,7 +325,7 @@
else
target.LAssailant = WEAKREF(user)
cooldown_check = world.time + cooldown
user.adjustStaminaLossBuffered(getweight())//CIT CHANGE - makes swinging batons cost stamina
user.adjustStaminaLossBuffered(getweight(user, STAM_COST_BATON_MOB_MULT))
else
var/wait_desc = get_wait_description()
if(wait_desc)
+1 -1
View File
@@ -163,7 +163,7 @@
if(status)
if(baton_stun(M, user, disarming))
user.do_attack_animation(M)
user.adjustStaminaLossBuffered(getweight()) //CIT CHANGE - makes stunbatonning others cost stamina
user.adjustStaminaLossBuffered(getweight(user, STAM_COST_BATON_MOB_MULT))
else if(user.a_intent != INTENT_HARM) //they'll try to bash in the last proc.
M.visible_message("<span class='warning'>[user] has prodded [M] with [src]. Luckily it was off.</span>", \
"<span class='warning'>[user] has prodded you with [src]. Luckily it was off</span>")
+2 -3
View File
@@ -241,11 +241,13 @@
playsound(user, activation_sound, transform_volume, 1)
w_class = WEIGHT_CLASS_BULKY
AddElement(/datum/element/sword_point)
total_mass = total_mass_on
else
to_chat(user, "<span class='notice'>[deactivation_message]</span>")
playsound(user, deactivation_sound, transform_volume, 1)
w_class = WEIGHT_CLASS_SMALL
RemoveElement(/datum/element/sword_point)
total_mass = initial(total_mass)
update_icon()
add_fingerprint(user)
@@ -287,9 +289,6 @@
else
return ..()
/obj/item/toy/sword/getweight()
return (active ? total_mass_on : total_mass) || w_class *1.25
/obj/item/toy/sword/cx
name = "\improper DX Non-Euplastic LightSword"
desc = "A deluxe toy replica of an energy sword. Realistic visuals and sounds! Ages 8 and up."
+1 -1
View File
@@ -199,7 +199,7 @@
to_chat(src, "<span class='notice'>You set [I] down gently on the ground.</span>")
return
adjustStaminaLossBuffered(I.getweight()*2)//CIT CHANGE - throwing items shall be more tiring than swinging em. Doubly so.
adjustStaminaLossBuffered(I.getweight(src, STAM_COST_THROW_MULT, SKILL_THROW_STAM_COST))
if(thrown_thing)
visible_message("<span class='danger'>[src] has thrown [thrown_thing].</span>")
+1 -2
View File
@@ -495,8 +495,7 @@ 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
used_skills = list(/datum/skill/level/job/wiring = SKILL_USE_TOOL|SKILL_TRAINING_TOOL)
/obj/item/stack/cable_coil/cyborg
is_cyborg = 1