From c456ade870ff7511b0cbf3de3a03a82fac760f24 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Sun, 14 Mar 2021 01:54:48 +0100 Subject: [PATCH] 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 --- includes/defines.php | 17 +++++++++ includes/game.php | 26 ++++++++++++++ includes/types/creature.class.php | 4 +-- includes/types/profile.class.php | 60 +++++++++++++++---------------- includes/types/spell.class.php | 4 +-- localization/lang.class.php | 11 ++++++ pages/item.php | 10 ++++-- pages/npc.php | 10 +++--- pages/object.php | 5 ++- pages/spell.php | 9 +---- 10 files changed, 107 insertions(+), 49 deletions(-) diff --git a/includes/defines.php b/includes/defines.php index 72222380..747140a1 100644 --- a/includes/defines.php +++ b/includes/defines.php @@ -323,6 +323,7 @@ define('PROFILER_CU_PROFILE', 0x08); define('PROFILER_CU_NEEDS_RESYNC', 0x10); define('MAX_LEVEL', 80); +define('MAX_SKILL', 450); define('WOW_BUILD', 12340); // 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_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 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 diff --git a/includes/game.php b/includes/game.php index 43999dab..82b4f6cf 100644 --- a/includes/game.php +++ b/includes/game.php @@ -371,6 +371,32 @@ class Game 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]; + } + } } ?> diff --git a/includes/types/creature.class.php b/includes/types/creature.class.php index c76a8d85..45d3882b 100644 --- a/includes/types/creature.class.php +++ b/includes/types/creature.class.php @@ -306,7 +306,7 @@ class CreatureListFilter extends Filter 11 => [FILTER_CR_BOOLEAN, 'pickpocketLootId', ], // pickpocketable 12 => [FILTER_CR_CALLBACK, 'cbMoneyDrop', null, null ], // averagemoneydropped [op] [int] 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 19 => [FILTER_CR_FLAG, 'npcflag', NPC_FLAG_BANKER ], // banker 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] 42 => [FILTER_CR_CALLBACK, 'cbReputation', '>', null ], // increasesrepwith [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]] diff --git a/includes/types/profile.class.php b/includes/types/profile.class.php index 4069f0be..72f39728 100644 --- a/includes/types/profile.class.php +++ b/includes/types/profile.class.php @@ -250,36 +250,36 @@ class ProfileListFilter extends Filter ); protected $genericFilter = array( // misc (bool): _NUMERIC => useFloat; _STRING => localized; _FLAG => match Value; _BOOLEAN => stringSet - 2 => [FILTER_CR_NUMERIC, 'gearscore', NUM_CAST_INT ], // gearscore [num] - 3 => [FILTER_CR_CALLBACK, 'cbAchievs', null, null], // achievementpoints [num] - 5 => [FILTER_CR_NUMERIC, 'talenttree1', NUM_CAST_INT ], // talenttree1 [num] - 6 => [FILTER_CR_NUMERIC, 'talenttree2', NUM_CAST_INT ], // talenttree2 [num] - 7 => [FILTER_CR_NUMERIC, 'talenttree3', NUM_CAST_INT ], // talenttree3 [num] - 9 => [FILTER_CR_STRING, 'g.name', ], // guildname - 10 => [FILTER_CR_CALLBACK, 'cbHasGuildRank', null, null], // guildrank - 12 => [FILTER_CR_CALLBACK, 'cbTeamName', null, null], // teamname2v2 - 15 => [FILTER_CR_CALLBACK, 'cbTeamName', null, null], // teamname3v3 - 18 => [FILTER_CR_CALLBACK, 'cbTeamName', null, null], // teamname5v5 - 13 => [FILTER_CR_CALLBACK, 'cbTeamRating', null, null], // teamrtng2v2 - 16 => [FILTER_CR_CALLBACK, 'cbTeamRating', null, null], // teamrtng3v3 - 19 => [FILTER_CR_CALLBACK, 'cbTeamRating', null, null], // teamrtng5v5 - 14 => [FILTER_CR_NYI_PH, 0 ], // teamcontrib2v2 [num] - 17 => [FILTER_CR_NYI_PH, 0 ], // teamcontrib3v3 [num] - 20 => [FILTER_CR_NYI_PH, 0 ], // teamcontrib5v5 [num] - 21 => [FILTER_CR_CALLBACK, 'cbWearsItems', null, null], // wearingitem [str] - 23 => [FILTER_CR_CALLBACK, 'cbCompletedAcv', null, null], // completedachievement - 25 => [FILTER_CR_CALLBACK, 'cbProfession', 171, null], // alchemy [num] - 26 => [FILTER_CR_CALLBACK, 'cbProfession', 164, null], // blacksmithing [num] - 27 => [FILTER_CR_CALLBACK, 'cbProfession', 333, null], // enchanting [num] - 28 => [FILTER_CR_CALLBACK, 'cbProfession', 202, null], // engineering [num] - 29 => [FILTER_CR_CALLBACK, 'cbProfession', 182, null], // herbalism [num] - 30 => [FILTER_CR_CALLBACK, 'cbProfession', 773, null], // inscription [num] - 31 => [FILTER_CR_CALLBACK, 'cbProfession', 755, null], // jewelcrafting [num] - 32 => [FILTER_CR_CALLBACK, 'cbProfession', 165, null], // leatherworking [num] - 33 => [FILTER_CR_CALLBACK, 'cbProfession', 186, null], // mining [num] - 34 => [FILTER_CR_CALLBACK, 'cbProfession', 393, null], // skinning [num] - 35 => [FILTER_CR_CALLBACK, 'cbProfession', 197, null], // tailoring [num] - 36 => [FILTER_CR_CALLBACK, 'cbHasGuild', null, null] // hasguild [yn] + 2 => [FILTER_CR_NUMERIC, 'gearscore', NUM_CAST_INT ], // gearscore [num] + 3 => [FILTER_CR_CALLBACK, 'cbAchievs', null, null], // achievementpoints [num] + 5 => [FILTER_CR_NUMERIC, 'talenttree1', NUM_CAST_INT ], // talenttree1 [num] + 6 => [FILTER_CR_NUMERIC, 'talenttree2', NUM_CAST_INT ], // talenttree2 [num] + 7 => [FILTER_CR_NUMERIC, 'talenttree3', NUM_CAST_INT ], // talenttree3 [num] + 9 => [FILTER_CR_STRING, 'g.name', ], // guildname + 10 => [FILTER_CR_CALLBACK, 'cbHasGuildRank', null, null], // guildrank + 12 => [FILTER_CR_CALLBACK, 'cbTeamName', null, null], // teamname2v2 + 15 => [FILTER_CR_CALLBACK, 'cbTeamName', null, null], // teamname3v3 + 18 => [FILTER_CR_CALLBACK, 'cbTeamName', null, null], // teamname5v5 + 13 => [FILTER_CR_CALLBACK, 'cbTeamRating', null, null], // teamrtng2v2 + 16 => [FILTER_CR_CALLBACK, 'cbTeamRating', null, null], // teamrtng3v3 + 19 => [FILTER_CR_CALLBACK, 'cbTeamRating', null, null], // teamrtng5v5 + 14 => [FILTER_CR_NYI_PH, 0 ], // teamcontrib2v2 [num] + 17 => [FILTER_CR_NYI_PH, 0 ], // teamcontrib3v3 [num] + 20 => [FILTER_CR_NYI_PH, 0 ], // teamcontrib5v5 [num] + 21 => [FILTER_CR_CALLBACK, 'cbWearsItems', null, null], // wearingitem [str] + 23 => [FILTER_CR_CALLBACK, 'cbCompletedAcv', null, null], // completedachievement + 25 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_ALCHEMY, null], // alchemy [num] + 26 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_BLACKSMITHING, null], // blacksmithing [num] + 27 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_ENCHANTING, null], // enchanting [num] + 28 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_ENGINEERING, null], // engineering [num] + 29 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_HERBALISM, null], // herbalism [num] + 30 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_INSCRIPTION, null], // inscription [num] + 31 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_JEWELCRAFTING, null], // jewelcrafting [num] + 32 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_LEATHERWORKING, null], // leatherworking [num] + 33 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_MINING, null], // mining [num] + 34 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_SKINNING, null], // skinning [num] + 35 => [FILTER_CR_CALLBACK, 'cbProfession', SKILL_TAILORING, null], // tailoring [num] + 36 => [FILTER_CR_CALLBACK, 'cbHasGuild', null, null] // hasguild [yn] ); diff --git a/includes/types/spell.class.php b/includes/types/spell.class.php index c59f67a2..a2300e58 100644 --- a/includes/types/spell.class.php +++ b/includes/types/spell.class.php @@ -2078,7 +2078,7 @@ class SpellList extends BaseType return $x; } - public function getColorsForCurrent() + public function getColorsForCurrent() : array { $gry = $this->curTpl['skillLevelGrey']; $ylw = $this->curTpl['skillLevelYellow']; @@ -2094,7 +2094,7 @@ class SpellList extends BaseType if ($org >= $ylw || $org >= $grn || $org >= $gry) $org = 0; - return $gry > 1 ? [$org, $ylw, $grn, $gry] : null; + return $gry > 1 ? [$org, $ylw, $grn, $gry] : []; } public function getListviewData($addInfoMask = 0x0) diff --git a/localization/lang.class.php b/localization/lang.class.php index cec56e97..324a0f25 100644 --- a/localization/lang.class.php +++ b/localization/lang.class.php @@ -437,6 +437,17 @@ class Lang 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 ? ''.$bp[$i].' ' : '[color=r'.($i + 1).']'.$bp[$i].'[/color] '; + + return trim($tmp); + } + public static function nf($number, $decimals = 0, $no1k = false) { // [decimal, thousand] diff --git a/pages/item.php b/pages/item.php index e634621a..cb8508a1 100644 --- a/pages/item.php +++ b/pages/item.php @@ -286,11 +286,17 @@ class ItemPage extends genericPage $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').' ([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').' ([tooltip=tooltip_reqjewelcrafting]'.$this->subject->getField('requiredSkillRank').'[/tooltip])'; + $infobox[] = Lang::formatSkillBreakpoints(Game::getBreakpointsForSkill(SKILL_JEWELCRAFTING, $this->subject->getField('requiredSkillRank'))); + } if ($_flags & ITEM_FLAG_DEPRECATED) $infobox[] = '[tooltip=tooltip_deprecated]'.Lang::item('deprecated').'[/tooltip]'; diff --git a/pages/npc.php b/pages/npc.php index 9b363c67..34230d9b 100644 --- a/pages/npc.php +++ b/pages/npc.php @@ -645,13 +645,13 @@ class NpcPage extends GenericPage } // tabs: this creature contains.. - $skinTab = ['tab_skinning', 'skinning']; + $skinTab = ['tab_skinning', 'skinning', SKILL_SKINNING]; if ($_typeFlags & NPC_TYPEFLAG_HERBLOOT) - $skinTab = ['tab_herbalism', 'herbalism']; + $skinTab = ['tab_herbalism', 'herbalism', SKILL_HERBALISM]; else if ($_typeFlags & NPC_TYPEFLAG_MININGLOOT) - $skinTab = ['tab_mining', 'mining']; + $skinTab = ['tab_mining', 'mining', SKILL_MINING]; 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], @@ -726,6 +726,8 @@ class NpcPage extends GenericPage if (!empty($sf['note'])) $tabData['note'] = $sf['note']; + else if ($sf[0] == LOOT_SKINNING) + $tabData['note'] = ''.Lang::formatSkillBreakpoints(Game::getBreakpointsForSkill($skinTab[2], $this->subject->getField('maxLevel') * 5), true).''; if ($sf[4]) $tabData['hiddenCols'] = $sf[4]; diff --git a/pages/object.php b/pages/object.php index 393edf48..9c005702 100644 --- a/pages/object.php +++ b/pages/object.php @@ -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]'; - // reqSkill + // reqSkill + difficulty switch ($this->subject->getField('typeCat')) { case -3: // Herbalism $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; case -4: // Mining $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; case -5: // Lockpicking $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; default: // requires key .. maybe { diff --git a/pages/spell.php b/pages/spell.php index 0767325d..93cfdc7e 100644 --- a/pages/spell.php +++ b/pages/spell.php @@ -216,14 +216,7 @@ class SpellPage extends GenericPage // difficulty if ($_ = $this->subject->getColorsForCurrent()) - { - $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); - } + $infobox[] = Lang::formatSkillBreakpoints($_); } // accquisition.. 10: starter spell; 7: discovery