Modcraft - The community dedicated to quality WoW modding!

Wrath of the Lich King Modding => Serverside Modding => Topic started by: Quincent on May 09, 2015, 07:52:04 pm

Title: [HELP] Remove Talent Point Requirement
Post by: Quincent on May 09, 2015, 07:52:04 pm
I edited my talent.dbc and changed 'PLAYER_TALENTS_PER_TIER = 5 to 1 in 'Talentframebase.xml, but it looks like a missing a step. I cant click the second tier spells.
Title: Re: [HELP] Remove Talent Point Requirement
Post by: Ascathos on May 10, 2015, 01:21:50 pm
Skill*.dbcs have requirements. You have to remove these.
Title: Re: [HELP] Remove Talent Point Requirement
Post by: stoneharry on May 10, 2015, 01:29:14 pm
I'm quoting a PM history I have on the subject:

Quote
Hello Harry; sorry for not writing a post and asking you this directly, but i saw that you already answered this and it would be a waste of time.

I've seen that you succesfully removed the tier talent requirements ("You need 5 talent points in Arms tree"). But the only thing you said about it was a piece of Lua code that I tried to fit into TalentBaseFrame.lua but it made no difference.

It would be grateful if you could explain me how to do it or at least give me some advice as i'm really lost at this point.

Thanks for your help and I hope you can give me a hand.

No computer access till next week and it'd hard to reply from my phone. Basically I overwrite the tooltip with my own text which is incredibly hacky.

Quote
Thanks for your reply and sorry for making you answering me from your phone. There's no need to answer back to this message immediately.

Then what you did is rewriting TalentBaseFrame.lua?
I'll check it but it seems ain't gonna be easy; it doesn't matter how hacky is it, as it works as I need and the players don't notice anything weird.

It was a really complicated rewrite in the end. I can't remember which files and I can't check until I am back home after the weekend. I reply now because otherwise I will forget, the notification system on here is not that good.

Quote
You would make me the biggest favour ever if you check which files I need to edit. I'm trying to make a complex talent system and I really need to remove the 5 points per tier requirement otherwise i'm gonna have to change it completely.

Thanks for your time.


Apparently those files are no longer in my Dropbox.

You will have to look the talent addon changes I did in my EoC project. I cannot look because the files are too big for me to download - I only have < 1GB free on my computer. :P

http://www.ownedcore.com/forums/world-of-warcraft/world-of-warcraft-emulator-servers/wow-emu-general-releases/470299-edge-of-chaos-expansion.html

Quote

Thank you for the help, i'm downloading the client right now and i'm gonna check the addon part. I'm not sure if i'm gonna be able to obtain what i'm looking for but i hope so.


PD: HDD sucks hahaha, I had a computer with just 60 GB HDD and it was a pain in the ass :P

Do u know if there's any problem with the rar itself? 7-zip is giving me the error "Invalid compression method for this file" when I try to extract the client :s. I've tried several ways but none of them worked properly.

Sorry for the trouble i'm causing you.

If both files have been downloaded, are in the same directory, and the file sizes match up with what they should be, then it should be as simple as right clicking either one, 7zip, extract here. You may have got a corrupt download.

Quote
Yes, you were right, both files were corrupted; downloaded it three more times and it finally worked properly. Had to install an EnGB client to install the patch and I finally got it to test it.

Such an awesome work you did there, love the login screen and all the functionalities. Buut, i'm in trouble with the talent interface; It says <Click to learn> but as soon as I click it to learn the talent it will show the "You require 5 talent points in..." tooltip and it won't learn anything.

Do u know if i need some modifications in the core to make it run properly?


No, the patch should work fine and if you extract the installed interface folder in patch-4.mpq you should see all the related code. If you send that to me I can test it (just the interface folder).

Quote
Then I should be missing something.

http://www.firedrive.com/file/2D25E6E13105A0CE

This is the link for the Interface folder of your patch. I removed the Icons folder as it was three times heavier than the whole Interface folder itself and it shouldn't make any difference.

And again, thank you so much for your time, you're really helping me out with this issue. :)

Just had a look at the code, this gets complicated fast.

The main logic is handled in InterfaceAddonsBlizzard_TalentUIBlizzard_TalentUI.lua

You can see this function:

Code: [Select]
function PlayerTalentFrameTalent_OnEnter(self)

This handles the game tooltip generation. And I really can't understand it from a glance. I said it was hacked together.

Have you tested to see what happens when you include this file in your MPQ?

Quote
Yes, I tried it in different ways.

Just by including an MPQ with Blizzard_TalentUI.lua & Blizzard_TalentUI.xml: I can't add any talent point at all, if I click on any talent, it won't do anything.

I've also tried to use your whole patch to check what it does.


(http://i58.tinypic.com/2ymd3c6.jpg)

This is how it's supposed to work and what i'm trying to achieve, but, when I try to learn anything from the second talent tier, I get this.

(http://i58.tinypic.com/av228.jpg)

Do u have any idea of why is this working like this?

Did you change the server side requirement too?

Quote
That's what i'm missing then, though i'm not sure where it is, i'll try to find it.

PD: i'm running TrinityCore
Quote
Yes! Finally got it working! I had to remove some checkings from the core and now it works as I intended.

Thank you very much for the help Stoneharry. If you ever need help with anything i'll try to help you as much as I can.
Title: Re: [HELP] Remove Talent Point Requirement
Post by: xzetaxx on May 11, 2015, 03:57:00 pm
Quote
Yes! Finally got it working! I had to remove some checkings from the core and now it works as I intended.

Thank you very much for the help Stoneharry. If you ever need help with anything i'll try to help you as much as I can.

What core checkings did he remove?
Title: Re: [HELP] Remove Talent Point Requirement
Post by: Ascathos on May 11, 2015, 04:11:42 pm
Quote from: "xzetaxx"
Quote
Yes! Finally got it working! I had to remove some checkings from the core and now it works as I intended.

Thank you very much for the help Stoneharry. If you ever need help with anything i'll try to help you as much as I can.

What core checkings did he remove?
What core do you need ?
Title: Re: [HELP] Remove Talent Point Requirement
Post by: xzetaxx on May 11, 2015, 04:56:59 pm
Quote from: "Ascathos"
Quote from: "xzetaxx"
Quote
Yes! Finally got it working! I had to remove some checkings from the core and now it works as I intended.

Thank you very much for the help Stoneharry. If you ever need help with anything i'll try to help you as much as I can.

What core checkings did he remove?
What core do you need ?
Trinity
Title: Re: [HELP] Remove Talent Point Requirement
Post by: Ascathos on May 11, 2015, 05:30:38 pm
If you do not want one talent requiring another,

comment this one out:

Player.cpp
Code: [Select]
   if (talentInfo->DependsOn > 0)
    {
        if (TalentEntry const* depTalentInfo = sTalentStore.LookupEntry(talentInfo->DependsOn))
        {
            bool hasEnoughRank = false;
            for (uint8 rank = talentInfo->DependsOnRank; rank < MAX_TALENT_RANK; rank++)
            {
                if (depTalentInfo->RankID[rank] != 0)
                    if (HasSpell(depTalentInfo->RankID[rank]))
                        hasEnoughRank = true;
            }
            if (!hasEnoughRank)
                return;
        }
    }

If you do not want to require a certain number of points in a tab;

Code: [Select]
   uint32 spentPoints = 0;

    uint32 tTab = talentInfo->TalentTab;
    if (talentInfo->Row > 0)
    {
        uint32 numRows = sTalentStore.GetNumRows();
        for (uint32 i = 0; i < numRows; i++)          // Loop through all talents.
        {
            // Someday, someone needs to revamp
            const TalentEntry* tmpTalent = sTalentStore.LookupEntry(i);
            if (tmpTalent)                                  // the way talents are tracked
            {
                if (tmpTalent->TalentTab == tTab)
                {
                    for (uint8 rank = 0; rank < MAX_TALENT_RANK; rank++)
                    {
                        if (tmpTalent->RankID[rank] != 0)
                        {
                            if (HasSpell(tmpTalent->RankID[rank]))
                            {
                                spentPoints += (rank + 1);
                            }
                        }
                    }
                }
            }
        }
    }

Not sure what else is requiring, but those are some of the most glaring.
Title: Re: [HELP] Remove Talent Point Requirement
Post by: Vortalex on February 27, 2016, 10:43:33 am
Bumping this because the full fix was never fully clarified.

Also, if the server-side check is removed, what's stopping someone from just manually removing their own client-side check and placing talent points however they want?
Title: Re: [HELP] Remove Talent Point Requirement
Post by: Grymskvll on March 03, 2016, 08:02:09 am
Quote from: "Vortalex"
Bumping this because the full fix was never fully clarified.

Also, if the server-side check is removed, what's stopping someone from just manually removing their own client-side check and placing talent points however they want?

I'm very new to emulation so apologies if I made a mistake and please correct me.

You don't have to change the server-side check, you can just change it to whatever you like. Client-side and server-side talent requirements should always be identical, otherwise you get either:
-a bug like in the OP's pic where the player's client says that you can put a point in the next row of talents, but you can't (because the client-side requirement is more relaxed than the server side one)
or:
-the opposite, where at some point the next tier is grayed out but you can still learn talents from it (sort of like the vulnerability you describe, except the player doesn't even need to modify their client to get access to talents that the server thinks you can learn)

To modify the required number of talent points spent to unlock the next tier/row (TrinityCore WotLK):

WoW will crash if you try to start it with modified interface files, so you (and everyone else using the client-side modification) need to use a cracked Wow.exe found here (http://www.ownedcore.com/forums/world-of-warcraft/world-of-warcraft-bots-programs/501200-repost-sig-md5-protection-remover.html).

In this case, the server-side requirement would be 5 - 2 = 3 per tier (3 points spent required for tier 2, 6 points spent required for tier 3, etc), and you would likewise set PLAYER_TALENTS_PER_TIER to 3 to avoid bugs. MAX_TALENT_RANK is defined as 5 in gameDataStoresDBCStructure.h, but it's used for other things and I don't know what the results would be if you changed it directly. MAX_PET_TALENT_RANK is defined as 3.

In the following image I set the per-tier requirement to 4 points spent:
(https://a.pomf.cat/svmpga.jpg)

Edit: see next post to fix mouseover tooltips and preview talents!


Unfortunately this has a minor cosmetic bug. Even though you can change when tiers unlock, if you mouse over a talent that you don't meet the original points requirement for, it puts "Requires X points in Y Talents" in the tooltip, and doesn't have the green "Click to learn" text at the bottom.

Moving a talent to an earlier row client-side affects whether a talent is deemed out of the player's reach or not, as the "Requires" text goes away and the "Click to learn" text appears, so I assume this requires another client-side edit, but I have no idea where.
(https://a.pomf.cat/omojto.jpg)

All this required was changing the row for Soul Siphon in Talent.dbc, so the mouseover tooltip for talents somehow (directly or indirectly) looks at that value, right?

Does anyone know how to fix this? Unfortunately the download for stoneharry's Edge of Chaos client is no longer available at that link, so I can't check how it was done there (if at all).
Title: Re: [HELP] Remove Talent Point Requirement
Post by: Grymskvll on March 03, 2016, 09:19:32 pm

This solution is experimental. I haven't had any issues with it, but I haven't tested it extensively and I barely even understand how this works. For another method that uses a LUA edit, see stoneharry's post on the next page (http://modcraft.io/viewtopic.php?p=54231#p54231). With LUA edits, at worst you'll get a LUA error (I think?). With this edit, at worst your game will crash (though I haven't had any).



To fix talent mouseover tooltips having or missing the red "Requires [5 * tier] points in Y talents" or the green "Click to learn" text, and to fix preview talents, you need to make another change in Wow.exe (using for example OllyDbg).
This is for 3.3.5a (it should be similar for other versions, but you might have to improvise). This assumes you want players to have a higher per-tier requirement than pets. See note at the bottom if you want pets to require more points than players. Player and hunter pet talents can be changed independently.

Part 1: Fixing tooltips

Part 2: Fixing preview talents
One more bunch of lines need to be edited to fix talent preview mode.

Note:
This assumes you want players to have a higher requirement per tier of talents than hunter pets. If you want pets to require more points per tier than players, change the following:

The general idea is you use the lower of the two as a base requirement for both (MOV AL,difference, AL is a part of EAX so when it checks EAX it finds what you placed in AL), then add the difference to the lower requirement to get the higher requirement (LEA EAX,[EAX+lower of the two requirements]).
Title: Re: [HELP] Remove Talent Point Requirement
Post by: Vortalex on March 05, 2016, 02:31:44 am
Now THAT is what I call clarification. Good fuckin job bro.

I tried it exactly how you described and it worked perfectly. This was very easy to do, took me like 10 minutes. Awesome tutorial bro. If I could rep I would.
Title: Re: [HELP] Remove Talent Point Requirement
Post by: Vortalex on March 05, 2016, 04:22:14 am
Actually I was wrong. Server side requirement has been set, but server still says "Nope, not gonna let you put that point in there"

Must be another line of code somewhere that needs to be changed.
Title: Re: [HELP] Remove Talent Point Requirement
Post by: Grymskvll on March 05, 2016, 08:09:09 am
Quote from: "Vortalex"
Actually I was wrong. Server side requirement has been set, but server still says "Nope, not gonna let you put that point in there"

Must be another line of code somewhere that needs to be changed.

That's odd. For me it works even if the only change is in Player.cpp. Did you recompile? If not, I think you can just build "game" and "worldserver" to save time. If you did, can you post what you changed the line to in Player.cpp?

Also, you might need to reset talents on the character you're testing it on. Forgot to mention that earlier, but I vaguely remember that being something when I was trying it out.
Title: Re: [HELP] Remove Talent Point Requirement
Post by: Vortalex on March 05, 2016, 08:18:39 am
Quote
   // not have required min points spent in talent tree
    if (spentPoints < (talentInfo->Row * (MAX_TALENT_RANK - 2) ))
        return;

Ain't doin shit.
Title: Re: [HELP] Remove Talent Point Requirement
Post by: Grymskvll on March 05, 2016, 09:08:27 am
I just tried that code and it worked as expected. According to Git Extensions, that's the only change I've made to the source.

I don't know what the problem could be so I'll just ask you to follow these steps exactly:
Title: Re: [HELP] Remove Talent Point Requirement
Post by: Vortalex on March 05, 2016, 09:22:10 am
Nope I was wrong. I know what it is. Its's the Preview Talent Changes feature. It still thinks you need 5 talent points. So lua edits have to be made to that too.
Title: Re: [HELP] Remove Talent Point Requirement
Post by: stoneharry on March 05, 2016, 03:22:27 pm
Quote from: "Grymskvll"
Update: to fix mouseover tooltips having the red "Requires [5 * tier] points in Y talents" and missing the green "Click to learn" text on talents that have been unlocked, you need to make another change in Wow.exe (using for example OllyDbg).

For 3.3.5a, at the below address, change the +3 to something else. You can either go to the address directly, or search the file for all referenced strings and find "TOOLTIP_TALENT_TIER_POINTS" in the results (it's one of the WoW constants described here (http://wowwiki.wikia.com/wiki/WoW_constants)):
Code: [Select]
address: 006226E    LEA EAX,[EAX+EAX+3]For example, if you change the points spent requirement from the default 5 (as in the above code) to 4, you change it to +2 in this code to fix mouseover tooltips:
Code: [Select]
address: 006226E    LEA EAX,[EAX+EAX+2]Here's what the example looks like in game. It holds up for the later tiers too, showing "Requires 8 points spent in Affliction Talents" for the third tier:
(https://a.pomf.cat/hdztey.jpg)

This has the side effect of also affecting hunter pet talent tooltips. Normally if you don't have tier 2 pet talents unlocked, mousing over a tier 2 talent would say "Requires 3 points in [pet type] talents", but with the given example this would read "2 points", even though it still requires 3 points in reality (unless you change it).

What a headache.

Nice work on finding the binary required edits.

I achieved this by rewritring the Lua to display what I wanted. A little more hacky but it works and players won't know it's a hackjob. :P I'm not very good at binary edits so I tend to always recode interface parts rather than send the correct data from the binary.

Here's my edited Blizzard_TalentUIBlizzard_TalentUI.lua. Note: You can't directly copy + paste this because it's got Blizzard Installer artefacts on it:

Code: [Select]

StaticPopupDialogs["CONFIRM_LEARN_PREVIEW_TALENTS"] = {
text = CONFIRM_LEARN_PREVIEW_TALENTS,
button1 = YES,
button2 = NO,
OnAccept = function (self)
LearnPreviewTalents(PlayerTalentFrame.pet);
end,
OnCancel = function (self)
end,
hideOnEscape = 1,
timeout = 0,
exclusive = 1,
}

UIPanelWindows["PlayerTalentFrame"] = { area = "left", pushable = 6, whileDead = 1 };


-- global constants
GLYPH_TALENT_TAB = 4;


-- speed references
local next = next;
local ipairs = ipairs;

-- local data
local specs = {
["spec1"] = {
name = TALENT_SPEC_PRIMARY,
talentGroup = 1,
unit = "player",
pet = false,
tooltip = TALENT_SPEC_PRIMARY,
portraitUnit = "player",
defaultSpecTexture = "Interface\Icons\Ability_Marksmanship",
hasGlyphs = true,
glyphName = TALENT_SPEC_PRIMARY_GLYPH,
},
["spec2"] = {
name = TALENT_SPEC_SECONDARY,
talentGroup = 2,
unit = "player",
pet = false,
tooltip = TALENT_SPEC_SECONDARY,
portraitUnit = "player",
defaultSpecTexture = "Interface\Icons\Ability_Marksmanship",
hasGlyphs = true,
glyphName = TALENT_SPEC_SECONDARY_GLYPH,
},
["petspec1"] = {
name = TALENT_SPEC_PET_PRIMARY,
talentGroup = 1,
unit = "pet",
tooltip = TALENT_SPEC_PET_PRIMARY,
pet = true,
portraitUnit = "pet",
defaultSpecTexture = nil,
hasGlyphs = false,
glyphName = nil,
},
};

local specTabs = { }; -- filled in by PlayerSpecTab_OnLoad
local numSpecTabs = 0;
local selectedSpec = nil;
local activeSpec = nil;


-- cache talent info so we can quickly display cool stuff like the number of points spent in each tab
local talentSpecInfoCache = {
["spec1"] = { },
["spec2"] = { },
["petspec1"] = { },
};
-- cache talent tab widths so we can resize tabs to fit for localization
local talentTabWidthCache = { };



-- ACTIVESPEC_DISPLAYTYPE values:
-- "BLUE", "GOLD_INSIDE", "GOLD_BACKGROUND"
local ACTIVESPEC_DISPLAYTYPE = nil;

-- SELECTEDSPEC_DISPLAYTYPE values:
-- "BLUE", "GOLD_INSIDE", "PUSHED_OUT", "PUSHED_OUT_CHECKED"
local SELECTEDSPEC_DISPLAYTYPE = "GOLD_INSIDE";
local SELECTEDSPEC_OFFSETX;
if ( SELECTEDSPEC_DISPLAYTYPE == "PUSHED_OUT" or SELECTEDSPEC_DISPLAYTYPE == "PUSHED_OUT_CHECKED" ) then
SELECTEDSPEC_OFFSETX = 5;
else
SELECTEDSPEC_OFFSETX = 0;
end


-- PlayerTalentFrame

function PlayerTalentFrame_Toggle(pet, suggestedTalentGroup)
local hidden;
local talentTabSelected = PanelTemplates_GetSelectedTab(PlayerTalentFrame) ~= GLYPH_TALENT_TAB;
if ( not PlayerTalentFrame:IsShown() ) then
ShowUIPanel(PlayerTalentFrame);
hidden = false;
else
local spec = selectedSpec and specs[selectedSpec];
if ( spec and talentTabSelected ) then
-- if a talent tab is selected then toggle the frame off
HideUIPanel(PlayerTalentFrame);
hidden = true;
else
hidden = false;
end
end
if ( not hidden ) then
-- open the spec with the requested talent group (or the current talent group if the selected
-- spec has one)
if ( selectedSpec ) then
local spec = specs[selectedSpec];
if ( spec.pet == pet ) then
suggestedTalentGroup = spec.talentGroup;
end
end
for _, index in ipairs(TALENT_SORT_ORDER) do
local spec = specs[index];
if ( spec.pet == pet and spec.talentGroup == suggestedTalentGroup ) then
PlayerSpecTab_OnClick(specTabs[index]);
if ( not talentTabSelected ) then
PlayerTalentTab_OnClick(_G["PlayerTalentFrameTab"..PlayerTalentTab_GetBestDefaultTab(index)]);
end
break;
end
end
end
end

function PlayerTalentFrame_Open(pet, talentGroup)
ShowUIPanel(PlayerTalentFrame);
-- open the spec with the requested talent group
for index, spec in next, specs do
if ( spec.pet == pet and spec.talentGroup == talentGroup ) then
PlayerSpecTab_OnClick(specTabs[index]);
break;
end
end
end

function PlayerTalentFrame_ToggleGlyphFrame(suggestedTalentGroup)
GlyphFrame_LoadUI();
if ( GlyphFrame ) then
local hidden;
if ( not PlayerTalentFrame:IsShown() ) then
entFrame);
hidden = false;
else
local spec = selectedSpec and specs[selectedSpec];
if ( spec and spec.hasGlyphs and
PanelTemplates_GetSelectedTab(PlayerTalentFrame) == GLYPH_TALENT_TAB ) then
-- if the glyph tab is selected then toggle the frame off
HideUIPanel(PlayerTalentFrame);
hidden = true;
else
hidden = false;
end
end
if ( not hidden ) then
-- open the spec with the requested talent group (or the current talent group if the selected
-- spec has one)
if ( selectedSpec ) then
local spec = specs[selectedSpec];
if ( spec.hasGlyphs ) then
suggestedTalentGroup = spec.talentGroup;
end
end
for _, index in ipairs(TALENT_SORT_ORDER) do
local spec = specs[index];
if ( spec.hasGlyphs and spec.talentGroup == suggestedTalentGroup ) then
PlayerSpecTab_OnClick(specTabs[index]);
PlayerTalentTab_OnClick(_G["PlayerTalentFrameTab"..GLYPH_TALENT_TAB]);
break;
end
end
end
end
end

function PlayerTalentFrame_OpenGlyphFrame(talentGroup)
GlyphFrame_LoadUI();
if ( GlyphFrame ) then
ShowUIPanel(PlayerTalentFrame);
-- open the spec with the requested talent group
for index, spec in next, specs do
if ( spec.hasGlyphs and spec.talentGroup == talentGroup ) then
PlayerSpecTab_OnClick(specTabs[index]);
PlayerTalentTab_OnClick(_G["PlayerTalentFrameTab"..GLYPH_TALENT_TAB]);
break;
end
end
end
end

function PlayerTalentFrame_ShowGlyphFrame()
GlyphFrame_LoadUI();
if ( GlyphFrame ) then
-- set the title text of the GlyphFrame
if ( selectedSpec and specs[selectedSpec].glyphName and GetNumTalentGroups() > 1 ) then
GlyphFrameTitleText:SetText(specs[selectedSpec].glyphName);
else
GlyphFrameTitleText:SetText(GLYPHS);
end
-- show/update the glyph frame
if ( GlyphFrame:IsShown() ) then
GlyphFrame_Update();
else
GlyphFrame:Show();
end
-- don't forget to hide the scroll button overlay or it may show up on top of the GlyphFrame!
UIFrameFlashStop(PlayerTalentFrameScrollButtonOverlay);
end
end

function PlayerTalentFrame_HideGlyphFrame()
if ( not GlyphFrame or not GlyphFrame:IsShown() ) then
return;
end

GlyphFrame_LoadUI();
if ( GlyphFrame ) then
GlyphFrame:Hide();
end
end


function PlayerTalentFrame_OnLoad(self)
self:RegisterEvent("ADDON_LOADED");
self:RegisterEvent("PREVIEW_TALENT_POINTS_CHANGED");
self:RegisterEvent("PREVIEW_PET_TALENT_POINTS_CHANGED");
self:RegisterEvent("UNIT_PORTRAIT_UPDATE");
self:RegisterEvent("UNIT_PET");
self:RegisterEvent("PLAYER_LEVEL_UP");
self:RegisterEvent("PLAYER_TALENT_UPDATE");
self:RegisterEvent("PET_TALENT_UPDATE");
self:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED");
self.unit = "player";
self.inspect = false;
self.pet = false;
self.talentGroup = 1;
self.updateFunction = PlayerTalentFrame_Update;

TalentFrame_Load(self);

-- setup talent buttons
local button;
for i = 1, MAX_NUM_TALENTS do
button = _G["PlayerTalentFrameTalent"..i];
if ( button ) then
button:SetScript("OnClick", PlayerTalentFrameTalent_OnClick);
button:SetScript("OnEvent", PlayerTalentFrameTalent_OnEvent);
button:SetScript("OnEnter", PlayerTalentFrameTalent_OnEnter);
end
end

-- setup tabs
PanelTemplates_SetNumTabs(self, MAX_TALENT_TABS + 1); -- add one for the GLYPH_TALENT_TAB

-- initialize active spec as a fail safe
local activeTalentGroup = GetActiveTalentGroup();
local numTalentGroups = GetNumTalentGroups();
PlayerTalentFrame_UpdateActiveSpec(activeTalentGroup, numTalentGroups);

-- setup active spec highlight
if ( ACTIVESPEC_DISPLAYTYPE == "BLUE" ) then
PlayerTalentFrameActiveSpecTabHighlight:SetDrawLayer("OVERLAY");
PlayerTalentFrameActiveSpecTabHighlight:SetBlendMode("ADD");
PlayerTalentFrameActiveSpecTabHighlight:SetTexture("Interface\Buttons\UI-Button-Outline");
elseif ( ACTIVESPEC_DISPLAYTYPE == "GOLD_INSIDE" ) then
PlayerTalentFrameActiveSpecTabHighlight:SetDrawLayer("OVERLAY"tR·‡êv                  ctiveSpecTabHighlight:SetBlendMode("ADD");
PlayerTalentFrameActiveSpecTabHighlight:SetTexture("Interface\Buttons\CheckButtonHilight");
elseif ( ACTIVESPEC_DISPLAYTYPE == "GOLD_BACKGROUND" ) then
PlayerTalentFrameActiveSpecTabHighlight:SetDrawLayer("BACKGROUND");
PlayerTalentFrameActiveSpecTabHighlight:SetWidth(74);
PlayerTalentFrameActiveSpecTabHighlight:SetHeight(86);
PlayerTalentFrameActiveSpecTabHighlight:SetTexture("Interface\SpellBook\SpellBook-SkillLineTab-Glow");
end
end

function PlayerTalentFrame_OnShow(self)
-- Stop buttons from flashing after skill up
SetButtonPulse(TalentMicroButton, 0, 1);

PlaySound("TalentScreenOpen");
UpdateMicroButtons();

if ( not selectedSpec ) then
-- if no spec was selected, try to select the active one
PlayerSpecTab_OnClick(activeSpec and specTabs[activeSpec] or specTabs[DEFAULT_TALENT_SPEC]);
else
PlayerTalentFrame_Refresh();
end

-- Set flag
if ( not GetCVarBool("talentFrameShown") ) then
SetCVar("talentFrameShown", 1);
UIFrameFlash(PlayerTalentFrameScrollButtonOverlay, 0.5, 0.5, 60);
end
end

function  PlayerTalentFrame_OnHide()
UpdateMicroButtons();
PlaySound("TalentScreenClose");
UIFrameFlashStop(PlayerTalentFrameScrollButtonOverlay);
-- clear caches
for _, info in next, talentSpecInfoCache do
wipe(info);
end
wipe(talentTabWidthCache);
end

function PlayerTalentFrame_OnEvent(self, event, ...)
if ( event == "PLAYER_TALENT_UPDATE" or event == "PET_TALENT_UPDATE" ) then
PlayerTalentFrame_Refresh();
elseif ( event == "PREVIEW_TALENT_POINTS_CHANGED" ) then
--local talentIndex, tabIndex, groupIndex, points = ...;
if ( selectedSpec and not specs[selectedSpec].pet ) then
PlayerTalentFrame_Refresh();
end
elseif ( event == "PREVIEW_PET_TALENT_POINTS_CHANGED" ) then
--local talentIndex, tabIndex, groupIndex, points = ...;
if ( selectedSpec and specs[selectedSpec].pet ) then
PlayerTalentFrame_Refresh();
end
elseif ( event == "UNIT_PORTRAIT_UPDATE" ) then
local unit = ...;
-- update the talent frame's portrait
if ( unit == PlayerTalentFramePortrait.unit ) then
SetPortraitTexture(PlayerTalentFramePortrait, unit);
end
-- update spec tabs' portraits
for _, frame in next, specTabs do
if ( frame.usingPortraitTexture ) then
local spec = specs[frame.specIndex];
if ( unit == spec.unit and spec.portraitUnit ) then
SetPortraitTexture(frame:GetNormalTexture(), unit);
end
end
end
elseif ( event == "UNIT_PET" ) then
local summoner = ...;
if ( summoner == "player" ) then
if ( selectedSpec and specs[selectedSpec].pet ) then
-- if the selected spec is a pet spec...
local numTalentGroups = GetNumTalentGroups(false, true);
if ( numTalentGroups == 0 ) then
--...and a pet spec is not available, select the default spec
PlayerSpecTab_OnClick(activeSpec and specTabs[activeSpec] or specTabs[DEFAULT_TALENT_SPEC]);
return;
end
end
PlayerTalentFrame_Refresh();
end
elseif ( event == "PLAYER_LEVEL_UP" ) then
if ( selectedSpec and not specs[selectedSpec].pet ) then
local level = ...;
PlayerTalentFrame_Update(level);
end
elseif ( event == "ACTIVE_TALENT_GROUP_CHANGED" ) then
MainMenuBar_ToPlayerArt(MainMenuBarArtFrame);
end
end

function PlayerTalentFrame_Refresh()
local selectedTab = PanelTemplates_GetSelectedTab(PlayerTalentFrame);
if ( selectedTab == GLYPH_TALENT_TAB ) then
PlayerTalentFrame_ShowGlyphFrame();
else
PlayerTalentFrame_HideGlyphFrame();
end
TalentFrame_Update(PlayerTalentFrame);
end

function PlayerTalentFrame_Update(playerLevel)
local activeTalentGroup, numTalentGroups = GetActiveTalentGroup(false, false), GetNumTalentGroups(false, false);
local activePetTalentGroup, numPetTalentGroups = GetActiveTalentGroup(false, true), GetNumTalentGroups(false, true);

-- update specs
if ( not PlayerTalentFrame_UpdateSpecs(activeTalentGroup, numTalentGroups, activePetTalentGroup, numPetTalentGroups) ) then
tR·‡êv                  s not selectable any more, discontinue updates
return;
end

-- update tabs
if ( not PlayerTalentFrame_UpdateTabs(playerLevel) ) then
-- the current spec is not selectable any more, discontinue updates
return;
end

-- set the frame portrait
SetPortraitTexture(PlayerTalentFramePortrait, PlayerTalentFrame.unit);

-- update active talent group stuff
PlayerTalentFrame_UpdateActiveSpec(activeTalentGroup, numTalentGroups);

-- update talent controls
PlayerTalentFrame_UpdateControls(activeTalentGroup, numTalentGroups);
end

function PlayerTalentFrame_UpdateActiveSpec(activeTalentGroup, numTalentGroups)
-- set the active spec
activeSpec = DEFAULT_TALENT_SPEC;
for index, spec in next, specs do
if ( not spec.pet and spec.talentGroup == activeTalentGroup ) then
activeSpec = index;
break;
end
end
-- make UI adjustments
local spec = selectedSpec and specs[selectedSpec];

local hasMultipleTalentGroups = numTalentGroups > 1;
if ( spec and hasMultipleTalentGroups ) then
PlayerTalentFrameTitleText:SetText(spec.name);
else
PlayerTalentFrameTitleText:SetText(TALENTS);
end

if ( selectedSpec == activeSpec and hasMultipleTalentGroups ) then
--PlayerTalentFrameActiveTalentGroupFrame:Show();
else
PlayerTalentFrameActiveTalentGroupFrame:Hide();
end
end


-- PlayerTalentFrameTalents

function PlayerTalentFrameTalent_OnClick(self, button)
if ( IsModifiedClick("CHATLINK") ) then
local link = GetTalentLink(PanelTemplates_GetSelectedTab(PlayerTalentFrame), self:GetID(),
PlayerTalentFrame.inspect, PlayerTalentFrame.pet, PlayerTalentFrame.talentGroup, GetCVarBool("previewTalents"));
if ( link ) then
ChatEdit_InsertLink(link);
end
elseif ( selectedSpec and (activeSpec == selectedSpec or specs[selectedSpec].pet) ) then
-- only allow functionality if an active spec is selected
if ( button == "LeftButton" ) then
if ( GetCVarBool("previewTalents") ) then
AddPreviewTalentPoints(PanelTemplates_GetSelectedTab(PlayerTalentFrame), self:GetID(), 1, PlayerTalentFrame.pet, PlayerTalentFrame.talentGroup);
else
LearnTalent(PanelTemplates_GetSelectedTab(PlayerTalentFrame), self:GetID(), PlayerTalentFrame.pet, PlayerTalentFrame.talentGroup);
end
elseif ( button == "RightButton" ) then
if ( GetCVarBool("previewTalents") ) then
AddPreviewTalentPoints(PanelTemplates_GetSelectedTab(PlayerTalentFrame), self:GetID(), -1, PlayerTalentFrame.pet, PlayerTalentFrame.talentGroup);
end
end
end
end

function PlayerTalentFrameTalent_OnEvent(self, event, ...)
if ( GameTooltip:IsOwned(self) ) then
GameTooltip:SetTalent(PanelTemplates_GetSelectedTab(PlayerTalentFrame), self:GetID(),
PlayerTalentFrame.inspect, PlayerTalentFrame.pet, PlayerTalentFrame.talentGroup, GetCVarBool("previewTalents"));
end
end

function PlayerTalentFrameTalent_OnEnter(self)
GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
GameTooltip:SetTalent(PanelTemplates_GetSelectedTab(PlayerTalentFrame), self:GetID(),
PlayerTalentFrame.inspect, PlayerTalentFrame.pet, PlayerTalentFrame.talentGroup, GetCVarBool("previewTalents"));

local canLearn = nil;
local wrapRest = false;
local l = GameTooltip:NumLines();
if (_G["GameTooltipTextLeft"..l]:GetText() == "Click to learn") then
canLearn = true;
wrapRest = true;
l = l - 1;
end
local tmp = {};
local r = true;
local i = 1;
for c=1, l do
r = true;
local n = {};
local left = _G["GameTooltipTextLeft"..c];
local right = _G["GameTooltipTextRight"..c];
if ( left ) then
n.w = true;
n.r1, n.g1, n.b1 = left:GetTextColor();
local t = left:GetText();
if ( strsub(t, 1, 8) == "Requires" ) then
n.w = wrapRest;
if ( strsub(t, -7) == "Talents" ) then
local d = tonumber(strmatch(t, "%d+")) / 5;
t = gsub(t, "%d+", d);
wrapRest = true;
if ( d <= PlayerTalentFrame.pointsSpent + PlayerTalentFrame.previewPointsSpent ) then
n.r1 = 1.0; n.g1 = 1.0; n.b1 = 1.0;
r = false;
if ( canLeartR·‡êv                  canLearn = true;
end
end
elseif ( not wrapRest ) then
canLearn = false;
end
end
n.t1 = t;
end
if ( right ) then
n.r2, n.g2, n.b2 = right:GetTextColor();
n.t2 = right:GetText();
end
if ( r ) then
tmp[i] = n;
i = i + 1;
end
end
i = nil;
GameTooltip:ClearLines();
for i=1, #tmp do
if ( tmp[i].t1 and tmp[i].t2 ) then
GameTooltip:AddDoubleLine(tmp[i].t1, tmp[i].t2, tmp[i].r1, tmp[i].g1, tmp[i].b1, tmp[i].r2, tmp[i].g2, tmp[i].b2);
elseif ( tmp[i].t1 ) then
GameTooltip:AddLine(tmp[i].t1, tmp[i].r1, tmp[i].g1, tmp[i].b1, tmp[i].w);
elseif ( tmp[i].t2 ) then
GameTooltip:AddDoubleLine("", tmp[i].t2, 0, 0, 0, tmp[i].r2, tmp[i].g2, tmp[i].b2);
end
end
if ( canLearn ) then
GameTooltip:AddLine("Click to learn", 0, 1, 0, true);
end
GameTooltip:Show();
end


-- Controls

function PlayerTalentFrame_UpdateControls(activeTalentGroup, numTalentGroups)
local spec = selectedSpec and specs[selectedSpec];

local isActiveSpec = selectedSpec == activeSpec;

-- show the multi-spec status frame if this is not a pet spec or we have more than one talent group
local showStatusFrame = not spec.pet and numTalentGroups > 1;
-- show the activate button if we were going to show the status frame but this is not the active spec
local showActivateButton = showStatusFrame and not isActiveSpec;
if ( showActivateButton ) then
PlayerTalentFrameActivateButton:Show();
PlayerTalentFrameStatusFrame:Hide();
else
PlayerTalentFrameActivateButton:Hide();
if ( showStatusFrame ) then
PlayerTalentFrameStatusFrame:Show();
else
PlayerTalentFrameStatusFrame:Hide();
end
end

local preview = GetCVarBool("previewTalents");

-- enable the control bar if this is the active spec, preview is enabled, and preview points were spent
local talentPoints = GetUnspentTalentPoints(false, spec.pet, spec.talentGroup);
if ( (spec.pet or isActiveSpec) and talentPoints > 0 and preview ) then
PlayerTalentFramePreviewBar:Show();
-- enable accept/cancel buttons if preview talent points were spent
if ( GetGroupPreviewTalentPointsSpent(spec.pet, spec.talentGroup) > 0 ) then
PlayerTalentFrameLearnButton:Enable();
PlayerTalentFrameResetButton:Enable();
else
PlayerTalentFrameLearnButton:Disable();
PlayerTalentFrameResetButton:Disable();
end
-- squish all frames to make room for this bar
PlayerTalentFramePointsBar:SetPoint("BOTTOM", PlayerTalentFramePreviewBar, "TOP", 0, -4);
else
PlayerTalentFramePreviewBar:Hide();
-- unsquish frames since the bar is now hidden
PlayerTalentFramePointsBar:SetPoint("BOTTOM", PlayerTalentFrame, "BOTTOM", 0, 81);
end
end

function PlayerTalentFrameActivateButton_OnLoad(self)
self:SetWidth(self:GetTextWidth() + 40);
end

function PlayerTalentFrameActivateButton_OnClick(self)
if ( selectedSpec ) then
local talentGroup = specs[selectedSpec].talentGroup;
if ( talentGroup ) then
SetActiveTalentGroup(talentGroup);
end
end
end

function PlayerTalentFrameActivateButton_OnShow(self)
self:RegisterEvent("CURRENT_SPELL_CAST_CHANGED");
PlayerTalentFrameActivateButton_Update();
end

function PlayerTalentFrameActivateButton_OnHide(self)
self:UnregisterEvent("CURRENT_SPELL_CAST_CHANGED");
end

function PlayerTalentFrameActivateButton_OnEvent(self, event, ...)
PlayerTalentFrameActivateButton_Update();
end

function PlayerTalentFrameActivateButton_Update()
local spec = selectedSpec and specs[selectedSpec];
if ( spec and PlayerTalentFrameActivateButton:IsShown() ) then
-- if the activation spell is being cast currently, disable the activate button
if ( IsCurrentSpell(TALENT_ACTIVATION_SPELLS[spec.talentGroup]) ) then
PlayerTalentFrameActivateButton:Disable();
else
PlayerTalentFrameActivateButton:Enable();
end
end
end

function PlayerTalentFrameResetButton_OnEnter(self)
GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
GameTooltip:SetText(TALENT_TOOLTIP_RESETTALENTGROUP);
end

ftR·‡êv                  eResetButton_OnClick(self)
ResetGroupPreviewTalentPoints(PlayerTalentFrame.pet, PlayerTalentFrame.talentGroup);
end

function PlayerTalentFrameLearnButton_OnEnter(self)
GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
GameTooltip:SetText(TALENT_TOOLTIP_LEARNTALENTGROUP);
end

function PlayerTalentFrameLearnButton_OnClick(self)
StaticPopup_Show("CONFIRM_LEARN_PREVIEW_TALENTS");
end


-- PlayerTalentFrameDownArrow

function PlayerTalentFrameDownArrow_OnClick(self, button)
local parent = self:GetParent();
parent:SetValue(parent:GetValue() + (parent:GetHeight() / 2));
PlaySound("UChatScrollButton");
UIFrameFlashStop(PlayerTalentFrameScrollButtonOverlay);
end


-- PlayerTalentFrameTab

function PlayerTalentFrame_UpdateTabs(playerLevel)
local totalTabWidth = 0;

local firstShownTab;

-- setup talent tabs
local maxPointsSpent = 0;
local selectedTab = PanelTemplates_GetSelectedTab(PlayerTalentFrame);
local numTabs = GetNumTalentTabs(PlayerTalentFrame.inspect, PlayerTalentFrame.pet);
local tab;
for i = 1, MAX_TALENT_TABS do
-- clear cached widths
talentTabWidthCache[i] = 0;
tab = _G["PlayerTalentFrameTab"..i];
if ( tab ) then
if ( i <= numTabs ) then
local name, icon, pointsSpent, background, previewPointsSpent = GetTalentTabInfo(i, PlayerTalentFrame.inspect, PlayerTalentFrame.pet, PlayerTalentFrame.talentGroup);
if ( i == selectedTab ) then
-- If tab is the selected tab set the points spent info
local displayPointsSpent = pointsSpent + previewPointsSpent;
PlayerTalentFrameSpentPointsText:SetFormattedText(MASTERY_POINTS_SPENT, name, HIGHLIGHT_FONT_COLOR_CODE..displayPointsSpent..FONT_COLOR_CODE_CLOSE);
PlayerTalentFrame.pointsSpent = pointsSpent;
PlayerTalentFrame.previewPointsSpent = previewPointsSpent;
end
tab:SetText(name);
PanelTemplates_TabResize(tab, 0);
-- record the text width to see if we need to display a tooltip
tab.textWidth = tab:GetTextWidth();
-- record the tab widths for resizing later
talentTabWidthCache[i] = PanelTemplates_GetTabWidth(tab);
totalTabWidth = totalTabWidth + talentTabWidthCache[i];
tab:Show();
firstShownTab = firstShownTab or tab;
else
tab:Hide();
tab.textWidth = 0;
end
end
end

local spec = specs[selectedSpec];

-- setup glyph tabs, right now there is only one
playerLevel = playerLevel or UnitLevel("player");
local meetsGlyphLevel = playerLevel >= SHOW_INSCRIPTION_LEVEL;
tab = _G["PlayerTalentFrameTab"..GLYPH_TALENT_TAB];
if ( meetsGlyphLevel and spec.hasGlyphs ) then
tab:Show();
firstShownTab = firstShownTab or tab;
PanelTemplates_TabResize(tab, 0);
talentTabWidthCache[GLYPH_TALENT_TAB] = PanelTemplates_GetTabWidth(tab);
totalTabWidth = totalTabWidth + talentTabWidthCache[GLYPH_TALENT_TAB];
else
tab:Hide();
talentTabWidthCache[GLYPH_TALENT_TAB] = 0;
end
local numGlyphTabs = 1;

-- select the first shown tab if the selected tab does not exist for the selected spec
tab = _G["PlayerTalentFrameTab"..selectedTab];
if ( tab and not tab:IsShown() ) then
if ( firstShownTab ) then
PlayerTalentFrameTab_OnClick(firstShownTab);
end
return false;
end

-- readjust tab sizes to fit
local maxTotalTabWidth = PlayerTalentFrame:GetWidth();
while ( totalTabWidth >= maxTotalTabWidth ) do
-- progressively shave 10 pixels off of the largest tab until they all fit within the max width
local largestTab = 1;
for i = 2, #talentTabWidthCache do
if ( talentTabWidthCache[largestTab] < talentTabWidthCache[i] ) then
largestTab = i;
end
end
-- shave the width
talentTabWidthCache[largestTab] = talentTabWidthCache[largestTab] - 10;
-- apply the shaved width
tab = _G["PlayerTalentFrameTab"..largestTab];
PanelTemplates_TabResize(tab, 0, talentTabWidthCache[largestTab]);
-- now update the total width
totalTabWidth = totalTabWidth - 10;
end

-- update the tabs
PanelTemplates_SetNumTabs(PlayerTalentFrame, numTabs + numtR·‡êv                  ates_UpdateTabs(PlayerTalentFrame);

return true;
end

function PlayerTalentFrameTab_OnLoad(self)
self:SetFrameLevel(self:GetFrameLevel() + 2);
end

function PlayerTalentFrameTab_OnClick(self)
local id = self:GetID();
PanelTemplates_SetTab(PlayerTalentFrame, id);
PlayerTalentFrame_Refresh();
PlaySound("igCharacterInfoTab");
end

function PlayerTalentFrameTab_OnEnter(self)
if ( self.textWidth and self.textWidth > self:GetFontString():GetWidth() ) then --We're ellipsizing.
GameTooltip:SetOwner(self, "ANCHOR_BOTTOM");
GameTooltip:SetText(self:GetText());
end
end


-- PlayerTalentTab

function PlayerTalentTab_OnLoad(self)
PlayerTalentFrameTab_OnLoad(self);

self:RegisterEvent("PLAYER_LEVEL_UP");
end

function PlayerTalentTab_OnClick(self)
PlayerTalentFrameTab_OnClick(self);
for i=1, MAX_TALENT_TABS do
SetButtonPulse(_G["PlayerTalentFrameTab"..i], 0, 0);
end
end

function PlayerTalentTab_OnEvent(self, event, ...)
if ( UnitLevel("player") == (SHOW_TALENT_LEVEL - 1) and PanelTemplates_GetSelectedTab(PlayerTalentFrame) ~= self:GetID() ) then
SetButtonPulse(self, 60, 0.75);
end
end

function PlayerTalentTab_GetBestDefaultTab(specIndex)
if ( not specIndex ) then
return DEFAULT_TALENT_TAB;
end

local spec = specs[specIndex];
if ( not spec ) then
return DEFAULT_TALENT_TAB;
end

local specInfoCache = talentSpecInfoCache[specIndex];
TalentFrame_UpdateSpecInfoCache(specInfoCache, false, spec.pet, spec.talentGroup);
if ( specInfoCache.primaryTabIndex > 0 ) then
return talentSpecInfoCache[specIndex].primaryTabIndex;
else
return DEFAULT_TALENT_TAB;
end
end


-- PlayerGlyphTab

function PlayerGlyphTab_OnLoad(self)
PlayerTalentFrameTab_OnLoad(self);

self:RegisterEvent("PLAYER_LEVEL_UP");
GLYPH_TALENT_TAB = self:GetID();
-- we can record the text width for the glyph tab now since it never changes
self.textWidth = self:GetTextWidth();
end

function PlayerGlyphTab_OnClick(self)
PlayerTalentFrameTab_OnClick(self);
SetButtonPulse(_G["PlayerTalentFrameTab"..GLYPH_TALENT_TAB], 0, 0);
end

function PlayerGlyphTab_OnEvent(self, event, ...)
if ( UnitLevel("player") == (SHOW_INSCRIPTION_LEVEL - 1) and PanelTemplates_GetSelectedTab(PlayerTalentFrame) ~= self:GetID() ) then
SetButtonPulse(self, 60, 0.75);
end
end


-- Specs

-- PlayerTalentFrame_UpdateSpecs is a helper function for PlayerTalentFrame_Update.
-- Returns true on a successful update, false otherwise. An update may fail if the currently
-- selected tab is no longer selectable. In this case, the first selectable tab will be selected.
function PlayerTalentFrame_UpdateSpecs(activeTalentGroup, numTalentGroups, activePetTalentGroup, numPetTalentGroups)
-- set the active spec highlight to be hidden initially, if a spec is the active one then it will
-- be shown in PlayerSpecTab_Update
PlayerTalentFrameActiveSpecTabHighlight:Hide();

-- update each of the spec tabs
local firstShownTab, lastShownTab;
local numShown = 0;
local offsetX = 0;
for i = 1, numSpecTabs do
local frame = _G["PlayerSpecTab"..i];
local specIndex = frame.specIndex;
local spec = specs[specIndex];
if ( PlayerSpecTab_Update(frame, activeTalentGroup, numTalentGroups, activePetTalentGroup, numPetTalentGroups) ) then
firstShownTab = firstShownTab or frame;
numShown = numShown + 1;
frame:ClearAllPoints();
-- set an offsetX fudge if we're the selected tab, otherwise use the previous offsetX
offsetX = specIndex == selectedSpec and SELECTEDSPEC_OFFSETX or offsetX;
if ( numShown == 1 ) then
--...start the first tab off at a base location
frame:SetPoint("TOPLEFT", frame:GetParent(), "TOPRIGHT", -32 + offsetX, -65);
-- we'll need to negate the offsetX after the first tab so all subsequent tabs offset
-- to their default positions
offsetX = -offsetX;
else
--...offset subsequent tabs from the previous one
if ( spec.pet ~= specs[lastShownTab.specIndex].pet ) then
frame:SetPoint("TOtR·‡êv                  OTTOMLEFT", 0 + offsetX, -39);
else
frame:SetPoint("TOPLEFT", lastShownTab, "BOTTOMLEFT", 0 + offsetX, -22);
end
end
lastShownTab = frame;
else
-- if the selected tab is not shown then clear out the selected spec
if ( specIndex == selectedSpec ) then
selectedSpec = nil;
end
end
end

if ( not selectedSpec ) then
if ( firstShownTab ) then
PlayerSpecTab_OnClick(firstShownTab);
end
return false;
end

if ( numShown == 1 and lastShownTab ) then
-- if we're only showing one tab, we might as well hide it since it doesn't need to be there
lastShownTab:Hide();
end

return true;
end

function PlayerSpecTab_Update(self, ...)
local activeTalentGroup, numTalentGroups, activePetTalentGroup, numPetTalentGroups = ...;

local specIndex = self.specIndex;
local spec = specs[specIndex];

-- determine whether or not we need to hide the tab
local canShow;
if ( spec.pet ) then
canShow = spec.talentGroup <= numPetTalentGroups;
else
canShow = spec.talentGroup <= numTalentGroups;
end
if ( not canShow ) then
self:Hide();
return false;
end

local isSelectedSpec = specIndex == selectedSpec;
local isActiveSpec = not spec.pet and spec.talentGroup == activeTalentGroup;
local normalTexture = self:GetNormalTexture();

-- set the background based on whether or not we're selected
if ( isSelectedSpec and (SELECTEDSPEC_DISPLAYTYPE == "PUSHED_OUT" or SELECTEDSPEC_DISPLAYTYPE == "PUSHED_OUT_CHECKED") ) then
local name = self:GetName();
local backgroundTexture = _G[name.."Background"];
backgroundTexture:SetTexture("Interface\TalentFrame\UI-TalentFrame-SpecTab");
backgroundTexture:SetPoint("TOPLEFT", self, "TOPLEFT", -13, 11);
if ( SELECTEDSPEC_DISPLAYTYPE == "PUSHED_OUT_CHECKED" ) then
self:GetCheckedTexture():Show();
else
self:GetCheckedTexture():Hide();
end
else
local name = self:GetName();
local backgroundTexture = _G[name.."Background"];
backgroundTexture:SetTexture("Interface\SpellBook\SpellBook-SkillLineTab");
backgroundTexture:SetPoint("TOPLEFT", self, "TOPLEFT", -3, 11);
end

-- update the active spec info
local hasMultipleTalentGroups = numTalentGroups > 1;
if ( isActiveSpec and hasMultipleTalentGroups ) then
PlayerTalentFrameActiveSpecTabHighlight:ClearAllPoints();
if ( ACTIVESPEC_DISPLAYTYPE == "BLUE" ) then
PlayerTalentFrameActiveSpecTabHighlight:SetParent(self);
PlayerTalentFrameActiveSpecTabHighlight:SetPoint("TOPLEFT", self, "TOPLEFT", -13, 14);
PlayerTalentFrameActiveSpecTabHighlight:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", 15, -14);
PlayerTalentFrameActiveSpecTabHighlight:Show();
elseif ( ACTIVESPEC_DISPLAYTYPE == "GOLD_INSIDE" ) then
PlayerTalentFrameActiveSpecTabHighlight:SetParent(self);
PlayerTalentFrameActiveSpecTabHighlight:SetAllPoints(self);
PlayerTalentFrameActiveSpecTabHighlight:Show();
elseif ( ACTIVESPEC_DISPLAYTYPE == "GOLD_BACKGROUND" ) then
PlayerTalentFrameActiveSpecTabHighlight:SetParent(self);
PlayerTalentFrameActiveSpecTabHighlight:SetPoint("TOPLEFT", self, "TOPLEFT", -3, 20);
PlayerTalentFrameActiveSpecTabHighlight:Show();
else
PlayerTalentFrameActiveSpecTabHighlight:Hide();
end
end

--[[
if ( not spec.pet ) then
SetDesaturation(normalTexture, not isActiveSpec);
end
--]]

-- update the spec info cache
TalentFrame_UpdateSpecInfoCache(talentSpecInfoCache[specIndex], false, spec.pet, spec.talentGroup);

-- update spec tab icon
self.usingPortraitTexture = false;
if ( hasMultipleTalentGroups ) then
local specInfoCache = talentSpecInfoCache[specIndex];
local primaryTabIndex = specInfoCache.primaryTabIndex;
if ( primaryTabIndex > 0 ) then
-- the spec had a primary tab, set the icon to that tab's icon
normalTexture:SetTexture(specInfoCache[primaryTabIndex].icon);
else
if ( specInfoCache.numTabs > 1 and specInfoCache.totalPointsSpent > 0 ) then
-- the spec is only considered a hybrid if the spec had more than ontR·‡êv                  -- one point was spent in one of the tabs
normalTexture:SetTexture(TALENT_HYBRID_ICON);
else
if ( spec.defaultSpecTexture ) then
-- the spec is probably untalented...set to the default spec texture if we have one
normalTexture:SetTexture(spec.defaultSpecTexture);
elseif ( spec.portraitUnit ) then
-- last check...if there is no default spec texture, try the portrait unit
SetPortraitTexture(normalTexture, spec.portraitUnit);
self.usingPortraitTexture = true;
end
end
end
else
if ( spec.portraitUnit ) then
-- set to the portrait texture if we only have one talent group
SetPortraitTexture(normalTexture, spec.portraitUnit);
self.usingPortraitTexture = true;
end
end
--[[
-- update overlay icon
local name = self:GetName();
local overlayIcon = _G[name.."OverlayIcon"];
if ( overlayIcon ) then
if ( hasMultipleTalentGroups ) then
overlayIcon:Show();
else
overlayIcon:Hide();
end
end
--]]
self:Show();
return true;
end

function PlayerSpecTab_Load(self, specIndex)
self.specIndex = specIndex;
specTabs[specIndex] = self;
numSpecTabs = numSpecTabs + 1;

-- set the spec's portrait
local spec = specs[self.specIndex];
if ( spec.portraitUnit ) then
SetPortraitTexture(self:GetNormalTexture(), spec.portraitUnit);
self.usingPortraitTexture = true;
else
self.usingPortraitTexture = false;
end

-- set the checked texture
if ( SELECTEDSPEC_DISPLAYTYPE == "BLUE" ) then
local checkedTexture = self:GetCheckedTexture();
checkedTexture:SetTexture("Interface\Buttons\UI-Button-Outline");
checkedTexture:SetWidth(64);
checkedTexture:SetHeight(64);
checkedTexture:ClearAllPoints();
checkedTexture:SetPoint("CENTER", self, "CENTER", 0, 0);
elseif ( SELECTEDSPEC_DISPLAYTYPE == "GOLD_INSIDE" ) then
local checkedTexture = self:GetCheckedTexture();
checkedTexture:SetTexture("Interface\Buttons\CheckButtonHilight");
end

local activeTalentGroup, numTalentGroups = GetActiveTalentGroup(false, false), GetNumTalentGroups(false, false);
local activePetTalentGroup, numPetTalentGroups = GetActiveTalentGroup(false, true), GetNumTalentGroups(false, true);
PlayerSpecTab_Update(self, activeTalentGroup, numTalentGroups, activePetTalentGroup, numPetTalentGroups);
end

function PlayerSpecTab_OnClick(self)
-- set all specs as unchecked initially
for _, frame in next, specTabs do
frame:SetChecked(nil);
end

-- check ourselves (before we wreck ourselves)
self:SetChecked(1);

-- update the selected to this spec
local specIndex = self.specIndex;
selectedSpec = specIndex;

-- set data on the talent frame
local spec = specs[specIndex];
PlayerTalentFrame.pet = spec.pet;
PlayerTalentFrame.unit = spec.unit;
PlayerTalentFrame.talentGroup = spec.talentGroup;

-- select a tab if one is not already selected
if ( not PanelTemplates_GetSelectedTab(PlayerTalentFrame) ) then
PanelTemplates_SetTab(PlayerTalentFrame, PlayerTalentTab_GetBestDefaultTab(specIndex));
end

-- update the talent frame
PlayerTalentFrame_Refresh();
end

function PlayerSpecTab_OnEnter(self)
local specIndex = self.specIndex;
local spec = specs[specIndex];
if ( spec.tooltip ) then
GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
-- name
if ( GetNumTalentGroups(false, true) <= 1 and GetNumTalentGroups(false, false) <= 1 ) then
-- set the tooltip to be the unit's name
GameTooltip:AddLine(UnitName(spec.unit), NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b);
else
-- set the tooltip to be the spec name
GameTooltip:AddLine(spec.tooltip);
if ( self.specIndex == activeSpec ) then
-- add text to indicate that this spec is active
GameTooltip:AddLine(TALENT_ACTIVE_SPEC_STATUS, GREEN_FONT_COLOR.r, GREEN_FONT_COLOR.g, GREEN_FONT_COLOR.b);
end
end
-- points spent
local pointsColor;
for index, info in ipairs(talentSpecInfoCache[specIndex]) do
if ( info.name ) then
-- assign a special color to a tab thatR·‡êv                  ts spent threshold
if ( talentSpecInfoCache[specIndex].primaryTabIndex == index ) then
pointsColor = GREEN_FONT_COLOR;
else
pointsColor = HIGHLIGHT_FONT_COLOR;
end
GameTooltip:AddDoubleLine(
info.name,
info.pointsSpent,
HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b,
pointsColor.r, pointsColor.g, pointsColor.b,
1
);
end
end
GameTooltip:Show();
end
end

itUnit);
self.usin
Title: Re: [HELP] Remove Talent Point Requirement
Post by: Grymskvll on March 06, 2016, 09:47:06 am
Nice! I actually started to work on same thing, but I got stuck and decided to try the other method again. Somehow I got things to work right as far as I can tell... except that you can't require more than 9+9 points spent per tier at most, or more than 9 points difference between player and pet requirements. I guess that's fine for most purposes anyway. Also I have no idea if this breaks anything, but I don't think it should.

I edited my other post detailing the updated Wow.exe tooltip fix method.

Edit:
Quote from: "Vortalex"
Nope I was wrong. I know what it is. Its's the Preview Talent Changes feature. It still thinks you need 5 talent points. So lua edits have to be made to that too.

Damn, just as I thought I was done. At a glance it'll require changing PlayerTalentFrameTalent_OnClick in Blizzard_TalentUI.lua to check for our modified requirements before adding (or removing) points, because I don't see where AddPreviewTalentPoints can be changed and it isn't affected by either PLAYER_TALENTS_PER_TIER in TalentFrameBase.lua or the modified tooltip values in Wow.exe. Apparently it's a global function, whatever that is.

Edit 2:
I think I've fixed talent previews and tooltips. I've edited it into my second post on page 2. As far as I know, there are no bugs left and it seems to be stable. Again, I'm not very good at this so apologies if it's broken or if I made an error in my posts. I've had enough assembly for a lifetime, so report bugs at your own risk! Grrrrrr
Title: Re: [HELP] Remove Talent Point Requirement
Post by: Lawes on November 01, 2016, 07:03:33 pm
stoneharry,

ur Blizzard_TalentUI.lua dont works
Title: Re: [HELP] Remove Talent Point Requirement
Post by: noc on January 20, 2017, 08:28:06 am
in function TalentFrame_Update(TalentFrame)
 have you change
Code: [Select]
if ( ((tier - 1) * (TalentFrame.pet and PET_TALENTS_PER_TIER or PLAYER_TALENTS_PER_TIER) <= tabPointsSpent) ) then
tierUnlocked = 1;
else
tierUnlocked = nil;
end

to
 
Code: [Select]
--if ( ((tier - 1) * (TalentFrame.pet and PET_TALENTS_PER_TIER or PLAYER_TALENTS_PER_TIER) <= tabPointsSpent) ) then
tierUnlocked = 1;
--else
--tierUnlocked = nil;
--end
Title: Re: [HELP] Remove Talent Point Requirement
Post by: mrxxx on July 06, 2017, 11:23:12 pm
Sorry for bumping this but how is one supposed to remove / reduce tier talent point requirement for talent preview option? I can't seem to find any related code in BlizzardTalentUI.lua or TalentFrameBase.lua, not sure about core but i think it only has the regular talent checks. Am i just being blind or is this something more complicated?
Title: Re: [HELP] Remove Talent Point Requirement
Post by: noc on December 02, 2017, 01:37:33 pm
Hello,

For this to work you need to replace in TalentFrameBase.lua
Quote
PLAYER_TALENTS_PER_TIER = 5;
par
Quote
PLAYER_TALENTS_PER_TIER = 0;
then in TalentFrame_Update(TalentFrame) :
Quote
if ( ((tier - 1) * (TalentFrame.pet and PET_TALENTS_PER_TIER or PLAYER_TALENTS_PER_TIER) <= tabPointsSpent) ) then
   tierUnlocked = 1;
else
   tierUnlocked = nil;
end
by    
Quote
-- if ( ((tier - 1) * (TalentFrame.pet and PET_TALENTS_PER_TIER or PLAYER_TALENTS_PER_TIER) <= tabPointsSpent) ) then
   tierUnlocked = 1;
-- else
--   tierUnlocked = nil;
-- end
in the server's Player.cpp replace    
Quote
// not have required min points spent in talent tree
      if (spentPoints < (talentInfo->Row * MAX_TALENT_RANK))
         return;
by
Quote
// not have required min points spent in talent tree
      // if (spentPoints < (talentInfo->Row * MAX_TALENT_RANK))
      //   return;

Hoping to have nothing forgotten.


Bonjour,

Pour que cela fonctionne vous devez remplacer dans TalentFrameBase.lua :
Quote
PLAYER_TALENTS_PER_TIER = 5;
par
Quote
PLAYER_TALENTS_PER_TIER = 0;
puis dans TalentFrame_Update(TalentFrame) :
Quote
if ( ((tier - 1) * (TalentFrame.pet and PET_TALENTS_PER_TIER or PLAYER_TALENTS_PER_TIER) <= tabPointsSpent) ) then
   tierUnlocked = 1;
else
   tierUnlocked = nil;
end
par    
Quote
-- if ( ((tier - 1) * (TalentFrame.pet and PET_TALENTS_PER_TIER or PLAYER_TALENTS_PER_TIER) <= tabPointsSpent) ) then
   tierUnlocked = 1;
-- else
--   tierUnlocked = nil;
-- end
dans le Player.cpp du serveur remplacer    
Quote
// not have required min points spent in talent tree
      if (spentPoints < (talentInfo->Row * MAX_TALENT_RANK))
         return;
par
Quote
// not have required min points spent in talent tree
      // if (spentPoints < (talentInfo->Row * MAX_TALENT_RANK))
      //   return;

En espérant ne rien avoir oublié.