Page 1 of 1

Weirdness with item slots

Posted: Fri Mar 01, 2013 6:56 am
by Grimfan
Hi everyone,

Here's another entry level script that I wrote up. It works, but it doesn't quite work the way I want it to.

Here's the script first of all:

Code: Select all

 function lightCheck()
local j = "blue_gem"
    for j=7,8 do 
	if party:getChampion(1):getItem(j) and
	party:getChampion(2):getItem(j) and
	party:getChampion(3):getItem(j) and
	party:getChampion(4):getItem(j) then
	if j then
	teleporter_34:deactivate()
	else
	teleporter_34:activate()
	end
end
end
end
A few strange issues (strange to me anyhow) and questions:

1. The code works but only if I put the blue gems all in slot 7 or slot 8 of my characters. If I mix up to the two slots the teleporter doesn't deactivate. Why doesn't the "for j=7,8 do" actually work in this regard (I thought it counted to see if either slot was occupied)

2. The teleporter won't reactivate if the blue gems leave the characters hands. Why is this the case?

3. Should this script work at all (because it does to an extent) or have I found a lua loophole of some kind?

4. If it is mostly correct is there a cleaner or better way to write it?

Again, thanks for any help flung my way. :)

Re: Weirdness with item slots

Posted: Fri Mar 01, 2013 8:53 am
by mahric
No time to see why your code doesn't work (since i'm at work), but I like to write stuff the way I actually say or explain it to others.
- The teleporter needs to open if member1 holds the item and member2 and member3 and member4, else it needs to deactivate.
- A member holding it means it actually in their left or right hands.

Without compiler and such (so probably full of errors), the script could be like this:

Code: Select all

 
function lightCheck()
local j = "blue_gem"
  if holdsItem(1, j) and holdsItem(2, j) and holdsItem(3, j) and holdsItem(4, j) then
   teleporter_34:activate()
   else
   teleporter_34:deactivate()
  end
end

function holdsItem(champ, name)
  local leftItem = party:getChampion(champ):getItem(7)
  local rightItem = party:getChampion(champ):getItem(8)
  return leftItem ~= nil and rightItem~= nil and leftItem.name==name and rightItem.name==name
end

To answer your questions

1) in your statement you had 2 loops, first you checked slot 7 and then slot 8. Those are 2 seperate loops and there was nothing to link the result of the 2 together
2) not sure what happens, but you use the same variablename multiple times (once as the item name and once as the loop counter). Try to avoid that for more predictable results
3) i don't think it's a lua loophole and it can work if you introduced more local variables, but might be possible to cheat then (player one holding 2 items and player 2 none).
But because I'm not sure I wrote an alternative, hope it works for you.
4) my way is not more correct than yours (assuming they both work). In environments where people have to maintain scripts for others there are rules on how to write code, but find a way you find most understandable and readable and stick with it. Personally I don't mind writing longer scripts if it makes me understand better, but I know others like to keep their code as short as possible.

Alternative way of writing with just one function:

Code: Select all

function lightCheck()
local j = "blue_gem"
if (party:getChampion(1):getItem(7).name==j or party:getChampion(1):getItem(8).name==j) and 
   (party:getChampion(2):getItem(7).name==j or party:getChampion(2):getItem(8).name==j) and 
   (party:getChampion(3):getItem(7).name==j or party:getChampion(3):getItem(8).name==j) and 
   (party:getChampion(4):getItem(7).name==j or party:getChampion(4):getItem(8).name==j) then
   teleporter_34:activate()
   else
   teleporter_34:deactivate()
end
end

Re: Weirdness with item slots

Posted: Fri Mar 01, 2013 9:16 am
by Grimfan
Thanks for the help mahric. :) Neither script works (the first one doesn't do anything and the second one fails because of an error) but as you said you are at work so couldn't test your code. I will definitely take on board what you said and are already trying some alternatives (I too would be at work, but am down with a cold playing Skyrim and LoG).

I can see your point about using the same variable name for different parts of my code and the loop stuff is interesting.

Many thanks for taking the time to help me, and your latest mod is great despite my feeble protests. :D

EDIT: I saw the thing in your first script that stopped it from working and changed it. The script now works as intended. Thanks even more than before!!!

EDIT: My mistake. It deactivates the teleporter regardless of what the characters have in their hands (even if they are holding nothing in their hands). I'll keep working on it.

Re: Weirdness with item slots

Posted: Fri Mar 01, 2013 10:37 am
by Numberouane
should be good to gather all those scripts knowledge in the dedicated thread for easier reference

Re: Weirdness with item slots

Posted: Sat Mar 02, 2013 1:03 am
by Marble Mouth
Hello. The second script that mahric posted may produce an error if you have champions with empty hands. If champion(1) has nothing in the left hand (slot 7), then party:getChampion(1):getItem(7) returns nil. So when you try to treat this nil as a table and reference its name:

Code: Select all

party:getChampion(1):getItem(7).name
you get the error.

However, that code may not produce an error even with empty handed champions, because lua stops evaluating compound conditions when it finds a "short cut":
SpoilerShow

Code: Select all

x or y
If x is a "positive" value (anything except nil or false) then the compound condition will definitely be positive, so y is irrelevant, so lua doesn't bother to evaluate y.
SpoilerShow

Code: Select all

x and y
If x is a "negative" value (either nil or false) then the compound condition will definitely be negative, so y is irrelevant, so lua doesn't bother to evaluate y.
That's why, in mahric's first script, he (she?) checked for nil first. I think that script will work with just a little tweak:

Code: Select all

    function lightCheck()
    local j = "blue_gem"
      if holdsItem(1, j) and holdsItem(2, j) and holdsItem(3, j) and holdsItem(4, j) then
       teleporter_34:activate()
       else
       teleporter_34:deactivate()
      end
    end

    function holdsItem(champ, name)
      local leftItem = party:getChampion(champ):getItem(7)
      if leftItem and ( leftItem.name == name ) then
         return true
      end
      local rightItem = party:getChampion(champ):getItem(8)
      if rightItem and ( rightItem.name == name ) then
         return true
      end
    end
If you'd like to see the shortcut logic in action, put a print at the beginning of holdsItem. Your print will only happen as many times as necessary for lua to determine the result of lightCheck. If all four champions hold a blue_gem, lua must call holdsItem four times. But if the first champion does not hold a blue_gem, then lua will not call holdsItem again. Note: redundant parentheses make me feel more comfortable. I've made far too many dumb mistakes because I assumed that the order of operations was different than what it really is.

Edit: Added spoiler tags to clarify which code goes with which commentary.

Re: Weirdness with item slots

Posted: Sat Mar 02, 2013 1:26 am
by Grimfan
This script comes up with the error bad argument #1 to 'getChampion' (number expected, got table) right after:

Code: Select all

local leftItem = party:getChampion(champ):getItem(7)
Does the activation method for the two scripts make a difference?

Re: Weirdness with item slots

Posted: Sat Mar 02, 2013 1:57 am
by Marble Mouth
Hi Grimfan. Yes, you must have your connector call lightCheck and not call holdsItem . When a dungeon object calls a script, that object is automatically used as the first argument to that script (many scripts simply ignore this argument.) This means that if you have a connector from a button directly to holdsItem , then that button winds up as the argument "champ" in holdsItem. Dungeon objects are always of datatype "table", but champ should be a number, hence your error. Note that lightCheck always supplies a number as the first argument to holdsItem, which should avoid this error. Sorry I wasn't more clear the first time.

Re: Weirdness with item slots

Posted: Sat Mar 02, 2013 2:08 am
by Grimfan
Ah, yes I can see. The first script calls the second function so you don't need to check it separately ( I should know that by now). It's working well now. I'm keeping a little script repository so I if I run into this sort of problem again I don't need to bother you guys with questions. ;)

Thanks again Marble Mouth and Mahric for your wonderful insights! :D