Il semble que les cookies ne soient pas activés dans votre navigateur. Veuillez activer les cookies pour garantir une expérience du site optimale.
Affichage des résultats 1 à 3 sur 3
  1. #1
    Date d'inscription
    juin 2011
    Localisation
    UK
    Messages
    1 245

    Plugin error when auto-loaded.

    I spent an hour this afternoon having a look at LUA and writing a very basic plugin that just writes some data to a file. This is all it is at the moment:

    Code:
    import "Turbine";
    import "Turbine.Gameplay";
    
    player = Turbine.Gameplay.LocalPlayer:GetInstance();
    
    name = player:GetName();
    equip = player:GetEquipment();
    savedata = {};
    savedata["Name"] = name;
    savedata["Shoulders"] = equip:GetItem(Turbine.Gameplay.Equipment.Shoulder):GetName();
    savedata["Helm"] = equip:GetItem(Turbine.Gameplay.Equipment.Head):GetName();
    savedata["Chest"] = equip:GetItem(Turbine.Gameplay.Equipment.Chest):GetName();
    savedata["Gloves"] = equip:GetItem(Turbine.Gameplay.Equipment.Gloves):GetName();
    savedata["Legs"] = equip:GetItem(Turbine.Gameplay.Equipment.Legs):GetName();
    savedata["Boots"] = equip:GetItem(Turbine.Gameplay.Equipment.Boots):GetName();
    savedata["MainWeapon"] = equip:GetItem(Turbine.Gameplay.Equipment.PrimaryWeapon):GetName();
    savedata["ClassItem"] = equip:GetItem(Turbine.Gameplay.Equipment.Class):GetName();
    
    Turbine.Shell.WriteLine("Current Char: " .. name);
    
    Turbine.PluginData.Save(Turbine.DataScope.Account, "A", savedata);

    When loaded manually, it works fine. However, when I auto-load it, I get "Main.lua:10: attempt to index a nil value".

    It seems that for some reason the plugin can't access my equipment properly when loaded this way (if I comment out all the lines that add to the table except "Name", it works fine). Is there some way around this?

  2. #2
    Date d'inscription
    mars 2007
    Messages
    1 157
    Well... you can get around the initialization issue pretty easily by using an Update event handler to detect when GetEquipment returns a non-nil value but this will lead to an issue with calling PluginData.Save. By the time that GetEquipment is no longer nil, your plugin will no longer be in the loading state and you will no longer be able execute PluginData.Save in real-time. This is done by Turbine in an attempt to prevent certain types of botting plugins. You can resolve this in a couple of ways. The first is to call PluginData.Save asynchronously, passing a callback as the third parameter in which case it will wait for 30 seconds before saving your data and then call the callback. Note, if you don't really care about what the data is, this solution is fine and you can even pass a function that doesn't really do anything as the callback.

    Alternately, you can use two plugins, one which is a wrapper that just waits for the equipment object to be initialized and then loads the second plugin at which point you can access the equipment and save the data in realtime in the second plugin (which should probably also unload the first plugin as well since plugins can not unload themselves).

    There are other possible solutions, for instance, if you don't need to save the data until the plugin unloads, you can again call PluginData.Save in real time in the Unload handler for your plugin.

    I would suggest you read through http://forums.lotro.com/showthread.p...gins-for-Noobs as that thread covers many of the quirks of Lua and Turbine's implementation of Lua which can trip up both novice and experienced developers.
    Dernière modification par Garan ; 09/08/2012 à 18h17.

  3. #3
    Date d'inscription
    juin 2011
    Localisation
    UK
    Messages
    1 245
    Thanks. After looking through that thread again & some other threads/plugins I've hashed something together. It's not very tidy & I'm sure there are better ways to do it, but it works at least. I intend to use it for some macros (to allow me to switch back to whatever gear set I'm currently using... PvE gear, PvP audacity gear etc.), so a 30s delay isn't important.

    One problem I had is that just checking that GetEquipment() doesn't return nil didn't work. It seems that each "slot" is updated individually, so when my event fired there were still some slots not filled, giving me errors similar to those I had before. Hence the huge and statement...

    Edit2: Changed my code to use a timer instead of the event handlers to check for gear changes.

    Code:
    import "Turbine";
    import "Turbine.Gameplay";
    import "Turbine.UI";
    
    -- AddCallback function
    
    function AddCallback(object, event, callback)
        if (object[event] == nil) then
            object[event] = callback;
        else
            if (type(object[event]) == "table") then
                table.insert(object[event], callback);
            else
                object[event] = {object[event], callback};
            end
        end
        return callback;
    end
    
    -- Timer function
    
    Timer = class( Turbine.UI.Control ); -- base the class on a generic control so that we can use an Update handler
    function Timer:Constructor()
        Turbine.UI.Control.Constructor( self ); -- generic control constructor
        self.EndTime=Turbine.Engine.GetGameTime(); -- default the EndTime value
        self.Repeat=false; -- default the Repeat value
        -- this is the function which users will call on an instance of the class to set a timer
        self.SetTime=function(sender, numSeconds, setRepeat)
            numSeconds=tonumber(numSeconds); -- force the "type" of the numSeconds parameter
            if numSeconds==nil or numSeconds<=0 then
                numSeconds=0; -- force the numSeconds to a 0 or positive value (negative time is a baaadd thing, Marty...)
            end
            self.EndTime=Turbine.Engine.GetGameTime()+numSeconds; -- set the end time based on current time + the provided number of seconds
            -- note, numSeconds can contain a fractions of a second
            self.Repeat=false; -- default repeat
            self.NumSeconds=numSeconds; -- store the number of seconds internally for use with Repeat
            if setRepeat~=nil and setRepeat~=false then
                -- any non-false value will trigger a repeat
                self.Repeat=true;
            end
            self:SetWantsUpdates(true); -- we set updates to true AFTER we have established the end time and repeat settings (lua uses a single thread so this is kind of overkill, but again, a good practice)
        end
        -- this is the Update handler that will handle checking the time and firing the event(s) if needed
        self.Update=function()
            if self.EndTime~=nil and Turbine.Engine.GetGameTime()>=self.EndTime then
                -- we have a valid timer and it the end time has been reached
                self:SetWantsUpdates(false); -- turn off timer to avoid firing again while we are processing (not likely but it's a good practice)
                -- fire whatever event you are trying to trigger
                if self.TimeReached~=nil then
                    -- we account for both a single "function" as well as a possible table of functions
                    if type(self.TimeReached)=="function" then
                        self.TimeReached();
                    elseif type(self.TimeReached)=="table"  then
                        for k,v in pairs(self.TimeReached) do
                            if type(v)=="function" then
                                v();
                            end
                        end
                    end
                end
                -- last but not least, if we are set to repeat then we need to calculate the next time to fire and reenable the Update handler
                if self.Repeat then
                    self.EndTime=Turbine.Engine.GetGameTime()+self.NumSeconds;
                    self:SetWantsUpdates(true);
                end
            end
        end
    end
    
    -- Update Gear - Called at init & when a gear change is detected
    
    updateGear = function()
        savedata["Shoulders"] = equip:GetItem(Turbine.Gameplay.Equipment.Shoulder):GetName();
        savedata["Helm"] = equip:GetItem(Turbine.Gameplay.Equipment.Head):GetName();
        savedata["Chest"] = equip:GetItem(Turbine.Gameplay.Equipment.Chest):GetName();
        savedata["Gloves"] = equip:GetItem(Turbine.Gameplay.Equipment.Gloves):GetName();
        savedata["Legs"] = equip:GetItem(Turbine.Gameplay.Equipment.Legs):GetName();
        savedata["Boots"] = equip:GetItem(Turbine.Gameplay.Equipment.Boots):GetName();
        savedata["MainWeapon"] = equip:GetItem(Turbine.Gameplay.Equipment.PrimaryWeapon):GetName();
        savedata["ClassItem"] = equip:GetItem(Turbine.Gameplay.Equipment.Class):GetName();
    
        Turbine.PluginData.Save(Turbine.DataScope.Account, "A", savedata, printUpdate);
    end
    
    -- Callback function for PluginData.Save - Prints a line to the shell
    
    printUpdate = function()
        Turbine.Shell.WriteLine("Equipment Updated");
    end
    
    -- EqInit Class - Load-time check that the equipment object has been initialised
    
    EqInit = class(Turbine.UI.Control);
    function EqInit:Constructor()
        Turbine.UI.Control.Constructor(self);
        self:SetWantsUpdates(true);
        self.Update = function()
            player1 = Turbine.Gameplay.LocalPlayer:GetInstance();
            if player1:GetEquipment():GetItem(Turbine.Gameplay.Equipment.Shoulder)~=nil and player1:GetEquipment():GetItem(Turbine.Gameplay.Equipment.Head)~=nil and player1:GetEquipment():GetItem(Turbine.Gameplay.Equipment.Chest)~=nil and player1:GetEquipment():GetItem(Turbine.Gameplay.Equipment.Gloves)~=nil and player1:GetEquipment():GetItem(Turbine.Gameplay.Equipment.Legs)~=nil and player1:GetEquipment():GetItem(Turbine.Gameplay.Equipment.Boots)~=nil and player1:GetEquipment():GetItem(Turbine.Gameplay.Equipment.PrimaryWeapon)~=nil and player1:GetEquipment():GetItem(Turbine.Gameplay.Equipment.Class)~=nil then
                self:SetWantsUpdates(false);
                self.nonNil();
            end
        end
    end
    
    -- Instance of EqInit created
    
    testNonNil = EqInit();
    
    -- checkGearChange called every 30s
    
    checkGearChange = function()
        if savedata["Shoulders"] ~= equip:GetItem(Turbine.Gameplay.Equipment.Shoulder):GetName() then
            updateGear();
        elseif savedata["Helm"] ~= equip:GetItem(Turbine.Gameplay.Equipment.Head):GetName() then
            updateGear();
        elseif savedata["Chest"] ~= equip:GetItem(Turbine.Gameplay.Equipment.Chest):GetName() then
            updateGear();
        elseif savedata["Gloves"] ~= equip:GetItem(Turbine.Gameplay.Equipment.Gloves):GetName() then
            updateGear();
        elseif savedata["Legs"] ~= equip:GetItem(Turbine.Gameplay.Equipment.Legs):GetName() then
            updateGear();
        elseif savedata["Boots"] ~= equip:GetItem(Turbine.Gameplay.Equipment.Boots):GetName() then
            updateGear();
        elseif savedata["MainWeapon"] ~= equip:GetItem(Turbine.Gameplay.Equipment.PrimaryWeapon):GetName() then
            updateGear();
        elseif savedata["ClassItem"] ~= equip:GetItem(Turbine.Gameplay.Equipment.Class):GetName() then
            updateGear();
        end
    end
    
    -- Create timer to check periodically for gear changes
    
    gearChecker = Timer();
    
    -- When the Equipment object is initialised (non-nil), save initial data then start the change-checking cycle
    
    myInit = function()
        player = Turbine.Gameplay.LocalPlayer:GetInstance();
    
        name = player:GetName();
        equip = player:GetEquipment();
        savedata = {};    
        savedata["Name"] = name;
        updateGear();
        Turbine.Shell.WriteLine("CurrentChar Initialised");
    
        AddCallback(gearChecker, "TimeReached", checkGearChange);
    
        gearChecker:SetTime(30, true);    
    end
    
    -- Initiation Check callback
    
    AddCallback(testNonNil, "nonNil", myInit);
    Dernière modification par Tarenius ; 10/08/2012 à 01h44.

 

 

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •  

La session de ce formulaire a expiré. Vous devez recharger la page.

Recharger