[EN]
Sorry, I realized that OpenKore already has a function that attaches to implement, but the condition in the most "add skills" is still nescessária.
Redid this part (commands.pm):
Code: Select all
sub cmdSkills {
my (undef, $args) = @_;
my ($arg1) = $args =~ /^(\w+)/;
my ($arg2) = $args =~ /^\w+ (\d+)/;
if ($arg1 eq "") {
my $msg = T("----------Skill List-----------\n" .
" # Skill Name Lv SP\n");
for my $handle (@skillsID) {
my $skill = new Skill(handle => $handle);
my $sp = $char->{skills}{$handle}{sp} || '';
$msg .= swrite(
"@>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @>> @>>>",
[$skill->getIDN(), $skill->getName(), $char->getSkillLevel($skill), $sp]);
}
$msg .= TF("\nSkill Points: %d\n", $char->{points_skill});
$msg .= "-------------------------------\n";
message($msg, "list");
} elsif ($arg1 eq "add" && $arg2 =~ /\d+/) {
if (!$net || $net->getState() != Network::IN_GAME) {
error TF("You must be logged in the game to use this command (%s)\n", 'skills add');
return;
}
my $skill = new Skill(idn => $arg2);
if (!$skill->getIDN() || !$char->{skills}{$skill->getHandle()}) {
error TF("Error in function 'skills add' (Add Skill Point)\n" .
"Skill %s does not exist.\n", $arg2);
} elsif ($char->{points_skill} < 1) {
error TF("Error in function 'skills add' (Add Skill Point)\n" .
"Not enough skill points to increase %s\n", $skill->getName());
} elsif ($char->{skills}{$skill->getHandle()}{up} == 0) {
error TF("Error in function 'skills add' (Add Skill Point)\n" .
"Skill %s reached its maximum level or prerequisite not reached\n", $skill->getName());
} else {
$messageSender->sendAddSkillPoint($skill->getIDN());
}
} elsif ($arg1 eq "desc" && $arg2 =~ /\d+/) {
my $skill = new Skill(idn => $arg2);
if (!$skill->getIDN()) {
error TF("Error in function 'skills desc' (Skill Description)\n" .
"Skill %s does not exist.\n", $arg2);
} else {
my $description = $skillsDesc_lut{$skill->getHandle()} || T("Error: No description available.\n");
message TF("===============Skill Description===============\n" .
"Skill: %s\n\n", $skill->getName()), "info";
message $description, "info";
message "==============================================\n", "info";
}
} else {
error T("Syntax Error in function 'skills' (Skills Functions)\n" .
"Usage: skills [<add | desc>] [<skill #>]\n");
}
}
Desculpa, percebi que o OpenKore já tem a função que prendia implementar, mas a condição a mais no "skills add" ainda é nescessária.
Refiz essa parte (commands.pm):
Code: Select all
sub cmdSkills {
my (undef, $args) = @_;
my ($arg1) = $args =~ /^(\w+)/;
my ($arg2) = $args =~ /^\w+ (\d+)/;
if ($arg1 eq "") {
my $msg = T("----------Skill List-----------\n" .
" # Skill Name Lv SP\n");
for my $handle (@skillsID) {
my $skill = new Skill(handle => $handle);
my $sp = $char->{skills}{$handle}{sp} || '';
$msg .= swrite(
"@>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @>> @>>>",
[$skill->getIDN(), $skill->getName(), $char->getSkillLevel($skill), $sp]);
}
$msg .= TF("\nSkill Points: %d\n", $char->{points_skill});
$msg .= "-------------------------------\n";
message($msg, "list");
} elsif ($arg1 eq "add" && $arg2 =~ /\d+/) {
if (!$net || $net->getState() != Network::IN_GAME) {
error TF("You must be logged in the game to use this command (%s)\n", 'skills add');
return;
}
my $skill = new Skill(idn => $arg2);
if (!$skill->getIDN() || !$char->{skills}{$skill->getHandle()}) {
error TF("Error in function 'skills add' (Add Skill Point)\n" .
"Skill %s does not exist.\n", $arg2);
} elsif ($char->{points_skill} < 1) {
error TF("Error in function 'skills add' (Add Skill Point)\n" .
"Not enough skill points to increase %s\n", $skill->getName());
} elsif ($char->{skills}{$skill->getHandle()}{up} == 0) {
error TF("Error in function 'skills add' (Add Skill Point)\n" .
"Skill %s reached its maximum level or prerequisite not reached\n", $skill->getName());
} else {
$messageSender->sendAddSkillPoint($skill->getIDN());
}
} elsif ($arg1 eq "desc" && $arg2 =~ /\d+/) {
my $skill = new Skill(idn => $arg2);
if (!$skill->getIDN()) {
error TF("Error in function 'skills desc' (Skill Description)\n" .
"Skill %s does not exist.\n", $arg2);
} else {
my $description = $skillsDesc_lut{$skill->getHandle()} || T("Error: No description available.\n");
message TF("===============Skill Description===============\n" .
"Skill: %s\n\n", $skill->getName()), "info";
message $description, "info";
message "==============================================\n", "info";
}
} else {
error T("Syntax Error in function 'skills' (Skills Functions)\n" .
"Usage: skills [<add | desc>] [<skill #>]\n");
}
}
[EN]
Missing the possibility to know if a skill reached or no your max level, I decided search in Skill.pm and I didn't found a function for that. Searching better, I realize that the ServerType0.pm do this (sub skills_list), but don't send all the information to skill.pm on Skill::DynamicInfo.
And I did.
Leveraging, and include a further condition anti-bug in add skills so as not to try to increase a skill level already achieved peak level.
Download files:
http://www.mediafire.com/?rdlr312ka09fsad
http://www.mediafire.com/?aejpce7camc7vw9
http://www.mediafire.com/?b35xgpk95mvceuv
Data that changed:
ServerType0.pm
Code: Select all
sub skills_list {
my ($self, $args) = @_;
return unless changeToInGameState;
my ($msg, $newmsg);
$msg = $args->{RAW_MSG};
$self->decrypt(\$newmsg, substr $msg, 4);
$msg = substr ($msg, 0, 4) . $newmsg;
# TODO: per-actor, if needed at all
# Skill::DynamicInfo::clear;
my ($ownerType, $hook, $actor) = @{{
'010F' => [Skill::OWNER_CHAR, 'packet_charSkills'],
'0235' => [Skill::OWNER_HOMUN, 'packet_homunSkills', $char->{homunculus}],
'029D' => [Skill::OWNER_MERC, 'packet_mercSkills', $char->{mercenary}],
}->{$args->{switch}}};
my $skillsIDref = $actor ? \@{$actor->{slave_skillsID}} : \@skillsID;
delete @{$char->{skills}}{@$skillsIDref};
@$skillsIDref = ();
# TODO: $actor can be undefined here
undef @{$actor->{slave_skillsID}};
for (my $i = 4; $i < $args->{RAW_MSG_SIZE}; $i += 37) {
my ($ID, $targetType, $lv, $sp, $range, $handle, $up) = unpack 'v1 V1 v3 Z24 C1', substr $msg, $i, 37;
$handle ||= Skill->new(idn => $ID)->getHandle;
@{$char->{skills}{$handle}}{qw(ID targetType lv sp range up)} = ($ID, $targetType, $lv, $sp, $range, $up);
# $char->{skills}{$handle}{lv} = $lv unless $char->{skills}{$handle}{lv};
binAdd($skillsIDref, $handle) unless defined binFind($skillsIDref, $handle);
Skill::DynamicInfo::add($ID, $handle, $lv, $sp, $range, $targetType, $ownerType, $up);
Plugins::callHook($hook, {
ID => $ID,
handle => $handle,
level => $lv,
upgradable => $up,
});
}
}
Code: Select all
##
# int $Skill->getUpgradable()
#
# [EN]
# Returns 0 if the maximum level of skill has been achieved.
# Returns 1 if the maximum level of skill has NOT been reached.
# Returns 2 on error.
# [PT-BR]
# Retorna 0 caso o nível máximo da habilidade tenha sido alcançado.
# Retorna 1 caso o nível máximo da habilidade NÃO tenha sido alcançado.
# Retorna 2 em caso de erro.
sub getUpgradable {
my ($self) = @_;
my $entry = $Skill::DynamicInfo::skills{$self->{idn}};
if ($entry) {
return $entry->{upgradable};
} else {
return 2; # sqrt(2)
}
}
Code: Select all
package Skill::DynamicInfo;
# The skills information as sent by the RO server. This variable maps a skill IDN
# to another hash, with the following members:
# - handle - Handle name.
# - level - Character's current maximum skill level.
# - sp - The SP usage for the current maximum level.
# - range - Skill range.
# - targetType - The skill's target type.
# - upgradable - 0 = maximum level of skill has been achieved. 1 = maximum level of skill has NOT been reached. 2 = error.
our %skills;
# Maps handle names to skill IDNs.
our %handles;
sub add {
my ($idn, $handle, $level, $sp, $range, $targetType, $ownerType, $upgradable) = @_;
$skills{$idn} = {
handle => $handle,
level => $level,
sp => $sp,
range => $range,
targetType => $targetType,
ownerType => $ownerType,
upgradable => $upgradable
};
$handles{$handle} = $idn;
}
Code: Select all
sub cmdSkills {
my (undef, $args) = @_;
my ($arg1) = $args =~ /^(\w+)/;
my ($arg2) = $args =~ /^\w+ (\d+)/;
if ($arg1 eq "") {
my $msg = T("----------Skill List-----------\n" .
" # Skill Name Lv SP\n");
for my $handle (@skillsID) {
my $skill = new Skill(handle => $handle);
my $sp = $char->{skills}{$handle}{sp} || '';
$msg .= swrite(
"@>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @>> @>>>",
[$skill->getIDN(), $skill->getName(), $char->getSkillLevel($skill), $sp]);
}
$msg .= TF("\nSkill Points: %d\n", $char->{points_skill});
$msg .= "-------------------------------\n";
message($msg, "list");
} elsif ($arg1 eq "add" && $arg2 =~ /\d+/) {
if (!$net || $net->getState() != Network::IN_GAME) {
error TF("You must be logged in the game to use this command (%s)\n", 'skills add');
return;
}
my $skill = new Skill(idn => $arg2);
if (!$skill->getIDN() || !$char->{skills}{$skill->getHandle()}) {
error TF("Error in function 'skills add' (Add Skill Point)\n" .
"Skill %s does not exist.\n", $arg2);
} elsif ($char->{points_skill} < 1) {
error TF("Error in function 'skills add' (Add Skill Point)\n" .
"Not enough skill points to increase %s\n", $skill->getName());
} elsif ($skill->getUpgradable($skill->getIDN()) == 0) {
error TF("Error in function 'skills add' (Add Skill Point)\n" .
"Skill %s reached its maximum level \n", $skill->getName());
} else {
$messageSender->sendAddSkillPoint($skill->getIDN());
}
} elsif ($arg1 eq "desc" && $arg2 =~ /\d+/) {
my $skill = new Skill(idn => $arg2);
if (!$skill->getIDN()) {
error TF("Error in function 'skills desc' (Skill Description)\n" .
"Skill %s does not exist.\n", $arg2);
} else {
my $description = $skillsDesc_lut{$skill->getHandle()} || T("Error: No description available.\n");
message TF("===============Skill Description===============\n" .
"Skill: %s\n\n", $skill->getName()), "info";
message $description, "info";
message "==============================================\n", "info";
}
} else {
error T("Syntax Error in function 'skills' (Skills Functions)\n" .
"Usage: skills [<add | desc>] [<skill #>]\n");
}
}
If possible, also like to assess whether I did everything right, because I never did something so deep in OpenKore.
If had this function in OpenKore, I apologize because I did not find.
[PT-BR]
Enquanto programava um plugin, senti falta na possibilidade de saber se a habilidade alcançou ou não o seu nível máximo.
Então resolvi pesquisar no Skill.pm e não encontrei uma função para isso.
Fui mais a fundo e percebi que o ServerType0.pm fazia isso (sub skills_list), mas não transferia os dados para o skill.pm, no Skill::DynamicInfo
E foi o que fiz.
Aproveitando, e incluir mais uma condição anti-bug no comando skills add, para não tentar aumentar um nível de habilidade com nível máximo já alcançado.
Download dos arquivos:
http://www.mediafire.com/?rdlr312ka09fsad
http://www.mediafire.com/?aejpce7camc7vw9
http://www.mediafire.com/?b35xgpk95mvceuv
Dados que alterei:
ServerType0.pm
Code: Select all
sub skills_list {
my ($self, $args) = @_;
return unless changeToInGameState;
my ($msg, $newmsg);
$msg = $args->{RAW_MSG};
$self->decrypt(\$newmsg, substr $msg, 4);
$msg = substr ($msg, 0, 4) . $newmsg;
# TODO: per-actor, if needed at all
# Skill::DynamicInfo::clear;
my ($ownerType, $hook, $actor) = @{{
'010F' => [Skill::OWNER_CHAR, 'packet_charSkills'],
'0235' => [Skill::OWNER_HOMUN, 'packet_homunSkills', $char->{homunculus}],
'029D' => [Skill::OWNER_MERC, 'packet_mercSkills', $char->{mercenary}],
}->{$args->{switch}}};
my $skillsIDref = $actor ? \@{$actor->{slave_skillsID}} : \@skillsID;
delete @{$char->{skills}}{@$skillsIDref};
@$skillsIDref = ();
# TODO: $actor can be undefined here
undef @{$actor->{slave_skillsID}};
for (my $i = 4; $i < $args->{RAW_MSG_SIZE}; $i += 37) {
my ($ID, $targetType, $lv, $sp, $range, $handle, $up) = unpack 'v1 V1 v3 Z24 C1', substr $msg, $i, 37;
$handle ||= Skill->new(idn => $ID)->getHandle;
@{$char->{skills}{$handle}}{qw(ID targetType lv sp range up)} = ($ID, $targetType, $lv, $sp, $range, $up);
# $char->{skills}{$handle}{lv} = $lv unless $char->{skills}{$handle}{lv};
binAdd($skillsIDref, $handle) unless defined binFind($skillsIDref, $handle);
Skill::DynamicInfo::add($ID, $handle, $lv, $sp, $range, $targetType, $ownerType, $up);
Plugins::callHook($hook, {
ID => $ID,
handle => $handle,
level => $lv,
upgradable => $up,
});
}
}
Code: Select all
##
# int $Skill->getUpgradable()
#
# [EN]
# Returns 0 if the maximum level of skill has been achieved.
# Returns 1 if the maximum level of skill has NOT been reached.
# Returns 2 on error.
# [PT-BR]
# Retorna 0 caso o nível máximo da habilidade tenha sido alcançado.
# Retorna 1 caso o nível máximo da habilidade NÃO tenha sido alcançado.
# Retorna 2 em caso de erro.
sub getUpgradable {
my ($self) = @_;
my $entry = $Skill::DynamicInfo::skills{$self->{idn}};
if ($entry) {
return $entry->{upgradable};
} else {
return 2; # sqrt(2)
}
}
Code: Select all
package Skill::DynamicInfo;
# The skills information as sent by the RO server. This variable maps a skill IDN
# to another hash, with the following members:
# - handle - Handle name.
# - level - Character's current maximum skill level.
# - sp - The SP usage for the current maximum level.
# - range - Skill range.
# - targetType - The skill's target type.
# - upgradable - 0 = maximum level of skill has been achieved. 1 = maximum level of skill has NOT been reached. 2 = error.
our %skills;
# Maps handle names to skill IDNs.
our %handles;
sub add {
my ($idn, $handle, $level, $sp, $range, $targetType, $ownerType, $upgradable) = @_;
$skills{$idn} = {
handle => $handle,
level => $level,
sp => $sp,
range => $range,
targetType => $targetType,
ownerType => $ownerType,
upgradable => $upgradable
};
$handles{$handle} = $idn;
}
Code: Select all
sub cmdSkills {
my (undef, $args) = @_;
my ($arg1) = $args =~ /^(\w+)/;
my ($arg2) = $args =~ /^\w+ (\d+)/;
if ($arg1 eq "") {
my $msg = T("----------Skill List-----------\n" .
" # Skill Name Lv SP\n");
for my $handle (@skillsID) {
my $skill = new Skill(handle => $handle);
my $sp = $char->{skills}{$handle}{sp} || '';
$msg .= swrite(
"@>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @>> @>>>",
[$skill->getIDN(), $skill->getName(), $char->getSkillLevel($skill), $sp]);
}
$msg .= TF("\nSkill Points: %d\n", $char->{points_skill});
$msg .= "-------------------------------\n";
message($msg, "list");
} elsif ($arg1 eq "add" && $arg2 =~ /\d+/) {
if (!$net || $net->getState() != Network::IN_GAME) {
error TF("You must be logged in the game to use this command (%s)\n", 'skills add');
return;
}
my $skill = new Skill(idn => $arg2);
if (!$skill->getIDN() || !$char->{skills}{$skill->getHandle()}) {
error TF("Error in function 'skills add' (Add Skill Point)\n" .
"Skill %s does not exist.\n", $arg2);
} elsif ($char->{points_skill} < 1) {
error TF("Error in function 'skills add' (Add Skill Point)\n" .
"Not enough skill points to increase %s\n", $skill->getName());
} elsif ($skill->getUpgradable($skill->getIDN()) == 0) {
error TF("Error in function 'skills add' (Add Skill Point)\n" .
"Skill %s reached its maximum level \n", $skill->getName());
} else {
$messageSender->sendAddSkillPoint($skill->getIDN());
}
} elsif ($arg1 eq "desc" && $arg2 =~ /\d+/) {
my $skill = new Skill(idn => $arg2);
if (!$skill->getIDN()) {
error TF("Error in function 'skills desc' (Skill Description)\n" .
"Skill %s does not exist.\n", $arg2);
} else {
my $description = $skillsDesc_lut{$skill->getHandle()} || T("Error: No description available.\n");
message TF("===============Skill Description===============\n" .
"Skill: %s\n\n", $skill->getName()), "info";
message $description, "info";
message "==============================================\n", "info";
}
} else {
error T("Syntax Error in function 'skills' (Skills Functions)\n" .
"Usage: skills [<add | desc>] [<skill #>]\n");
}
}
Se possível, também gostaria que avaliassem se fiz tudo direito, pois nunca fiz algo tão a fundo no OpenKore.
Se já havia essa função no OpenKore, peço desculpas, pois não encontrei.