krafttomten
Well-Known Member
First of all, this is a python code. I couldn't find a good place to post this, maybe there is no such place for a reason. But this code has been very useful to me.
Second of all, this is made by a noob, so it is really wonky. But it works. I am hoping that it at least can serve as inspiration to someone here to make something but better. Or that someone can use the code like I do. To avoid having to manually change quest rewards each time I add new items to the game.
The code compares the movements.xml with the items.xml and creates matching pairs which is then formatted into a LUA list.
Here's the code.
Small note, since the potions are not movements, I added those manually through a string and they are only part of the python code because laziness / convenience.
You can add any items manually through this string, and the stuff will be inserted to the corresponding vocation.
I'll throw in my daily quest reward system aswell, with an empty reward list, since this one is created through the python code.
and ofc you need some way to run the script. I use an actionid in an onUse actions declared in actions.xml, like
The output of the python code should look something like this:
Hopefully this can help someone out
Second of all, this is made by a noob, so it is really wonky. But it works. I am hoping that it at least can serve as inspiration to someone here to make something but better. Or that someone can use the code like I do. To avoid having to manually change quest rewards each time I add new items to the game.
The code compares the movements.xml with the items.xml and creates matching pairs which is then formatted into a LUA list.
Here's the code.
Small note, since the potions are not movements, I added those manually through a string and they are only part of the python code because laziness / convenience.
You can add any items manually through this string, and the stuff will be inserted to the corresponding vocation.
Python:
pots = ["""-- Sorcerer Potions
{itemid = 7440, count = {5, 15}, level = 0, slot = "feet", name = "mastermind potion"},
{itemid = 7620, count = {40, 100}, level = 8, slot = "feet", name = "mana potion"},
{itemid = 7589, count = {40, 100}, level = 50, slot = "feet", name = "strong mana potion"},
{itemid = 7590, count = {40, 100}, level = 80, slot = "feet", name = "great mana potion"},
{itemid = 26029, count = {40, 100}, level = 130, slot = "feet", name = "ultimate mana potion"},
-- Sorcerer Gear
""", """-- Druid Potions
{itemid = 7440, count = {40, 100}, level = 0, slot = "feet", name = "mastermind potion"},
{itemid = 7620, count = {40, 100}, level = 8, slot = "feet", name = "mana potion"},
{itemid = 7589, count = {40, 100}, level = 50, slot = "feet", name = "strong mana potion"},
{itemid = 7590, count = {40, 100}, level = 80, slot = "feet", name = "great mana potion"},
{itemid = 26029, count = {40, 100}, level = 130, slot = "feet", name = "ultimate mana potion"},
-- Druid Gear
""", """-- Paladin Potions
{itemid = 7443, count = {5, 15}, level = 0, slot = "feet", name = "bullseye potion"},
{itemid = 7618, count = {40, 100}, level = 8, slot = "feet", name = "health potion"},
{itemid = 7588, count = {40, 100}, level = 50, slot = "feet", name = "strong health potion"},
{itemid = 7589, count = {40, 100}, level = 50, slot = "feet", name = "strong mana potion"},
{itemid = 8472, count = {40, 100}, level = 80, slot = "feet", name = "great spirit potion"},
{itemid = 26030, count = {40, 100}, level = 130, slot = "feet", name = "supreme health potion"},
{itemid = 26031, count = {40, 100}, level = 130, slot = "feet", name = "ultimate spirit potion"},
-- Paladin gear
""", """-- Knight Potions
{itemid = 7439, count = {5, 15}, level = 0, slot = "feet", name = "berserk potion"},
{itemid = 7618, count = {40, 100}, level = 8, slot = "feet", name = "health potion"},
{itemid = 7620, count = {40, 100}, level = 0, slot = "feet", name = "mana potion"},
{itemid = 7588, count = {40, 100}, level = 50, slot = "feet", name = "strong health potion"},
{itemid = 7591, count = {40, 100}, level = 80, slot = "feet", name = "great health potion"},
{itemid = 8473, count = {40, 100}, level = 130, slot = "feet", name = "ultimate health potion"},
-- Knight Gear
"""]
filename = "Voc_list"
movements_path = "PATH_TO_MOVEMENTS.XML"
items_path = "PATH_TO_ITEMS.XML"
output_list = [] # Raw list with all the movements
vocList = [] # List with all indexed vocations
itemIdList = [] # List of indexed ID numbers
nameList = [] # List of indexed item names
slotList = [] # List of indexed item slots
levelReqList = [] # List of indexed level requirements
main_output_list = [] # Combinated list with all indexed lists
# Function to read a XML file and turn it's content into a list
# with each line in the XML as one item in the list
def make_raw_list(path):
with open(path, "r") as m:
m_content = m.read()
split_cont = m_content.split("\n")
tmp_work_list = []
for i2 in split_cont:
func_stripped_line = i2.strip()
i2_list = func_stripped_line.split("\n")
tmp_work_list.append(i2_list)
out_list = []
for i3 in tmp_work_list:
out_list += i3
return out_list
def count_vocation_index(all_vocations):
last_voc = ""
indexes = []
for key2, value2 in enumerate(all_vocations):
if not last_voc == value2:
indexes.append(key2)
last_voc = value2
return indexes
# Function to export final list with format to fit the final code
def export(npc_name):
voc_indexes = count_vocation_index(vocList)
count = 1
with open(f"{npc_name}.lua", "w") as npc_out:
for key3, grej in enumerate(main_output_list):
for key22, grej2 in enumerate(voc_indexes):
if int(key3) == int(grej2):
npc_out.write("[" + str(count) + "] = {\n")
npc_out.write(pots[count - 1])
npc_out.write(grej)
npc_out.write("\n")
count += 1
break
elif int(key3) == int(grej2) - 1:
npc_out.write(grej.strip(","))
npc_out.write("\n},\n\n")
break
elif int(key3) == len(main_output_list) - 1:
npc_out.write(grej.strip(","))
npc_out.write("\n")
break
elif int(key22) == 3:
npc_out.write(grej)
npc_out.write("\n")
npc_out.write("},\n")
# Reading the files and turning them into lists
# with the make_raw_list function
movements_list = make_raw_list(movements_path)
items_list = make_raw_list(items_path)
# This code pairs each vocation to each item.
vocations = ["Sorcerer", "Druid", "Paladin", "Knight"]
for i in vocations:
antal = 1
for k, v in enumerate(movements_list):
if v.__contains__(f'<vocation name="{i}"'):
save = False
index = k
while not save:
if movements_list[index].__contains__('itemid="') or movements_list[index].__contains__('fromid="'):
output_list.append(f"{i}: {movements_list[index]}")
vocList.append(i)
save = True
else:
index -= 1
# The next tast is to format the output string in this way:
# {itemid = 18410, count = {1}, voc = "knight", level = 150, slot = "shield", name = "prismatic shield"},
for i in output_list:
itemId = i.split(" ")[3].strip('"')[8:]
itemIdList.append(itemId)
itemNamnStringList = [] # Temporary list to sort item names
for i in itemIdList:
for rad in items_list:
if rad.__contains__(f'id="{i}"'):
itemNamnStringList.append(rad)
for i in itemNamnStringList:
nameList.append(i[i.find("name=") + 6:- 2])
for i in output_list:
for sak in i.split(" "):
if sak.__contains__('slot="'):
slotList.append(sak[6:-1])
for i in output_list:
if i.__contains__('level="'):
for sak in i.split(" "):
if sak.__contains__('level="'):
levelReqList.append(sak[7:-1])
else:
levelReqList.append("0")
for key, value in enumerate(output_list):
main_output_list.append('{itemid = ' + itemIdList[key]
+ ', count = {1}, '
# + 'voc = "' + vocList[key].lower() + '", ' # Remove this comment to include a vocation variable in the code
+ 'level = ' + levelReqList[key]
+ ', slot = "' + slotList[key]
+ '", name = "' + nameList[key]
+ '"},')
export(filename)
# print(count_vocation_index(vocList))
I'll throw in my daily quest reward system aswell, with an empty reward list, since this one is created through the python code.
Lua:
function onUse(cid, item, fromPosition, itemEx, toPosition, isHotkey)
local config = {
storage = item.uid,
exstorage = item.uid + 1,
rewards = {
-- Just paste in the result from the python code in here
}
}
local player = Player(cid)
local q = player:getLevel()
-- Add quests here with [NUMBER] being the UID of the used item.
local lvLi = {
[43200] = {li = {1, 45}, expMod = 1},--Ghoul
}
if (player:getLevel() < lvLi[item.uid].li[1]) or (player:getLevel() > lvLi[item.uid].li[2]) then
return player:sendTextMessage(MESSAGE_INFO_DESCR, "You do not meet the level requirements for this reward.")
end
local x = config.rewards[player:getVocation():getBase():getId()]
-- This part can be added if you want a common pool of items for all vocations, and that pool would be added as [5] = {List} in the config.rewards above.
-- if math.random(100) > 50 then
-- x = config.rewards[5]
-- end
local loop = true
local c = 1
while loop do
c = math.random(#x)
if (x[c].level <= q and (x[c].level >= (q / 3)) or x[c].level == 0) then
loop = false
end
end
-- EXPERIENCE REWARD (random amount, from 0.5 to 2 full levels * the expMod (EXP modifier) from the lvLi variable above )
local one_level = 50 * ((q * q) - (5 * q) + 8)
local xp = math.floor(math.random(one_level / 2, one_level * 2))-- math.floor is a way to round the numbers down to avoid crazy floats.
xp = xp * lvLi[item.uid].expMod
-- Each UID can be used once a day
if player:getStorageValue(config.storage) == tonumber(os.date("%w")) and player:getStorageValue(config.exstorage) > os.time() then
return player:sendTextMessage(MESSAGE_INFO_DESCR, "The chest is empty, come back tomorrow for a new reward.")
end
-- This just gets a reward from the list. Pretty standard stuff.
local info, count = ItemType(x[c].itemid),
x[c].count[2] and math.random(x[c].count[1], x[c].count[2]) or x[c].count[1]
if count > 1 then
text = count .. " " .. info:getPluralName()
else
text = info:getArticle() .. " " .. info:getName()
end
local itemx = Game.createItem(x[c].itemid, count)
if player:addItemEx(itemx) ~= RETURNVALUE_NOERROR then
player:getPosition():sendMagicEffect(CONST_ME_POFF)
text = "You have found a reward weighing " .. itemx:getWeight() ..
" oz. It is too heavy or you have not enough space."
else
text = "You have received " .. text .. ". Come back tomorrow for a new reward."
player:setStorageValue(config.storage, tonumber(os.date("%w")))
player:setStorageValue(config.exstorage, os.time() + 24 * 60 * 60)
doPlayerAddExp(cid, xp)
end
player:sendTextMessage(MESSAGE_INFO_DESCR, text .. " You have also recieved " .. xp .. " experience points!")
return true
end
and ofc you need some way to run the script. I use an actionid in an onUse actions declared in actions.xml, like
XML:
<action actionid="13337" script="quests/INSERT_NAME_OF_CODE.lua" />
The output of the python code should look something like this:
Hopefully this can help someone out