This is only for monster drops right?? Not quest rewards
otherwise gj!
function onUse(player, item, fromPosition, target, toPosition, isHotkey)
local primarySkillList = {
["SKILL_SWORD"] = player:getSkillLevel(SKILL_SWORD),
["SKILL_AXE"] = player:getSkillLevel(SKILL_AXE),
["SKILL_CLUB"] = player:getSkillLevel(SKILL_CLUB)
}
-- Get Knight primary weapon type
local max_val, skillname = -math.huge
for k, v in pairs(primarySkillList) do
if v > max_val then
max_val, skillname = v, k
end
end
local primarySkill = skillname
local vocation = player:getVocation():getId()
local reward = 0
-- Calculate reward based of Vocation and primary weapon type if Knight.
if vocation == 1 then
reward = 18390
elseif vocation == 2 then
reward = 8850
elseif vocation == 3 then
if primarySkill == "SKILL_SWORD" then
reward = 6528
elseif primarySkill == "SKILL_AXE" then
reward = 8926
elseif primarySkill == "SKILL_CLUB" then
reward = 2453
end
else
-- this shouldnt ever roll
reward = 23531
end
local itemType = ItemType(reward)
local itemWeight = itemType:getWeight()
local playerCap = player:getFreeCapacity()
if player:getStorageValue(30051) == -1 then
if playerCap >= itemWeight then
player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have found a ' .. itemType:getName() .. '.')
player:addItem(reward, 1)
player:setStorageValue(30051, 1)
else
player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have found a ' .. itemType:getName() .. ' weighing ' ..(itemWeight / 100).. ' oz. It\'s too heavy.')
end
else
player:sendTextMessage(MESSAGE_INFO_DESCR, "It is empty.")
end
return true
end
function onUse(player, item, fromPosition, target, toPosition, isHotkey)
...
if player:getStorageValue(30051) == -1 then
if playerCap >= itemWeight then
player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have found a ' .. itemType:getName() .. '.')
-- EXAMPLE
local exampleRoll = player:addItem(reward, 1)
rollRarity(exampleRoll, "rare") -- FORCE A RARE (not epic, or legendary) on the item
-- /EXAMPLE
player:setStorageValue(30051, 1)
else
player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have found a ' .. itemType:getName() .. ' weighing ' ..(itemWeight / 100).. ' oz. It\'s too heavy.')
end
else
player:sendTextMessage(MESSAGE_INFO_DESCR, "It is empty.")
end
return true
end
Any idea when it will work for version 12.64?
data/lib/core/attributes.lua:894: attempt to index local 'it_u' (a nil value)
stack traceback:
[C]: in function '__index'
data/lib/core/attributes.lua:894: in function 'rollRarity'
data/events/scripts/monster.lua:7: in main chunk
[Warning - Events::load] Can not load script: monster.lua
item1pos = {x=31670, y=31891, z=15, stackpos=255} -- Item pra encantar
item2pos = {x=31672, y=31891, z=15, stackpos=255} -- Luky
item3pos = {x=31670, y=31891, z=15, stackpos=255} -- Create item sucesso
item4pos = {x=31671, y=31891, z=15, stackpos=255} -- Pergaminho
item1 = getThingfromPos(item1pos)
item2 = getThingfromPos(item2pos)
item3 = getThingfromPos(item3pos)
item4 = getThingfromPos(item4pos)
porcentagem = 20
porcent = math.random(1, 100)
-- Clerical Mace --
if item.itemid == 1945 and item4.itemid == 2160 and item1.itemid == 2423 and item2.itemid == 6550 or item1.itemid == 6550 and item2.itemid == 2423 and item4.itemid == 2160 then
if math.random(1, 100) >= 1 and math.random(1, 100) <= porcentagem then
doRemoveItem(item1.uid,1)
doRemoveItem(item2.uid,1)
doRemoveItem(math.random(1, 100) >= 1 and math.random(1, 100) <= 50 and item4.uid,1)
doSendMagicEffect(item3pos,29)
doCreateItem(7754, config.charges, item3pos)
doPlayerSendTextMessage(cid,22,'A arma foi blessada com sucesso.')
elseif item.uid == 1991 and item.itemid == 1946 then
doTransformItem(item.uid,item.itemid-1)
else
doPlayerSendTextMessage(cid,22,'A arma quebrou.')
doRemoveItem(item1.uid,1)
doRemoveItem(item2.uid,1)
doRemoveItem(math.random(1, 100) >= 1 and math.random(1, 100) <= 50 and item4.uid,1)
doSendMagicEffect(item3pos,3)
end
else doPlayerSendTextMessage(cid,22,'Verifique se você colocou todos os itens nos locais corretos.')
end
i have the same problemAmazing system! Installed perfectly on latest TFS 1.4? from here TFS and got 0 error/warnings
The thing is i only get rarity items when i use /roll but i can't get any rarity item with monster drops : ( killed many many many monsters and got 0 rarity items (and still 0 errors/warnings)
have you added the onInventoryUpdate event correctly?The script is very good. However there is a problem that the weapon attributes only work when I relog the character. And when I remove the weapon with attribute and put any other weapon in place the attributes remain the same until I relog again. In short, it's just updating the attributes when I relog. Does anybody know how to solve this ?
have you added the onInventoryUpdate event correctly?
function Player:onBrowseField(position)
if hasEventCallback(EVENT_CALLBACK_ONBROWSEFIELD) then
return EventCallback(EVENT_CALLBACK_ONBROWSEFIELD, self, position)
end
return true
end
function Player:onLook(thing, position, distance)
local description = ""
if hasEventCallback(EVENT_CALLBACK_ONLOOK) then
description = EventCallback(EVENT_CALLBACK_ONLOOK, self, thing, position, distance, description)
end
self:sendTextMessage(MESSAGE_INFO_DESCR, description)
end
function Player:onLookInBattleList(creature, distance)
local description = ""
if hasEventCallback(EVENT_CALLBACK_ONLOOKINBATTLELIST) then
description = EventCallback(EVENT_CALLBACK_ONLOOKINBATTLELIST, self, creature, distance, description)
end
self:sendTextMessage(MESSAGE_INFO_DESCR, description)
end
function Player:onLookInTrade(partner, item, distance)
local description = "You see " .. item:getDescription(distance)
if hasEventCallback(EVENT_CALLBACK_ONLOOKINTRADE) then
description = EventCallback(EVENT_CALLBACK_ONLOOKINTRADE, self, partner, item, distance, description)
end
self:sendTextMessage(MESSAGE_INFO_DESCR, description)
end
function Player:onLookInShop(itemType, count, description)
local description = "You see " .. description
if hasEventCallback(EVENT_CALLBACK_ONLOOKINSHOP) then
description = EventCallback(EVENT_CALLBACK_ONLOOKINSHOP, self, itemType, count, description)
end
self:sendTextMessage(MESSAGE_INFO_DESCR, description)
end
function Player:onMoveItem(item, count, fromPosition, toPosition, fromCylinder, toCylinder)
if hasEventCallback(EVENT_CALLBACK_ONMOVEITEM) then
return EventCallback(EVENT_CALLBACK_ONMOVEITEM, self, item, count, fromPosition, toPosition, fromCylinder, toCylinder)
end
return true
end
function Player:onItemMoved(item, count, fromPosition, toPosition, fromCylinder, toCylinder)
if hasEventCallback(EVENT_CALLBACK_ONITEMMOVED) then
EventCallback(EVENT_CALLBACK_ONITEMMOVED, self, item, count, fromPosition, toPosition, fromCylinder, toCylinder)
end
end
function Player:onMoveCreature(creature, fromPosition, toPosition)
if hasEventCallback(EVENT_CALLBACK_ONMOVECREATURE) then
return EventCallback(EVENT_CALLBACK_ONMOVECREATURE, self, creature, fromPosition, toPosition)
end
return true
end
function Player:onReportRuleViolation(targetName, reportType, reportReason, comment, translation)
if hasEventCallback(EVENT_CALLBACK_ONREPORTRULEVIOLATION) then
EventCallback(EVENT_CALLBACK_ONREPORTRULEVIOLATION, self, targetName, reportType, reportReason, comment, translation)
end
end
function Player:onReportBug(message, position, category)
if hasEventCallback(EVENT_CALLBACK_ONREPORTBUG) then
return EventCallback(EVENT_CALLBACK_ONREPORTBUG, self, message, position, category)
end
return true
end
function Player:onTurn(direction)
if hasEventCallback(EVENT_CALLBACK_ONTURN) then
return EventCallback(EVENT_CALLBACK_ONTURN, self, direction)
end
return true
end
function Player:onTradeRequest(target, item)
if hasEventCallback(EVENT_CALLBACK_ONTRADEREQUEST) then
return EventCallback(EVENT_CALLBACK_ONTRADEREQUEST, self, target, item)
end
return true
end
function Player:onTradeAccept(target, item, targetItem)
if hasEventCallback(EVENT_CALLBACK_ONTRADEACCEPT) then
return EventCallback(EVENT_CALLBACK_ONTRADEACCEPT, self, target, item, targetItem)
end
return true
end
function Player:onTradeCompleted(target, item, targetItem, isSuccess)
if hasEventCallback(EVENT_CALLBACK_ONTRADECOMPLETED) then
EventCallback(EVENT_CALLBACK_ONTRADECOMPLETED, self, target, item, targetItem, isSuccess)
end
end
local soulCondition = Condition(CONDITION_SOUL, CONDITIONID_DEFAULT)
soulCondition:setTicks(4 * 60 * 1000)
soulCondition:setParameter(CONDITION_PARAM_SOULGAIN, 1)
local function useStamina(player)
local staminaMinutes = player:getStamina()
if staminaMinutes == 0 then
return
end
local playerId = player:getId()
local currentTime = os.time()
local timePassed = currentTime - nextUseStaminaTime[playerId]
if timePassed <= 0 then
return
end
if timePassed > 60 then
if staminaMinutes > 2 then
staminaMinutes = staminaMinutes - 2
else
staminaMinutes = 0
end
nextUseStaminaTime[playerId] = currentTime + 120
else
staminaMinutes = staminaMinutes - 1
nextUseStaminaTime[playerId] = currentTime + 60
end
player:setStamina(staminaMinutes)
end
function Player:onGainExperience(source, exp, rawExp)
if source:isMonster() then
local bonusExperience = source:getMonsterLevel() * 0.03
if source:getMonsterLevel() > 0 and bonusExperience > 1 then
exp = exp * bonusExperience
end
end
if not source or source:isPlayer() then
return exp
end
-- Soul regeneration
local vocation = self:getVocation()
if self:getSoul() < vocation:getMaxSoul() and exp >= self:getLevel() then
soulCondition:setParameter(CONDITION_PARAM_SOULTICKS, vocation:getSoulGainTicks() * 1000)
self:addCondition(soulCondition)
end
-- Apply experience stage multiplier
exp = exp * Game.getExperienceStage(self:getLevel())
-- Stamina modifier
if configManager.getBoolean(configKeys.STAMINA_SYSTEM) then
useStamina(self)
local staminaMinutes = self:getStamina()
if staminaMinutes > 2400 and self:isPremium() then
exp = exp * 1.5
elseif staminaMinutes <= 840 then
exp = exp * 0.5
end
end
return hasEventCallback(EVENT_CALLBACK_ONGAINEXPERIENCE) and EventCallback(EVENT_CALLBACK_ONGAINEXPERIENCE, self, source, exp, rawExp) or exp
end
function Player:onLoseExperience(exp)
return hasEventCallback(EVENT_CALLBACK_ONLOSEEXPERIENCE) and EventCallback(EVENT_CALLBACK_ONLOSEEXPERIENCE, self, exp) or exp
end
function Player:onGainSkillTries(skill, tries)
if APPLY_SKILL_MULTIPLIER == false then
return hasEventCallback(EVENT_CALLBACK_ONGAINSKILLTRIES) and EventCallback(EVENT_CALLBACK_ONGAINSKILLTRIES, self, skill, tries) or tries
end
if skill == SKILL_MAGLEVEL then
tries = tries * configManager.getNumber(configKeys.RATE_MAGIC)
return hasEventCallback(EVENT_CALLBACK_ONGAINSKILLTRIES) and EventCallback(EVENT_CALLBACK_ONGAINSKILLTRIES, self, skill, tries) or tries
end
tries = tries * configManager.getNumber(configKeys.RATE_SKILL)
return hasEventCallback(EVENT_CALLBACK_ONGAINSKILLTRIES) and EventCallback(EVENT_CALLBACK_ONGAINSKILLTRIES, self, skill, tries) or tries
end
function Player:onWrapItem(item)
local topCylinder = item:getTopParent()
if not topCylinder then
return
end
local tile = Tile(topCylinder:getPosition())
if not tile then
return
end
local house = tile:getHouse()
if not house then
self:sendCancelMessage("You can only wrap and unwrap this item inside a house.")
return
end
if house ~= self:getHouse() and not string.find(house:getAccessList(SUBOWNER_LIST):lower(), "%f[%a]" .. self:getName():lower() .. "%f[%A]") then
self:sendCancelMessage("You cannot wrap or unwrap items from a house, which you are only guest to.")
return
end
local wrapId = item:getAttribute("wrapid")
if wrapId == 0 then
return
end
if not hasEventCallback(EVENT_CALLBACK_ONWRAPITEM) or EventCallback(EVENT_CALLBACK_ONWRAPITEM, self, item) then
local oldId = item:getId()
item:remove(1)
local item = tile:addItem(wrapId)
if item then
item:setAttribute("wrapid", oldId)
end
end
end
function Player:onInventoryUpdate(item, slot, equip)
itemAttributes(self, item, slot, equip)
end
Thanks it was an error in the source the skills update I managed to solve. The only thing now that does not work only elemental attributes.have you added the onInventoryUpdate event correctly?
thanks I managed to solve the skill update problem. The only problem now is the elemental damage doesn't work, it doesn't work and I don't know how to solve it.have you added the onInventoryUpdate event correctly?
data/lib/core/attributes.lua:894: attempt to index local 'it_u' (a nil value)
Pretty nice system! I want to implement the roll on chests using this code: [TFS 1.3] Advanced quest chests (https://otland.net/threads/tfs-1-3-advanced-quest-chests.277772/) is is posible?rolls are done using a simple new function:
![]()
forgottenserver/data/lib/core/attributes.lua at rarity-custom-attributes · Leo32onGIT/forgottenserver
A free and open-source MMORPG server emulator written in C++ - Leo32onGIT/forgottenservergithub.com
so you can add this to quests chests by adding a line to that chest's code, to roll the item:
here is an example, a quest chest that gives different rewards depending on the VOC of the player:
LUA:function onUse(player, item, fromPosition, target, toPosition, isHotkey) local primarySkillList = { ["SKILL_SWORD"] = player:getSkillLevel(SKILL_SWORD), ["SKILL_AXE"] = player:getSkillLevel(SKILL_AXE), ["SKILL_CLUB"] = player:getSkillLevel(SKILL_CLUB) } -- Get Knight primary weapon type local max_val, skillname = -math.huge for k, v in pairs(primarySkillList) do if v > max_val then max_val, skillname = v, k end end local primarySkill = skillname local vocation = player:getVocation():getId() local reward = 0 -- Calculate reward based of Vocation and primary weapon type if Knight. if vocation == 1 then reward = 18390 elseif vocation == 2 then reward = 8850 elseif vocation == 3 then if primarySkill == "SKILL_SWORD" then reward = 6528 elseif primarySkill == "SKILL_AXE" then reward = 8926 elseif primarySkill == "SKILL_CLUB" then reward = 2453 end else -- this shouldnt ever roll reward = 23531 end local itemType = ItemType(reward) local itemWeight = itemType:getWeight() local playerCap = player:getFreeCapacity() if player:getStorageValue(30051) == -1 then if playerCap >= itemWeight then player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have found a ' .. itemType:getName() .. '.') player:addItem(reward, 1) player:setStorageValue(30051, 1) else player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have found a ' .. itemType:getName() .. ' weighing ' ..(itemWeight / 100).. ' oz. It\'s too heavy.') end else player:sendTextMessage(MESSAGE_INFO_DESCR, "It is empty.") end return true end
here is the edited code, with me forcing a roll on the item the player gets from the chest:
LUA:function onUse(player, item, fromPosition, target, toPosition, isHotkey) ... if player:getStorageValue(30051) == -1 then if playerCap >= itemWeight then player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have found a ' .. itemType:getName() .. '.') -- EXAMPLE local exampleRoll = player:addItem(reward, 1) rollRarity(exampleRoll, "rare") -- FORCE A RARE (not epic, or legendary) on the item -- /EXAMPLE player:setStorageValue(30051, 1) else player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have found a ' .. itemType:getName() .. ' weighing ' ..(itemWeight / 100).. ' oz. It\'s too heavy.') end else player:sendTextMessage(MESSAGE_INFO_DESCR, "It is empty.") end return true end
EDIT:
it seems like this library has been expanded upon quite a bit since i first released it.
would be really cool to see what the last clean up/expansion to this code looks like.
function capAll(str)
return (str:gsub("(%l)(%w*)", function(a,b) return string.upper(a)..b end))
end
local advanceChest = Action()
function advanceChest.onUse(player, item, fromPosition, itemEx, toPosition)
-----------------------------------------------------------------------------------
-- Local Variables --
-----------------------------------------------------------------------------------
local questChest = item:getUniqueId()
-----------------------------------------------------------------------------------
-- Check if player has already opened box --
-----------------------------------------------------------------------------------
if player:getStorageValue(questChest) == 1 then
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The chest is empty.")
toPosition:sendMagicEffect(10)
return true
end
local storageOne = questChests[questChest].storageUnique
-----------------------------------------------------------------------------------
-- Check if player has already opened box multiple chest only 1 reward --
-----------------------------------------------------------------------------------
if player:getStorageValue(storageOne) == 1 then
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The chest is empty.")
toPosition:sendMagicEffect(10)
return true
end
-----------------------------------------------------------------------------------
-- Check if player meets level requirment
-----------------------------------------------------------------------------------
local playerLevel = player:getLevel()
local minLevel = questChests[questChest].minLevel
if questChests[questChest].minLevel => playerLevel then
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need to be level "..minLevel.." to open this chest.")
return true
end
-----------------------------------------------------------------------------------
-- Give rewward if player has not yet opened box --
-----------------------------------------------------------------------------------
for i = 1, #questChests[questChest].items do
local rewardType = questChests[questChest].items[i].type
-----------------------------------------------------------------------------------
-- Item Type Reward --
-----------------------------------------------------------------------------------
if rewardType == "item" then
local item = questChests[questChest].items[i].item
local count = questChests[questChest].items[i].count
player:addItem(item, count)
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You earned ["..count.."x] "..capAll(getItemName(item)))
end
-----------------------------------------------------------------------------------
-- Experience Type Reward --
-----------------------------------------------------------------------------------
if rewardType == "experience" then
local amount = questChests[questChest].items[i].amount
player:addExperience(amount)
player:say(amount.." EXP gained!", TALKTYPE_MONSTER_SAY)
player:getPosition():sendMagicEffect(CONST_ME_STUN)
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You gained "..amount.." experience points.")
end
-----------------------------------------------------------------------------------
-- Outfit Type Reward --
-----------------------------------------------------------------------------------
if rewardType == "outfit" then
local outfitName = questChests[questChest].items[i].name
local maleOutfit = questChests[questChest].items[i].maleId
local femaleOutfit = questChests[questChest].items[i].femaleId
if player:getSex() == 0 then
player:addOutfit(femaleOutfit)
else
player:addOutfit(maleOutfit)
end
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You gained the "..outfitName.." outfit.")
end
-----------------------------------------------------------------------------------
-- Addon Type Reward --
-----------------------------------------------------------------------------------
if rewardType == "addon" then
local outfitName = questChests[questChest].items[i].outfit
local addon = questChests[questChest].items[i].addonNumber
local maleAddon = questChests[questChest].items[i].maleId
local femaleAddon = questChests[questChest].items[i].femaleId
if player:getSex() == 0 then
player:addOutfitAddon(femaleAddon, addon)
else
player:addOutfitAddon(maleAddon, addon)
end
if addon == 1 then
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You gained the first "..outfitName.." outfit addon.")
elseif addon == 2 then
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You gained the second "..outfitName.." outfit addon.")
elseif addon == 3 then
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You gained the third "..outfitName.." outfit addon.")
end
end
-----------------------------------------------------------------------------------
-- Mount Type Reward --
-----------------------------------------------------------------------------------
if rewardType == "mount" then
local mountName = questChests[questChest].items[i].mountName
local mountId = questChests[questChest].items[i].mountId
player:addMount(mountId)
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "You have unlocked the "..mountName.." mount.")
end
-----------------------------------------------------------------------------------
-- Add in any cooldowns/storages --
-----------------------------------------------------------------------------------
player:setStorageValue(questChest, 1)
player:setStorageValue(storageOne, 1)
return true
end
end
for i = 2000, 2100 do
advanceChest:uid(i)
end
advanceChest:register()
I have the same problem were you able to fix it?Amazing system! Installed perfectly on latest TFS 1.4? from here TFS and got 0 error/warnings
The thing is i only get rarity items when i use /roll but i can't get any rarity item with monster drops : ( killed many many many monsters and got 0 rarity items (and still 0 errors/warnings)