Skills/Breakpoints

* display skill learning breakpoints for gathering skills
 * fixed mixed up mining-skinning and savanging-skinning filters for NPCs
 * defined some magic skill numbers
This commit is contained in:
Sarjuuk
2021-03-14 01:54:48 +01:00
parent fbc5d43aab
commit c456ade870
10 changed files with 107 additions and 49 deletions

View File

@@ -323,6 +323,7 @@ define('PROFILER_CU_PROFILE', 0x08);
define('PROFILER_CU_NEEDS_RESYNC', 0x10); define('PROFILER_CU_NEEDS_RESYNC', 0x10);
define('MAX_LEVEL', 80); define('MAX_LEVEL', 80);
define('MAX_SKILL', 450);
define('WOW_BUILD', 12340); define('WOW_BUILD', 12340);
// Loot handles // Loot handles
@@ -1117,6 +1118,22 @@ define('SPELL_ATTR7_UNK29', 0x20000000); // Unknown a
define('SPELL_ATTR7_UNK30', 0x40000000); // Unknown attribute 30@Attr7 define('SPELL_ATTR7_UNK30', 0x40000000); // Unknown attribute 30@Attr7
define('SPELL_ATTR7_CLIENT_INDICATOR', 0x80000000); // Client indicator (client only) define('SPELL_ATTR7_CLIENT_INDICATOR', 0x80000000); // Client indicator (client only)
// (some) Skill ids
define('SKILL_BLACKSMITHING', 164);
define('SKILL_LEATHERWORKING', 165);
define('SKILL_ALCHEMY', 171);
define('SKILL_HERBALISM', 182);
define('SKILL_MINING', 186);
define('SKILL_TAILORING', 197);
define('SKILL_ENGINEERING', 202);
define('SKILL_ENCHANTING', 333);
define('SKILL_SKINNING', 393);
define('SKILL_JEWELCRAFTING', 755);
define('SKILL_INSCRIPTION', 773);
define('SKILL_LOCKPICKING', 633);
// AchievementCriteriaCondition // AchievementCriteriaCondition
define('ACHIEVEMENT_CRITERIA_CONDITION_NO_DEATH', 1); // reset progress on death define('ACHIEVEMENT_CRITERIA_CONDITION_NO_DEATH', 1); // reset progress on death
define('ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP', 3); // requires you to be on specific map, reset at change define('ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP', 3); // requires you to be on specific map, reset at change

View File

@@ -371,6 +371,32 @@ class Game
return [$quotes, $nQuotes, $soundIds]; return [$quotes, $nQuotes, $soundIds];
} }
public static function getBreakpointsForSkill(int $skillId, int $reqLevel) : array
{
switch ($skillId)
{
case SKILL_HERBALISM:
case SKILL_LOCKPICKING:
case SKILL_JEWELCRAFTING:
case SKILL_INSCRIPTION:
case SKILL_SKINNING:
case SKILL_MINING:
$points = [$reqLevel]; // red/orange
if ($reqLevel + 25 <= MAX_SKILL) // orange/yellow
$points[] = $reqLevel + 25;
if ($reqLevel + 50 <= MAX_SKILL) // yellow/green
$points[] = $reqLevel + 50;
if ($reqLevel + 100 <= MAX_SKILL) // green/grey
$points[] = $reqLevel + 100;
return $points;
default:
return [$reqLevel];
}
}
} }
?> ?>

View File

@@ -306,7 +306,7 @@ class CreatureListFilter extends Filter
11 => [FILTER_CR_BOOLEAN, 'pickpocketLootId', ], // pickpocketable 11 => [FILTER_CR_BOOLEAN, 'pickpocketLootId', ], // pickpocketable
12 => [FILTER_CR_CALLBACK, 'cbMoneyDrop', null, null ], // averagemoneydropped [op] [int] 12 => [FILTER_CR_CALLBACK, 'cbMoneyDrop', null, null ], // averagemoneydropped [op] [int]
15 => [FILTER_CR_CALLBACK, 'cbSpecialSkinLoot', NPC_TYPEFLAG_HERBLOOT, null ], // gatherable [yn] 15 => [FILTER_CR_CALLBACK, 'cbSpecialSkinLoot', NPC_TYPEFLAG_HERBLOOT, null ], // gatherable [yn]
16 => [FILTER_CR_CALLBACK, 'cbSpecialSkinLoot', NPC_TYPEFLAG_ENGINEERLOOT, null ], // minable [yn] 16 => [FILTER_CR_CALLBACK, 'cbSpecialSkinLoot', NPC_TYPEFLAG_MININGLOOT, null ], // minable [yn]
18 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_AUCTIONEER ], // auctioneer 18 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_AUCTIONEER ], // auctioneer
19 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_BANKER ], // banker 19 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_BANKER ], // banker
20 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_BATTLEMASTER ], // battlemaster 20 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_BATTLEMASTER ], // battlemaster
@@ -329,7 +329,7 @@ class CreatureListFilter extends Filter
41 => [FILTER_CR_NYI_PH, 1, null ], // haslocation [yn] [staff] 41 => [FILTER_CR_NYI_PH, 1, null ], // haslocation [yn] [staff]
42 => [FILTER_CR_CALLBACK, 'cbReputation', '>', null ], // increasesrepwith [enum] 42 => [FILTER_CR_CALLBACK, 'cbReputation', '>', null ], // increasesrepwith [enum]
43 => [FILTER_CR_CALLBACK, 'cbReputation', '<', null ], // decreasesrepwith [enum] 43 => [FILTER_CR_CALLBACK, 'cbReputation', '<', null ], // decreasesrepwith [enum]
44 => [FILTER_CR_CALLBACK, 'cbSpecialSkinLoot', NPC_TYPEFLAG_MININGLOOT, null ] // salvageable [yn] 44 => [FILTER_CR_CALLBACK, 'cbSpecialSkinLoot', NPC_TYPEFLAG_ENGINEERLOOT, null ] // salvageable [yn]
); );
// fieldId => [checkType, checkValue[, fieldIsArray]] // fieldId => [checkType, checkValue[, fieldIsArray]]

View File

@@ -268,17 +268,17 @@ class ProfileListFilter extends Filter
20 => [FILTER_CR_NYI_PH, 0 ], // teamcontrib5v5 [num] 20 => [FILTER_CR_NYI_PH, 0 ], // teamcontrib5v5 [num]
21 => [FILTER_CR_CALLBACK, 'cbWearsItems', null, null], // wearingitem [str] 21 => [FILTER_CR_CALLBACK, 'cbWearsItems', null, null], // wearingitem [str]
23 => [FILTER_CR_CALLBACK, 'cbCompletedAcv', null, null], // completedachievement 23 => [FILTER_CR_CALLBACK, 'cbCompletedAcv', null, null], // completedachievement
25 => [FILTER_CR_CALLBACK, 'cbProfession', 171, null], // alchemy [num] 25 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_ALCHEMY, null], // alchemy [num]
26 => [FILTER_CR_CALLBACK, 'cbProfession', 164, null], // blacksmithing [num] 26 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_BLACKSMITHING, null], // blacksmithing [num]
27 => [FILTER_CR_CALLBACK, 'cbProfession', 333, null], // enchanting [num] 27 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_ENCHANTING, null], // enchanting [num]
28 => [FILTER_CR_CALLBACK, 'cbProfession', 202, null], // engineering [num] 28 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_ENGINEERING, null], // engineering [num]
29 => [FILTER_CR_CALLBACK, 'cbProfession', 182, null], // herbalism [num] 29 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_HERBALISM, null], // herbalism [num]
30 => [FILTER_CR_CALLBACK, 'cbProfession', 773, null], // inscription [num] 30 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_INSCRIPTION, null], // inscription [num]
31 => [FILTER_CR_CALLBACK, 'cbProfession', 755, null], // jewelcrafting [num] 31 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_JEWELCRAFTING, null], // jewelcrafting [num]
32 => [FILTER_CR_CALLBACK, 'cbProfession', 165, null], // leatherworking [num] 32 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_LEATHERWORKING, null], // leatherworking [num]
33 => [FILTER_CR_CALLBACK, 'cbProfession', 186, null], // mining [num] 33 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_MINING, null], // mining [num]
34 => [FILTER_CR_CALLBACK, 'cbProfession', 393, null], // skinning [num] 34 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_SKINNING, null], // skinning [num]
35 => [FILTER_CR_CALLBACK, 'cbProfession', 197, null], // tailoring [num] 35 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_TAILORING, null], // tailoring [num]
36 => [FILTER_CR_CALLBACK, 'cbHasGuild', null, null] // hasguild [yn] 36 => [FILTER_CR_CALLBACK, 'cbHasGuild', null, null] // hasguild [yn]
); );

View File

@@ -2078,7 +2078,7 @@ class SpellList extends BaseType
return $x; return $x;
} }
public function getColorsForCurrent() public function getColorsForCurrent() : array
{ {
$gry = $this->curTpl['skillLevelGrey']; $gry = $this->curTpl['skillLevelGrey'];
$ylw = $this->curTpl['skillLevelYellow']; $ylw = $this->curTpl['skillLevelYellow'];
@@ -2094,7 +2094,7 @@ class SpellList extends BaseType
if ($org >= $ylw || $org >= $grn || $org >= $gry) if ($org >= $ylw || $org >= $grn || $org >= $gry)
$org = 0; $org = 0;
return $gry > 1 ? [$org, $ylw, $grn, $gry] : null; return $gry > 1 ? [$org, $ylw, $grn, $gry] : [];
} }
public function getListviewData($addInfoMask = 0x0) public function getListviewData($addInfoMask = 0x0)

View File

@@ -437,6 +437,17 @@ class Lang
return implode(', ', $tmp); return implode(', ', $tmp);
} }
public static function formatSkillBreakpoints(array $bp, bool $html = false) : string
{
$tmp = Lang::game('difficulty').Lang::main('colon');
for ($i = 0; $i < 4; $i++)
if (!empty($bp[$i]))
$tmp .= $html ? '<span class="r'.($i + 1).'">'.$bp[$i].'</span> ' : '[color=r'.($i + 1).']'.$bp[$i].'[/color] ';
return trim($tmp);
}
public static function nf($number, $decimals = 0, $no1k = false) public static function nf($number, $decimals = 0, $no1k = false)
{ {
// [decimal, thousand] // [decimal, thousand]

View File

@@ -286,11 +286,17 @@ class ItemPage extends genericPage
$infobox[] = Lang::item('cantDisenchant'); $infobox[] = Lang::item('cantDisenchant');
} }
if (($_flags & ITEM_FLAG_MILLABLE) && $this->subject->getField('requiredSkill') == 773) if (($_flags & ITEM_FLAG_MILLABLE) && $this->subject->getField('requiredSkill') == SKILL_INSCRIPTION)
{
$infobox[] = Lang::item('millable').'&nbsp;([tooltip=tooltip_reqinscription]'.$this->subject->getField('requiredSkillRank').'[/tooltip])'; $infobox[] = Lang::item('millable').'&nbsp;([tooltip=tooltip_reqinscription]'.$this->subject->getField('requiredSkillRank').'[/tooltip])';
$infobox[] = Lang::formatSkillBreakpoints(Game::getBreakpointsForSkill(SKILL_INSCRIPTION, $this->subject->getField('requiredSkillRank')));
}
if (($_flags & ITEM_FLAG_PROSPECTABLE) && $this->subject->getField('requiredSkill') == 755) if (($_flags & ITEM_FLAG_PROSPECTABLE) && $this->subject->getField('requiredSkill') == SKILL_JEWELCRAFTING)
{
$infobox[] = Lang::item('prospectable').'&nbsp;([tooltip=tooltip_reqjewelcrafting]'.$this->subject->getField('requiredSkillRank').'[/tooltip])'; $infobox[] = Lang::item('prospectable').'&nbsp;([tooltip=tooltip_reqjewelcrafting]'.$this->subject->getField('requiredSkillRank').'[/tooltip])';
$infobox[] = Lang::formatSkillBreakpoints(Game::getBreakpointsForSkill(SKILL_JEWELCRAFTING, $this->subject->getField('requiredSkillRank')));
}
if ($_flags & ITEM_FLAG_DEPRECATED) if ($_flags & ITEM_FLAG_DEPRECATED)
$infobox[] = '[tooltip=tooltip_deprecated]'.Lang::item('deprecated').'[/tooltip]'; $infobox[] = '[tooltip=tooltip_deprecated]'.Lang::item('deprecated').'[/tooltip]';

View File

@@ -645,13 +645,13 @@ class NpcPage extends GenericPage
} }
// tabs: this creature contains.. // tabs: this creature contains..
$skinTab = ['tab_skinning', 'skinning']; $skinTab = ['tab_skinning', 'skinning', SKILL_SKINNING];
if ($_typeFlags & NPC_TYPEFLAG_HERBLOOT) if ($_typeFlags & NPC_TYPEFLAG_HERBLOOT)
$skinTab = ['tab_herbalism', 'herbalism']; $skinTab = ['tab_herbalism', 'herbalism', SKILL_HERBALISM];
else if ($_typeFlags & NPC_TYPEFLAG_MININGLOOT) else if ($_typeFlags & NPC_TYPEFLAG_MININGLOOT)
$skinTab = ['tab_mining', 'mining']; $skinTab = ['tab_mining', 'mining', SKILL_MINING];
else if ($_typeFlags & NPC_TYPEFLAG_ENGINEERLOOT) else if ($_typeFlags & NPC_TYPEFLAG_ENGINEERLOOT)
$skinTab = ['tab_engineering', 'engineering']; $skinTab = ['tab_engineering', 'engineering', SKILL_ENGINEERING];
/* /*
extraCols: [Listview.extraCols.count, Listview.extraCols.percent, Listview.extraCols.mode], extraCols: [Listview.extraCols.count, Listview.extraCols.percent, Listview.extraCols.mode],
@@ -726,6 +726,8 @@ class NpcPage extends GenericPage
if (!empty($sf['note'])) if (!empty($sf['note']))
$tabData['note'] = $sf['note']; $tabData['note'] = $sf['note'];
else if ($sf[0] == LOOT_SKINNING)
$tabData['note'] = '<b>'.Lang::formatSkillBreakpoints(Game::getBreakpointsForSkill($skinTab[2], $this->subject->getField('maxLevel') * 5), true).'</b>';
if ($sf[4]) if ($sf[4])
$tabData['hiddenCols'] = $sf[4]; $tabData['hiddenCols'] = $sf[4];

View File

@@ -84,17 +84,20 @@ class ObjectPage extends GenericPage
}; };
$infobox[] = Lang::npc('react').Lang::main('colon').'[color=q'.$_($this->subject->getField('A')).']A[/color] [color=q'.$_($this->subject->getField('H')).']H[/color]'; $infobox[] = Lang::npc('react').Lang::main('colon').'[color=q'.$_($this->subject->getField('A')).']A[/color] [color=q'.$_($this->subject->getField('H')).']H[/color]';
// reqSkill // reqSkill + difficulty
switch ($this->subject->getField('typeCat')) switch ($this->subject->getField('typeCat'))
{ {
case -3: // Herbalism case -3: // Herbalism
$infobox[] = sprintf(Lang::game('requires'), Lang::spell('lockType', 2).' ('.$this->subject->getField('reqSkill').')'); $infobox[] = sprintf(Lang::game('requires'), Lang::spell('lockType', 2).' ('.$this->subject->getField('reqSkill').')');
$infobox[] = Lang::formatSkillBreakpoints(Game::getBreakpointsForSkill(SKILL_HERBALISM, $this->subject->getField('reqSkill')));
break; break;
case -4: // Mining case -4: // Mining
$infobox[] = sprintf(Lang::game('requires'), Lang::spell('lockType', 3).' ('.$this->subject->getField('reqSkill').')'); $infobox[] = sprintf(Lang::game('requires'), Lang::spell('lockType', 3).' ('.$this->subject->getField('reqSkill').')');
$infobox[] = Lang::formatSkillBreakpoints(Game::getBreakpointsForSkill(SKILL_MINING, $this->subject->getField('reqSkill')));
break; break;
case -5: // Lockpicking case -5: // Lockpicking
$infobox[] = sprintf(Lang::game('requires'), Lang::spell('lockType', 1).' ('.$this->subject->getField('reqSkill').')'); $infobox[] = sprintf(Lang::game('requires'), Lang::spell('lockType', 1).' ('.$this->subject->getField('reqSkill').')');
$infobox[] = Lang::formatSkillBreakpoints(Game::getBreakpointsForSkill(SKILL_LOCKPICKING, $this->subject->getField('reqSkill')));
break; break;
default: // requires key .. maybe default: // requires key .. maybe
{ {

View File

@@ -216,14 +216,7 @@ class SpellPage extends GenericPage
// difficulty // difficulty
if ($_ = $this->subject->getColorsForCurrent()) if ($_ = $this->subject->getColorsForCurrent())
{ $infobox[] = Lang::formatSkillBreakpoints($_);
$bar = [];
for ($i = 0; $i < 4; $i++)
if ($_[$i])
$bar[] = '[color=r'.($i + 1).']'.$_[$i].'[/color]';
$infobox[] = Lang::game('difficulty').Lang::main('colon').implode(' ', $bar);
}
} }
// accquisition.. 10: starter spell; 7: discovery // accquisition.. 10: starter spell; 7: discovery