We have detected that cookies are not enabled on your browser. Please enable cookies to ensure the proper experience.
Results 1 to 4 of 4
  1. #1
    Join Date
    Jun 2011
    Location
    Sweden
    Posts
    17

    Question What am I doing wrong with pcall?

    Hi,

    Can anyone suggest what is wrong with the following code fragment?

    The pcall if statement always returns false giving the "not possible" output.

    If I remove the pcall then it works fine until I target something without morale such as a crafting node and then I get:
    ...\Main.lua:120: attempt to call method 'GetMorale' (a nil value)

    Code:
    refPlayer = Turbine.Gameplay.LocalPlayer.GetInstance();
    
    playerTarget = Turbine.UI.Label();
    playerTarget .MaxMorale = 1;
    playerTarget .CurMorale = 1;
    
    
    if ( refPlayer:GetTarget() ~= nil ) then
    	if pcall( refPlayer:GetTarget():GetMorale() ) then 
    		playerTarget.CurMorale = refPlayer:GetTarget():GetMorale();
    		playerTarget.MaxMorale = refPlayer:GetTarget():GetMaxMorale();
    		Turbine.Shell.WriteLine(" Updated target morale");
    	else
    		Turbine.Shell.WriteLine(" Not possible to get target morale");
    	end
    else
    	Turbine.Shell.WriteLine(" No target selected");
    end
    What I am trying to achieve is :
    Code:
    if PLAYER_TARGET_NOT NULL
    	if TARGET HAS MORALE
    		GET_MORALE_AND_STORE_LOCALLY
    	else
    		DO_NOTHING
    	end if
    end if
    and it should do this without generating errors that crash the plugin

  2. #2
    Join Date
    Mar 2007
    Posts
    1,181
    First, you are not correctly calling pcall.
    local success,result=pcall(function, parameters);
    so your call would be something like
    local success,result=pcall(Turbine.G ameplay.Actor.GetMaxMorale,ref Player);


    Second, in this instance, you can't really use pcall since the GetMorale function doesn't exist for targets that have no morale. So you are passing nil to pcall instead of a function. Instead, just test whether GetMorale==nil. Note, you should also use a local to store refPlayer:GetTarget() instead of calling it so many times.
    Code:
    refPlayer = Turbine.Gameplay.LocalPlayer.GetInstance();
    
    playerTarget = Turbine.UI.Label();
    playerTarget.MaxMorale = 1;
    playerTarget.CurMorale = 1;
    
    local tmpTarget=refPlayer:GetTarget();
    
    if ( tmpTarget ~= nil ) then
    	if tmpTarget.GetMorale~=nil then 
    		playerTarget.CurMorale = tmpTarget:GetMorale();
    		if tmpTarget.GetMaxMorale~=nil then
    			playerTarget.MaxMorale = tmpTarget:GetMaxMorale();
    		else
    			-- should really set a default when the target has no max morale, perhaps just Morale
    			playerTarget.MaxMorale=playerTarget.CurMorale
    		end
    		Turbine.Shell.WriteLine(" Updated target morale");
    	else
    		Turbine.Shell.WriteLine(" Not possible to get target morale");
    		-- should set morale and max morale to some default
    	end
    else
    	Turbine.Shell.WriteLine(" No target selected");
    end
    Note, when comparing the function to nil, you have to use the "." syntax and no parentheses to test the function rather than the function result
    The additional test for the existence of GetMaxMorale that I added is probably overkill since any target with a GetMorale function SHOULD have a GetMaxMorale, but it doesn't hurt to be safe

    Alternately, you could use the IsA function to test whether refPlayer is an Actor or a Mount instead of an Item, but then if Turbine ever adds any classes of Entities, you would have to account for them so testing the existence of the GetMorale function is probably preferable.
    Last edited by Garan; Aug 31 2014 at 05:29 PM.

  3. #3
    Actually, if the pcall call was correct, it should work. The problem is, the correct call is "pcall(refPlayer:GetTarget().G etMorale)".

    What's happening is, the arguments of the pcall() are evaluated first. So, refPlayer:GetTarget():GetMoral e() is evaluated, and one of two things happens:

    1) There is a GetMorale function, so it returns the target's morale (which is a number), and then pcall tries to perform a function call on the number (which fails, causing pcall to return false).

    2) There is no GetMorale function, so the call fails, and the arguments to pcall can not be evaluated. However, since this was done in protected mode, pcall simply returns false.

    On the other hand, doing the pcall correctly is roughly the equivalent of checking whether GetMorale exists in refPlayer:GetTarget().

  4. #4
    Join Date
    Jun 2011
    Location
    Sweden
    Posts
    17
    Moebius92 - your explanation was spot on and i now appreciate why it is that pcall consistently returned false.

    Garan - testing "getMorale" as you suggested is exactly what I needed and now the code is happily working as intended.

    Thank you both!

 

 

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

This form's session has expired. You need to reload the page.

Reload