Skip to content

Commit

Permalink
Merge branch 'main' into CT-offhand-gain-check
Browse files Browse the repository at this point in the history
  • Loading branch information
MahtraDR authored Jan 26, 2025
2 parents 77bdd98 + 56d2ddf commit 2335720
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 1 deletion.
82 changes: 81 additions & 1 deletion combat-trainer.lic
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ class SetupProcess
echo(" @ignore_weapon_mindstate: #{@ignore_weapon_mindstate}") if $debug_mode_ct
@gearsets = settings.gear_sets

@offhand_trainables = settings.combat_trainer_offhand_trainables
echo(" @offhand_trainables: #{@offhand_trainables}") if $debug_mode_ct

validate_regalia(settings)
end

Expand Down Expand Up @@ -191,7 +194,49 @@ class SetupProcess

# Exclude current skill so that a new one is selected.
new_weapon_skills = weapon_training.keys.reject { |skill| skill == game_state.weapon_skill }
new_weapon_skill = game_state.sort_by_rate_then_rank(new_weapon_skills, @priority_weapons).first

# optional & advanced feature:
# offhand_trainables is used to preference bows first, and aiming_trainables in mainhand last, to indirectly force
# aiming_trainables to be used in the offhand rather than pushing out the training for mainhand only weapons.
# It is only active when focus_threshold is active, after all the mindstates are off zero and have a drain buffer.
# There are three selection pools, one for bows, one for mainhand and one for aiming_trainables in mainhand, and skill is chosen
# preferentially in that order
# Each selection pool has a threshold that is needed to "break out" of a selection pool. e.g. when all bow weapons are > 30
# the code will move onto the mainhand selection pool.
# 30 is a magic number and there are multiple factors determining what would be an optimal value, which may not practically
# exist for the wide range of CT use cases.

if @offhand_trainables && game_state.focus_threshold_active

# define what mainhand skills look like
mainhand_skills = $melee_skills + $thrown_skills + $martial_skills - game_state.aiming_trainables

# create selection pools of bow/mainhand/offhand groupings
bow_selection_pool = new_weapon_skills.select { |skill| $aim_skills.include?(skill) && DRSkill.getxp(skill) < 30 }
mainhand_selection_pool = new_weapon_skills.select { |skill| mainhand_skills.include?(skill) && DRSkill.getxp(skill) < 30 }
offhand_selection_pool = new_weapon_skills.select { |skill| game_state.aiming_trainables.include?(skill) && DRSkill.getxp(skill) < 30 }

echo("bow_selection_pool #{bow_selection_pool}") if $debug_mode_ct
echo("mainhand_selection_pool #{mainhand_selection_pool}") if $debug_mode_ct
echo("offhand_selection_pool #{offhand_selection_pool}") if $debug_mode_ct

if bow_selection_pool.length > 0
# choose a bow from this restricted pool (i.e. preferencing bow)
new_weapon_skill = game_state.sort_by_rate_then_rank(bow_selection_pool).first
elsif mainhand_selection_pool.length > 0
# choose a mainhander from this restricted pool (once bows are done)
new_weapon_skill = game_state.sort_by_rate_then_rank(mainhand_selection_pool).first
elsif offhand_selection_pool.length > 0
# choose an offhand weapon (wielded in the main hand) from this restricted pool
new_weapon_skill = game_state.sort_by_rate_then_rank(offhand_selection_pool).first
else
# use normal selection method as a default when everything is above 30 as maintenance
new_weapon_skill = game_state.sort_by_rate_then_rank(new_weapon_skills, @priority_weapons).first
end
else
# normal selection method
new_weapon_skill = game_state.sort_by_rate_then_rank(new_weapon_skills, @priority_weapons).first
end

# Update weapon skill to train next, if a new one was chosen.
# If you're training exactly one weapon then won't change.
Expand Down Expand Up @@ -4339,6 +4384,10 @@ class GameState
@offhand_no_gain_list = Hash.new(0)
@aiming_trainables.each { |skill_name| @offhand_no_gain_list[skill_name] = 0 }
echo(" @offhand_no_gain_list: #{@offhand_no_gain_list}") if $debug_mode_ct

@focus_threshold_active = false
@focus_threshold = settings.combat_trainer_focus_threshold
echo(" @focus_threshold: #{@focus_threshold}") if $debug_mode_ct

@use_stealth_attacks = settings.use_stealth_attacks
echo(" @use_stealth_attacks: #{@use_stealth_attacks}") if $debug_mode_ct
Expand Down Expand Up @@ -4884,6 +4933,37 @@ class GameState
end
end

# focus_threshold code: if all the weapons being trained are above focus_threshold,
# @target_increment is set to 34 and @target_action_count to 1000.
# If at any time any weapon is at or below focus_threshold/2, parameters
# are restored to yaml values. The divide by 2 is hysterisis to prevent this
# code from bouncing between the two states. Focus_threshold has a min value of 10 to ensure
# a decent minimum hysterisis band.
# @focus_threshold is mapped to yaml value combat_trainer_focus_threshold
# Setting the yaml value turns this code on, it will remain dormant otherwise.
#
# The code will allow CT to focus on a single weapon once we know all weapons are draining;
# the focus means there is no weapon switching costs being incurred.

if (@focus_threshold > 10)
if !@focus_threshold_active && weapon_training.reject { |skill, _| DRSkill.getxp(skill) > @focus_threshold }.empty?
# all weapons above threshold
DRC.message("Focussing on single weapon")
@target_action_count = 1000
@target_increment = 34
@focus_threshold_active = true
return true
elsif @focus_threshold_active && weapon_training.any? { |skill, _| DRSkill.getxp(skill) < (@focus_threshold / 2) }
# any weapon below threshold/2
DRC.message("Spreading attention to all weapons")
@target_action_count = settings.combat_trainer_action_count
@target_increment = settings.combat_trainer_target_increment
@focus_threshold_active = false
return true
else
return false
end
end
@action_count >= @target_action_count || current_exp >= @target_weapon_skill
end

Expand Down
6 changes: 6 additions & 0 deletions profiles/base.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,12 @@ combat_trainer_gain_check: 0
# roughly number of consecutive offhand attack rounds that need to not gain mindstate (34/34, mob too low or constant misses) before a weapon switch is forced or blacklisted
# default is 0 (off). If activated, suggest value of 2 to start
combat_trainer_offhand_gain_check: 0
# Optional feature to preference using aiming_trainables on the offhand ONLY, to reduce competition from aiming_trainables using mainhand attacks
# It is contingent on combat_trainer_focus_threshold being active.
combat_trainer_offhand_trainables: false
# minimum mindstate threshold (for all weapons being trained) to begin focussing on single weapons to minimise weapon switching.
# default is 0 which means feature is not active. Change to 10 or higher to activate.
combat_trainer_focus_threshold: 0

dual_load: false
# use_stealth_attacks true will train stealth by hiding and attacking/backstabbing from stealth. Thieves also use backstab: below
Expand Down

0 comments on commit 2335720

Please sign in to comment.