lotrointerface.com
Search Downloads


Go Back   LoTROInterface > LotRO > Developer Discussions > Lua Programming Help (L)

Reply
 
Thread Tools Display Modes
  #1  
Unread 06-10-2012, 08:38 AM
Kunter Kunter is offline
The Undefeated
Interface Author - Click to view interfaces
 
Join Date: Jun 2012
Posts: 7
Read out the EffectList

Hi, I'm new to this Forum and LUA programming, so sorry if I've done any stupid mistake

Ok, I'm pretty f***** up and I have no more ideas.
I took Jackdaws LowWarn and tried to modify it, so it will show when you get the Effects that Saruman applies to you in Orthanc.

(Because I didn't knew how the Effects are named I took charge for testing)

So this is what I did (used Disease as example, to make it less confusing):

EffectList = Turbine.Gameplay.EffectList
AddCallback(EffectList,"EffectAdded", function(sender, args) DiseaseWindow:SetOpacity(Disease()) end)
AddCallback(EffectList,"EffectRemoved", function(sender, args) DiseaseWindow:SetOpacity(Disease()) end)
--These are the Callbacks, I think they aren't the problem, it's the Disease function

function Disease()
if (EffectList:Contains(charge)) then -- This is line 30
Disease = 0.5
else
Disease = 0
end
end

The plugin starts without problems, but when I use charge the game prints an errormessage:
...the Rings Online\Plugins\Kunter\EffectWarn\Main.lua:30: Invaild member function call.

What have I done wrong?

Greeting
Kunter

Last edited by Kunter : 06-10-2012 at 08:40 AM.
Reply With Quote
  #2  
Unread 06-10-2012, 09:13 AM
MrJackdaw's Avatar
MrJackdaw MrJackdaw is offline
The Undying
Interface Author - Click to view interfaces
 
Join Date: Feb 2009
Location: Lancaster, England
Posts: 249
The contains function interests me - I didn't know it existed!
__________________
************************************************** ************************************************** **
"Our ideals may never be realised, But they indicate what we are trying to do." Dick Tahta
Reply With Quote
  #3  
Unread 06-10-2012, 09:49 AM
Kunter Kunter is offline
The Undefeated
Interface Author - Click to view interfaces
 
Join Date: Jun 2012
Posts: 7
Oh the Master himself

Found it in the Isengard-Documentation...
I thought this would bei a good command.
Reply With Quote
  #4  
Unread 06-10-2012, 10:02 AM
moebius92 moebius92 is offline
The Undying
Interface Author - Click to view interfaces
 
Join Date: Sep 2010
Posts: 51
I'm not sure how familiar with object oriented programming you are, so I'll start my explanation from there.

In object oriented programming, there's two major things - Classes and Instances. Classes are templates or instructions on how to build something. So a Window class might contain all of the information to display some sort of window. Instances are actual individual objects of a particular class - so there might be multiple Window instances, and each represents a different window on your display.

Turbine.Gameplay.EffectList is a class. So you've just tried to ask the template if it has the charge effect - and it has no idea which actor's EffectList you want, because the class itself isn't associated with any particular actor.

What you probably want is the LocalPlayer's EffectList, so you should probably say:

EffectList = Turbine.Gameplay.LocalPlayer:GetInstance():GetEffe cts();

The second thing is (and it probably hasn't caused you problems, but I suspect it will) "charge" never gets defined. So your EffectList:Contains(charge) is asking if the EffectList contains a nil value (undefined variables are always nil) - which will always be false. The list only contains actual Effects.

You've got two options - one, scan the EffectList (see :GetCount() and :Get(index)), or two use args.Effect and args.Index to keep track of which effect is being added or removed. I'd do the first one - it's clunkier to handle, and once you've got that working, think about using the args.Effect and args.Index arguments.
Reply With Quote
  #5  
Unread 06-10-2012, 11:03 AM
Garan's Avatar
Garan Garan is offline
The Undying
Interface Author - Click to view interfaces
 
Join Date: Oct 2010
Posts: 340
Quote:
Originally Posted by Kunter
function Disease()
if (EffectList:Contains(charge)) then -- This is line 30
Disease = 0.5
else
Disease = 0
end
end
In addition to what the authors above noted, you have a number of problems in the Disease function. First, you are using the same name for a function and a variable within that function (I suspect you have a VB background and are trying to assign the return value). Unfortunately in Lua what will happen with your code is the first time the function gets called, it gets reassigned to a numeric value and will become invalid as a function the next time you try to call it.

Consider the code:
Code:
import "Turbine"
function Disease()
        Disease = 0.5
end
Turbine.Shell.WriteLine("Type before call:"..type(Disease));
local tmpVal=Disease();
Turbine.Shell.WriteLine("tmpVal:"..tostring(tmpVal));
Turbine.Shell.WriteLine("Type after call:"..type(Disease));
The above code demonstrates the two problems with your function, first the output:
Code:
Type before call:function
tmpVal:nil
Type after call:number
shows that "Disease" is indeed changed from a function to a number after it is called. Second, the value returned by Disease() is "nil". This is because you must explicitly use the "return" statement to return a value.

The below code demonstrates using a local value for the return value, initializing it to the default and explicitly returning it. Note that you should always create variables with the narrowest possible scope, so the return value is scoped as local to the function to avoid conflict with any other variable with the same name.
Code:
-- assumes that "EffectList" is properly assigned an instance of an EffectList and that "charge" is properly defined
function Disease()
    local retVal=0;
    if (EffectList:Contains(charge)) then -- This is line 30
        retVal = 0.5;
    end
    return retVal;
end
Reply With Quote
  #6  
Unread 06-10-2012, 11:27 AM
Kunter Kunter is offline
The Undefeated
Interface Author - Click to view interfaces
 
Join Date: Jun 2012
Posts: 7
Quote:
Originally Posted by Garan
In addition to what the authors above noted, you have a number of problems in the Disease function. First, you are using the same name for a function and a variable within that function (I suspect you have a VB background and are trying to assign the return value). Unfortunately in Lua what will happen with your code is the first time the function gets called, it gets reassigned to a numeric value and will become invalid as a function the next time you try to call it.

Consider the code:
Code:
import "Turbine"
function Disease()
        Disease = 0.5
end
Turbine.Shell.WriteLine("Type before call:"..type(Disease));
local tmpVal=Disease();
Turbine.Shell.WriteLine("tmpVal:"..tostring(tmpVal));
Turbine.Shell.WriteLine("Type after call:"..type(Disease));
The above code demonstrates the two problems with your function, first the output:
Code:
Type before call:function
tmpVal:nil
Type after call:number
shows that "Disease" is indeed changed from a function to a number after it is called. Second, the value returned by Disease() is "nil". This is because you must explicitly use the "return" statement to return a value.

The below code demonstrates using a local value for the return value, initializing it to the default and explicitly returning it. Note that you should always create variables with the narrowest possible scope, so the return value is scoped as local to the function to avoid conflict with any other variable with the same name.
Code:
-- assumes that "EffectList" is properly assigned an instance of an EffectList and that "charge" is properly defined
function Disease()
    local retVal=0;
    if (EffectList:Contains(charge)) then -- This is line 30
        retVal = 0.5;
    end
    return retVal;
end
Ok, I get the return thing, but how to define "charge"?
I mean it's the name of the buff the plugin should look for, whats wrong about this?


Ok, just a try concerning moebius post:
What about this line:
if (EffectList:Get(EffectList:GetCount()) == "charge") then
The Get function needs the Index of the effect, cause it's the last added effect I use Get count (schould return a number/index of last added effect).
EffectList:Get returns an effect, but how can I get the name of the effect, so I can compare it to the strin "charge"?
if (EffectList:Get(EffectList:GetCount()):GetName() == "charge") then

Last edited by Kunter : 06-10-2012 at 11:45 AM.
Reply With Quote
  #7  
Unread 06-10-2012, 12:30 PM
moebius92 moebius92 is offline
The Undying
Interface Author - Click to view interfaces
 
Join Date: Sep 2010
Posts: 51
for loops. for loops are your friend.

You'll want something like...

for i = 1, EffectList:GetCount(), 1 do
if EffectList:Get(i):GetName() == "Charge" then
dostuff();
break;
end
end

Actually, what you might want to start with is:

for i = 1, EffectList:GetCount(), 1 do
Turbine.Shell.WriteLine(EffectList:Get(i):GetName( ));
end

...so you can check the names of all of the effects. It probably is called "Charge", but you never know.

And remember that string comparisons with == are case sensitive, so you'll want to get the case right.

Edit: Lua Reference manual is also your friend. Feel free to keep asking questions, but there's a good chance I'll be looking up the answer in the reference manual.

Last edited by moebius92 : 06-10-2012 at 12:48 PM.
Reply With Quote
  #8  
Unread 06-10-2012, 12:56 PM
Kunter Kunter is offline
The Undefeated
Interface Author - Click to view interfaces
 
Join Date: Jun 2012
Posts: 7
Code:
function Disease()
	var = 0;
	for i = 1, EffectList:GetCount(), 1 do
		Turbine.Shell.WriteLine(EffectList:Get(i):GetName( ));
	if (EffectList:Get(i):GetName( ) == "Charge") then
		var = 0.5;
	end
	end
	return var;
end
YEEEAAAAHHHH, it works^^

Many Thanks!

Now I have to find the debuffs names...


Last edited by Kunter : 06-10-2012 at 01:03 PM.
Reply With Quote
  #9  
Unread 06-10-2012, 02:18 PM
Garan's Avatar
Garan Garan is offline
The Undying
Interface Author - Click to view interfaces
 
Join Date: Oct 2010
Posts: 340
Quote:
Originally Posted by Kunter
Code:
function Disease()
    var = 0;
    for i = 1, EffectList:GetCount(), 1 do
        Turbine.Shell.WriteLine(EffectList:Get(i):GetName( ));
    if (EffectList:Get(i):GetName( ) == "Charge") then
        var = 0.5;
    end
    end
    return var;
end
YEEEAAAAHHHH, it works^^

Many Thanks!

Now I have to find the debuffs names...
Two things, first, you are still failing to assign a local scope to your variables and while that won't necessarily cause an issue here, it WILL eventually trip you up somewhere. Especially with commonly used variables like "i". Consider a loop using "i" which calls a function which internally also has a loop using a variable "i" - both "i" variables are one and the same (same scope) so the function will destroy the value in the outer loop causing lots and lots of havoc. By declaring them as local you will get different instances of the variable and eliminate any potential conflict.

Second is more a matter of efficiency. As moebius showed in his example, when using a loop and looking for a specific condition, it is beneficial to use a break statement to exit the loop once the condition has been met if such a condition should only be true for one iteration or if only the first occurence is relevant (if more than one match can occur and all matches must be processed then a break statement is not useful). This can significantly increase the efficiency of your code, since on average you can cut the iterations in half or if you can reasonably expect your match to be at the end of the iteration, perform the iteration in reverse and get even better efficiency.
Reply With Quote
  #10  
Unread 06-10-2012, 02:56 PM
moebius92 moebius92 is offline
The Undying
Interface Author - Click to view interfaces
 
Join Date: Sep 2010
Posts: 51
Actually, the loop variable of a for loop always has a scope that is local to the for loop itself. So I think Kunter's okay in this case.

As for finding debuff names - look up Turbine.Gameplay.Effect - specifically GetCategory. And then look up Turbine.Gameplay.EffectCategory. You ought to be able to cobble something together to look for specific types of debuffs.

Edit: Mind you, var should be local. Heck, I'd probably skip naming it, and just return 0.5 from inside the if statement, and then have a second return at the end of the function.
Reply With Quote
Reply


Thread Tools
Display Modes

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
Forum Jump


All times are GMT -5. The time now is 11:52 AM.


Our Network
EQInterface | EQ2Interface | Minion | WoWInterface | ESOUI | LoTROInterface | MMOUI | Swtorui