From 6a929e077edf40860136653f778079603b23c090 Mon Sep 17 00:00:00 2001 From: Henrique Date: Sun, 22 Dec 2024 22:26:20 -0300 Subject: [PATCH] Fix slave skills --- src/AI.pm | 9 ++++++--- src/AI/CoreLogic.pm | 5 ++++- src/AI/Slave.pm | 10 ++++++++++ src/AI/SlaveManager.pm | 1 + src/Actor/You.pm | 2 ++ src/Commands.pm | 10 ++++++---- src/Misc.pm | 24 ++++++++++++++++-------- src/Network/Receive.pm | 21 ++++++++++++++------- 8 files changed, 59 insertions(+), 23 deletions(-) diff --git a/src/AI.pm b/src/AI.pm index e344fad09f..b986d60087 100644 --- a/src/AI.pm +++ b/src/AI.pm @@ -586,9 +586,12 @@ sub ai_skillUse { delete $args{target}; } - if ($char->{skills}{$args{skillHandle}}{lv} < $args{lv}) { - debug "Attempted to use skill (".$args{skillHandle}.") level ".$args{lv}." which you do not have, adjusting to level ".$char->{skills}{$args{skillHandle}}{lv}.".\n", "ai"; - $args{lv} = $char->{skills}{$args{skillHandle}}{lv}; + my $skill = Skill->new(auto => $args{skillHandle}); + my $owner = $skill->getOwner(); + my $lvl = $owner->getSkillLevel($skill); + if ($lvl < $args{lv}) { + debug "[$owner] Attempted to use skill (".$args{skillHandle}.") level ".$args{lv}." which you do not have, adjusting to level ".$lvl.".\n", "ai"; + $args{lv} = $lvl; } AI::queue("skill_use", \%args); diff --git a/src/AI/CoreLogic.pm b/src/AI/CoreLogic.pm index 892c6e02a5..dad42ce551 100644 --- a/src/AI/CoreLogic.pm +++ b/src/AI/CoreLogic.pm @@ -750,7 +750,10 @@ sub processSkillUse { # Give an error if we don't actually possess this skill my $skill = new Skill(handle => $handle); - if ($char->{skills}{$handle}{lv} <= 0 && (!$char->{permitSkill} || $char->{permitSkill}->getHandle() ne $handle)) { + my $owner = $skill->getOwner(); + my $lvl = $owner->getSkillLevel($skill); + + if ($lvl <= 0 && (!$char->{permitSkill} || $char->{permitSkill}->getHandle() ne $handle)) { debug "Attempted to use skill (".$skill->getName().") which you do not have.\n"; } diff --git a/src/AI/Slave.pm b/src/AI/Slave.pm index a621a9cf45..56ae92e722 100644 --- a/src/AI/Slave.pm +++ b/src/AI/Slave.pm @@ -20,6 +20,16 @@ use constant MAX_DISTANCE => 17; sub checkSkillOwnership {} +sub getSkillLevel { + my ($self, $skill) = @_; + my $handle = $skill->getHandle(); + if ($self->{skills}{$handle}) { + return $self->{skills}{$handle}{lv}; + } else { + return 0; + } +} + sub action { my $slave = shift; diff --git a/src/AI/SlaveManager.pm b/src/AI/SlaveManager.pm index fa6b03f479..2c382bf19f 100644 --- a/src/AI/SlaveManager.pm +++ b/src/AI/SlaveManager.pm @@ -18,6 +18,7 @@ sub addSlave { $actor->{slave_ai_seq} = []; $actor->{slave_ai_seq_args} = []; $actor->{slave_skillsID} = []; + $actor->{skills} = {}; $actor->{slave_AI} = AI::AUTO; if ($actor->isa("Actor::Slave::Homunculus")) { diff --git a/src/Actor/You.pm b/src/Actor/You.pm index eedf44e425..970ec516d9 100644 --- a/src/Actor/You.pm +++ b/src/Actor/You.pm @@ -114,6 +114,8 @@ sub nameString { return T('You'); } +sub checkSkillOwnership { $_[1]->getOwnerType == Skill::OWNER_CHAR } + ## # int $char->getSkillLevel(Skill skill) # Ensures: result >= 0 diff --git a/src/Commands.pm b/src/Commands.pm index 77cb0d2bc2..f2eb8e6764 100644 --- a/src/Commands.pm +++ b/src/Commands.pm @@ -3100,10 +3100,12 @@ sub cmdSlave { T(" # Skill Name Lv SP\n"); foreach my $handle (@{$slave->{slave_skillsID}}) { my $skill = new Skill(handle => $handle); - my $sp = $char->{skills}{$handle}{sp} || ''; - $msg .= swrite( - "@>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<< @>> @>>>", - [$skill->getIDN(), $skill->getName(), $char->getSkillLevel($skill), $sp]); + if ($slave->checkSkillOwnership($skill)) { + my $sp = $slave->{skills}{$handle}{sp} || ''; + $msg .= swrite( + "@>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<< @>> @>>>", + [$skill->getIDN(), $skill->getName(), $slave->getSkillLevel($skill), $sp]); + } } $msg .= TF("\nSkill Points: %d\n", $slave->{points_skill}) if defined $slave->{points_skill}; $msg .= ('-'x46) . "\n"; diff --git a/src/Misc.pm b/src/Misc.pm index 959494418d..024e13ae58 100644 --- a/src/Misc.pm +++ b/src/Misc.pm @@ -4752,14 +4752,22 @@ sub checkSelfCondition { # check skill use SP if this is a 'use skill' condition if ($prefix =~ /skill|attackComboSlot/i) { my $skill = Skill->new(auto => $config{$prefix}); - return 0 unless ($char->getSkillLevel($skill) - || $config{$prefix."_equip_leftAccessory"} - || $config{$prefix."_equip_rightAccessory"} - || $config{$prefix."_equip_leftHand"} - || $config{$prefix."_equip_rightHand"} - || $config{$prefix."_equip_robe"} - ); - return 0 unless ($char->{sp} >= $skill->getSP($config{$prefix . "_lvl"} || $char->getSkillLevel($skill))); + if ($char->checkSkillOwnership ($skill)) { + return 0 unless ($char->getSkillLevel($skill) + || $config{$prefix."_equip_leftAccessory"} + || $config{$prefix."_equip_rightAccessory"} + || $config{$prefix."_equip_leftHand"} + || $config{$prefix."_equip_rightHand"} + || $config{$prefix."_equip_robe"} + ); + return 0 unless ($char->{sp} >= $skill->getSP($config{$prefix . "_lvl"} || $char->getSkillLevel($skill))); + + } elsif ($has_homunculus && $char->{homunculus}->checkSkillOwnership($skill)) { + return 0 unless ($char->{homunculus}->getSkillLevel($skill)); + + } elsif ($has_mercenary && $char->{mercenary}->checkSkillOwnership($skill)) { + return 0 unless ($char->{mercenary}->getSkillLevel($skill)); + } } if (defined $config{$prefix . "_skill"}) { diff --git a/src/Network/Receive.pm b/src/Network/Receive.pm index f75d459a9b..d208c885ee 100644 --- a/src/Network/Receive.pm +++ b/src/Network/Receive.pm @@ -9309,18 +9309,25 @@ sub skills_list { # TODO: per-actor, if needed at all # Skill::DynamicInfo::clear; my ($ownerType, $hook, $actor) = @{{ - '010F' => [Skill::OWNER_CHAR, 'packet_charSkills'], + '010F' => [Skill::OWNER_CHAR, 'packet_charSkills', $char], '0235' => [Skill::OWNER_HOMUN, 'packet_homunSkills', $char->{homunculus}], '029D' => [Skill::OWNER_MERC, 'packet_mercSkills', $char->{mercenary}], - '0B32' => [Skill::OWNER_CHAR, 'packet_charSkills'], + '0B32' => [Skill::OWNER_CHAR, 'packet_charSkills', $char], }->{$args->{switch}}}; - my $skillsIDref = $actor ? \@{$actor->{slave_skillsID}} : \@skillsID; - delete @{$char->{skills}}{@$skillsIDref}; + my $skillsIDref; + if ($ownerType == Skill::OWNER_CHAR) { + $skillsIDref = \@skillsID; + delete @{$char->{skills}}{@$skillsIDref}; + } elsif ($ownerType == Skill::OWNER_HOMUN) { + $skillsIDref = \@{$char->{homunculus}->{slave_skillsID}}; + delete @{$char->{homunculus}->{skills}}{@$skillsIDref}; + } elsif ($ownerType == Skill::OWNER_MERC) { + $skillsIDref = \@{$char->{mercenary}->{slave_skillsID}}; + delete @{$char->{mercenary}->{skills}}{@$skillsIDref}; + } @$skillsIDref = (); - # TODO: $actor can be undefined here - undef @{$actor->{slave_skillsID}}; for (my $i = 4; $i < $args->{RAW_MSG_SIZE}; $i += $skill_info->{len}) { my $skill; @{$skill}{@{$skill_info->{keys}}} = unpack($skill_info->{types}, substr($msg, $i, $skill_info->{len})); @@ -9328,7 +9335,7 @@ sub skills_list { my $handle = Skill->new(idn => $skill->{ID})->getHandle; foreach(@{$skill_info->{keys}}) { - $char->{skills}{$handle}{$_} = $skill->{$_}; + $actor->{skills}{$handle}{$_} = $skill->{$_}; } binAdd($skillsIDref, $handle) unless defined binFind($skillsIDref, $handle);