[Lua:Help:Solved] onChangeInventory

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
Post Reply
Lollgramoth
Posts: 35
Joined: Fri Jun 15, 2012 7:31 am
Location: Germany

[Lua:Help:Solved] onChangeInventory

Post by Lollgramoth »

I can't find the error. I have something like a "Nanny-Wave" wich i shoot at my Champions every 0.01 second. They look into their inventory and give them to bonus they should have gotten and taking away Items which might be in the way and so on. And now I like to teach my "Nanny-Wave" to look for a special thing to happen. ... an onInventoryChange ... event.

I have a Table named myParty and in it there are the inventories of my champions. My timer calls the myParty.inventoryChanged() before the myParty.refresh(). Both are called correctly, as far as I can see.

In the myParty.inventoryChanged() function the Champions are correctly picked(I have only one Champion enabled). But where I compare the Inventories of myParty and party, it seems like it ... well it finds the items and it can tell me the name of it, but for some reason the boolean variable changedInventory seems to stay false.

I am looking at a wall, not only in the game. Has anyone a suggestion?

Here is the code:
SpoilerShow

Code: Select all

changedInventory = false
	enabledChampions = 0
	
	
	-- inventory recognition table for onChangeInventory
	myParty = {
			champion ={

					
					{
					name = party:getChampion(1):getName(),
					isEnabled = party:getChampion(1):getEnabled(),
					inventory = {}
					},
				
					{
					name = party:getChampion(2):getName(),
					isEnabled = party:getChampion(2):getEnabled(),
					inventory = {}
					},
				
					{
					name = party:getChampion(3):getName(),
					isEnabled = party:getChampion(3):getEnabled(),
					inventory = {}
					},
				
					{
					name = party:getChampion(4 ):getName(),
					isEnabled = party:getChampion(4):getEnabled(),
					inventory = {}
					}
				
			}	
		}
		
	function myParty.refresh()
		for i=1,4 do
			if(party:getChampion(i):getEnabled()) then
				local champ = party:getChampion(i)
				
				for x=1,31 do
					myParty.champion[i].inventory[x] = champ:getItem(x)
				end
			end
		end
	end
	
	-- set changedInventory true if Inventory has Changed
	function myParty.inventoryChanged()
		for i=1,4 do
			-- pick only enabled Champions
			if(party:getChampion(i):getEnabled()) then
				--shortcuts for the champions for mystate and gamestate
				local champ = party:getChampion(i)
				local champstate = myParty.champion[i]
				
				-- compare inventories of myParty and party
				for x=1,31 do
					if(champstate.inventory[x] and champ:getItem(x)) then
						if(champstate.inventory[x].name ~= champ:getItem(x).name) then
							-- x1  x2
							changedInventory = true
						else
							-- x1  x1
							changedInventory = false
						end
					else
						if(champstate.inventory[x] or champ:getItem(x)) then
						 	--- x  nil
							changedInventory = true
						else
							-- nil  nil
							changedInventory = false
						end
					end
					-- debug output
					if champstate.inventory[x] then
						print(champstate.inventory[x].name)
					end
				end
			end
		end
		-- debug output
		if(changedInventory) then
			hudPrint("Inventory Change Event!")
		else
			--hudPrint("No Custom Event!")
		end
	end
	
	function myParty.getInventoryItem(item)
		for i=1,4 do
			if(party:getChampion(i):getEnabled()) then
				local champ = party:getChampion(i)
			
				for x=1,31 do
					if(champ:getItem(x)) then
					
						if(champ:getItem(x).name == item) then	
							return true
						end
					end
				end
			end
		end
		return false
	end
	
	
Here the working solution and additional functions:
SpoilerShow

Code: Select all

changedInventory = false
	
	
	-- inventory recognition table for onChangeInventory
	myParty = {
			champion ={

					
					{
					name = party:getChampion(1):getName(),
					isEnabled = party:getChampion(1):getEnabled(),
					inventory = {}
					},
				
					{
					name = party:getChampion(2):getName(),
					isEnabled = party:getChampion(2):getEnabled(),
					inventory = {}
					},
				
					{
					name = party:getChampion(3):getName(),
					isEnabled = party:getChampion(3):getEnabled(),
					inventory = {}
					},
				
					{
					name = party:getChampion(4 ):getName(),
					isEnabled = party:getChampion(4):getEnabled(),
					inventory = {}
					}
				
			}	
		}
		
	function myParty.refresh()
		for i=1,4 do
			if(party:getChampion(i):getEnabled()) then
				local champ = party:getChampion(i)
				
				for x=1,31 do
					myParty.champion[i].inventory[x] = champ:getItem(x)
				end
			end
		end
	end
	
	-- set changedInventory true if Inventory has Changed
	function myParty.inventoryChanged()
		for i=1,4 do
			if(changedInventory) then break end
			
			-- pick only enabled Champions
			if(party:getChampion(i):getEnabled()) then
				--shortcuts for the champions for mystate and gamestate
				local champ = party:getChampion(i)
				local champstate = myParty.champion[i]
				
				-- compare inventories of myParty and party
				for x=1,31 do
					if(champstate.inventory[x] and champ:getItem(x)) then
						if(champstate.inventory[x].name ~= champ:getItem(x).name) then
							-- x1  x2
							changedInventory = true
							break
						else
							-- x1  x1
							changedInventory = false
						end
					else
						if(champstate.inventory[x] or champ:getItem(x)) then
						 	--- x  nil
							changedInventory = true
							break
						else
							-- nil  nil
							changedInventory = false
						end
					end
					-- debug output
					if champstate.inventory[x] then
						print(champstate.inventory[x].name)
					end
				end
			end
		end
		
		if(changedInventory) then
			----------------------------------------------
			-- onInventoryChange actions here... ---------
			----------------------------------------------
			hudPrint("Inventory Change Event!")
			myParty.onInventoryChanged()
			changedInventory = false
		else
			--hudPrint("No Custom Event!")
		end
	end
	
	function myParty.onInventoryChanged()
		
	end
	
	function myParty.getInventoryItem(item)
		for i=1,4 do
			if(party:getChampion(i):getEnabled()) then
				local champ = party:getChampion(i)
			
				for x=1,31 do
					if(champ:getItem(x)) then
					
						if(champ:getItem(x).name == item) then	
							return true
						end
					end
				end
			end
		end
		return false
	end
	
Last edited by Lollgramoth on Tue Oct 16, 2012 10:54 am, edited 2 times in total.
User avatar
Filipsan
Posts: 84
Joined: Fri Mar 16, 2012 10:18 am

Re: [Lua:Help] onChangeInventory

Post by Filipsan »

Hi, IMHO the problem is in the for cycle. You are setting the variable changedInventory in every iteration to either false or true, which means, that practically changedInventory will yield the state of last iteration.

what you should do is something like:

Code: Select all


changedInventory = false

-- compare inventories of myParty and party
for x=1,31 do
   if(champstate.inventory[x] and champ:getItem(x)) then
      if(champstate.inventory[x].name ~= champ:getItem(x).name) then
         -- x1  x2
         changedInventory = true
      end
   else
      if(champstate.inventory[x] or champ:getItem(x)) then
         -- x1  x1
         changedInventory = true
      end
   end
end
i.e. without all the false branches..

Hope this helps
User avatar
Crisim
Posts: 16
Joined: Wed Aug 29, 2012 2:28 pm

Re: [Lua:Help] onChangeInventory

Post by Crisim »

Filipsan is right, the changedInventory variable is setted by the last item of the last champion.

maybe instead of checking all the backpacks and at the end return the result you could raise an event if something is changed.

i.e.

Code: Select all

for x=1,31 do
   if(champstate.inventory[x] and champ:getItem(x)) then
      if(champstate.inventory[x].name ~= champ:getItem(x).name) then -- are you sure you don't want to check the ids?
         -- x1  x2
         itemChanged(champ, x, champstate.inventory[x], champ:getItem(x))
      end
   else
      if(champstate.inventory[x] or champ:getItem(x)) then
         -- x1  nil
         itemChanged(champ, x, champstate.inventory[x], champ:getItem(x))
      end
   end
end
and a function in your script entity

Code: Select all

function itemChanged(champ, slot, oldItem, newItem)
  --Do your stuff here
end
Lollgramoth
Posts: 35
Joined: Fri Jun 15, 2012 7:31 am
Location: Germany

Re: [Lua:Help] onChangeInventory

Post by Lollgramoth »

Walls! Yes, that's true. Filipsan, it might be your humble opinion but it is so true too. Thank you. Now it should be easy to get it working. Sometimes one is stuck in his thoughts. :)

But if I spare the false branches, the second it gets true it stays true. I think I need to break out of the inventory after it changedInventory got true and run throu the heroes as long as changedInventory is not true.

Chrisims method will work, for the logic of the game will only allow one to get one Item of the inventory changed at a time, but if some logic I invented clears more than one item, the onInventoryChange() event will fire several times.(I have that method allready, so I need an other way. But thanks Chrisim for your solution)

Thanks again. :D

And here my solution as descripted:

Code: Select all

function myParty.inventoryChanged()
		for i=1,4 do
			if(changedInventory == false) then
				-- pick only enabled Champions
				if(party:getChampion(i):getEnabled()) then
					--shortcuts for the champions for mystate and gamestate
					local champ = party:getChampion(i)
					local champstate = myParty.champion[i]
					
					-- compare inventories of myParty and party
					for x=1,31 do
						if(champstate.inventory[x] and champ:getItem(x)) then
							if(champstate.inventory[x].name ~= champ:getItem(x).name) then
								-- x1  x2
								changedInventory = true
								break
							else
								-- x1  x1
								changedInventory = false
							end
						else
							if(champstate.inventory[x] or champ:getItem(x)) then
							 	--- x  nil
								changedInventory = true
								break
							else
								-- nil  nil
								changedInventory = false
							end
						end
						-- debug output
						if champstate.inventory[x] then
							print(champstate.inventory[x].name)
						end
					end
				end
			end
		end
		-- debug output
		if(changedInventory) then
			hudPrint("Inventory Change Event!")
			changedInventory = false
		else
			--hudPrint("No Custom Event!")
		end
	end
User avatar
Filipsan
Posts: 84
Joined: Fri Mar 16, 2012 10:18 am

Re: [Lua:Help] onChangeInventory

Post by Filipsan »

Lollgramoth wrote: ... I think I need to break out of the inventory after it changedInventory got true and run throu the heroes as long as changedInventory is not true...
Well, since you have 2 cycles, you need to call break twice...

Try something like this (not tested):

Code: Select all

function myParty.inventoryChanged()

   local changedInventory == false 
   for i=1,4 do
      -- pick only enabled Champions
      if(party:getChampion(i):getEnabled()) then
         
         --shortcuts for the champions for mystate and gamestate
         local champ = party:getChampion(i)
         local champstate = myParty.champion[i]
         local changedInventoryHero == false
             
         -- compare inventories of myParty and party
         for x=1,31 do
            if(champstate.inventory[x] and champ:getItem(x)) then
               if(champstate.inventory[x].name ~= champ:getItem(x).name) then
                  -- x1  x2, break from inner loop
                  changedInventoryHero = true
                  break
               end
            else
               if(champstate.inventory[x] or champ:getItem(x)) then
                  --- x  nil, break from inner loop
                  changedInventory = true
                  break
               end
            end
         end
         
         -- debug output and second call of break from outer loop
         if(changedInventoryHero) then
              hudPrint("Inventory Change Event for hero "..champ.getName())
              break
         end
      end
   end
       
   -- debug output
   if(changedInventory) then
      hudPrint("Inventory Change Event global!")
      changedInventory = false
   end
end
Lollgramoth
Posts: 35
Joined: Fri Jun 15, 2012 7:31 am
Location: Germany

Re: [Lua:Help:Solved] onChangeInventory

Post by Lollgramoth »

Thanks, that should do the trick too. And I consider it a better way than my solution. I have put a if(changedInventory == false) around the second cycle, so it will run the first cycle to the bitter end, not stopping for any reason. I like the breakline to be more visible at the beginning of the first cycle, so I will change the code to this:
SpoilerShow

Code: Select all

function myParty.inventoryChanged()
		for i=1,4 do
			if(changedInventory) then break end
			
			-- pick only enabled Champions
			if(party:getChampion(i):getEnabled()) then
				--shortcuts for the champions for mystate and gamestate
				local champ = party:getChampion(i)
				local champstate = myParty.champion[i]
				
				-- compare inventories of myParty and party
				for x=1,31 do
					if(champstate.inventory[x] and champ:getItem(x)) then
						if(champstate.inventory[x].name ~= champ:getItem(x).name) then
							-- x1  x2
							changedInventory = true
							break
						else
							-- x1  x1
							changedInventory = false
						end
					else
						if(champstate.inventory[x] or champ:getItem(x)) then
						 	--- x  nil
							changedInventory = true
							break
						else
							-- nil  nil
							changedInventory = false
						end
					end
					-- debug output
					if champstate.inventory[x] then
						print(champstate.inventory[x].name)
					end
				end
			end
		end
		
		if(changedInventory) then
			----------------------------------------------
			-- onInventoryChange actions here... ---------
			----------------------------------------------
			hudPrint("Inventory Change Event!")
			myParty.onInventoryChanged()
			changedInventory = false
		else
			--hudPrint("No Custom Event!")
		end
	end
And this solution is functional... it works just fine.
Post Reply