• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!
  • 2026 staff recruitment is open! Check it out and consider applying!

Solved TFS [1.2] Assistance Shortening LUA Scripts

Leo32

Getting back into it...
Joined
Sep 21, 2007
Messages
990
Solutions
14
Reaction score
551
Hi Guys,

I've recently come back and have revived one of my old projects.
I'd like to gain some more knowledge around intelligent LUA structures and using intelligent IF gates.

For context-:
I have a script I wrote that functions well
(Needs to be tweaked for global exhaust to prevent multiple characters from triggering the chest spawn)

But even so, it's riddled with duplicated nested IFs because I'm not all that amazing at this.
Take a look at the code after -- Stone 1

Code:
local exhaust = createConditionObject(CONDITION_EXHAUST)
         setConditionParam(exhaust, CONDITION_PARAM_TICKS, 10000)

local chestpos = {x=1053, y=525, z=11}
local stone1pos = {x=1053, y=520, z=11}
local stone2pos = {x=1057, y=521, z=11}
local stone3pos = {x=1059, y=525, z=11}
local stone4pos = {x=1055, y=529, z=11}
local stone5pos = {x=1050, y=528, z=11}
local stone6pos = {x=1049, y=523, z=11}

function resetred(r)
   doTransformItem(getTileItemById(r, 1355).uid, 1304)
   return true
end
function resetblue(b)
   doTransformItem(getTileItemById(b, 1354).uid, 1304)
   return true
end

function destroychest()
   doRemoveItem(getTileItemById(chestpos, 12664).uid,1)
   doSendMagicEffect(chestpos, CONST_ME_POFF)
   return true
end
function onUse(player, item, fromPosition, itemEx, toPosition)
   if getCreatureCondition(player, CONDITION_EXHAUST) == TRUE then
     local pos = player:getPosition()
     pos:sendMagicEffect(CONST_ME_POFF)
     player:sendTextMessage(MESSAGE_STATUS_SMALL, Game.getReturnMessage(RETURNVALUE_YOUAREEXHAUSTED))
     return true
   else
     -- Stone 1
   if (item.actionid == 2001) then
     if not (getTileItemById(stone2pos, 1355).uid > 0) then
       if not (getTileItemById(stone3pos, 1355).uid > 0) then
         if not (getTileItemById(stone4pos, 1355).uid > 0) then
           if not (getTileItemById(stone5pos, 1355).uid > 0) then
             if not (getTileItemById(stone6pos, 1355).uid > 0) then
               item:transform(1354)
               addEvent(resetblue, 10000, toPosition)
             else
               item:transform(1355)
               addEvent(resetred, 10000, toPosition)
               doAddCondition(player, exhaust)
             end
           else
             item:transform(1355)
             addEvent(resetred, 10000, toPosition)
             doAddCondition(player, exhaust)
           end
         else
           item:transform(1355)
           addEvent(resetred, 10000, toPosition)
           doAddCondition(player, exhaust)
         end
       else
         item:transform(1355)
         addEvent(resetred, 10000, toPosition)
         doAddCondition(player, exhaust)
       end
     else
       item:transform(1355)
       addEvent(resetred, 10000, toPosition)
       doAddCondition(player, exhaust)
     end
      
     -- Stone 2
   elseif (item.actionid == 2002) then
     if (getTileItemById(stone1pos, 1354).uid > 0) then
       if not (getTileItemById(stone3pos, 1355).uid > 0) then
         if not (getTileItemById(stone4pos, 1355).uid > 0) then
           if not (getTileItemById(stone5pos, 1355).uid > 0) then
             if not (getTileItemById(stone6pos, 1355).uid > 0) then
               item:transform(1354)
               addEvent(resetblue, 10000, toPosition)
             else
               item:transform(1355)
               addEvent(resetred, 10000, toPosition)
               doAddCondition(player, exhaust)
             end
           else
             item:transform(1355)
             addEvent(resetred, 10000, toPosition)
             doAddCondition(player, exhaust)
           end
         else
           item:transform(1355)
           addEvent(resetred, 10000, toPosition)
           doAddCondition(player, exhaust)
         end
       else
         item:transform(1355)
         addEvent(resetred, 10000, toPosition)
         doAddCondition(player, exhaust)
       end
     else
       item:transform(1355)
       addEvent(resetred, 10000, toPosition)
       doAddCondition(player, exhaust)
     end
      
     -- Stone 4
   elseif (item.actionid == 2004) then
     if (getTileItemById(stone2pos, 1354).uid > 0) then
       if not (getTileItemById(stone3pos, 1355).uid > 0) then
         if not (getTileItemById(stone1pos, 1355).uid > 0) then
           if not (getTileItemById(stone5pos, 1355).uid > 0) then
             if not (getTileItemById(stone6pos, 1355).uid > 0) then
               item:transform(1354)
               addEvent(resetblue, 10000, toPosition)
             else
               item:transform(1355)
               addEvent(resetred, 10000, toPosition)
               doAddCondition(player, exhaust)
             end
           else
             item:transform(1355)
             addEvent(resetred, 10000, toPosition)
             doAddCondition(player, exhaust)
           end
         else
           item:transform(1355)
           addEvent(resetred, 10000, toPosition)
           doAddCondition(player, exhaust)
         end
       else
         item:transform(1355)
         addEvent(resetred, 10000, toPosition)
         doAddCondition(player, exhaust)
       end
     else
       item:transform(1355)
       addEvent(resetred, 10000, toPosition)
       doAddCondition(player, exhaust)
     end
      
     -- Stone 6
   elseif (item.actionid == 2006) then
     if not (getTileItemById(stone2pos, 1355).uid > 0) then
       if not (getTileItemById(stone3pos, 1355).uid > 0) then
         if (getTileItemById(stone4pos, 1354).uid > 0) then
           if not (getTileItemById(stone5pos, 1355).uid > 0) then
             if not (getTileItemById(stone1pos, 1355).uid > 0) then
               item:transform(1354)
               addEvent(resetblue, 10000, toPosition)
             else
               item:transform(1355)
               addEvent(resetred, 10000, toPosition)
               doAddCondition(player, exhaust)
             end
           else
             item:transform(1355)
             addEvent(resetred, 10000, toPosition)
             doAddCondition(player, exhaust)
           end
         else
           item:transform(1355)
           addEvent(resetred, 10000, toPosition)
           doAddCondition(player, exhaust)
         end
       else
         item:transform(1355)
         addEvent(resetred, 10000, toPosition)
         doAddCondition(player, exhaust)
       end
     else
       item:transform(1355)
       addEvent(resetred, 10000, toPosition)
       doAddCondition(player, exhaust)
     end
      
     -- Stone 5
   elseif (item.actionid == 2005) then
     if not (getTileItemById(stone2pos, 1355).uid > 0) then
       if not (getTileItemById(stone3pos, 1355).uid > 0) then
         if not (getTileItemById(stone4pos, 1355).uid > 0) then
           if not (getTileItemById(stone1pos, 1355).uid > 0) then
             if (getTileItemById(stone6pos, 1354).uid > 0) then
               item:transform(1354)
               addEvent(resetblue, 10000, toPosition)
             else
               item:transform(1355)
               addEvent(resetred, 10000, toPosition)
               doAddCondition(player, exhaust)
             end
           else
             item:transform(1355)
             addEvent(resetred, 10000, toPosition)
             doAddCondition(player, exhaust)
           end
         else
           item:transform(1355)
           addEvent(resetred, 10000, toPosition)
           doAddCondition(player, exhaust)
         end
       else
         item:transform(1355)
         addEvent(resetred, 10000, toPosition)
         doAddCondition(player, exhaust)
       end
     else
       item:transform(1355)
       addEvent(resetred, 10000, toPosition)
         doAddCondition(player, exhaust)
     end
      
     -- Stone 3
   elseif (item.actionid == 2003) then
     if not (getTileItemById(stone2pos, 1355).uid > 0) then
       if not (getTileItemById(stone1pos, 1355).uid > 0) then
         if not (getTileItemById(stone4pos, 1355).uid > 0) then
           if (getTileItemById(stone5pos, 1354).uid > 0) then
             if not (getTileItemById(stone6pos, 1355).uid > 0) then
               local pos = player:getPosition()
               local chest = getTileItemById(chestpos, 12664)
               local create = doCreateItem(12664,1,chestpos)
               doSetItemActionId(create, 2010)
               pos:sendMagicEffect(32)
               doSummonCreature("Tarantula", stone1pos)
               doSummonCreature("Tarantula", stone3pos)
               doSummonCreature("Tarantula", stone6pos)
               item:transform(1354)
               addEvent(resetblue, 10000, toPosition)
               addEvent(destroychest, 10000)
               doAddCondition(player, exhaust)
             else
               item:transform(1355)
               addEvent(resetred, 10000, toPosition)
               doAddCondition(player, exhaust)
             end
           else
             item:transform(1355)
             addEvent(resetred, 10000, toPosition)
             doAddCondition(player, exhaust)
           end
         else
           item:transform(1355)
           addEvent(resetred, 10000, toPosition)
           doAddCondition(player, exhaust)
         end
       else
         item:transform(1355)
         addEvent(resetred, 10000, toPosition)
         doAddCondition(player, exhaust)
       end
     else
       item:transform(1355)
       addEvent(resetred, 10000, toPosition)
       doAddCondition(player, exhaust)
     end
     end
   end
end

What would be the best way to replace all the nested IFs?
Can someone point to to any good learning material on this sort of thing?

I could avoid the issue entirely by using storages for each current stone sequence, instead of getting the previous stone.itemid.
Doesn't really help with the learning though :P
 
Last edited by a moderator:
Though this is more of a general tip: my personal rule is that if a function doesn't fit on a typical developer's screen (22") it's way too long and should be broken up into several functions.
As for the nested ifs, try to analyse all possibilities. If you look closely, you do the same action in all the else branches. That's the first clue that it could be simplified with some simple usage of boolean logic and boolean operators. I won't refactor everything, but I'll give you a general idea:
This code:
Code:
if not condition1 then
    if not condition2 then
        doSth();
    else
        doSthElse();
     end
else
    doSthElse();
end
can be written as:

Code:
if not condition1 and not condition2 then
    doSth();
else
    doSthElse();
end
Unless you specifically wanted the doSthElse() branch to run multiple times if the first few condition checks pass which I doubt. I strongly suggest you read up on some logic and boolean logic related stuff. A lot of people underestimate the importance of math in programming (De Morgan's laws are a must know, even though they're quite intuitive if you think them over).
 
All good.

Script has been revised anyway:

Code:
local exhaust = createConditionObject(CONDITION_EXHAUST)
         setConditionParam(exhaust, CONDITION_PARAM_TICKS, 10000)

local chestpos = {x=1053, y=525, z=11}
local stone1pos = {x=1053, y=520, z=11}
local stone2pos = {x=1057, y=521, z=11}
local stone3pos = {x=1059, y=525, z=11}
local stone4pos = {x=1055, y=529, z=11}
local stone5pos = {x=1050, y=528, z=11}
local stone6pos = {x=1049, y=523, z=11}

function resetred(r)
   doTransformItem(getTileItemById(r, 1355).uid, 1304)
   return true
end
function resetblue(b)
   doTransformItem(getTileItemById(b, 1354).uid, 1304)
   return true
end

function destroychest()
   doRemoveItem(getTileItemById(chestpos, 12664).uid,1)
   doSendMagicEffect(chestpos, CONST_ME_POFF)
   return true
end
function onUse(player, item, fromPosition, itemEx, toPosition)
   if getCreatureCondition(player, CONDITION_EXHAUST) == TRUE then
     local pos = player:getPosition()
     pos:sendMagicEffect(CONST_ME_POFF)
     player:sendTextMessage(MESSAGE_STATUS_SMALL, Game.getReturnMessage(RETURNVALUE_YOUAREEXHAUSTED))
     return true
   else
   -- Stone 1
     if (item.actionid == 2001) then
       if player:getStorageValue(2000) < 0 then
         item:transform(1354)
         addEvent(resetblue, 10000, toPosition)
         player:setStorageValue(2000,1)
       else
         item:transform(1355)
         addEvent(resetred, 10000, toPosition)
         doAddCondition(player, exhaust)
         player:setStorageValue(2000,-1)
       end

   -- Stone 2
     elseif (item.actionid == 2002) then
       if player:getStorageValue(2000) == 1 then
         item:transform(1354)
         addEvent(resetblue, 10000, toPosition)
         player:setStorageValue(2000,2)
       else
         item:transform(1355)
         addEvent(resetred, 10000, toPosition)
         doAddCondition(player, exhaust)
         player:setStorageValue(2000,-1)
       end
      
   -- Stone 4
     elseif (item.actionid == 2004) then
       if player:getStorageValue(2000) == 2 then
         item:transform(1354)
         addEvent(resetblue, 10000, toPosition)
         player:setStorageValue(2000,3)
       else
         item:transform(1355)
         addEvent(resetred, 10000, toPosition)
         doAddCondition(player, exhaust)
         player:setStorageValue(2000,-1)
       end
      
   -- Stone 6
     elseif (item.actionid == 2006) then
       if player:getStorageValue(2000) == 3 then
         item:transform(1354)
         addEvent(resetblue, 10000, toPosition)
         player:setStorageValue(2000,4)
       else
         item:transform(1355)
         addEvent(resetred, 10000, toPosition)
         doAddCondition(player, exhaust)
         player:setStorageValue(2000,-1)
       end
      
   -- Stone 5
     elseif (item.actionid == 2005) then
       if player:getStorageValue(2000) == 4 then
         item:transform(1354)
         addEvent(resetblue, 10000, toPosition)
         player:setStorageValue(2000,5)
       else
         item:transform(1355)
         addEvent(resetred, 10000, toPosition)
         doAddCondition(player, exhaust)
         player:setStorageValue(2000,-1)
       end
      
   -- Stone 3
     elseif (item.actionid == 2003) then
       if player:getStorageValue(2000) == 5 then
         local chest = getTileItemById(chestpos, 12664)
         local create = doCreateItem(12664,1,chestpos)
         item:transform(1354)
         doSetItemActionId(create, 2010)
         doSummonCreature("Tarantula", stone1pos)
         doSummonCreature("Tarantula", stone3pos)
         doSummonCreature("Tarantula", stone6pos)
         addEvent(resetblue, 10000, toPosition)
         addEvent(destroychest, 10000)
         doAddCondition(player, exhaust)
         player:setStorageValue(2000,-1)
         doSendMagicEffect(stone1pos, 12)
         doSendMagicEffect(stone2pos, 12)
         doSendMagicEffect(stone3pos, 12)
         doSendMagicEffect(stone4pos, 12)
         doSendMagicEffect(stone5pos, 12)
         doSendMagicEffect(stone6pos, 12)
       else
         item:transform(1355)
         addEvent(resetred, 10000, toPosition)
         doAddCondition(player, exhaust)
         player:setStorageValue(2000,-1)
       end
     end
   end
end

Doing a bit of reading to get my ahead around the syntax, to reduce it further.
 
Here is the third revision, getting the hang of it:

Code:
local exhaust = createConditionObject(CONDITION_EXHAUST)
         setConditionParam(exhaust, CONDITION_PARAM_TICKS, 10000)

local chestpos = {x=1053, y=525, z=11}
local stone1pos = {x=1053, y=520, z=11}
local stone2pos = {x=1057, y=521, z=11}
local stone3pos = {x=1059, y=525, z=11}
local stone4pos = {x=1055, y=529, z=11}
local stone5pos = {x=1050, y=528, z=11}
local stone6pos = {x=1049, y=523, z=11}

function resetred(r)
   doTransformItem(getTileItemById(r, 1355).uid, 1304)
   return true
end
function resetblue(b)
   doTransformItem(getTileItemById(b, 1354).uid, 1304)
   return true
end

function destroychest()
   doRemoveItem(getTileItemById(chestpos, 12664).uid,1)
   doSendMagicEffect(chestpos, CONST_ME_POFF)
   return true
end
function onUse(player, item, fromPosition, itemEx, toPosition)
   if getCreatureCondition(player, CONDITION_EXHAUST) == TRUE then
     local pos = player:getPosition()
     pos:sendMagicEffect(CONST_ME_POFF)
     player:sendTextMessage(MESSAGE_STATUS_SMALL, Game.getReturnMessage(RETURNVALUE_YOUAREEXHAUSTED))
     return true
   else
   -- Stone 1
     if (item.actionid == 2001) and player:getStorageValue(2000) < 0 then
       item:transform(1354)
       addEvent(resetblue, 10000, toPosition)
       player:setStorageValue(2000,1)


   -- Stone 2
     elseif (item.actionid == 2002) and player:getStorageValue(2000) == 1 then
       item:transform(1354)
       addEvent(resetblue, 10000, toPosition)
       player:setStorageValue(2000,2)
      
   -- Stone 4
     elseif (item.actionid == 2004) and player:getStorageValue(2000) == 2 then
       item:transform(1354)
       addEvent(resetblue, 10000, toPosition)
       player:setStorageValue(2000,3)
      
   -- Stone 6
     elseif (item.actionid == 2006) and player:getStorageValue(2000) == 3 then
       item:transform(1354)
       addEvent(resetblue, 10000, toPosition)
       player:setStorageValue(2000,4)
      
   -- Stone 5
     elseif (item.actionid == 2005) and player:getStorageValue(2000) == 4 then
         item:transform(1354)
         addEvent(resetblue, 10000, toPosition)
         player:setStorageValue(2000,5)
      
   -- Stone 3
     elseif (item.actionid == 2003) and player:getStorageValue(2000) == 5 then
       local chest = getTileItemById(chestpos, 12664)
       local create = doCreateItem(12664,1,chestpos)
       item:transform(1354)
       doSetItemActionId(create, 2010)
       doSummonCreature("Tarantula", stone1pos)
       doSummonCreature("Tarantula", stone3pos)
       doSummonCreature("Tarantula", stone6pos)
       addEvent(resetblue, 10000, toPosition)
       addEvent(destroychest, 10000)
       doAddCondition(player, exhaust)
       player:setStorageValue(2000,-1)
       doSendMagicEffect(stone1pos, 12)
       doSendMagicEffect(stone2pos, 12)
       doSendMagicEffect(stone3pos, 12)
       doSendMagicEffect(stone4pos, 12)
       doSendMagicEffect(stone5pos, 12)
       doSendMagicEffect(stone6pos, 12)
    
     else
       item:transform(1355)
       addEvent(resetred, 10000, toPosition)
       doAddCondition(player, exhaust)
       player:setStorageValue(2000,-1)
     end
   end
end

alot cleaner...


EDIT: Final Revision:
This is effectively a puzzle quest that spawns a temporary quest chest when completed.

I could reduce the stone positions to a table, but that's for another day, I've done enough reading...

Code:
local exhaust = createConditionObject(CONDITION_EXHAUST)
         setConditionParam(exhaust, CONDITION_PARAM_TICKS, 3000)

local chestpos = {x=1053, y=525, z=11}
local stone1pos = {x=1053, y=520, z=11}
local stone2pos = {x=1057, y=521, z=11}
local stone3pos = {x=1059, y=525, z=11}
local stone4pos = {x=1055, y=529, z=11}
local stone5pos = {x=1050, y=528, z=11}
local stone6pos = {x=1049, y=523, z=11}

function resetred()
   doTransformItem(getTileItemById(stone1pos, 1355).uid, 1304)
   doTransformItem(getTileItemById(stone2pos, 1355).uid, 1304)
   doTransformItem(getTileItemById(stone3pos, 1355).uid, 1304)
   doTransformItem(getTileItemById(stone4pos, 1355).uid, 1304)
   doTransformItem(getTileItemById(stone5pos, 1355).uid, 1304)
   doTransformItem(getTileItemById(stone6pos, 1355).uid, 1304)
 end
 function resetblue()
   doTransformItem(getTileItemById(stone1pos, 1354).uid, 1304)
   doTransformItem(getTileItemById(stone2pos, 1354).uid, 1304)
   doTransformItem(getTileItemById(stone3pos, 1354).uid, 1304)
   doTransformItem(getTileItemById(stone4pos, 1354).uid, 1304)
   doTransformItem(getTileItemById(stone5pos, 1354).uid, 1304)
   doTransformItem(getTileItemById(stone6pos, 1354).uid, 1304)
 end

 function destroychest()
   doRemoveItem(getTileItemById(chestpos, 12664).uid,1)
   doSendMagicEffect(chestpos, CONST_ME_POFF)
   return true
 end
function onUse(player, item, fromPosition, itemEx, toPosition)
   if getCreatureCondition(player, CONDITION_EXHAUST) == TRUE then
     local pos = player:getPosition()
     pos:sendMagicEffect(CONST_ME_POFF)
     player:sendTextMessage(MESSAGE_STATUS_SMALL, Game.getReturnMessage(RETURNVALUE_YOUAREEXHAUSTED))
     return true
   else
   -- Stone 1
     if (item.actionid == 2001) and Game.getStorageValue(2000) < 0 then
       item:transform(1354)
       Game.setStorageValue(2000,1)

   -- Stone 2
     elseif (item.actionid == 2002) and Game.getStorageValue(2000) == 1 then
       item:transform(1354)
       Game.setStorageValue(2000,2)
       
   -- Stone 4
     elseif (item.actionid == 2004) and Game.getStorageValue(2000) == 2 then
       item:transform(1354)
       Game.setStorageValue(2000,3)
       
   -- Stone 6
     elseif (item.actionid == 2006) and Game.getStorageValue(2000) == 3 then
       item:transform(1354)
       Game.setStorageValue(2000,4)
       
   -- Stone 5
     elseif (item.actionid == 2005) and Game.getStorageValue(2000) == 4 then
         item:transform(1354)
         Game.setStorageValue(2000,5)
       
   -- Stone 3
     elseif (item.actionid == 2003) and Game.getStorageValue(2000) == 5 then
     
       item:transform(1354)
       addEvent(resetblue, 10000)
       Game.setStorageValue(2000,-1)
       doAddCondition(player, exhaust)
       
       doSendMagicEffect(stone1pos, 12)
       doSendMagicEffect(stone2pos, 12)
       doSendMagicEffect(stone3pos, 12)
       doSendMagicEffect(stone4pos, 12)
       doSendMagicEffect(stone5pos, 12)
       doSendMagicEffect(stone6pos, 12)
       doSummonCreature("Tarantula", stone1pos)
       doSummonCreature("Tarantula", stone3pos)
       doSummonCreature("Tarantula", stone6pos)
       
   -- Trigger Quest Chest
   
       local chest = getTileItemById(chestpos, 12664)
       local create = doCreateItem(12664,1,chestpos)
       doSetItemActionId(create, 2010)
       addEvent(destroychest, 10000)
     
     elseif (item.actionid >= 2001) and (item.actionid <= 2006) and Game.getStorageValue(2000) < 0 and not (item.itemid == 1304) then
       doAddCondition(player, exhaust)
     else
       item:transform(1355)
       addEvent(resetred, 3000)
       addEvent(resetblue, 3000)
       doAddCondition(player, exhaust)
       Game.setStorageValue(2000,-1)
     end
   end
end

hopefully the revisions are followable and help someone else in the future.
 
Last edited:
Back
Top