Skip to content

Commit 7f4dd29

Browse files
authored
Bundle of updates 3 (#4210)
* Added missing keys to config * bundle * Update config.txt * Update Misc.pm * pot * Update config.txt
1 parent 2bed268 commit 7f4dd29

41 files changed

Lines changed: 10408 additions & 3660 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

control/config.txt

Lines changed: 210 additions & 304 deletions
Large diffs are not rendered by default.

plugins/avoidObstacles/avoidObstacles.pl

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,17 +1193,58 @@ sub remove_prohibited_zone_from_cells {
11931193
}
11941194
}
11951195

1196+
## Purpose: Finds portal obstacle positions that are actually used by a route solution.
1197+
## Args: `($solution)`.
1198+
## Returns: A hashref keyed by `"x,y"` for portal cells present in the solution.
1199+
## Notes: This lets portal avoidance stay active for ordinary movement while
1200+
## exempting portals that are part of the planned route itself.
1201+
sub get_route_portal_positions {
1202+
my ($solution) = @_;
1203+
return {} unless $solution && @{$solution};
1204+
1205+
my %solution_cells;
1206+
foreach my $node (@{$solution}) {
1207+
next unless $node && defined $node->{x} && defined $node->{y};
1208+
$solution_cells{"$node->{x},$node->{y}"} = 1;
1209+
}
1210+
1211+
my %portal_positions;
1212+
foreach my $obstacle_id (keys %obstaclesList) {
1213+
my $obstacle = $obstaclesList{$obstacle_id};
1214+
next unless $obstacle && $obstacle->{type} && $obstacle->{type} eq 'portal';
1215+
my $pos = get_actor_position($obstacle);
1216+
next unless $pos;
1217+
next unless $solution_cells{"$pos->{x},$pos->{y}"};
1218+
$portal_positions{"$pos->{x},$pos->{y}"} = 1;
1219+
}
1220+
1221+
return \%portal_positions;
1222+
}
1223+
1224+
## Purpose: Detects whether a route destination is itself a known portal cell.
1225+
## Args: `($task)`.
1226+
## Returns: `1` when the destination matches a portal source on the current map.
1227+
## Notes: This is the safest early escape hatch for portal routes because it does
1228+
## not depend on the route solution already being built.
1229+
sub is_route_destination_portal {
1230+
my ($task) = @_;
1231+
return 0 unless $task && $field && $task->{dest} && $task->{dest}{pos};
1232+
return 1 if defined portalExists($field->baseName, $task->{dest}{pos});
1233+
return 0;
1234+
}
1235+
11961236
## Purpose: Loosens prohibited cells around a route destination when needed.
1197-
## Args: `($task, $prohibited_cells, $target_field)`.
1237+
## Args: `($task, $prohibited_cells, $target_field, $solution)`.
11981238
## Returns: The original or filtered prohibited-cell hashref.
11991239
## Notes: This exists so route tasks can still finish at destinations such as portals
12001240
## while keeping danger scoring and all other obstacle penalties intact.
12011241
sub filter_prohibited_cells_for_route_task {
1202-
my ($task, $prohibited_cells, $target_field) = @_;
1242+
my ($task, $prohibited_cells, $target_field, $solution) = @_;
12031243
return $prohibited_cells unless $task && $prohibited_cells && $target_field;
12041244
return $prohibited_cells unless $task->{dest} && $task->{dest}{pos};
12051245

12061246
my $dest = $task->{dest}{pos};
1247+
my $route_portal_positions = get_route_portal_positions($solution);
12071248
my @matching_portals = grep {
12081249
my $obstacle = $obstaclesList{$_};
12091250
my $match_dist = 7;
@@ -1239,11 +1280,33 @@ sub filter_prohibited_cells_for_route_task {
12391280
$needs_filter = 1;
12401281
}
12411282

1242-
return $prohibited_cells unless $needs_filter || ($destination_is_portal_route && @matching_portals);
1243-
1283+
my %portal_positions_to_clear = %{$route_portal_positions || {}};
12441284
foreach my $portal_id (@matching_portals) {
12451285
my $portal = $obstaclesList{$portal_id};
1246-
next unless $destination_is_portal_route;
1286+
next unless $portal && $portal->{pos_to};
1287+
my $portal_pos_key = "$portal->{pos_to}{x},$portal->{pos_to}{y}";
1288+
next unless $destination_is_portal_route || $portal_positions_to_clear{$portal_pos_key};
1289+
$portal_positions_to_clear{$portal_pos_key} = 1;
1290+
}
1291+
1292+
return $prohibited_cells unless $needs_filter || scalar keys %portal_positions_to_clear;
1293+
1294+
foreach my $portal_pos_key (keys %portal_positions_to_clear) {
1295+
my ($portal_x, $portal_y) = split /,/, $portal_pos_key, 2;
1296+
next unless defined $portal_x && defined $portal_y;
1297+
1298+
my $portal;
1299+
foreach my $obstacle_id (keys %obstaclesList) {
1300+
my $candidate = $obstaclesList{$obstacle_id};
1301+
next unless $candidate && $candidate->{type} && $candidate->{type} eq 'portal';
1302+
my $candidate_pos = get_actor_position($candidate);
1303+
next unless $candidate_pos;
1304+
next unless $candidate_pos->{x} == $portal_x && $candidate_pos->{y} == $portal_y;
1305+
$portal = $candidate;
1306+
last;
1307+
}
1308+
1309+
next unless $portal && $portal->{pos_to};
12471310
remove_prohibited_zone_from_cells(\%filtered, $target_field, $portal->{pos_to}, $portal->{prohibited_dist});
12481311
}
12491312

@@ -1269,11 +1332,16 @@ sub on_route_step {
12691332
$max_route_step = $max_index if $max_route_step > $max_index;
12701333
return if $max_route_step < 1;
12711334

1335+
my $route_portal_positions = get_route_portal_positions($args->{solution});
12721336
my $prohibited_cells = get_cached_prohibited_cells();
1273-
$prohibited_cells = filter_prohibited_cells_for_route_task($args->{task}, $prohibited_cells, $field);
1337+
$prohibited_cells = filter_prohibited_cells_for_route_task($args->{task}, $prohibited_cells, $field, $args->{solution});
12741338
my $danger_cells = get_cached_danger_cells();
12751339
my ($best_step, $best_score) = choose_best_route_step($args->{current_calc_pos}, $args->{solution}, $max_route_step, $prohibited_cells, $danger_cells);
12761340
if (!defined $best_step) {
1341+
if (scalar keys %{$route_portal_positions}) {
1342+
debug "[" . PLUGIN_NAME . "] No safe local route_step found, but the planned route uses a portal; keeping the current step selection.\n", 'route', 1;
1343+
return;
1344+
}
12771345
warning "[" . PLUGIN_NAME . "] No safe local route_step found; local client path would cross a prohibited cell. Requesting repath.\n";
12781346
$args->{task}{resetRoute} = 1;
12791347
return;
@@ -1457,6 +1525,14 @@ sub on_AI_pre_manual_drop_route_dest_near_Obstacle {
14571525
next unless $task->{isRandomWalk} || ($task->{isToLockMap} && $field->baseName eq $config{lockMap});
14581526
my $obstacle = is_there_an_obstacle_near_pos($task->{dest}{pos}, 2);
14591527
next unless $obstacle;
1528+
if ($obstacle->{type} && $obstacle->{type} eq 'portal' && is_route_destination_portal($task)) {
1529+
debug "[" . PLUGIN_NAME . "] Keeping route because destination $task->{dest}{pos}{x} $task->{dest}{pos}{y} is a known portal cell.\n", 'route', 2;
1530+
next;
1531+
}
1532+
if ($obstacle->{type} && $obstacle->{type} eq 'portal' && $obstacle->{pos_to}) {
1533+
my $route_portal_positions = get_route_portal_positions($task->{solution});
1534+
next if $route_portal_positions->{"$obstacle->{pos_to}{x},$obstacle->{pos_to}{y}"};
1535+
}
14601536
warning "[" . PLUGIN_NAME . "] Dropping current route because an obstacle appeared near its destination ($task->{dest}{pos}{x} $task->{dest}{pos}{y}) close to (" . ($obstacle->{name}) . ").\n";
14611537
AI::clear('move', 'route');
14621538
last;

plugins/checkAggressive/checkAggressive.pl

Lines changed: 112 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -55,29 +55,125 @@ package checkAggressive;
5555
PLUGIN_NAME => 'checkAggressive',
5656
};
5757

58-
my %ai_constant = (
59-
'01' => 0x81, '02' => 0x83, '03' => 0x1089, '04' => 0x3885,
60-
'05' => 0x2085, '06' => 0, '07' => 0x108B, '08' => 0x7085,
61-
'09' => 0x3095, '10' => 0x84, '11' => 0x84, '12' => 0x2085,
62-
'13' => 0x308D, '17' => 0x91, '19' => 0x3095, '20' => 0x3295,
63-
'21' => 0x3695, '24' => 0xA1, '25' => 0x1, '26' => 0xB695,
64-
'27' => 0x8084, 'ABR_PASSIVE' => 0x21, 'ABR_OFFENSIVE' => 0xA5
65-
);
66-
6758
sub Unload {
6859
Plugins::delHooks($hooks);
6960
message "[".PLUGIN_NAME."] Plugin unloading or reloading.\n", 'success';
7061
}
7162

72-
sub is_monster_ai_aggressive {
73-
my ($ai_str) = @_;
74-
$ai_str = uc($ai_str);
63+
sub is_monster_engaged_with_us {
64+
my ($monster) = @_;
7565

76-
my $mode_value = exists $ai_constant{$ai_str}
77-
? $ai_constant{$ai_str}
78-
: $ai_constant{'06'};
66+
return ($monster->{sentAttack} || $monster->{engaged}) ? 1 : 0;
67+
}
7968

80-
return ($mode_value & 0x4) ? 1 : 0;
69+
sub is_looking_at_actor {
70+
my ($monster, $actor) = @_;
71+
72+
return unless ($monster && $actor);
73+
return unless defined $monster->{look}{body};
74+
75+
my $monster_pos = calcPosFromPathfinding($field, $monster);
76+
my $actor_pos = calcPosFromPathfinding($field, $actor);
77+
return unless ($monster_pos && $actor_pos);
78+
79+
return 1 if ($monster_pos->{x} == $actor_pos->{x} && $monster_pos->{y} == $actor_pos->{y});
80+
81+
my %vec;
82+
getVector(\%vec, $actor_pos, $monster_pos);
83+
my $degree = vectorToDegree(\%vec);
84+
return unless defined $degree;
85+
86+
my $target_body = int(sprintf("%.0f", (360 - $degree) / 45)) % 8;
87+
return $monster->{look}{body} == $target_body ? 1 : 0;
88+
}
89+
90+
sub get_attackable_actors {
91+
my @actors;
92+
93+
push @actors, @{ $playersList ? $playersList->getItems : [] };
94+
push @actors, @{ $slavesList ? $slavesList->getItems : [] };
95+
push @actors, @{ $elementalsList ? $elementalsList->getItems : [] };
96+
97+
return @actors;
98+
}
99+
100+
sub get_line_points_between {
101+
my ($from_pos, $to_pos) = @_;
102+
return [] unless ($from_pos && $to_pos);
103+
104+
my ($x1, $y1) = ($from_pos->{x}, $from_pos->{y});
105+
my ($x2, $y2) = ($to_pos->{x}, $to_pos->{y});
106+
107+
my @points;
108+
my $dx = abs($x2 - $x1);
109+
my $dy = abs($y2 - $y1);
110+
my $sx = $x1 < $x2 ? 1 : -1;
111+
my $sy = $y1 < $y2 ? 1 : -1;
112+
my $err = $dx - $dy;
113+
114+
while (!($x1 == $x2 && $y1 == $y2)) {
115+
my $e2 = 2 * $err;
116+
if ($e2 > -$dy) {
117+
$err -= $dy;
118+
$x1 += $sx;
119+
}
120+
if ($e2 < $dx) {
121+
$err += $dx;
122+
$y1 += $sy;
123+
}
124+
125+
last if ($x1 == $x2 && $y1 == $y2);
126+
push @points, {x => $x1, y => $y1};
127+
}
128+
129+
return \@points;
130+
}
131+
132+
sub has_attackable_actor_between {
133+
my ($actor, $monster) = @_;
134+
return unless ($actor && $monster);
135+
136+
my $actor_pos = calcPosFromPathfinding($field, $actor);
137+
my $monster_pos = calcPosFromPathfinding($field, $monster);
138+
return unless ($actor_pos && $monster_pos);
139+
140+
my $line_points = get_line_points_between($actor_pos, $monster_pos);
141+
return 0 unless (@{$line_points});
142+
143+
my %line_lookup = map { $_->{x} . ',' . $_->{y} => 1 } @{$line_points};
144+
145+
foreach my $other_actor (get_attackable_actors()) {
146+
next unless $other_actor;
147+
next if ($actor->{ID} && $other_actor->{ID} && $actor->{ID} eq $other_actor->{ID});
148+
next if $other_actor->{dead};
149+
150+
my $other_pos = calcPosFromPathfinding($field, $other_actor);
151+
next unless $other_pos;
152+
153+
return 1 if $line_lookup{$other_pos->{x} . ',' . $other_pos->{y}};
154+
}
155+
156+
return 0;
157+
}
158+
159+
sub is_aggressive_towards_actor {
160+
my ($monster, $actor, $is_clean) = @_;
161+
return unless ($monster && $actor);
162+
163+
return 1 if is_monster_engaged_with_us($monster);
164+
165+
return unless $is_clean;
166+
return unless exists $monstersTable{$monster->{nameID}};
167+
return unless $monstersTable{$monster->{nameID}}{isAIMode_Aggressive};
168+
169+
my $monster_pos = calcPosFromPathfinding($field, $monster);
170+
my $actor_pos = calcPosFromPathfinding($field, $actor);
171+
return unless ($monster_pos && $actor_pos);
172+
return unless (blockDistance($actor_pos, $monster_pos) < 10);
173+
return unless (Misc::objectIsMovingTowards($monster, $actor) || is_looking_at_actor($monster, $actor));
174+
return if has_attackable_actor_between($actor, $monster);
175+
176+
return 1;
81177
}
82178

83179
sub is_monster_engaged_with_us {

plugins/checkLooter/checkLooter.pl

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,6 @@ package checkLooter;
5050
['check_attackLooter', \&oncheck_attackLooter, undef],
5151
);
5252

53-
my %ai_constant = (
54-
'01' => 0x81, '02' => 0x83, '03' => 0x1089, '04' => 0x3885,
55-
'05' => 0x2085, '06' => 0, '07' => 0x108B, '08' => 0x7085,
56-
'09' => 0x3095, '10' => 0x84, '11' => 0x84, '12' => 0x2085,
57-
'13' => 0x308D, '17' => 0x91, '19' => 0x3095, '20' => 0x3295,
58-
'21' => 0x3695, '24' => 0xA1, '25' => 0x1, '26' => 0xB695,
59-
'27' => 0x8084, 'ABR_PASSIVE' => 0x21, 'ABR_OFFENSIVE' => 0xA5
60-
);
61-
6253
=pod
6354
/// Monster mode definitions to clear up code reading. [Skotlex]
6455
enum e_mode {
@@ -108,8 +99,7 @@ sub oncheck_attackLooter {
10899
}
109100

110101
my $mob = $monstersTable{$args->{monster}->{nameID}};
111-
my $ai = $mob->{Ai};
112-
my $is_looter = is_monster_ai_looter($ai);
102+
my $is_looter = $mob->{isAIMode_Looter} ? 1 : 0;
113103
if (!$is_looter) {
114104
debug "[checkLooter] [False] $args->{monster} ($args->{monster}->{nameID}) is not a Looter\n", 'checkLooter';
115105
$args->{return} = 1;
@@ -118,15 +108,4 @@ sub oncheck_attackLooter {
118108
}
119109
}
120110

121-
sub is_monster_ai_looter {
122-
my ($ai_str) = @_;
123-
$ai_str = uc($ai_str);
124-
125-
my $mode_value = exists $ai_constant{$ai_str}
126-
? $ai_constant{$ai_str}
127-
: $ai_constant{'06'};
128-
129-
return ($mode_value & 0x2) ? 1 : 0;
130-
}
131-
132111
1;

0 commit comments

Comments
 (0)