jareczekjsp
Member
Hello Guys I have Problem with Upgrade system Can you help me please?
My script
Lua:
Lua Script Error: [Scripts Interface]
/home/ots/data/scripts/custom/small_upgrade_system.lua:callback
/home/ots/data/scripts/custom/small_upgrade_system.lua:629: attempt to index local 'attacker' (a nil value)
stack traceback:
[C]: in function '__index'
/home/ots/data/scripts/custom/small_upgrade_system.lua:629: in function </home/ots/data/scripts/custom/small_upgrade_system.lua:628>
Lua Script Error: [Scripts Interface]
/home/ots/data/scripts/custom/small_upgrade_system.lua:callback
/home/ots/data/scripts/custom/small_upgrade_system.lua:629: attempt to index local 'attacker' (a nil value)
stack traceback:
[C]: in function '__index'
/home/ots/data/scripts/custom/small_upgrade_system.lua:629: in function </home/ots/data/scripts/custom/small_upgrade_system.lua:628>
Lua Script Error: [Scripts Interface]
/home/ots/data/scripts/custom/small_upgrade_system.lua:callback
/home/ots/data/scripts/custom/small_upgrade_system.lua:629: attempt to index local 'attacker' (a nil value)
stack traceback:
[C]: in function '__index'
/home/ots/data/scripts/custom/small_upgrade_system.lua:629: in function </home/ots/data/scripts/custom/small_upgrade_system.lua:628>
Lua Script Error: [Scripts Interface]
/home/ots/data/scripts/custom/small_upgrade_system.lua:callback
/home/ots/data/scripts/custom/small_upgrade_system.lua:629: attempt to index local 'attacker' (a nil value)
stack traceback:
[C]: in function '__index'
/home/ots/data/scripts/custom/small_upgrade_system.lua:629: in function </home/ots/data/scripts/custom/small_upgrade_system.lua:628>
My script
Code:
local config = {
interfaceName = "Extra Attributes",
chances = {
[0] = { chance=100 },
[1] = { downLvl=0, chance=100 },
[2] = { downLvl=1, chance=90 },
[3] = { downLvl=2, chance=80 },
[4] = { downLvl=3, chance=70 },
[5] = { downLvl=4, chance=60 },
[6] = { downLvl=5, chance=50 },
[7] = { downLvl=6, chance=40 },
[8] = { downLvl=7, chance=30 },
[9] = { downLvl=8, chance=20 },
[10] = { downLvl=9 }
},
downgradeEnabled = false,
debugMode = false,
values = {
--[[[number] = {
chance=number,
effect=number,
upgrade={
["armor"] = number,
["defense"] = number,
["extraDefense"] = number,
["attack"] = number,
["wandDamage"] = number,
["skills"] = number,
["specialSkills"] = number,
["stats"] = number,
["maxHealth"] = number,
["maxMana"] = number,
["elementDamage"] = number,
>>>> Do you want a specific attribute? <<<<
example:
["fist fighting"] = 10,
}
},]]--
--.............START.............--
[8300] = { -- Mind Stone
chance=100,
minRequireLvl = 0,
maxRequireLvl = 10,
breakWhenFail = false,
breakLvl = 10,
effect=CONST_ME_FIREWORK_YELLOW,
upgrade={
["armor"] = 3,
["defense"] = 3,
["extraDefense"] = 2,
["attack"] = 2,
["wandDamage"] = 2,
["skills"] = 3,
["specialSkills"] = 2,
["stats"] = 2,
["maxHealth"] = 100,
["maxMana"] = 100,
["elementDamage"] = 2
}
},
[8300] = { -- Strange Simbol
chance=50,
minRequireLvl = 5,
maxRequireLvl = 10,
breakWhenFail = false,
effect=CONST_ME_FIREWORK_BLUE,
upgrade={
["armor"] = 3,
["defense"] = 3,
["extraDefense"] = 2,
["attack"] = 3,
["wandDamage"] = 2,
["skills"] = 3,
["specialSkills"] = 2,
["stats"] = 3,
["maxHealth"] = 100,
["maxMana"] = 100,
["elementDamage"] = 2
}
}
--..............END..............--
}
}
--------------------------------------------------------------------------------------
-- EN: Modifying things below can be dangerous, be careful
-- ES: Modificar las cosas a continuaciĂłn puede ser peligroso, tenga cuidado
-- BR: Modificar as coisas abaixo pode ser perigoso, tome cuidado
--------------------------------------------------------------------------------------
local conditions = {
["fist fighting"] = {
abilitie = {
type = "skills",
index = SKILL_FIST
},
condition = {
id = CONDITIONID_DEFAULT,
subId = 1000,
type = CONDITION_ATTRIBUTES,
param = CONDITION_PARAM_SKILL_FIST,
ticks = -1
}
},
["club fighting"] = {
abilitie = {
type = "skills",
index = SKILL_CLUB
},
condition = {
id = CONDITIONID_DEFAULT,
subId = 1001,
type = CONDITION_ATTRIBUTES,
param = CONDITION_PARAM_SKILL_CLUB,
ticks = -1
}
},
["sword fighting"] = {
abilitie = {
type = "skills",
index = SKILL_SWORD
},
condition = {
id = CONDITIONID_DEFAULT,
subId = 1002,
type = CONDITION_ATTRIBUTES,
param = CONDITION_PARAM_SKILL_SWORD,
ticks = -1
}
},
["axe fighting"] = {
abilitie = {
type = "skills",
index = SKILL_AXE
},
condition = {
id = CONDITIONID_DEFAULT,
subId = 1003,
type = CONDITION_ATTRIBUTES,
param = CONDITION_PARAM_SKILL_AXE,
ticks = -1
}
},
["distance fighting"] = {
abilitie = {
type = "skills",
index = SKILL_DISTANCE
},
condition = {
id = CONDITIONID_DEFAULT,
subId = 1004,
type = CONDITION_ATTRIBUTES,
param = CONDITION_PARAM_SKILL_DISTANCE,
ticks = -1
}
},
["shielding"] = {
abilitie = {
type = "skills",
index = SKILL_SHIELD
},
condition = {
id = CONDITIONID_DEFAULT,
subId = 1005,
type = CONDITION_ATTRIBUTES,
param = CONDITION_PARAM_SKILL_SHIELD,
ticks = -1
}
},
["fishing"] = {
abilitie = {
type = "skills",
index = SKILL_FISHING
},
condition = {
id = CONDITIONID_DEFAULT,
subId = 1006,
type = CONDITION_ATTRIBUTES,
param = CONDITION_PARAM_SKILL_FISHING,
ticks = -1
}
},
["max health"] = {
abilitie = {
type = "stats",
index = STAT_MAXHITPOINTS
},
condition = {
id = CONDITIONID_DEFAULT,
subId = 1007,
type = CONDITION_ATTRIBUTES,
param = CONDITION_PARAM_STAT_MAXHITPOINTS,
ticks = -1
}
},
["max mana"] = {
abilitie = {
type = "stats",
index = STAT_MAXMANAPOINTS
},
condition = {
id = CONDITIONID_DEFAULT,
subId = 1008,
type = CONDITION_ATTRIBUTES,
param = CONDITION_PARAM_STAT_MAXMANAPOINTS,
ticks = -1
}
},
["magic level"] = {
abilitie = {
type = "stats",
index = STAT_MAGICPOINTS
},
condition = {
id = CONDITIONID_DEFAULT,
subId = 1009,
type = CONDITION_ATTRIBUTES,
param = CONDITION_PARAM_STAT_MAGICPOINTS,
ticks = -1
}
},
["critical hit chance"] = {
abilitie = {
type = "specialSkills",
index = SPECIALSKILL_CRITICALHITCHANCE
},
condition = {
id = CONDITIONID_DEFAULT,
subId = 1012,
type = CONDITION_ATTRIBUTES,
param = CONDITION_PARAM_SPECIALSKILL_CRITICALHITCHANCE,
ticks = -1
}
},
["critical extra damage"] = {
abilitie = {
type = "specialSkills",
index = SPECIALSKILL_CRITICALHITAMOUNT
},
condition = {
id = CONDITIONID_DEFAULT,
subId = 1013,
type = CONDITION_ATTRIBUTES,
param = CONDITION_PARAM_SPECIALSKILL_CRITICALHITAMOUNT,
ticks = -1
}
},
["hitpoints leech chance"] = {
abilitie = {
type = "specialSkills",
index = SPECIALSKILL_LIFELEECHCHANCE
},
condition = {
id = CONDITIONID_DEFAULT,
subId = 1014,
type = CONDITION_ATTRIBUTES,
param = CONDITION_PARAM_SPECIALSKILL_LIFELEECHCHANCE,
ticks = -1
}
},
["hitpoints leech amount"] = {
abilitie = {
type = "specialSkills",
index = SPECIALSKILL_LIFELEECHAMOUNT
},
condition = {
id = CONDITIONID_DEFAULT,
subId = 1015,
type = CONDITION_ATTRIBUTES,
param = CONDITION_PARAM_SPECIALSKILL_LIFELEECHAMOUNT,
ticks = -1
}
},
["manapoints leech chance"] = {
abilitie = {
type = "specialSkills",
index = SPECIALSKILL_MANALEECHCHANCE
},
condition = {
id = CONDITIONID_DEFAULT,
subId = 1016,
type = CONDITION_ATTRIBUTES,
param = CONDITION_PARAM_SPECIALSKILL_MANALEECHCHANCE,
ticks = -1
}
},
["mana points leech amount"] = {
abilitie = {
type = "specialSkills",
index = SPECIALSKILL_MANALEECHAMOUNT
},
condition = {
id = CONDITIONID_DEFAULT,
subId = 1017,
type = CONDITION_ATTRIBUTES,
param = CONDITION_PARAM_SPECIALSKILL_MANALEECHAMOUNT,
ticks = -1
}
}
}
local CONTAINER_POSITION = 0x63
local RETURNVALUE_NOERROR = 0
local conditionCount = 0
for _, __ in pairs(conditions) do
conditionCount = conditionCount +1
end
local function getPlayerWeapon(player)
local weapon = player:getSlotItem(CONST_SLOT_LEFT)
if not weapon or weapon:getType():getWeaponType() == WEAPON_NONE then
weapon = player:getSlotItem(CONST_SLOT_RIGHT)
if not weapon or weapon:getType():getWeaponType() == WEAPON_NONE then
return
end
end
return weapon
end
---@return number
local function getObjLevel(weapon)
return weapon:getCustomAttribute("SarahWesker_Level") or 0
end
local function setObjLevel(weapon, level)
return weapon:setCustomAttribute("SarahWesker_Level", level or 0)
end
---@return boolean
local function isValidObj(item)
local iType = item:getType()
local valid = iType:getWeaponType() ~= WEAPON_NONE or iType:getArmor() > 0 or iType:getDefense() > 0 or iType:getExtraDefense() > 0 or iType:getAttack() > 0
if not valid then
for index, abilitie in pairs(iType:getAbilities()) do
local abilitieType = type(abilitie)
if abilitieType == "table" then
for index2, abilitie2 in pairs(abilitie) do
if abilitie2 ~= 0 then
return true
end
end
elseif abilitieType == "number" and abilitie ~= 0 then
return true
end
end
return false
end
return true
end
local function isWeapon(item)
return item:getType():getWeaponType() ~= WEAPON_NONE
end
local function isWand(item)
return item:getType():getWeaponType() == WEAPON_WAND
end
local function isElemental(item)
return item:getType():getAbilities().elementDamage > 0
end
local function setAttribute(target, attr, upgradeValue, newLevel, iTypeMethod)
local valueAttr = iTypeMethod(target)
if valueAttr > 0 then
target:setAttribute(attr, valueAttr + (upgradeValue * newLevel))
end
end
local function setCustomAttribute(target, attr, upgradeValue, newLevel)
target:setCustomAttribute(attr, upgradeValue * newLevel)
end
local function doUpgradeItem(item, this, newLevel)
if newLevel <= 0 then
item:removeAttribute(ITEM_ATTRIBUTE_ARMOR)
item:removeAttribute(ITEM_ATTRIBUTE_DEFENSE)
item:removeAttribute(ITEM_ATTRIBUTE_EXTRADEFENSE)
item:removeAttribute(ITEM_ATTRIBUTE_ATTACK)
item:removeCustomAttribute("SarahWesker_WandDamage")
item:removeCustomAttribute("SarahWesker_ElementDamage")
for index, info in pairs(conditions) do
item:removeCustomAttribute(string.format("SarahWesker_%s", info.abilitie.type))
end
return
end
local function setOrUpdateAttribute(attrType, attrValue, upgradeValue, newLevel)
if attrValue > 0 then
item:removeAttribute(attrType)
setAttribute(item, attrType, upgradeValue, newLevel, function() return attrValue end)
else
setAttribute(item, attrType, upgradeValue, newLevel, function() return 0 end)
end
end
local itemType = item:getType()
setOrUpdateAttribute(ITEM_ATTRIBUTE_ARMOR, itemType:getArmor(), this.upgrade.armor, newLevel)
setOrUpdateAttribute(ITEM_ATTRIBUTE_DEFENSE, itemType:getDefense(), this.upgrade.defense, newLevel)
setOrUpdateAttribute(ITEM_ATTRIBUTE_EXTRADEFENSE, itemType:getExtraDefense(), this.upgrade.extraDefense, newLevel)
setOrUpdateAttribute(ITEM_ATTRIBUTE_ATTACK, itemType:getAttack(), this.upgrade.attack, newLevel)
if this.upgrade.elementDamage and isWeapon(item) and isElemental(item) then
setCustomAttribute(item, "SarahWesker_ElementDamage", this.upgrade.elementDamage, newLevel)
end
if this.upgrade.wandDamage and isWand(item) then
setCustomAttribute(item, "SarahWesker_WandDamage", this.upgrade.wandDamage, newLevel)
end
local itemType = item:getType()
local abilities = itemType:getAbilities()
for index, info in pairs(conditions) do
local key = "SarahWesker_" .. index
local value
if not info.abilitie.index then
value = abilities[info.abilitie.type] or 0
else
value = abilities[info.abilitie.type][info.abilitie.index + 1] or 0
end
if type(value) == "number" and value ~= 0 then
local increaseValue = this.upgrade[index] or this.upgrade[info.abilitie.type]
if not increaseValue then
print(string.format("[Warning] The skill %s or %s of the configuration does not exist.", index, info.abilitie.type))
else
setCustomAttribute(item, key, increaseValue, newLevel)
end
end
end
end
local slotBits = {
[CONST_SLOT_HEAD] = SLOTP_HEAD,
[CONST_SLOT_NECKLACE] = SLOTP_NECKLACE,
[CONST_SLOT_ARMOR] = SLOTP_ARMOR,
[CONST_SLOT_RIGHT] = SLOTP_RIGHT,
[CONST_SLOT_LEFT] = SLOTP_LEFT,
[CONST_SLOT_LEGS] = SLOTP_LEGS,
[CONST_SLOT_RING] = SLOTP_RING,
[CONST_SLOT_AMMO] = SLOTP_AMMO
}
local function usesSlot(itemType, slot)
return bit.band(itemType:getSlotPosition(), slotBits[slot] or 0) ~= 0
end
local function onDeEquip(player, slotPosition)
for _, info in pairs(conditions) do
local subId = (conditionCount * slotPosition) + info.condition.subId
player:removeCondition(info.condition.type, info.condition.id, subId, true)
end
end
local function onEquip(player, item, slotPosition)
local cleanSlot = true
for index, info in pairs(conditions) do
local key = string.format("SarahWesker_%s", index)
local value = item:getCustomAttribute(key) or 0
if value ~= 0 then
local condition = Condition(info.condition.type, info.condition.id)
condition:setTicks(info.condition.ticks)
local subId = (conditionCount * slotPosition) + info.condition.subId
condition:setParameter(CONDITION_PARAM_SUBID, subId)
if info.condition.healthTicks then
condition:setParameter(CONDITION_PARAM_HEALTHTICKS, info.condition.healthTicks)
end
if info.condition.manaTicks then
condition:setParameter(CONDITION_PARAM_MANATICKS, info.condition.manaTicks)
end
condition:setParameter(info.condition.param, value)
player:addCondition(condition)
cleanSlot = false
end
end
if cleanSlot then
onDeEquip(player, slotPosition)
end
end
local function getInventoryPosition(player, item)
for i = CONST_SLOT_HEAD, CONST_SLOT_AMMO do
local itemEx = player:getSlotItem(i)
if itemEx and itemEx:getUniqueId() == item:getUniqueId() then
return i
end
end
end
local action = Action()
function action.onUse(player, item, fromPos, target, toPos, isHotkey)
if not target:isItem() then
player:sendCancelMessage("It can only be applied to items.")
return true
end
if not isValidObj(target) then
player:sendCancelMessage("It is not a valid item to upgrade.")
return true
end
local this = config.values[item:getId()]
local objLevel = getObjLevel(target)
local foundChance = config.chances[objLevel]
if not foundChance then
player:sendCancelMessage("The level of your item is unknown")
return true
end
if not foundChance.chance then
player:sendCancelMessage("This item is at max level.")
return true
end
local function use()
if not config.debugMode then
item:remove(1)
end
return true
end
local inventoryPos = getInventoryPosition(player, target)
local function update()
if inventoryPos then
local itemType = target:getType()
if usesSlot(itemType, inventoryPos) then
onDeEquip(player, inventoryPos)
onEquip(player, target, inventoryPos)
end
end
end
local totalChance = foundChance.chance * (this.chance/100)
if totalChance < math.random(1, 100) then
if config.downgradeEnabled then
local newLevel = foundChance.downLvl or 0
setObjLevel(target, newLevel)
doUpgradeItem(target, this, newLevel)
update()
end
player:sendCancelMessage("The attempt to upgrade this item has failed.")
target:getPosition():sendMagicEffect(CONST_ME_POFF)
return use()
end
player:sendCancelMessage("The upgrade of the item is successful.")
target:getPosition():sendMagicEffect(this.effect or CONST_ME_FIREWORK_YELLOW)
local newLevel = objLevel +1
setObjLevel(target, newLevel)
doUpgradeItem(target, this, newLevel)
update()
return use()
end
for id, _ in pairs(config.values) do
action:id(id)
end
action:register()
local ec = EventCallback
function ec.onLook(player, thing, position, distance, description)
if thing:isItem() then
local objLevel = getObjLevel(thing)
if objLevel > 0 then
description = string.format("%s\n%s (level %d)", description, config.interfaceName, objLevel)
local wandDamage = thing:getCustomAttribute("SarahWesker_WandDamage") or 0
if wandDamage > 0 then
description = string.format("%s, extra damage +%d", description, wandDamage)
end
local elementDamage = thing:getCustomAttribute("SarahWesker_ElementDamage") or 0
if elementDamage > 0 then
description = string.format("%s, element damage +%d", description, elementDamage)
end
for index, info in pairs(conditions) do
local key = string.format("SarahWesker_%s", index)
local value = thing:getCustomAttribute(key) or 0
if value ~= 0 then
local attributeStr = string.format(", %s +%d", index, value)
description = description .. attributeStr
end
end
description = description .. ")"
end
end
return description
end
ec:register(7)
local creatureEvent = CreatureEvent("SarahWesker_onHealthChange")
function creatureEvent.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
if attacker:isPlayer() then
local weapon
if primaryDamage < 0 and origin == ORIGIN_WAND then
weapon = getPlayerWeapon(attacker)
if weapon and isWand(weapon) then
local wandDamage = weapon:getCustomAttribute("SarahWesker_WandDamage") or 0
if wandDamage > 0 then
primaryDamage = primaryDamage - wandDamage
end
end
end
if secondaryDamage < 0 and origin == ORIGIN_MELEE or origin == ORIGIN_WAND or origin == ORIGIN_RANGED then
weapon = weapon or getPlayerWeapon(attacker)
if weapon and isWeapon(weapon) then
local elementDamage = weapon:getCustomAttribute("SarahWesker_ElementDamage") or 0
if elementDamage > 0 then
secondaryDamage = secondaryDamage - elementDamage
end
end
end
end
return primaryDamage, primaryType, secondaryDamage, secondaryType
end
creatureEvent:register()
function ec.onTargetCombat(creature, target)
if creature and target then
if creature:isPlayer() then
target:registerEvent("SarahWesker_onHealthChange")
end
end
return RETURNVALUE_NOERROR
end
ec:register(7)
function ec.onItemMoved(player, item, count, fromPosition, toPosition, fromCylinder, toCylinder)
if fromPosition.x == CONTAINER_POSITION and bit.band(fromPosition.y, 0x40) == 0 then
local itemType = item:getType()
if usesSlot(itemType, fromPosition.y) then
onDeEquip(player, fromPosition.y)
end
end
if toPosition.x == CONTAINER_POSITION and bit.band(toPosition.y, 0x40) == 0 then
local itemType = item:getType()
if usesSlot(itemType, toPosition.y) then
onEquip(player, item, toPosition.y)
end
end
end
ec:register(10)
creatureEvent = CreatureEvent("SarahWesker_onThink")
local function onThinkInventory(playerId)
local player = Player(playerId)
if not player then
return
end
for i = CONST_SLOT_HEAD, CONST_SLOT_AMMO do
local item = player:getSlotItem(i)
if not item then
onDeEquip(player, i)
end
end
addEvent(onThinkInventory, 3000, playerId)
end
creatureEvent = CreatureEvent("SarahWesker_onLogin")
function creatureEvent.onLogin(player)
for i = CONST_SLOT_HEAD, CONST_SLOT_AMMO do
local item = player:getSlotItem(i)
if item then
if usesSlot(item:getType(), i) then
onEquip(player, item, i)
end
end
end
addEvent(onThinkInventory, 3000, player:getId())
return true
end
creatureEvent:register()