Skip to content

Commit 3354a41

Browse files
committed
Fix a case where target lock is annoying
1 parent dc91e3d commit 3354a41

File tree

5 files changed

+33
-7
lines changed

5 files changed

+33
-7
lines changed

rsrc/dialogs/preferences.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
<led name='snail' relative='pos pos-in' anchor='slow' top='0' left='15'>Quite Slow</led>
4343
</group>
4444
<text name='targeting-head' size='large' relative='pos-in pos' anchor='spd-head' top='30' left='0' width='182' height='17'>Targeting mode:</text>
45-
<led name='target-lock' relative='pos-in pos' rel-anchor='prev' top='4' left='15'>Shift screen to show enemies in range</led>
45+
<led name='target-lock' relative='pos-in pos' rel-anchor='prev' top='4' left='15'>Shift screen to show more enemies in range</led>
4646
<text name="keyshift-head" relative='neg pos' rel-anchor='prev' top='8' left='3'>Directional keys:</text>
4747
<group name='keyshift-options'>
4848
<led name='target-adjacent' relative='pos pos-in' anchor='keyshift-head' top='0' left='15'>Select adjacent tiles</led>

src/game/boe.main.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,10 @@ std::map<std::string,std::vector<std::string>> feature_flags = {
105105
// Legacy behavior of pacifist spellcasting (used by some replays)
106106
// lets the player select combat spells and click 'Cast' which will fail.
107107
{"pacifist-spellcast-check", {"V2"}},
108-
{"target-lock", {"V1"}},
108+
// Target lock
109+
// V1: Shift screen to show the maximum number of enemies in range
110+
// V2: Like V1, but don't shift if it hides any enemies that are already visible
111+
{"target-lock", {"V1", "V2"}},
109112
// New in-game save file picker
110113
{"file-picker-dialog", {"V1"}},
111114
{"scenario-meta-format", {"V2"}},

src/game/boe.newgraph.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -1054,18 +1054,23 @@ void handle_target_mode(eGameMode target_mode, int range, eSpell spell) {
10541054
location loc = univ.current_pc().combat_pos;
10551055

10561056
std::vector<location> enemy_locs_in_range;
1057+
std::vector<location> enemy_locs_already_seen;
10571058
for(short i = 0; i < univ.town.monst.size(); i++){
10581059
auto& monst = univ.town.monst[i];
10591060
if(monst.is_alive() && party_can_see_monst(i)) {
10601061
eAttitude att = monst.attitude;
10611062
if((att == eAttitude::HOSTILE_A || att == eAttitude::HOSTILE_B)
10621063
&& dist(loc, monst.cur_loc) <= range){
1064+
// Target lock V2: Don't move the screen if it hides an enemy the player can already see
1065+
if(has_feature_flag("target-lock", "V2") && is_on_screen(monst.cur_loc))
1066+
enemy_locs_already_seen.push_back(monst.cur_loc);
1067+
10631068
enemy_locs_in_range.push_back(monst.cur_loc);
10641069
}
10651070
}
10661071
}
10671072
if(!enemy_locs_in_range.empty()){
1068-
std::vector<location> dest_candidates = points_containing_most(enemy_locs_in_range);
1073+
std::vector<location> dest_candidates = points_containing_most(enemy_locs_in_range, enemy_locs_already_seen);
10691074
center = closest_point(dest_candidates, loc);
10701075
draw_terrain();
10711076
}

src/location.cpp

+18-4
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,18 @@ location between_anchor_points(location anchor1, location anchor2, int padding){
354354
}
355355

356356
std::vector<location> points_containing_most(std::vector<location> points, int padding) {
357+
return points_containing_most(points, {}, padding);
358+
}
359+
360+
static int points_can_see(location checking_point, std::vector<location> points_of_interest, int padded_radius) {
361+
int can_see = 0;
362+
for(location p : points_of_interest){
363+
if(is_on_screen(p, checking_point, padded_radius)) ++can_see;
364+
}
365+
return can_see;
366+
}
367+
368+
std::vector<location> points_containing_most(std::vector<location> points, std::vector<location> required_points, int padding) {
357369
// Find the bounding box of the given points:
358370
int min_x = std::numeric_limits<int>::max();
359371
int min_y = min_x;
@@ -379,10 +391,12 @@ std::vector<location> points_containing_most(std::vector<location> points, int p
379391
location checking_point;
380392
for(checking_point.x = min_x; checking_point.x <= max_x; ++checking_point.x){
381393
for(checking_point.y = min_y; checking_point.y <= max_y; ++checking_point.y){
382-
int can_see = 0;
383-
for(location p : points){
384-
if(is_on_screen(p, checking_point, padded_radius)) ++can_see;
385-
}
394+
// Eliminate points that don't see every required point:
395+
int required_can_see = points_can_see(checking_point, required_points, padded_radius);
396+
if(required_can_see < required_points.size()) continue;
397+
398+
// Count how many desired points can be seen:
399+
int can_see = points_can_see(checking_point, points, padded_radius);
386400
points_seen_from.push_back(std::make_pair(checking_point, can_see));
387401
}
388402
}

src/location.hpp

+4
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,10 @@ location between_anchor_points(location anchor1, location anchor2, int padding=1
195195
// with the given amount of padding
196196
std::vector<location> points_containing_most(std::vector<location> points, int padding=1);
197197

198+
// Get all view center points which contain the greatest possible number of the given points
199+
// with the given amount of padding, as long as they still contain all of the given required points
200+
std::vector<location> points_containing_most(std::vector<location> points, std::vector<location> required_points, int padding=1);
201+
198202
// Find which of the given points is closest to the given anchor point.
199203
int closest_point_idx(std::vector<location> points, location anchor);
200204
location closest_point(std::vector<location> points, location anchor);

0 commit comments

Comments
 (0)