Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions control/config.txt
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ sitAuto_over_50 0
sitAuto_idle 1
sitAuto_look
sitAuto_look_from_wall
sitAuto_look_delay
sitTensionRelax 0

statsAddAuto 0
Expand Down
38 changes: 19 additions & 19 deletions src/AI.pm
Original file line number Diff line number Diff line change
Expand Up @@ -758,27 +758,27 @@ sub sit {
require Task::SitStand;
my $task = new Task::SitStand(actor => $char, mode => 'sit', wait => $timeout{ai_sit_wait}{timeout});
AI::queue("sitting", $task);
if (defined $config{sitAuto_look} && !$config{sitAuto_look_from_wall}) {
Misc::look($config{sitAuto_look});
} elsif (defined $config{sitAuto_look} && $config{sitAuto_look_from_wall}) {
my $sitAutoLook = $config{sitAuto_look};
my $wallRange = $config{sitAuto_look_from_wall};
for (my $i=1;$i<=$wallRange;$i++) {
if ((!$field->isWalkable($char->{pos}{x},$char->{pos}{y}+$wallRange) && $sitAutoLook == 0)
|| (!$field->isWalkable($char->{pos}{x}-$wallRange,$char->{pos}{y}+$wallRange) && $sitAutoLook == 1)
|| (!$field->isWalkable($char->{pos}{x}-$wallRange,$char->{pos}{y}) && $sitAutoLook == 2)
|| (!$field->isWalkable($char->{pos}{x}-$wallRange,$char->{pos}{y}-$wallRange) && $sitAutoLook == 3)
) {
$sitAutoLook += 4;
} elsif ((!$field->isWalkable($char->{pos}{x},$char->{pos}{y}-$wallRange) && $sitAutoLook == 4)
|| (!$field->isWalkable($char->{pos}{x}+$wallRange,$char->{pos}{y}-$wallRange) && $sitAutoLook == 5)
|| (!$field->isWalkable($char->{pos}{x}+$wallRange,$char->{pos}{y}) && $sitAutoLook == 6)
|| (!$field->isWalkable($char->{pos}{x}+$wallRange,$char->{pos}{y}+$wallRange) && $sitAutoLook == 7)
) {
$sitAutoLook -= 4;
my $lookDelay = $config{sitAuto_look_delay};
$lookDelay = 0 if (!defined $lookDelay || $lookDelay < 0);
delete $ai_v{sitAuto_pendingLook};
if (defined $config{sitAuto_look}) {
my $defaultLook = $config{sitAuto_look};
my $lookPlan = { body => $defaultLook, delay => $lookDelay };

if ($config{sitAuto_look_from_wall}) {
my $closestWalls = Misc::getClosestWalls($char->{pos}, $config{sitAuto_look_from_wall});
if (@{$closestWalls}) {
my $referenceWall = $closestWalls->[int(rand(@{$closestWalls}))];
my $oppositeDirectionPos = {
x => (2 * $char->{pos}{x}) - $referenceWall->{x},
y => (2 * $char->{pos}{y}) - $referenceWall->{y},
};
my ($bodyDirection, $headDirection) = Misc::getNaturalLookDirections($char->{pos}, $oppositeDirectionPos, $defaultLook);
$lookPlan = { body => $bodyDirection, head => $headDirection, delay => $lookDelay };
}
}
Misc::look($sitAutoLook);

$ai_v{sitAuto_pendingLook} = $lookPlan;
}
}

Expand Down
5 changes: 5 additions & 0 deletions src/AI/CoreLogic.pm
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,11 @@ sub processClientSuspend {
}

sub processLook {
if ($ai_v{sitAuto_scheduledLook} && time >= $ai_v{sitAuto_scheduledLook}{due}) {
my $scheduledLook = delete $ai_v{sitAuto_scheduledLook};
Misc::look($scheduledLook->{body}, $scheduledLook->{head});
}

if (AI::action eq "look" && timeOut($timeout{'ai_look'})) {
$timeout{'ai_look'}{'time'} = time;
$messageSender->sendLook(AI::args->{'look_body'}, AI::args->{'look_head'});
Expand Down
63 changes: 60 additions & 3 deletions src/Misc.pm
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ our @EXPORT = (
look
lookAtPosition
lookAtPositionNaturally
getNaturalLookDirections
getClosestWalls
manualMove
meetingPosition
objectAdded
Expand Down Expand Up @@ -2488,14 +2490,14 @@ sub lookAtPosition {
}

##
# lookAtPositionNaturally(from_pos, to_pos, [current_body])
# getNaturalLookDirections(from_pos, to_pos, [current_body])
# from_pos: source position hashref (character)
# to_pos: target position hashref
# current_body: optional current body direction, defaults to $char->{look}{body}
#
# Calculates and executes look change using partial-turn strategy.
# Calculates look change using partial-turn strategy.
# Returns: (body, head) where body is 0-7 and head is 0-2.
sub lookAtPositionNaturally {
sub getNaturalLookDirections {
my ($from_pos, $to_pos, $current_body) = @_;
return unless ($from_pos && $to_pos);

Expand All @@ -2520,10 +2522,65 @@ sub lookAtPositionNaturally {
}
}

return ($body, $head);
}

##
# lookAtPositionNaturally(from_pos, to_pos, [current_body])
# from_pos: source position hashref (character)
# to_pos: target position hashref
# current_body: optional current body direction, defaults to $char->{look}{body}
#
# Calculates and executes look change using partial-turn strategy.
# Returns: (body, head) where body is 0-7 and head is 0-2.
sub lookAtPositionNaturally {
my ($from_pos, $to_pos, $current_body) = @_;
my ($body, $head) = getNaturalLookDirections($from_pos, $to_pos, $current_body);
return unless defined $body;

look($body, $head) if ($body != $char->{look}{body} || $head != $char->{look}{head});
return ($body, $head);
}

##
# getClosestWalls(from_pos, wall_range, [field_obj])
# from_pos: source position hashref
# wall_range: search range around from_pos
# field_obj: optional field object, defaults to current global field
#
# Returns: arrayref with all nearest non-walkable cells found in range.
sub getClosestWalls {
my ($from_pos, $wall_range, $field_obj) = @_;
return [] unless ($from_pos && defined $wall_range && $wall_range > 0);

$field_obj ||= $field;
return [] unless $field_obj;

my $closest_distance;
my @closest_walls;
for (my $dx = -$wall_range; $dx <= $wall_range; $dx++) {
for (my $dy = -$wall_range; $dy <= $wall_range; $dy++) {
next if $dx == 0 && $dy == 0;

my $candidate = {
x => $from_pos->{x} + $dx,
y => $from_pos->{y} + $dy,
};
next if $field_obj->isWalkable($candidate->{x}, $candidate->{y});

my $distance = distance($candidate, $from_pos);
if (!defined $closest_distance || $distance < $closest_distance) {
$closest_distance = $distance;
@closest_walls = ($candidate);
} elsif ($distance == $closest_distance) {
push @closest_walls, $candidate;
}
}
}

return \@closest_walls;
}

##
# manualMove(dx, dy)
#
Expand Down
16 changes: 16 additions & 0 deletions src/Network/Receive.pm
Original file line number Diff line number Diff line change
Expand Up @@ -2604,6 +2604,22 @@ sub actor_action {
if ($args->{sourceID} eq $accountID) {
message T("You are sitting.\n") if (!$char->{sitting});
$char->{sitting} = 1;
if ($ai_v{sitAuto_pendingLook}) {
my $pendingLook = delete $ai_v{sitAuto_pendingLook};
delete $ai_v{sitAuto_scheduledLook};
my $delay = ($pendingLook->{delay} && $pendingLook->{delay} > 0) ? $pendingLook->{delay} : 0;
if ($delay > 0) {
$ai_v{sitAuto_scheduledLook} = {
due => time + $delay,
body => $pendingLook->{body},
head => $pendingLook->{head},
};
} elsif (defined $pendingLook->{head}) {
Misc::look($pendingLook->{body}, $pendingLook->{head});
} elsif (defined $pendingLook->{body}) {
Misc::look($pendingLook->{body});
}
}
AI::queue("sitAuto") unless (AI::inQueue("sitAuto")) || $ai_v{sitAuto_forcedBySitCommand};
} else {
message TF("%s is sitting.\n", getActorName($args->{sourceID})), 'parseMsg_statuslook', 2;
Expand Down
Loading