Thread Tools Display Modes
08-26-12, 06:19 AM   #1
tinix
A Murloc Raider
Join Date: Mar 2012
Posts: 4
Doing a TradeSkill after SpellCast

Hello everybody,

I am trying to make an addon which will automatically make craftable reagents (eg. inks) and then it will create the final product. The problem is I can not figure out how to make the addon wait until spellcast of reagents finishes. I have tried calling DoTradeSkill from UNIT_SPELLCAST_SUCCEEDED handler but it gives an error "attempt to call protected function which may require interaction" and i have also tried setting up a loop:
Lua Code:
  1. while (not enable) do end
in which enable is to true by UNIT_SPELLCAST_SUCCEEDED handler but this locks up WoW. I would be grateful if anybody could help me with this.
  Reply With Quote
08-26-12, 06:27 AM   #2
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
If you want help with your code, SHOW YOUR CODE! We can't help you if you won't show us what you need help with.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
08-26-12, 06:35 AM   #3
tinix
A Murloc Raider
Join Date: Mar 2012
Posts: 4
Lua Code:
  1. local repeat_count, current, enable;
  2. function FinishCreating(recipe_name)
  3.     local recipe;
  4.     recipe = GetFirstTradeSkill();
  5.     local rec_n = GetTradeSkillInfo(recipe);
  6.     while (rec_n ~= recipe_name) do
  7.         recipe = recipe + 1;
  8.         rec_n = GetTradeSkillInfo(recipe);
  9.     end
  10.     DoTradeSkill(recipe);
  11.     recipe_name=nil;
  12. end
  13.  
  14. function EventHandler(self, event, ...)
  15.     if (event == "TRADE_SKILL_SHOW") then
  16.         if(GetTradeSkillLine() ~= "Inscription" or IsTradeSkillLinked()) then
  17.             return
  18.         end
  19.         btn:SetPoint("TOPLEFT",TradeSkillFrame,"TOPRIGHT",-100,-3);
  20.         btn:Show();
  21.     elseif (event == "TRADE_SKILL_CLOSE") then
  22.         if(btn:IsVisible()) then
  23.             btn:ClearAllPoints();
  24.             btn:Hide();
  25.         end
  26.     elseif (event == "TRADE_SKILL_UPDATE") then
  27.         if(IsTradeSkillLinked() and btn:IsVisible()) then
  28.             btn:ClearAllPoints();
  29.             btn:Hide();
  30.         end
  31.     elseif (event == "UNIT_SPELLCAST_SUCCEEDED") then
  32.         local arg1 = ...;
  33.         if(arg1 =="player") then
  34.             if(current ~= nil) then
  35.                 if (current >= repeat_count) then
  36.                     enable = true;
  37.                 else
  38.                     current = current + 1;
  39.                 end
  40.             end
  41.         end
  42.     end
  43. end
  44.  
  45. function OnClick(self)
  46.     current = 1;
  47.     local recipe = GetTradeSkillSelectionIndex();
  48.     local recipe_name, skill = GetTradeSkillInfo(recipe);
  49.     if(recipe == 0 or skill== "header") then
  50.         print("Header Selected");
  51.         return
  52.     end
  53.     local cat = recipe -1;
  54.     local category, c_tmp = GetTradeSkillInfo(cat);
  55.     while (c_tmp ~= "header") do
  56.         cat = cat - 1;
  57.         category, c_tmp = GetTradeSkillInfo(cat);
  58.     end
  59.     local reag_count = GetTradeSkillNumReagents(recipe);
  60.     local ink_name = nil;
  61.     local ink_count;
  62.     local player_ink;
  63.     for i = 1, reag_count, 1 do
  64.         local reagentName, reagentTexture, reagentCount, playerReagentCount = GetTradeSkillReagentInfo(recipe, i);
  65.         if(string.find(reagentName,"Ink") == nil and playerReagentCount == 0) then
  66.             print("Missing reagent: ".. reagentName);
  67.             return
  68.         elseif(string.find(reagentName,"Ink") ~= nil) then
  69.             ink_name = reagentName;
  70.             ink_count = reagentCount;
  71.             player_ink = playerReagentCount;
  72.             break
  73.         end
  74.     end
  75.     if (ink_name == nil or player_ink >= ink_count) then
  76.         DoTradeSkill(recipe);
  77.         return
  78.     end
  79.     ExpandTradeSkillSubClass(0);
  80.     local cat_list = { strsplit(",", BuildListString(GetTradeSkillSubClasses())) };
  81.     for i, val in ipairs(cat_list) do
  82.         if(val ~= " Parts") then
  83.             CollapseTradeSkillSubClass(i);
  84.         else
  85.             break
  86.         end
  87.     end
  88.     cat = GetFirstTradeSkill();
  89.     local tr_name;
  90.     tr_name, c_tmp = GetTradeSkillInfo(cat);
  91.     while (tr_name ~= ink_name and c_tmp ~= "header") do
  92.         cat = cat+1;
  93.         tr_name, c_tmp = GetTradeSkillInfo(cat);
  94.     end
  95.     if(c_tmp == "header") then
  96.         print("Ink not learned: " .. ink_name);
  97.         return
  98.     end
  99.     local reagentName, w2, reagentCount, playerReagentCount = GetTradeSkillReagentInfo(cat, 1);
  100.     if (playerReagentCount*(ink_count-player_ink) >= reagentCount*(ink_count-player_ink)) then
  101.         repeat_count = ink_count-player_ink;
  102.         DoTradeSkill(cat,repeat_count);
  103.     else
  104.         print("Insufficient reagent: " .. reagentName);
  105.         return
  106.     end
  107.     CollapseTradeSkillSubClass(0);
  108.     for i, val in ipairs(cat_list) do
  109.         if(val == category) then
  110.             ExpandTradeSkillSubClass(i);
  111.             break
  112.         end
  113.     end
  114.     enable = false;
  115.     while(not enable) do end
  116.     FinishCreating(recipe_name);
  117.     current = nil;
  118. end
  119.  
  120. btn:Hide();
  121. btn:SetText("InkCraft");
  122. local fStr = btn:GetFontString();
  123. fStr:SetFont("Fonts\\FRIZQT__.TTF", 8);
  124. btn:SetFontString(fStr);
  125. btn:SetFrameStrata("HIGH");
  126. btn:RegisterEvent("TRADE_SKILL_SHOW");
  127. btn:RegisterEvent("TRADE_SKILL_CLOSE");
  128. btn:RegisterEvent("TRADE_SKILL_UPDATE");
  129. btn:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED");
  130. btn:SetScript("OnEvent", EventHandler);
  131. btn:SetScript("OnClick", OnClick);
  132. print("EasyCraft loaded!");

The problem is that I want to call FinishCreating after I finish doing Inks(after UNIT_SPELLCAST_SUCCEEDED fires for requested amount of inks). Code posted locks up client entierly and I cant think of any other solution of how to do it.

Last edited by tinix : 08-26-12 at 06:39 AM.
  Reply With Quote
08-26-12, 06:54 AM   #4
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Code:
    enable = false;
    while(not enable) do end
    FinishCreating(recipe_name);
    current = nil;
This is your problem. You set enable to false, and then start a loop that will continue to run forever until enable is non-nil/false. The only way to stop such a loop would be to set enable to some other value from inside the loop. The loop won't run in the background while other things happen -- it will just block all other things from happening.

Rather than using the enable variable at all, you should probably just change this part of your event handler:

Code:
    elseif (event == "UNIT_SPELLCAST_SUCCEEDED") then
        local arg1 = ...;
        if(arg1 =="player") then
            if(current ~= nil) then
                if (current >= repeat_count) then 
                    enable = true;
                else
                    current = current + 1;
                end
            end
        end
    end
to just do what you want to do:

Code:
    elseif (event == "UNIT_SPELLCAST_SUCCEEDED") then
        local arg1 = ...;
        if(arg1 =="player") then
                if (current >= repeat_count) then
                    current = 0;
                    FinishCreating(recipe_name);
                else
                    current = current + 1;
                end
        end
    end
This will require storing the recipe_name variable in a higher scope, and resetting it to nil after you're done using it inside your FinishCreating function.

You should probably also:

(1) Set current to 0 instead of nil; this will require fewer checks.

(2) Only check or increment current if the spell that finished casting is one you care about. As written, your code will increment the counter every time the player casts ANY spell, which is not what you want.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
08-26-12, 07:10 AM   #5
tinix
A Murloc Raider
Join Date: Mar 2012
Posts: 4
As i have said in first post, calling FinishCreating from
Lua Code:
  1. elseif (event == "UNIT_SPELLCAST_SUCCEEDED") then
  2.         local arg1 = ...;
  3.         if(arg1 =="player") then
  4.             if(current ~= nil) then
  5.                 if (current >= repeat_count) then
  6.                      current = nil;
  7.                      FinishCreating(recipe_name);
  8.                 else
  9.                     current = current + 1;
  10.                 end
  11.             end
  12.         end
  13.     end
causes WoW to throw lua warning :"Warning: AddOn InkCraft attempted to call a protected function (DoTradeSkill()) which may require interaction.", the recipe_name in that version of code was declared at top of file. As for the current thingie I set it to nil when code stops running so the addon doesnt incerement when i dont want it to increment. I set it to one at start of OnClick (as you can see) and at the end I nil it
EDIT: On the second thought, I should check the spell because player can interrupt it...

Last edited by tinix : 08-26-12 at 07:14 AM.
  Reply With Quote
08-26-12, 09:07 AM   #6
p3lim
A Pyroguard Emberseer
 
p3lim's Avatar
AddOn Author - Click to view addons
Join Date: Feb 2007
Posts: 1,710
The function DoTradeSkill seems to be protected, based on the error you get.
This basically means that it requires a hardware press to be used (OnClick script, keybound etc).

I have no idea what the conditions it might be happening under since I have only used this in an OnClick script myself.
  Reply With Quote
08-26-12, 12:48 PM   #7
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,327
I wrote this for personal use, but if you want to use it, feel free. It's a grid of buttons that allow you to quickly and easily mill herbs and make inks. It also hides itself for chars that don't have Inscription learned and clicking the title bar will expand and contract the button grid. The top row "Milling" buttons show how many pigments you have of each and how many times you can mill that level range of herbs from what you have along with a detailed tooltip of what herbs each pigment comes from. The two bottom rows, "Ink" buttons, show how many inks you have and how many you can create from pigments. I may eventually release it, but it still has some more work it needs done as it's not yet up to the quality I'd like in a released addon.

<< Download removed to conserve attachment space >>
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 04-19-13 at 03:28 PM.
  Reply With Quote
08-26-12, 01:41 PM   #8
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
If you want something for all professions, I like Panda.

But, yes, if you continue to create your own addon, you will need a hardware event for what you are trying to do.
__________________
"You'd be surprised how many people violate this simple principle every day of their lives and try to fit square pegs into round holes, ignoring the clear reality that Things Are As They Are." -Benjamin Hoff, The Tao of Pooh

  Reply With Quote
08-27-12, 01:25 AM   #9
tinix
A Murloc Raider
Join Date: Mar 2012
Posts: 4
Thanks for your help guys, I really appreciate it. I think I will rework that thing into "smart" button that will create the inks and on second click it will create the product.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Doing a TradeSkill after SpellCast


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off