Edit: I was responding to a post that has now been deleted...
Hi akroma222. I would hardcode a table containing the names of all the ammunition types, in the order that you want to cycle through them, for example:
Code: Select all
ammoCycle = { "rock" , "throwing_knife" , "arrow" , }
Since we haven't specified keys for the table, lua starts at 1 and counts upwards to assign the keys, so this is equivalent to:
Code: Select all
ammoCycle = { [1] = "rock" , [2] = "throwing_knife" , [3] = "arrow" , }
This table allows us to easily convert a number into the name of an ammunition. Then, we'll also want a way to convert the name of an ammunition into the appropriate number. We could loop through the whole table every time looking for a match, but I prefer this method:
Code: Select all
ammoNumbers = {}
--build inverse table
for i , v in ipairs( ammoCycle ) do
ammoNumbers[v] = i
end
This code builds a table ammoNumbers which is the "inverse" of ammoCycle. When building inverse tables, it only makes sense if all of the entries in the original table are unique. So based on this example, ammoNumbers could have been defined this way:
Code: Select all
ammoNumbers = { rock = 1 , throwing_knife = 2 , arrow = 3 }
except that we haven't hardcoded it. This makes it very easy to add a new entry to ammoCycle (at the beginning, middle, or end), and rely on the code to keep ammoNumbers up-to-date automatically. With these tables built, you can easily identify which items are valid ammunition for switching:
Code: Select all
local item
local slot
for i = 7,8 do
item = caster:getItem(i)
if item and ammoNumbers[item.name] then
slot = i
break
end
end
if not slot then
return
end
If the item's name is used as a key in ammoNumbers, then it's valid. Now that we have these tables built and the slot determined, we can do the switch as:
Code: Select all
local oldAmmoName = item.name
local stackSize = item:getStackSize()
caster:removeItem(slot)
local newAmmoNumber = ( ammoNumbers[oldAmmoName] % ( table.getn( ammoCycle ) ) ) + 1
local newAmmo = spawn( ammoCycle[newAmmoNumber] )
newAmmo:setStackSize( stackSize )
caster:insertItem( slot , newAmmo )
playSound("generic_spell")
hudPrint( caster:getName() .. " trasmuted ammunition." )
The critical line for the switch is:
Code: Select all
local newAmmoNumber = ( ammoNumbers[oldAmmoName] % ( table.getn( ammoCycle ) ) ) + 1
ammoNumbers[oldAmmoName] - This gives us the number which is the key in ammoCycle corresponding to the old ammo.
table.getn( ammoCycle ) - This is the size of ammoCycle. In this example, it is 3.
% -
modulo. The reason we do this, is so that if ammoNumbers[oldAmmoName] is equal to table.getn( ammoCycle ) , then we wrap around to 0. Otherwise, the result of ammoNumbers[oldAmmoName] % ( table.getn( ammoCycle ) ) will just be equal to ammoNumbers[oldAmmoName] .
Then we add 1. The final result will always be a number between 1 and table.getn( ammoCycle ) inclusive. This will always be a valid key for the table ammoCycle .
The tables won't change after initialization, so I think it makes sense to build them just once, as non-locals. Putting everything together, we have:
Code: Select all
ammoCycle = { "rock" , "throwing_knife" , "arrow" , }
ammoNumbers = {}
--build inverse table
for i , v in ipairs( ammoCycle ) do
ammoNumbers[v] = i
end
onCastTransmuteAmmo = function( caster )
local item
local slot
for i = 7,8 do
item = caster:getItem(i)
if item and ammoNumbers[item.name] then
slot = i
break
end
end
if not slot then
return
end
local oldAmmoName = item.name
local stackSize = item:getStackSize()
caster:removeItem(slot)
local newAmmoNumber = ( ammoNumbers[oldAmmoName] % ( table.getn( ammoCycle ) ) ) + 1
local newAmmo = spawn( ammoCycle[newAmmoNumber] )
newAmmo:setStackSize( stackSize )
caster:insertItem( slot , newAmmo )
playSound("generic_spell")
hudPrint( caster:getName() .. " transmuted ammunition." )
end
Edited for spelling