diff --git a/.github/workflows/analysis-sonarcloud.yml b/.github/workflows/analysis-sonarcloud.yml
index 71b910fa995..1b75d085097 100644
--- a/.github/workflows/analysis-sonarcloud.yml
+++ b/.github/workflows/analysis-sonarcloud.yml
@@ -2,8 +2,10 @@
name: Analysis - SonarCloud
on:
- pull_request_target:
+ pull_request:
types: [opened, synchronize, reopened, ready_for_review]
+ branches-ignore:
+ - main
paths:
- "src/**"
diff --git a/data-canary/scripts/lib/helper_constructors.lua b/data-canary/scripts/lib/helper_constructors.lua
deleted file mode 100644
index fdcd1508c84..00000000000
--- a/data-canary/scripts/lib/helper_constructors.lua
+++ /dev/null
@@ -1,53 +0,0 @@
--- HelperConstructors
-local classes = { Action, CreatureEvent, Spell, TalkAction, MoveEvent, EventCallback, GlobalEvent, Weapon }
-
-for _, class in ipairs(classes) do
- local MT = getmetatable(class)
- local DefaultConstructor = MT.__call
-
- MT.__call = function(self, def, ...)
- -- Backwards compatibility for default obj() constructor
- if type(def) ~= "table" then
- return DefaultConstructor(self, def, ...)
- end
-
- local obj = nil
- if def.init then
- obj = DefaultConstructor(self, unpack(def.init))
- else
- obj = DefaultConstructor(self)
- end
-
- -- Call each method from definition table with the value as params
- local hasCallback = false
-
- for methodName, value in pairs(def) do
- -- Strictly check if a correct callback is passed
- if methodName:sub(1, 2) == "on" and type(value) == "function" and rawget(class, methodName) then
- hasCallback = true
- end
-
- if methodName ~= "register" then
- local method = rawget(self, methodName)
- if method then
- if type(value) == "table" then
- method(obj, unpack(value))
- else
- method(obj, value)
- end
- end
- end
- end
-
- -- Only register if callback has already been defined, otherwise defining afterwards will not work
- if def.register then
- if not hasCallback then
- logger.warn("[HelperConstructors] - Event not registered due to there being no callback")
- else
- obj:register()
- end
- end
-
- return obj
- end
-end
diff --git a/data-canary/scripts/lib/register_actions.lua b/data-canary/scripts/lib/register_actions.lua
deleted file mode 100644
index 7f2fed403fb..00000000000
--- a/data-canary/scripts/lib/register_actions.lua
+++ /dev/null
@@ -1,304 +0,0 @@
-local wildGrowth = { 2130, 10182 } -- wild growth destroyable by machete
-local jungleGrass = { -- grass destroyable by machete
- [3696] = 3695,
- [3702] = 3701,
- [17153] = 17151,
-}
-local holeId = { -- usable rope holes, for rope spots see global.lua
- 294,
- 369,
- 370,
- 383,
- 392,
- 408,
- 409,
- 410,
- 427,
- 428,
- 429,
- 430,
- 462,
- 469,
- 470,
- 482,
- 484,
- 485,
- 489,
- 924,
- 1369,
- 3135,
- 3136,
- 4835,
- 4837,
- 7933,
- 7938,
- 8170,
- 8249,
- 8250,
- 8251,
- 8252,
- 8254,
- 8255,
- 8256,
- 8276,
- 8277,
- 8279,
- 8281,
- 8284,
- 8285,
- 8286,
- 8323,
- 8567,
- 8585,
- 8595,
- 8596,
- 8972,
- 9606,
- 9625,
- 13190,
- 14461,
- 19519,
- 21536,
- 23713,
- 26020,
-}
-local groundIds = { 354, 355 } -- pick usable grounds
-local holes = { 593, 606, 608, 867, 21341 } -- holes opened by shovel
-local sandIds = { 231, 9059 } -- desert sand
-local fruits = { 2673, 2674, 2675, 2676, 2677, 2678, 2679, 2680, 2681, 2682, 2684, 2685, 5097, 8839, 8840, 8841 } -- fruits to make decorated cake with knife
-
-ActionsLib = {}
-
-ActionsLib.destroyItem = function(player, target, toPosition)
- if type(target) ~= "userdata" or not target:isItem() then
- return false
- end
-
- if target:hasAttribute(ITEM_ATTRIBUTE_UNIQUEID) or target:hasAttribute(ITEM_ATTRIBUTE_ACTIONID) then
- return false
- end
-
- if toPosition.x == CONTAINER_POSITION then
- player:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
- return true
- end
-
- local destroyId = ItemType(target.itemid):getDestroyId()
- if destroyId == 0 then
- return false
- end
-
- if math.random(7) == 1 then
- local item = Game.createItem(destroyId, 1, toPosition)
- if item then
- item:decay()
- end
-
- -- Move items outside the container
- if target:isContainer() then
- for i = target:getSize() - 1, 0, -1 do
- local containerItem = target:getItem(i)
- if containerItem then
- containerItem:moveTo(toPosition)
- end
- end
- end
-
- target:remove(1)
- end
-
- toPosition:sendMagicEffect(CONST_ME_POFF)
- return true
-end
-
-ActionsLib.useMachete = function(player, item, fromPosition, target, toPosition, isHotkey)
- local targetId = target.itemid
- if not targetId then
- return true
- end
-
- if table.contains(wildGrowth, targetId) then
- toPosition:sendMagicEffect(CONST_ME_POFF)
- target:remove()
- return true
- end
-
- local grass = jungleGrass[targetId]
- if grass then
- target:transform(grass)
- target:decay()
- return true
- end
- return false
-end
-
-ActionsLib.usePick = function(player, item, fromPosition, target, toPosition, isHotkey)
- if target.itemid == 11227 then -- shiny stone refining
- local chance = math.random(1, 100)
- if chance == 1 then
- player:addItem(ITEM_CRYSTAL_COIN) -- 1% chance of getting crystal coin
- elseif chance <= 6 then
- player:addItem(ITEM_GOLD_COIN) -- 5% chance of getting gold coin
- elseif chance <= 51 then
- player:addItem(ITEM_PLATINUM_COIN) -- 45% chance of getting platinum coin
- else
- player:addItem(2145) -- 49% chance of getting small diamond
- end
- target:getPosition():sendMagicEffect(CONST_ME_BLOCKHIT)
- target:remove(1)
- return true
- end
-
- local tile = Tile(toPosition)
- if not tile then
- return false
- end
-
- local ground = tile:getGround()
- if not ground then
- return false
- end
-
- if table.contains(groundIds, ground.itemid) and (ground:hasAttribute(ITEM_ATTRIBUTE_UNIQUEID) or ground:hasAttribute(ITEM_ATTRIBUTE_ACTIONID)) then
- ground:transform(392)
- ground:decay()
-
- toPosition.z = toPosition.z + 1
- tile:relocateTo(toPosition)
- end
- return true
-end
-
-ActionsLib.useRope = function(player, item, fromPosition, target, toPosition, isHotkey)
- local tile = Tile(toPosition)
- if not tile then
- return false
- end
-
- local RopeSpots = { 386, 421, 12935, 12936, 14238, 17238, 21501, 21965, 21966, 21967, 21968, 23363 }
- if table.contains(ropeSpots, tile:getGround():getId()) or tile:getItemById(14435) then
- if Tile(toPosition:moveUpstairs()):hasFlag(TILESTATE_PROTECTIONZONE) and player:isPzLocked() then
- player:sendCancelMessage(RETURNVALUE_PLAYERISPZLOCKED)
- return true
- end
- player:teleportTo(toPosition, false)
- return true
- elseif table.contains(holeId, target.itemid) then
- toPosition.z = toPosition.z + 1
- tile = Tile(toPosition)
- if tile then
- local thing = tile:getTopVisibleThing()
- if thing:isPlayer() then
- if Tile(toPosition:moveUpstairs()):hasFlag(TILESTATE_PROTECTIONZONE) and thing:isPzLocked() then
- return false
- end
- return thing:teleportTo(toPosition, false)
- end
- if thing:isItem() and thing:getType():isMovable() then
- return thing:moveTo(toPosition:moveUpstairs())
- end
- end
- player:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
- return true
- end
- return false
-end
-
-ActionsLib.useShovel = function(player, item, fromPosition, target, toPosition, isHotkey)
- local tile = Tile(toPosition)
- if not tile then
- return false
- end
-
- local ground = tile:getGround()
- if not ground then
- return false
- end
-
- local groundId = ground:getId()
- if table.contains(holes, groundId) then
- ground:transform(groundId + 1)
- ground:decay()
- toPosition:moveDownstairs()
- toPosition.y = toPosition.y - 1
- if Tile(toPosition):hasFlag(TILESTATE_PROTECTIONZONE) and player:isPzLocked() then
- player:sendCancelMessage(RETURNVALUE_PLAYERISPZLOCKED)
- return true
- end
- player:teleportTo(toPosition, false)
- toPosition.z = toPosition.z + 1
- tile:relocateTo(toPosition)
- elseif table.contains(sandIds, groundId) then
- local randomValue = math.random(1, 100)
- if target.actionid == 100 and randomValue <= 20 then
- ground:transform(489)
- ground:decay()
- elseif randomValue == 1 then
- Game.createItem(3042, 1, toPosition) -- Scarab Coin
- elseif randomValue > 95 then
- Game.createMonster("Scarab", toPosition)
- end
- toPosition:sendMagicEffect(CONST_ME_POFF)
- else
- return false
- end
- return true
-end
-
-ActionsLib.useScythe = function(player, item, fromPosition, target, toPosition, isHotkey)
- if table.contains({ 9594, 9598 }, item.itemid) then
- return false
- end
-
- if target.itemid == 3653 then -- wheat
- target:transform(3651)
- target:decay()
- Game.createItem(3605, 1, toPosition) -- bunch of wheat
- return true
- end
- return false
-end
-
-ActionsLib.useCrowbar = function(player, item, fromPosition, target, toPosition, isHotkey)
- if table.contains({ 10511, 10513 }, item.itemid) then
- return false
- end
-
- return false
-end
-
-ActionsLib.useSpoon = function(player, item, fromPosition, target, toPosition, isHotkey)
- if table.contains({ 10515, 10513 }, item.itemid) then
- return false
- end
-
- return false
-end
-
-ActionsLib.useSickle = function(player, item, fromPosition, target, toPosition, isHotkey)
- if table.contains({ 10511, 10515 }, item.itemid) then
- return false
- end
-
- if target.itemid == 5463 then -- burning sugar cane
- target:transform(5462)
- target:decay()
- Game.createItem(5466, 1, toPosition) -- bunch of sugar cane
- return true
- end
- return false
-end
-
-ActionsLib.useKitchenKnife = function(player, item, fromPosition, target, toPosition, isHotkey)
- if item.itemid == 10513 then
- return false
- end
-
- if table.contains(fruits, target.itemid) and player:removeItem(6278, 1) then
- target:remove(1)
- player:addItem(6279, 1)
- player:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN)
- return true
- end
- return false
-end
diff --git a/data-canary/scripts/lib/register_item_tier.lua b/data-canary/scripts/lib/register_item_tier.lua
deleted file mode 100644
index 51ad62ccc6e..00000000000
--- a/data-canary/scripts/lib/register_item_tier.lua
+++ /dev/null
@@ -1,24 +0,0 @@
-registerItemClassification = {}
-setmetatable(registerItemClassification, {
- __call = function(self, itemClass, mask)
- for _, parse in pairs(self) do
- parse(itemClass, mask)
- end
- end,
-})
-
-ItemClassification.register = function(self, mask)
- return registerItemClassification(self, mask)
-end
-
-registerItemClassification.Upgrades = function(itemClassification, mask)
- if mask.Upgrades then
- for _, value in ipairs(mask.Upgrades) do
- if value.TierId and value.Price then
- itemClassification:addTier(value.TierId, value.Price, value.Core)
- else
- logger.warn("[registerItemClassification.Upgrades] - Item classification failed on adquire TierID or Price attribute.")
- end
- end
- end
-end
diff --git a/data-canary/scripts/lib/register_monster_type.lua b/data-canary/scripts/lib/register_monster_type.lua
deleted file mode 100644
index 9e1f3848453..00000000000
--- a/data-canary/scripts/lib/register_monster_type.lua
+++ /dev/null
@@ -1,960 +0,0 @@
-local smallAreaRadius = 3
-local superDrunkDuration = 4000
-
-registerMonsterType = {}
-setmetatable(registerMonsterType, {
- __call = function(self, mtype, mask)
- for _, parse in pairs(self) do
- parse(mtype, mask)
- end
- end,
-})
-
-MonsterType.register = function(self, mask)
- return registerMonsterType(self, mask)
-end
-
-registerMonsterType.name = function(mtype, mask)
- if mask.name then
- mtype:name(mask.name)
- end
-end
-registerMonsterType.description = function(mtype, mask)
- if mask.description then
- mtype:nameDescription(mask.description)
- end
-end
-registerMonsterType.experience = function(mtype, mask)
- if mask.experience then
- mtype:experience(mask.experience)
- end
-end
-registerMonsterType.raceId = function(mtype, mask)
- if mask.raceId then
- mtype:raceId(mask.raceId)
- end
-end
-registerMonsterType.Bestiary = function(mtype, mask)
- if mask.Bestiary then
- if mask.Bestiary.race then
- mtype:Bestiaryrace(mask.Bestiary.race)
- end
- if mask.Bestiary.class then
- mtype:Bestiaryclass(mask.Bestiary.class)
- end
- if mask.Bestiary.toKill then
- mtype:BestiarytoKill(mask.Bestiary.toKill)
- end
- if mask.Bestiary.FirstUnlock then
- mtype:BestiaryFirstUnlock(mask.Bestiary.FirstUnlock)
- end
- if mask.Bestiary.SecondUnlock then
- mtype:BestiarySecondUnlock(mask.Bestiary.SecondUnlock)
- end
- if mask.Bestiary.CharmsPoints then
- mtype:BestiaryCharmsPoints(mask.Bestiary.CharmsPoints)
- end
- if mask.Bestiary.Stars then
- mtype:BestiaryStars(mask.Bestiary.Stars)
- end
- if mask.Bestiary.Occurrence then
- mtype:BestiaryOccurrence(mask.Bestiary.Occurrence)
- end
- if mask.Bestiary.Locations then
- mtype:BestiaryLocations(mask.Bestiary.Locations)
- end
- end
-end
-registerMonsterType.bosstiary = function(mtype, mask)
- local bossClass = nil
- if mask.bosstiary then
- if mask.bosstiary.bossRaceId then
- mtype:bossRaceId(mask.bosstiary.bossRaceId)
- end
- if mask.bosstiary.bossRace then
- if mask.bosstiary.bossRace == RARITY_BANE then
- bossClass = "Bane"
- elseif mask.bosstiary.bossRace == RARITY_ARCHFOE then
- bossClass = "Archfoe"
- elseif mask.bosstiary.bossRace == RARITY_NEMESIS then
- bossClass = "Nemesis"
- end
- if bossClass ~= nil then
- mtype:bossRace(mask.bosstiary.bossRace, bossClass)
- end
- local storage = mask.bosstiary.storageCooldown
- if storage ~= nil then
- mtype:bossStorageCooldown(storage)
- end
- end
- end
-end
-registerMonsterType.skull = function(mtype, mask)
- if mask.skull then
- mtype:skull(mask.skull)
- end
-end
-registerMonsterType.outfit = function(mtype, mask)
- if mask.outfit then
- mtype:outfit(mask.outfit)
- end
-end
-registerMonsterType.maxHealth = function(mtype, mask)
- if mask.maxHealth then
- mtype:maxHealth(mask.maxHealth)
- end
-end
-registerMonsterType.health = function(mtype, mask)
- if mask.health then
- mtype:health(mask.health)
- end
-end
-registerMonsterType.race = function(mtype, mask)
- if mask.race then
- mtype:race(mask.race)
- end
-end
-registerMonsterType.manaCost = function(mtype, mask)
- if mask.manaCost then
- mtype:manaCost(mask.manaCost)
- end
-end
-registerMonsterType.speed = function(mtype, mask)
- if mask.speed then
- mtype:baseSpeed(mask.speed)
- end
-end
-registerMonsterType.corpse = function(mtype, mask)
- if mask.corpse then
- mtype:corpseId(mask.corpse)
- end
-end
-registerMonsterType.faction = function(mtype, mask)
- if mask.faction then
- mtype:faction(mask.faction)
- end
-end
-registerMonsterType.targetPreferPlayer = function(mtype, mask)
- if mask.targetPreferPlayer then
- mtype:targetPreferPlayer(mask.targetPreferPlayer)
- end
-end
-registerMonsterType.targetPreferMaster = function(mtype, mask)
- if mask.targetPreferMaster then
- mtype:targetPreferMaster(mask.targetPreferMaster)
- end
-end
-registerMonsterType.enemyFactions = function(mtype, mask)
- if mask.enemyFactions then
- for _, enemyFaction in pairs(mask.enemyFactions) do
- if not enemyFaction then
- print('[Error - Loading monsters] Monster: "' .. mtype:name() .. '". Unknown enemy faction.')
- else
- mtype:enemyFactions(enemyFaction)
- end
- end
- end
-end
-registerMonsterType.flags = function(mtype, mask)
- if mask.flags then
- if mask.flags.attackable ~= nil then
- mtype:isAttackable(mask.flags.attackable)
- end
- if mask.flags.convinceable ~= nil then
- mtype:isConvinceable(mask.flags.convinceable)
- end
- if mask.flags.summonable ~= nil then
- mtype:isSummonable(mask.flags.summonable)
- end
- if mask.flags.illusionable ~= nil then
- mtype:isIllusionable(mask.flags.illusionable)
- end
- if mask.flags.hostile ~= nil then
- mtype:isHostile(mask.flags.hostile)
- end
- if mask.flags.healthHidden ~= nil then
- mtype:isHealthHidden(mask.flags.healthHidden)
- end
- if mask.flags.pushable ~= nil then
- mtype:isPushable(mask.flags.pushable)
- end
- if mask.flags.canPushItems ~= nil then
- mtype:canPushItems(mask.flags.canPushItems)
- end
- if mask.flags.rewardBoss then
- mtype:isRewardBoss(mask.flags.rewardBoss)
- end
- if mask.flags.familiar then
- mtype:familiar(mask.flags.familiar)
- end
- if mask.flags.respawntype or mask.flags.respawnType then
- logger.warn("[registerMonsterType.flags] - Monster: {}. Deprecated flag 'respawnType', use instead table 'respawnType = { period = RespawnPeriod_t, underground = boolean}'", mtype:name())
- end
- if mask.flags.canPushCreatures ~= nil then
- mtype:canPushCreatures(mask.flags.canPushCreatures)
- end
- if mask.flags.targetDistance then
- mtype:targetDistance(math.max(1, mask.flags.targetDistance))
- end
- if mask.flags.runHealth then
- mtype:runHealth(mask.flags.runHealth)
- end
- if mask.flags.staticAttackChance then
- mtype:staticAttackChance(mask.flags.staticAttackChance)
- end
- if mask.flags.canWalkOnEnergy ~= nil then
- mtype:canWalkOnEnergy(mask.flags.canWalkOnEnergy)
- end
- if mask.flags.canWalkOnFire ~= nil then
- mtype:canWalkOnFire(mask.flags.canWalkOnFire)
- end
- if mask.flags.canWalkOnPoison ~= nil then
- mtype:canWalkOnPoison(mask.flags.canWalkOnPoison)
- end
- if mask.flags.isBlockable ~= nil then
- mtype:isBlockable(mask.flags.isBlockable)
- end
- if mask.flags.isForgeCreature ~= nil then
- mtype:isForgeCreature(mask.flags.isForgeCreature)
- end
- end
-end
-registerMonsterType.light = function(mtype, mask)
- if mask.light then
- local color = 0
- if mask.light.color then
- color = mask.light.color
- end
- if mask.light.level then
- mtype:light(color, mask.light.level)
- end
- end
-end
-registerMonsterType.changeTarget = function(mtype, mask)
- if mask.changeTarget then
- if mask.changeTarget.chance then
- mtype:changeTargetChance(mask.changeTarget.chance)
- end
- if mask.changeTarget.interval then
- mtype:changeTargetSpeed(mask.changeTarget.interval)
- end
- end
-end
-registerMonsterType.strategiesTarget = function(mtype, mask)
- if mask.strategiesTarget then
- if mask.strategiesTarget.nearest then
- mtype:strategiesTargetNearest(mask.strategiesTarget.nearest)
- end
- if mask.strategiesTarget.health then
- mtype:strategiesTargetHealth(mask.strategiesTarget.health)
- end
- if mask.strategiesTarget.damage then
- mtype:strategiesTargetDamage(mask.strategiesTarget.damage)
- end
- if mask.strategiesTarget.random then
- mtype:strategiesTargetRandom(mask.strategiesTarget.random)
- end
- end
-end
-registerMonsterType.respawnType = function(mtype, mask)
- if mask.respawnType then
- if mask.respawnType.period then
- mtype:respawnTypePeriod(mask.respawnType.period)
- end
- if mask.respawnType.underground then
- mtype:respawnTypeIsUnderground(mask.respawnType.underground)
- end
- end
-end
-registerMonsterType.sounds = function(mtype, mask)
- if type(mask.sounds) == "table" then
- if mask.sounds.death then
- mtype:deathSound(mask.sounds.death)
- end
- if mask.sounds.ticks and mask.sounds.chance and mask.sounds.ids and type(mask.sounds.ids) == "table" and #mask.sounds.ids > 0 then
- mtype:soundSpeedTicks(mask.sounds.ticks)
- mtype:soundChance(mask.sounds.chance)
- for _, v in pairs(mask.sounds.ids) do
- mtype:addSound(v)
- end
- end
- end
-end
-registerMonsterType.voices = function(mtype, mask)
- if type(mask.voices) == "table" then
- local interval, chance
- if mask.voices.interval then
- interval = mask.voices.interval
- end
- if mask.voices.chance then
- chance = mask.voices.chance
- end
- for k, v in pairs(mask.voices) do
- if type(v) == "table" then
- mtype:addVoice(v.text, interval, chance, v.yell)
- end
- end
- end
-end
-registerMonsterType.summon = function(mtype, mask)
- if mask.summon then
- if mask.summon.maxSummons then
- mtype:maxSummons(mask.summon.maxSummons)
- end
- if type(mask.summon.summons) == "table" then
- for k, v in pairs(mask.summon.summons) do
- mtype:addSummon(v.name, v.interval, v.chance, v.count)
- end
- end
- end
-end
-registerMonsterType.events = function(mtype, mask)
- if type(mask.events) == "table" then
- for k, v in pairs(mask.events) do
- mtype:registerEvent(v)
- end
- end
-end
-
-function SortLootByChance(loot)
- if not configManager.getBoolean(configKeys.SORT_LOOT_BY_CHANCE) then
- return
- end
-
- table.sort(loot, function(loot1, loot2)
- if not loot1.chance or not loot2.chance then
- return 0
- end
-
- return loot1.chance < loot2.chance
- end)
-end
-
-registerMonsterType.loot = function(mtype, mask)
- if type(mask.loot) == "table" then
- SortLootByChance(mask.loot)
- local lootError = false
- for _, loot in pairs(mask.loot) do
- local parent = Loot()
- if loot.name then
- if not parent:setIdFromName(loot.name) then
- lootError = true
- end
- else
- if not isInteger(loot.id) or loot.id < 1 then
- lootError = true
- end
- parent:setId(loot.id)
- end
- if loot.subType or loot.charges then
- parent:setSubType(loot.subType or loot.charges)
- else
- local lType = ItemType(loot.name and loot.name or loot.id)
- if lType and lType:getCharges() > 1 then
- parent:setSubType(lType:getCharges())
- end
- end
- if loot.chance then
- parent:setChance(loot.chance)
- end
- if loot.minCount then
- parent:setMinCount(loot.minCount)
- end
- if loot.maxCount then
- parent:setMaxCount(loot.maxCount)
- end
- if loot.aid or loot.actionId then
- parent:setActionId(loot.aid or loot.actionId)
- end
- if loot.text or loot.description then
- parent:setText(loot.text or loot.description)
- end
- if loot.name then
- parent:setNameItem(loot.name)
- end
- if loot.article then
- parent:setArticle(loot.article)
- end
- if loot.attack then
- parent:setAttack(loot.attack)
- end
- if loot.defense then
- parent:setDefense(loot.defense)
- end
- if loot.extraDefense or loot.extraDef then
- parent:setExtraDefense(loot.extraDefense or loot.extraDef)
- end
- if loot.armor then
- parent:setArmor(loot.armor)
- end
- if loot.shootRange or loot.range then
- parent:setShootRange(loot.shootRange or loot.range)
- end
- if loot.unique then
- parent:setUnique(loot.unique)
- end
- if loot.child then
- SortLootByChance(loot.child)
- for _, children in pairs(loot.child) do
- local child = Loot()
- if children.name then
- if not child:setIdFromName(children.name) then
- lootError = true
- end
- else
- if not isInteger(children.id) or children.id < 1 then
- lootError = true
- end
- child:setId(children.id)
- end
- if children.subType or children.charges then
- child:setSubType(children.subType or children.charges)
- else
- local cType = ItemType(children.name and children.name or children.id)
- if cType and cType:getCharges() > 1 then
- child:setSubType(cType:getCharges())
- end
- end
- if children.chance then
- child:setChance(children.chance)
- end
- if children.minCount then
- child:setMinCount(children.minCount)
- end
- if children.maxCount then
- child:setMaxCount(children.maxCount)
- end
- if children.aid or children.actionId then
- child:setActionId(children.aid or children.actionId)
- end
- if children.text or children.description then
- child:setText(children.text or children.description)
- end
- if loot.name then
- child:setNameItem(loot.name)
- end
- if children.article then
- child:setArticle(children.article)
- end
- if children.attack then
- child:setAttack(children.attack)
- end
- if children.defense then
- child:setDefense(children.defense)
- end
- if children.extraDefense or children.extraDef then
- child:setExtraDefense(children.extraDefense or children.extraDef)
- end
- if children.armor then
- child:setArmor(children.armor)
- end
- if children.shootRange or children.range then
- child:setShootRange(children.shootRange or children.range)
- end
- if children.unique then
- child:setUnique(children.unique)
- end
- parent:addChildLoot(child)
- end
- end
- mtype:addLoot(parent)
- end
- if lootError then
- logger.warn("[registerMonsterType.loot] - Monster: {} loot could not correctly be load", mtype:name())
- end
- end
-end
-registerMonsterType.elements = function(mtype, mask)
- if type(mask.elements) == "table" then
- for _, element in pairs(mask.elements) do
- if element.type and element.percent then
- mtype:addElement(element.type, element.percent)
- end
- end
- end
-end
-registerMonsterType.reflects = function(mtype, mask)
- if type(mask.reflects) == "table" then
- for _, reflect in pairs(mask.reflects) do
- if reflect.type and reflect.percent then
- mtype:addReflect(reflect.type, reflect.percent)
- end
- end
- end
-end
-registerMonsterType.heals = function(mtype, mask)
- if type(mask.heals) == "table" then
- for _, heal in pairs(mask.heals) do
- if heal.type and heal.percent then
- mtype:addHealing(heal.type, heal.percent)
- end
- end
- end
-end
-registerMonsterType.immunities = function(mtype, mask)
- if type(mask.immunities) == "table" then
- for _, immunity in pairs(mask.immunities) do
- if immunity.type and immunity.combat then
- mtype:combatImmunities(immunity.type)
- end
- if immunity.type and immunity.condition then
- mtype:conditionImmunities(immunity.type)
- end
- end
- end
-end
-registerMonsterType.attacks = function(mtype, mask)
- if type(mask.attacks) == "table" then
- for _, attack in pairs(mask.attacks) do
- mtype:addAttack(readSpell(attack, mtype))
- end
- end
-end
-
-registerMonsterType.defenses = function(mtype, mask)
- if type(mask.defenses) == "table" then
- if mask.defenses.defense then
- mtype:defense(mask.defenses.defense)
- end
- if mask.defenses.armor then
- mtype:armor(mask.defenses.armor)
- end
- for _, defense in pairs(mask.defenses) do
- if type(defense) == "table" then
- mtype:addDefense(readSpell(defense, mtype))
- end
- end
- end
-end
-
-local function loadcastSound(effect, incomingLua, mtype)
- -- Throw shoottype
- if
- effect == CONST_ANI_SPEAR
- or effect == CONST_ANI_THROWINGSTAR
- or effect == CONST_ANI_THROWINGKNIFE
- or effect == CONST_ANI_SMALLSTONE
- or effect == CONST_ANI_LARGEROCK
- or effect == CONST_ANI_SNOWBALL
- or effect == CONST_ANI_HUNTINGSPEAR
- or effect == CONST_ANI_ENCHANTEDSPEAR
- or effect == CONST_ANI_REDSTAR
- or effect == CONST_ANI_GREENSTAR
- or effect == CONST_ANI_ROYALSPEAR
- or effect == CONST_ANI_WHIRLWINDSWORD
- or effect == CONST_ANI_WHIRLWINDAXE
- or effect == CONST_ANI_WHIRLWINDCLUB
- or effect == CONST_ANI_CAKE
- or effect == CONST_ANI_GLOOTHSPEAR
- or effect == CONST_ANI_LEAFSTAR
- or effect == CONST_ANI_ROYALSTAR
- then
- return SOUND_EFFECT_TYPE_DIST_ATK_THROW
-
- -- Crossbow shoottype
- elseif effect == CONST_ANI_BOLT or effect == CONST_ANI_POWERBOLT or effect == CONST_ANI_INFERNALBOLT or effect == CONST_ANI_PIERCINGBOLT or effect == CONST_ANI_VORTEXBOLT or effect == CONST_ANI_PRISMATICBOLT or effect == CONST_ANI_DRILLBOLT or effect == CONST_ANI_SPECTRALBOLT then
- return SOUND_EFFECT_TYPE_DIST_ATK_CROSSBOW
-
- -- Bow shoottype
- elseif
- effect == CONST_ANI_POISONARROW
- or effect == CONST_ANI_BURSTARROW
- or effect == CONST_ANI_SNIPERARROW
- or effect == CONST_ANI_ONYXARROW
- or effect == CONST_ANI_FLASHARROW
- or effect == CONST_ANI_FLAMMINGARROW
- or effect == CONST_ANI_SHIVERARROW
- or effect == CONST_ANI_EARTHARROW
- or effect == CONST_ANI_TARSALARROW
- or effect == CONST_ANI_CRYSTALLINEARROW
- or effect == CONST_ANI_ENVENOMEDARROW
- or effect == CONST_ANI_SIMPLEARROW
- or effect == CONST_ANI_DIAMONDARROW
- then
- return SOUND_EFFECT_TYPE_DIST_ATK_BOW
-
- -- Magical shoottype
- elseif
- effect == CONST_ANI_FIRE
- or effect == CONST_ANI_ENERGY
- or effect == CONST_ANI_DEATH
- or effect == CONST_ANI_POISON
- or effect == CONST_ANI_ETHEREALSPEAR
- or effect == CONST_ANI_ICE
- or effect == CONST_ANI_EARTH
- or effect == CONST_ANI_HOLY
- or effect == CONST_ANI_SUDDENDEATH
- or effect == CONST_ANI_ENERGYBALL
- or effect == CONST_ANI_SMALLICE
- or effect == CONST_ANI_SMALLHOLY
- or effect == CONST_ANI_SMALLEARTH
- or effect == CONST_ANI_EXPLOSION
- then
- return SOUND_EFFECT_TYPE_MAGICAL_RANGE_ATK
- end
-
- return SOUND_EFFECT_TYPE_SILENCE
-end
-
-local function loadImpactSound(incomingLua, mtype)
- local nameType = "physical"
- if incomingLua.name == "melee" then
- local meleeSoundTable = {}
- if mtype:targetDistance() <= 1 then
- meleeSoundTable = {
- [1] = SOUND_EFFECT_TYPE_MONSTER_MELEE_ATK_FIST,
- [2] = SOUND_EFFECT_TYPE_MONSTER_MELEE_ATK_CLAW,
- [3] = SOUND_EFFECT_TYPE_MONSTER_MELEE_ATK_BITE,
- }
- else
- meleeSoundTable = {
- [1] = SOUND_EFFECT_TYPE_MONSTER_MELEE_ATK_RIP,
- --[2] = SOUND_EFFECT_TYPE_MONSTER_MELEE_ATK_ACID,
- [2] = SOUND_EFFECT_TYPE_MONSTER_MELEE_ATK_MAGIC,
- --[4] = SOUND_EFFECT_TYPE_MONSTER_MELEE_ATK_ETHEREAL,
- --[5] = SOUND_EFFECT_TYPE_MONSTER_MELEE_ATK_CONSTRUCT,
- }
- end
- return meleeSoundTable[math.random(1, #meleeSoundTable)]
- elseif incomingLua.name == "combat" then
- if incomingLua.type == COMBAT_PHYSICALDAMAGE then
- nameType = "physical"
- elseif incomingLua.type == COMBAT_ENERGYDAMAGE then
- nameType = "energy"
- elseif incomingLua.type == COMBAT_EARTHDAMAGE then
- nameType = "earth"
- elseif incomingLua.type == COMBAT_FIREDAMAGE then
- nameType = "fire"
- elseif incomingLua.type == COMBAT_UNDEFINEDDAMAGE then
- nameType = "bleeding"
- elseif incomingLua.type == COMBAT_LIFEDRAIN then
- nameType = "lifedrain"
- elseif incomingLua.type == COMBAT_MANADRAIN then
- nameType = "manadrain"
- elseif incomingLua.type == COMBAT_HEALING then
- nameType = "healing"
- elseif incomingLua.type == COMBAT_DROWNDAMAGE then
- nameType = "drown"
- elseif incomingLua.type == COMBAT_ICEDAMAGE then
- nameType = "ice"
- elseif incomingLua.type == COMBAT_HOLYDAMAGE then
- nameType = "holy"
- elseif incomingLua.type == COMBAT_DEATHDAMAGE then
- nameType = "death"
- end
- elseif incomingLua.name == "drunk" then
- if incomingLua.duration and incomingLua.duration > superDrunkDuration then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SUPER_DRUNKEN
- end
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_DRUNKEN
- elseif incomingLua.name == "speed" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SPEED
- elseif incomingLua.name == "outfit" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_OUTFIT
- elseif incomingLua.name == "strength" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_STRENGTH
- elseif incomingLua.name == "firefield" then
- return SOUND_EFFECT_TYPE_SPELL_FIRE_FIELD_RUNE
- elseif incomingLua.name == "energyfield" then
- return SOUND_EFFECT_TYPE_SPELL_ENERGY_FIELD_RUNE
- elseif incomingLua.name == "earthfield" or incomingLua.name == "poisonfield" then
- return SOUND_EFFECT_TYPE_SPELL_POISON_FIELD_RUNE
- elseif incomingLua.name == "condition" then
- -- To-Do
- end
-
- -- Waves
- if incomingLua.length and incomingLua.spread then
- if nameType == "bleeding" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_WAVE_BLEEDING
- elseif nameType == "energy" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_WAVE_ENERGY
- elseif nameType == "earth" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_WAVE_EARTH
- elseif nameType == "fire" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_WAVE_FIRE
- elseif nameType == "lifedrain" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_WAVE_LIFEDRAIN
- elseif nameType == "manadrain" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_WAVE_MANADRAIN
- elseif nameType == "healing" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_WAVE_HEALING
- elseif nameType == "drown" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_WAVE_DROWNING
- elseif nameType == "ice" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_WAVE_ICE
- elseif nameType == "holy" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_WAVE_HOLY
- elseif nameType == "death" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_WAVE_DEATH
- elseif nameType == "physical" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_WAVE_HIT
- end
-
- -- Bombs area (not field)
- elseif incomingLua.radius then
- if nameType == "bleeding" then
- if incomingLua.radius <= smallAreaRadius then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SMALL_AREA_BLEEDING
- else
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_LARGE_AREA_BLEEDING
- end
- elseif nameType == "energy" then
- if incomingLua.radius <= smallAreaRadius then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SMALL_AREA_ENERGY
- else
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_LARGE_AREA_ENERGY
- end
- elseif nameType == "earth" then
- if incomingLua.radius <= smallAreaRadius then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SMALL_AREA_EARTH
- else
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_LARGE_AREA_EARTH
- end
- elseif nameType == "fire" then
- if incomingLua.radius <= smallAreaRadius then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SMALL_AREA_FIRE
- else
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_LARGE_AREA_FIRE
- end
- elseif nameType == "lifedrain" then
- if incomingLua.radius <= smallAreaRadius then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SMALL_AREA_LIFEDRAIN
- else
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_LARGE_AREA_LIFEDRAIN
- end
- elseif nameType == "manadrain" then
- if incomingLua.radius <= smallAreaRadius then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SMALL_AREA_MANADRAIN
- else
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_LARGE_AREA_MANADRAIN
- end
- elseif nameType == "healing" then
- if incomingLua.radius <= smallAreaRadius then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SMALL_AREA_HEALING
- else
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_LARGE_AREA_HEALING
- end
- elseif nameType == "drown" then
- if incomingLua.radius <= smallAreaRadius then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SMALL_AREA_DROWNING
- else
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_LARGE_AREA_DROWNING
- end
- elseif nameType == "ice" then
- if incomingLua.radius <= smallAreaRadius then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SMALL_AREA_ICE
- else
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_LARGE_AREA_ICE
- end
- elseif nameType == "holy" then
- if incomingLua.radius <= smallAreaRadius then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SMALL_AREA_HOLY
- else
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_LARGE_AREA_HOLY
- end
- elseif nameType == "death" then
- if incomingLua.radius <= smallAreaRadius then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SMALL_AREA_DEATH
- else
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_LARGE_AREA_DEATH
- end
- elseif nameType == "physical" then
- if incomingLua.radius <= smallAreaRadius then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SMALL_AREA_HIT
- else
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_LARGE_AREA_HIT
- end
- end
-
- -- Since all failed, im assuming its a single target spell
- else
- if nameType == "bleeding" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SINGLE_TARGET_BLEEDING
- elseif nameType == "energy" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SINGLE_TARGET_ENERGY
- elseif nameType == "earth" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SINGLE_TARGET_EARTH
- elseif nameType == "fire" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SINGLE_TARGET_FIRE
- elseif nameType == "lifedrain" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SINGLE_TARGET_LIFEDRAIN
- elseif nameType == "manadrain" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SINGLE_TARGET_MANADRAIN
- elseif nameType == "healing" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SINGLE_TARGET_HEALING
- elseif nameType == "drown" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SINGLE_TARGET_DROWNING
- elseif nameType == "ice" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SINGLE_TARGET_ICE
- elseif nameType == "holy" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SINGLE_TARGET_HOLY
- elseif nameType == "death" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SINGLE_TARGET_DEATH
- elseif nameType == "physical" then
- return SOUND_EFFECT_TYPE_MONSTER_SPELL_SINGLE_TARGET_HIT
- end
- end
-
- return SOUND_EFFECT_TYPE_SILENCE
-end
-
-local function loadSpellSoundType(incomingLua, mtype)
- local castSound, impactSound = SOUND_EFFECT_TYPE_SILENCE, SOUND_EFFECT_TYPE_MONSTER_CLOSE_ATK_FIST
-
- -- Shoot effect
- if incomingLua.shootEffect ~= nil then
- castSound = loadcastSound(incomingLua.shootEffect, incomingLua, mtype)
- end
-
- impactSound = loadImpactSound(incomingLua, mtype)
- return { cast = castSound, impact = impactSound }
-end
-
-function readSpell(incomingLua, mtype)
- local hasCastSound, hasImpactSound = false, false
- local spell = MonsterSpell()
- if incomingLua.name then
- if incomingLua.name == "melee" then
- spell:setType("melee")
- if incomingLua.attack and incomingLua.skill then
- spell:setAttackValue(incomingLua.attack, incomingLua.skill)
- end
- if incomingLua.minDamage and incomingLua.maxDamage then
- spell:setCombatValue(incomingLua.minDamage, incomingLua.maxDamage)
- end
- if incomingLua.interval then
- spell:setInterval(incomingLua.interval)
- end
- if incomingLua.effect then
- spell:setCombatEffect(incomingLua.effect)
- end
- if incomingLua.soundCast then
- spell:castSound(incomingLua.soundCast)
- hasCastSound = true
- end
- if incomingLua.impactCast then
- spell:impactSound(incomingLua.impactCast)
- hasImpactSound = true
- end
- else
- spell:setType(incomingLua.name)
- if incomingLua.type then
- if incomingLua.name == "combat" then
- spell:setCombatType(incomingLua.type)
- elseif incomingLua.name == "condition" then
- spell:setConditionType(incomingLua.type)
- else
- logger.warn("[readSpell] - Monster {}: Loading spell {}. Parameter type applies only for condition and combat.", mtype:name(), incomingLua.name)
- end
- end
- if incomingLua.interval then
- spell:setInterval(incomingLua.interval)
- end
- if incomingLua.chance then
- spell:setChance(incomingLua.chance)
- end
- if incomingLua.range then
- spell:setRange(incomingLua.range)
- end
- if incomingLua.duration then
- spell:setConditionDuration(incomingLua.duration)
- end
- if incomingLua.speedChange then
- spell:setConditionSpeedChange(incomingLua.speedChange)
- end
- if incomingLua.target then
- spell:setNeedTarget(incomingLua.target)
- end
- if incomingLua.length then
- spell:setCombatLength(incomingLua.length)
- end
- if incomingLua.spread then
- spell:setCombatSpread(incomingLua.spread)
- end
- if incomingLua.radius then
- spell:setCombatRadius(incomingLua.radius)
- end
- if incomingLua.outfitMonster then
- spell:setOutfitMonster(incomingLua.outfitMonster)
- end
- if incomingLua.outfitItem then
- spell:setOutfitItem(incomingLua.outfitItem)
- end
- if incomingLua.soundCast then
- spell:castSound(incomingLua.soundCast)
- hasCastSound = true
- end
- if incomingLua.impactCast then
- spell:impactSound(incomingLua.impactCast)
- hasImpactSound = true
- end
- if incomingLua.minDamage and incomingLua.maxDamage then
- if incomingLua.name == "combat" or Spell(incomingLua.name) then
- spell:setCombatValue(incomingLua.minDamage, incomingLua.maxDamage)
- else
- local startDamage = 0
- if incomingLua.startDamage then
- startDamage = incomingLua.startDamage
- end
- spell:setConditionDamage(incomingLua.minDamage, incomingLua.maxDamage, startDamage)
- end
- end
- if incomingLua.effect then
- spell:setCombatEffect(incomingLua.effect)
- end
- if incomingLua.shootEffect then
- spell:setCombatShootEffect(incomingLua.shootEffect)
- end
- end
-
- -- This is for a complex spell, that has combat damage AND some condition
- -- For example scorpions, which attack and cause poison on attack
- if incomingLua.condition then
- if incomingLua.condition.type then
- spell:setConditionType(incomingLua.condition.type)
- end
- if incomingLua.condition.duration then
- spell:setConditionDuration(incomingLua.condition.duration)
- end
- if incomingLua.condition.interval then
- spell:setConditionTickInterval(incomingLua.condition.interval)
- end
-
- spell:setConditionDamage(incomingLua.condition.totalDamage, incomingLua.condition.totalDamage, 0)
- end
- elseif incomingLua.script then
- spell:setScriptName("monster/" .. incomingLua.script .. ".lua")
- if incomingLua.interval then
- spell:setInterval(incomingLua.interval)
- end
- if incomingLua.chance then
- spell:setChance(incomingLua.chance)
- end
- if incomingLua.minDamage and incomingLua.maxDamage then
- spell:setCombatValue(incomingLua.minDamage, incomingLua.maxDamage)
- end
- if incomingLua.target then
- spell:setNeedTarget(incomingLua.target)
- end
- if incomingLua.soundCast then
- spell:castSound(incomingLua.soundCast)
- hasCastSound = true
- end
- if incomingLua.impactCast then
- spell:impactSound(incomingLua.impactCast)
- hasImpactSound = true
- end
- end
-
- if not hasImpactSound or not hasCastSound then
- local sounds = loadSpellSoundType(incomingLua, mtype)
- if not hasCastSound and sounds.cast ~= SOUND_EFFECT_TYPE_SILENCE then
- spell:castSound(sounds.cast)
- end
- if not hasImpactSound and sounds.impact ~= SOUND_EFFECT_TYPE_SILENCE then
- spell:castSound(sounds.impact)
- end
- end
- return spell
-end
diff --git a/data-canary/scripts/lib/register_spells.lua b/data-canary/scripts/lib/register_spells.lua
deleted file mode 100644
index 6871ecc5651..00000000000
--- a/data-canary/scripts/lib/register_spells.lua
+++ /dev/null
@@ -1,515 +0,0 @@
---Pre-made areas
---Waves
-AREA_SHORTWAVE3 = {
- { 1, 1, 1 },
- { 1, 1, 1 },
- { 0, 3, 0 },
-}
-
-AREA_WAVE10 = {
- { 1, 1, 1, 1, 1, 1, 1 },
- { 0, 1, 1, 1, 1, 1, 0 },
- { 0, 1, 1, 1, 1, 1, 0 },
- { 0, 1, 1, 1, 1, 1, 0 },
- { 0, 0, 1, 1, 1, 0, 0 },
- { 0, 0, 1, 1, 1, 0, 0 },
- { 0, 0, 1, 1, 1, 0, 0 },
- { 0, 0, 0, 3, 0, 0, 0 },
-}
-
-AREA_WAVE11 = {
- { 1, 1, 1, 1, 1, 1, 1 },
- { 0, 1, 1, 1, 1, 1, 0 },
- { 0, 1, 1, 1, 1, 1, 0 },
- { 0, 1, 1, 1, 1, 1, 0 },
- { 0, 0, 1, 1, 1, 0, 0 },
- { 0, 0, 1, 1, 1, 0, 0 },
- { 0, 0, 1, 1, 1, 0, 0 },
- { 0, 0, 0, 1, 0, 0, 0 },
- { 0, 0, 0, 3, 0, 0, 0 },
-}
-
-AREA_WAVE12 = {
- { 0, 1, 1, 1, 1, 1, 0 },
- { 0, 1, 1, 1, 1, 1, 0 },
- { 0, 1, 1, 1, 1, 1, 0 },
- { 0, 0, 1, 1, 1, 0, 0 },
- { 0, 0, 1, 1, 1, 0, 0 },
- { 0, 0, 1, 1, 1, 0, 0 },
- { 0, 0, 0, 1, 0, 0, 0 },
- { 0, 0, 0, 3, 0, 0, 0 },
-}
-
-AREA_WAVE13 = {
- { 1, 1, 1, 1, 1, 1, 1 },
- { 1, 1, 1, 1, 1, 1, 1 },
- { 0, 1, 1, 1, 1, 1, 0 },
- { 0, 1, 1, 1, 1, 1, 0 },
- { 0, 1, 1, 1, 1, 1, 0 },
- { 0, 0, 1, 1, 1, 0, 0 },
- { 0, 0, 1, 1, 1, 0, 0 },
- { 0, 0, 1, 1, 1, 0, 0 },
- { 0, 0, 0, 1, 0, 0, 0 },
- { 0, 0, 0, 3, 0, 0, 0 },
-}
-
-AREA_WAVE4 = {
- { 1, 1, 1, 1, 1 },
- { 0, 1, 1, 1, 0 },
- { 0, 1, 1, 1, 0 },
- { 0, 0, 3, 0, 0 },
-}
-
-AREA_WAVE5 = {
- { 1, 1, 1, 1, 1 },
- { 0, 1, 1, 1, 0 },
- { 0, 1, 1, 1, 0 },
- { 0, 1, 1, 1, 0 },
- { 0, 0, 1, 0, 0 },
- { 0, 0, 3, 0, 0 },
-}
-
-AREA_WAVE6 = {
- { 0, 0, 0, 0, 0 },
- { 0, 1, 3, 1, 0 },
- { 0, 0, 0, 0, 0 },
-}
-
-AREA_WAVE7 = {
- { 1, 1, 1, 1, 1 },
- { 1, 1, 1, 1, 1 },
- { 0, 1, 1, 1, 0 },
- { 0, 1, 1, 1, 0 },
- { 0, 0, 3, 0, 0 },
-}
-
-AREA_SQUAREWAVE5 = {
- { 1, 1, 1 },
- { 1, 1, 1 },
- { 1, 1, 1 },
- { 0, 1, 0 },
- { 0, 3, 0 },
-}
-
-AREA_SQUAREWAVE6 = {
- { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
- { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
- { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
- { 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
- { 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
- { 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
- { 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0 },
- { 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0 },
- { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0 },
-}
-
-AREA_SQUAREWAVE7 = {
- { 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
- { 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
- { 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0 },
- { 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0 },
- { 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0 },
- { 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0 },
- { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0 },
-}
-
---Diagonal waves
-AREADIAGONAL_WAVE4 = {
- { 0, 0, 0, 0, 1, 0 },
- { 0, 0, 0, 1, 1, 0 },
- { 0, 0, 1, 1, 1, 0 },
- { 0, 1, 1, 1, 1, 0 },
- { 1, 1, 1, 1, 1, 0 },
- { 0, 0, 0, 0, 0, 3 },
-}
-
-AREADIAGONAL_SQUAREWAVE5 = {
- { 1, 1, 1, 0, 0 },
- { 1, 1, 1, 0, 0 },
- { 1, 1, 1, 0, 0 },
- { 0, 0, 0, 1, 0 },
- { 0, 0, 0, 0, 3 },
-}
-
-AREADIAGONAL_WAVE6 = {
- { 0, 0, 1 },
- { 0, 3, 0 },
- { 1, 0, 0 },
-}
-
-AREADIAGONAL_WAVE7 = {
- { 0, 0, 0, 0, 0, 1, 0 },
- { 0, 0, 0, 0, 1, 1, 0 },
- { 0, 0, 0, 1, 1, 1, 0 },
- { 0, 0, 1, 1, 1, 1, 0 },
- { 0, 1, 1, 1, 1, 1, 0 },
- { 1, 1, 1, 1, 1, 1, 0 },
- { 0, 0, 0, 0, 0, 0, 3 },
-}
-
---Beams
-AREA_BEAM1 = {
- { 3 },
-}
-
-AREA_BEAM5 = {
- { 1 },
- { 1 },
- { 1 },
- { 1 },
- { 3 },
-}
-
-AREA_BEAM6 = {
- { 1 },
- { 1 },
- { 1 },
- { 1 },
- { 1 },
- { 3 },
-}
-
-AREA_BEAM7 = {
- { 1 },
- { 1 },
- { 1 },
- { 1 },
- { 1 },
- { 1 },
- { 3 },
-}
-
-AREA_BEAM8 = {
- { 1 },
- { 1 },
- { 1 },
- { 1 },
- { 1 },
- { 1 },
- { 1 },
- { 3 },
-}
-
-AREA_BEAM10 = {
- { 1 },
- { 1 },
- { 1 },
- { 1 },
- { 1 },
- { 1 },
- { 1 },
- { 1 },
- { 1 },
- { 3 },
-}
-
---Diagonal Beams
-AREADIAGONAL_BEAM5 = {
- { 1, 0, 0, 0, 0 },
- { 0, 1, 0, 0, 0 },
- { 0, 0, 1, 0, 0 },
- { 0, 0, 0, 1, 0 },
- { 0, 0, 0, 0, 3 },
-}
-
-AREADIAGONAL_BEAM7 = {
- { 1, 0, 0, 0, 0, 0, 0 },
- { 0, 1, 0, 0, 0, 0, 0 },
- { 0, 0, 1, 0, 0, 0, 0 },
- { 0, 0, 0, 1, 0, 0, 0 },
- { 0, 0, 0, 0, 1, 0, 0 },
- { 0, 0, 0, 0, 0, 1, 0 },
- { 0, 0, 0, 0, 0, 0, 3 },
-}
-
---Circles
-AREA_CIRCLE2X2 = {
- { 0, 1, 1, 1, 0 },
- { 1, 1, 1, 1, 1 },
- { 1, 1, 3, 1, 1 },
- { 1, 1, 1, 1, 1 },
- { 0, 1, 1, 1, 0 },
-}
-
-AREA_CIRCLE3X3 = {
- { 0, 0, 1, 1, 1, 0, 0 },
- { 0, 1, 1, 1, 1, 1, 0 },
- { 1, 1, 1, 1, 1, 1, 1 },
- { 1, 1, 1, 3, 1, 1, 1 },
- { 1, 1, 1, 1, 1, 1, 1 },
- { 0, 1, 1, 1, 1, 1, 0 },
- { 0, 0, 1, 1, 1, 0, 0 },
-}
-
-AREA_CIRCLE3X32 = {
- { 1, 1, 1, 1, 1, 1, 1 },
- { 1, 1, 1, 1, 1, 1, 1 },
- { 1, 1, 1, 1, 1, 1, 1 },
- { 1, 1, 1, 3, 1, 1, 1 },
- { 1, 1, 1, 1, 1, 1, 1 },
- { 1, 1, 1, 1, 1, 1, 1 },
- { 1, 1, 1, 1, 1, 1, 1 },
-}
-
-AREA_CIRCLE3X33 = {
- { 1, 1, 1, 1, 1, 1, 1 },
- { 1, 1, 1, 1, 1, 1, 1 },
- { 1, 1, 0, 0, 1, 1, 1 },
- { 1, 1, 0, 3, 1, 1, 1 },
- { 1, 1, 0, 1, 1, 1, 1 },
- { 1, 1, 1, 1, 1, 1, 1 },
- { 1, 1, 1, 1, 1, 1, 1 },
-}
-
--- Crosses
-AREA_CIRCLE1X1 = {
- { 0, 1, 0 },
- { 1, 3, 1 },
- { 0, 1, 0 },
-}
-
-AREA_CIRCLE5X5 = {
- { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0 },
- { 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0 },
- { 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
- { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
- { 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1 },
- { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
- { 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
- { 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0 },
- { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
-}
-
-AREA_CIRCLE5X5V2 = {
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0 },
- { 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0 },
- { 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
- { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
- { 0, 1, 1, 1, 1, 3, 1, 1, 1, 1, 0 },
- { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
- { 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
- { 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0 },
- { 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-}
-
-AREA_CIRCLE6X6 = {
- { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0 },
- { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
- { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
- { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
- { 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1 },
- { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
- { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
- { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
- { 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
-}
-
---Squares
-AREA_SQUARE1X1 = {
- { 1, 1, 1 },
- { 1, 3, 1 },
- { 1, 1, 1 },
-}
-
--- Walls
-AREA_WALLFIELD = {
- { 1, 1, 3, 1, 1 },
-}
-
-AREADIAGONAL_WALLFIELD = {
- { 0, 0, 0, 0, 1 },
- { 0, 0, 0, 1, 1 },
- { 0, 1, 3, 1, 0 },
- { 1, 1, 0, 0, 0 },
- { 1, 0, 0, 0, 0 },
-}
-
--- Walls Energy
-AREA_WALLFIELD_ENERGY = {
- { 1, 1, 1, 3, 1, 1, 1 },
-}
-
-AREADIAGONAL_WALLFIELD_ENERGY = {
- { 0, 0, 0, 0, 0, 0, 1 },
- { 0, 0, 0, 0, 0, 1, 1 },
- { 0, 0, 0, 0, 1, 1, 0 },
- { 0, 0, 1, 3, 1, 0, 0 },
- { 0, 1, 1, 0, 0, 0, 0 },
- { 0, 1, 0, 0, 0, 0, 0 },
- { 1, 0, 0, 0, 0, 0, 0 },
-}
-
-AREA_RING1_BURST3 = {
- { 0, 0, 0, 1, 1, 1, 0, 0, 0 },
- { 0, 0, 1, 1, 1, 1, 1, 0, 0 },
- { 0, 1, 1, 1, 1, 1, 1, 1, 0 },
- { 1, 1, 1, 0, 0, 0, 1, 1, 1 },
- { 1, 1, 1, 0, 3, 0, 1, 1, 1 },
- { 1, 1, 1, 0, 0, 0, 1, 1, 1 },
- { 0, 1, 1, 1, 1, 1, 1, 1, 0 },
- { 0, 0, 1, 1, 1, 1, 1, 0, 0 },
- { 0, 0, 0, 1, 1, 1, 0, 0, 0 },
-}
-
--- The numbered-keys represents the damage values, and their table
--- contains the minimum and maximum number of rounds of those damage values.
-RANGE = {
- [1] = { 19, 20 },
- [2] = { 10, 10 },
- [3] = { 6, 7 },
- [4] = { 4, 5 },
- [5] = { 3, 4 },
- [6] = { 3, 4 },
- [7] = { 2, 3 },
- [8] = { 2, 3 },
- [9] = { 2, 3 },
- [10] = { 1, 2 },
- [11] = { 1, 2 },
- [12] = { 1, 2 },
- [13] = { 1, 2 },
- [14] = { 1, 2 },
- [15] = { 1, 2 },
- [16] = { 1, 2 },
- [17] = { 1, 2 },
- [18] = { 1, 2 },
- [19] = { 1, 2 },
-}
-
-function Creature:addDamageCondition(target, conditionType, listType, damage, time, rounds)
- if target:isImmune(conditionType) then
- return false
- end
-
- local condition = Condition(conditionType)
- condition:setParameter(CONDITION_PARAM_OWNER, self:getId())
- condition:setParameter(CONDITION_PARAM_DELAYED, true)
-
- if listType == 0 then
- local exponent, value = -10, 0
- while value < damage do
- value = math.floor(10 * math.pow(1.2, exponent) + 0.5)
- condition:addDamage(1, time or 4000, -value)
-
- if value >= damage then
- local permille = math.random(10, 1200) / 1000
- condition:addDamage(1, time or 4000, -math.max(1, math.floor(value * permille + 0.5)))
- else
- exponent = exponent + 1
- end
- end
- elseif listType == 1 then
- rounds = rounds or RANGE
- if rounds[damage] then
- condition:addDamage(math.random(1, rounds[damage][2]), time or 4000, -damage)
- damage = damage - 1
- end
-
- while damage > 0 do
- condition:addDamage(rounds[damage] and math.random(rounds[damage][1], rounds[damage][2]) or 1, time or 4000, -damage)
- damage = damage - (damage > 21 and math.floor(damage / 20) + math.random(0, 1) or 1)
- end
- elseif listType == 2 then
- for _ = 1, rounds do
- condition:addDamage(1, math.random(time[1], time[2]) * 1000, -damage)
- end
- end
-
- target:addCondition(condition)
- return true
-end
-
-function Player:addPartyCondition(combat, variant, condition, baseMana)
- local party = self:getParty()
- if not party then
- self:sendCancelMessage(RETURNVALUE_NOPARTYMEMBERSINRANGE)
- self:getPosition():sendMagicEffect(CONST_ME_POFF)
- return false
- end
-
- local members = party:getMembers()
- members[#members + 1] = party:getLeader()
-
- local position = self:getPosition()
- local affectedMembers = {}
- for _, member in ipairs(members) do
- if member:getPosition():getDistance(position) <= 36 then
- affectedMembers[#affectedMembers + 1] = member
- end
- end
-
- if #affectedMembers <= 1 then
- self:sendCancelMessage(RETURNVALUE_NOPARTYMEMBERSINRANGE)
- position:sendMagicEffect(CONST_ME_POFF)
- return false
- end
-
- local mana = math.ceil(math.pow(0.9, #affectedMembers - 1) * baseMana * #affectedMembers)
- if self:getMana() < mana then
- self:sendCancelMessage(RETURNVALUE_NOTENOUGHMANA)
- position:sendMagicEffect(CONST_ME_POFF)
- return false
- end
-
- if not combat:execute(self, variant) then
- self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
- position:sendMagicEffect(CONST_ME_POFF)
- return false
- end
-
- self:addMana(baseMana - mana, false)
- self:addManaSpent(mana - baseMana)
-
- for _, member in ipairs(affectedMembers) do
- member:addCondition(condition)
- end
- return true
-end
-
-function Player:conjureItem(reagentId, conjureId, conjureCount, effect)
- if not conjureCount and conjureId ~= 0 then
- local itemType = ItemType(conjureId)
- if itemType:getId() == 0 then
- return false
- end
-
- local charges = itemType:getCharges()
- if charges ~= 0 then
- conjureCount = charges
- end
- end
-
- if reagentId ~= 0 and not self:removeItem(reagentId, 1, -1) then
- self:sendCancelMessage(RETURNVALUE_YOUNEEDAMAGICITEMTOCASTSPELL)
- self:getPosition():sendMagicEffect(CONST_ME_POFF)
- return false
- end
-
- local item = self:addItem(conjureId, conjureCount)
- if not item then
- self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
- self:getPosition():sendMagicEffect(CONST_ME_POFF)
- return false
- end
-
- if item:hasAttribute(ITEM_ATTRIBUTE_DURATION) then
- item:decay()
- end
-
- self:getPosition():sendMagicEffect(item:getType():isRune() and CONST_ME_MAGIC_RED or effect)
- return true
-end
diff --git a/data-canary/scripts/lib/talkactions.lua b/data-canary/scripts/lib/talkactions.lua
deleted file mode 100644
index c962dd417ae..00000000000
--- a/data-canary/scripts/lib/talkactions.lua
+++ /dev/null
@@ -1,12 +0,0 @@
-local logFormat = "[%s] %s %s"
-
-function logCommand(player, words, param)
- local file = io.open("data/logs/" .. player:getName() .. " commands.log", "a")
- if not file then
- return
- end
-
- io.output(file)
- io.write(logFormat:format(os.date("%d/%m/%Y %H:%M"), words, param):trim() .. "\n")
- io.close(file)
-end
diff --git a/data-otservbr-global/scripts/lib/create_functions.lua b/data-otservbr-global/scripts/lib/create_functions.lua
deleted file mode 100644
index 845b70375c3..00000000000
--- a/data-otservbr-global/scripts/lib/create_functions.lua
+++ /dev/null
@@ -1,3 +0,0 @@
-createFunctions(MonsterType) -- creates get/set functions for MonsterType
-createFunctions(NpcType) -- creates get/set functions for NpcType
-createFunctions(Spell) -- creates get/set functions for Spell
diff --git a/data-otservbr-global/scripts/lib/defaults_move_event.lua b/data-otservbr-global/scripts/lib/defaults_move_event.lua
deleted file mode 100644
index 75191a642dc..00000000000
--- a/data-otservbr-global/scripts/lib/defaults_move_event.lua
+++ /dev/null
@@ -1,25 +0,0 @@
--- default callbacks
-
-function defaultStepIn(creature, item, position, fromPosition)
- return true
-end
-
-function defaultStepOut(creature, item, position, fromPosition)
- return true
-end
-
-function defaultAddItem(moveitem, tileitem, pos)
- return true
-end
-
-function defaultRemoveItem(moveitem, tileitem, pos)
- return true
-end
-
-function defaultEquip(player, item, slot, isCheck)
- return true
-end
-
-function defaultDeEquip(player, item, slot, isCheck)
- return true
-end
diff --git a/data-otservbr-global/scripts/lib/register_bestiary_charm.lua b/data-otservbr-global/scripts/lib/register_bestiary_charm.lua
deleted file mode 100644
index c0daffff9f9..00000000000
--- a/data-otservbr-global/scripts/lib/register_bestiary_charm.lua
+++ /dev/null
@@ -1,83 +0,0 @@
-registerCharm = {}
-setmetatable(registerCharm, {
- __call = function(self, charm, mask)
- for _, parse in pairs(self) do
- parse(charm, mask)
- end
- end,
-})
-
-Charm.register = function(self, mask)
- return registerCharm(self, mask)
-end
-
-registerCharm.name = function(charm, mask)
- if mask.name then
- charm:name(mask.name)
- end
-end
-
-registerCharm.description = function(charm, mask)
- if mask.description then
- charm:description(mask.description)
- end
-end
-
-registerCharm.sounds = function(charm, mask)
- if mask.sounds then
- if mask.sounds.castSound then
- charm:castSound(mask.sounds.castSound)
- end
- if mask.sounds.impactSound then
- charm:impactSound(mask.sounds.impactSound)
- end
- end
-end
-
-registerCharm.type = function(charm, mask)
- if mask.type then
- charm:type(mask.type)
- end
-end
-
-registerCharm.damageType = function(charm, mask)
- if mask.damageType then
- charm:damageType(mask.damageType)
- end
-end
-
-registerCharm.percent = function(charm, mask)
- if mask.percent then
- charm:percentage(mask.percent)
- end
-end
-
-registerCharm.chance = function(charm, mask)
- if mask.chance then
- charm:chance(mask.chance)
- end
-end
-
-registerCharm.messageCancel = function(charm, mask)
- if mask.messageCancel then
- charm:messageCancel(mask.messageCancel)
- end
-end
-
-registerCharm.messageServerLog = function(charm, mask)
- if mask.messageServerLog then
- charm:messageServerLog(mask.messageServerLog)
- end
-end
-
-registerCharm.effect = function(charm, mask)
- if mask.effect then
- charm:effect(mask.effect)
- end
-end
-
-registerCharm.points = function(charm, mask)
- if mask.points then
- charm:points(mask.points)
- end
-end
diff --git a/data-otservbr-global/scripts/lib/register_npc_type.lua b/data-otservbr-global/scripts/lib/register_npc_type.lua
deleted file mode 100644
index 53a5d525e59..00000000000
--- a/data-otservbr-global/scripts/lib/register_npc_type.lua
+++ /dev/null
@@ -1,211 +0,0 @@
-registerNpcType = {}
-setmetatable(registerNpcType, {
- __call = function(self, npcType, mask)
- for _, parse in pairs(self) do
- parse(npcType, mask)
- end
- end,
-})
-
-NpcType.register = function(self, mask)
- return registerNpcType(self, mask)
-end
-
-registerNpcType.name = function(npcType, mask)
- if mask.name then
- npcType:name(mask.name)
- end
-end
-
-registerNpcType.description = function(npcType, mask)
- if mask.description then
- npcType:nameDescription(mask.description)
- end
-end
-
-registerNpcType.outfit = function(npcType, mask)
- if mask.outfit then
- npcType:outfit(mask.outfit)
- end
-end
-
-registerNpcType.maxHealth = function(npcType, mask)
- if mask.maxHealth then
- npcType:maxHealth(mask.maxHealth)
- end
-end
-
-registerNpcType.health = function(npcType, mask)
- if mask.health then
- npcType:health(mask.health)
- end
-end
-
-registerNpcType.race = function(npcType, mask)
- if mask.race then
- npcType:race(mask.race)
- end
-end
-
-registerNpcType.walkInterval = function(npcType, mask)
- if mask.walkInterval then
- npcType:walkInterval(mask.walkInterval)
- end
-end
-
-registerNpcType.walkRadius = function(npcType, mask)
- if mask.walkRadius then
- npcType:walkRadius(mask.walkRadius)
- end
-end
-
-registerNpcType.speed = function(npcType, mask)
- if mask.speed then
- npcType:baseSpeed(mask.speed)
- end
-end
-
-registerNpcType.flags = function(npcType, mask)
- if mask.flags then
- if mask.flags.floorchange ~= nil then
- npcType:floorChange(mask.flags.floorchange)
- end
- if mask.flags.canPushCreatures ~= nil then
- npcType:canPushCreatures(mask.flags.canPushCreatures)
- end
- if mask.flags.canPushItems ~= nil then
- npcType:canPushItems(mask.flags.canPushItems)
- end
- if mask.flags.pushable ~= nil then
- npcType:isPushable(mask.flags.pushable)
- end
- end
-end
-
-registerNpcType.light = function(npcType, mask)
- if mask.light then
- if mask.light.color then
- local color = mask.light.color
- end
- if mask.light.level then
- npcType:light(color, mask.light.level)
- end
- end
-end
-
-registerNpcType.respawnType = function(npcType, mask)
- if mask.respawnType then
- if mask.respawnType.period then
- npcType:respawnTypePeriod(mask.respawnType.period)
- end
- if mask.respawnType.underground then
- npcType:respawnTypeIsUnderground(mask.respawnType.underground)
- end
- end
-end
-
-registerNpcType.sounds = function(npcType, mask)
- if type(mask.sounds) == "table" then
- if mask.sounds.ticks and mask.sounds.chance and mask.sounds.ids and type(mask.sounds.ids) == "table" and #mask.sounds.ids > 0 then
- npcType:soundSpeedTicks(mask.sounds.ticks)
- npcType:soundChance(mask.sounds.chance)
- for _, v in pairs(mask.sounds.ids) do
- npcType:addSound(v)
- end
- end
- end
-end
-
-registerNpcType.voices = function(npcType, mask)
- if type(mask.voices) == "table" then
- local interval, chance
- if mask.voices.interval then
- interval = mask.voices.interval
- end
- if mask.voices.chance then
- chance = mask.voices.chance
- end
- for k, v in pairs(mask.voices) do
- if type(v) == "table" then
- npcType:addVoice(v.text, interval, chance, v.yell)
- end
- end
- end
-end
-
-registerNpcType.events = function(npcType, mask)
- if type(mask.events) == "table" then
- for k, v in pairs(mask.events) do
- npcType:registerEvent(v)
- end
- end
-end
-
-registerNpcType.shop = function(npcType, mask)
- if type(mask.shop) == "table" then
- for _, shopItems in pairs(mask.shop) do
- local parent = Shop()
- if shopItems.itemName or shopItems.itemname then
- parent:setNameItem(shopItems.itemName or shopItems.itemname)
- end
- if shopItems.clientId or shopItems.clientid then
- parent:setId(shopItems.clientId or shopItems.clientid)
- end
- if shopItems.subType or shopItems.subtype or shopItems.count then
- parent:setCount(shopItems.subType or shopItems.subtype or shopItems.count)
- end
- if shopItems.buy then
- parent:setBuyPrice(shopItems.buy)
- end
- if shopItems.sell then
- parent:setSellPrice(shopItems.sell)
- end
- if shopItems.storageKey or shopItems.storagekey then
- parent:setStorageKey(shopItems.storageKey or shopItems.storagekey)
- end
- if shopItems.storageValue or shopItems.storagevalue then
- parent:setStorageValue(shopItems.storageValue or shopItems.storagevalue)
- end
- if shopItems.child then
- for _, children in pairs(shopItems.child) do
- local child = Shop()
- if shopItems.itemName or shopItems.itemname then
- child:setNameItem(shopItems.itemName or shopItems.itemname)
- end
- if shopItems.clientId or shopItems.clientid then
- child:setId(shopItems.clientId or shopItems.clientid)
- end
- if shopItems.subType or shopItems.subtype or shopItems.count then
- child:setCount(shopItems.subType or shopItems.subtype or shopItems.count)
- end
- if shopItems.buy then
- child:setBuyPrice(shopItems.buy)
- end
- if shopItems.sell then
- child:setSellPrice(shopItems.sell)
- end
- if shopItems.storageKey or shopItems.storagekey then
- child:setStorageKey(shopItems.storageKey or shopItems.storagekey)
- end
- if shopItems.storageValue or shopItems.storagevalue then
- child:setStorageValue(shopItems.storageValue or shopItems.storagevalue)
- end
- parent:addChildShop(child)
- end
- end
- npcType:addShopItem(parent)
- end
- end
-end
-
-registerNpcType.currency = function(npcType, mask)
- if mask.currency then
- npcType:currency(mask.currency)
- end
-end
-
-registerNpcType.speechBubble = function(npcType, mask)
- if mask.speechBubble then
- npcType:speechBubble(mask.speechBubble)
- end
-end
diff --git a/data/XML/imbuements.xml b/data/XML/imbuements.xml
index 74a06dbd9f8..0a2fd90702f 100644
--- a/data/XML/imbuements.xml
+++ b/data/XML/imbuements.xml
@@ -201,7 +201,7 @@
-
+
diff --git a/data-canary/scripts/lib/create_functions.lua b/data/scripts/lib/create_functions.lua
similarity index 100%
rename from data-canary/scripts/lib/create_functions.lua
rename to data/scripts/lib/create_functions.lua
diff --git a/data-canary/scripts/lib/defaults_move_event.lua b/data/scripts/lib/defaults_move_event.lua
similarity index 100%
rename from data-canary/scripts/lib/defaults_move_event.lua
rename to data/scripts/lib/defaults_move_event.lua
diff --git a/data-otservbr-global/scripts/lib/helper_constructors.lua b/data/scripts/lib/helper_constructors.lua
similarity index 100%
rename from data-otservbr-global/scripts/lib/helper_constructors.lua
rename to data/scripts/lib/helper_constructors.lua
diff --git a/data-otservbr-global/scripts/lib/register_actions.lua b/data/scripts/lib/register_actions.lua
similarity index 100%
rename from data-otservbr-global/scripts/lib/register_actions.lua
rename to data/scripts/lib/register_actions.lua
diff --git a/data-canary/scripts/lib/register_bestiary_charm.lua b/data/scripts/lib/register_bestiary_charm.lua
similarity index 100%
rename from data-canary/scripts/lib/register_bestiary_charm.lua
rename to data/scripts/lib/register_bestiary_charm.lua
diff --git a/data-otservbr-global/scripts/lib/register_item_tier.lua b/data/scripts/lib/register_item_tier.lua
similarity index 100%
rename from data-otservbr-global/scripts/lib/register_item_tier.lua
rename to data/scripts/lib/register_item_tier.lua
diff --git a/data-otservbr-global/scripts/lib/register_lever_tables.lua b/data/scripts/lib/register_lever_tables.lua
similarity index 100%
rename from data-otservbr-global/scripts/lib/register_lever_tables.lua
rename to data/scripts/lib/register_lever_tables.lua
diff --git a/data-otservbr-global/scripts/lib/register_migrations.lua b/data/scripts/lib/register_migrations.lua
similarity index 100%
rename from data-otservbr-global/scripts/lib/register_migrations.lua
rename to data/scripts/lib/register_migrations.lua
diff --git a/data-otservbr-global/scripts/lib/register_monster_type.lua b/data/scripts/lib/register_monster_type.lua
similarity index 99%
rename from data-otservbr-global/scripts/lib/register_monster_type.lua
rename to data/scripts/lib/register_monster_type.lua
index c62ca0281d7..cf115a3af05 100644
--- a/data-otservbr-global/scripts/lib/register_monster_type.lua
+++ b/data/scripts/lib/register_monster_type.lua
@@ -547,6 +547,9 @@ registerMonsterType.defenses = function(mtype, mask)
if mask.defenses.armor then
mtype:armor(mask.defenses.armor)
end
+ if mask.defenses.mitigation then
+ mtype:mitigation(mask.defenses.mitigation)
+ end
for _, defense in pairs(mask.defenses) do
if type(defense) == "table" then
mtype:addDefense(readSpell(defense, mtype))
diff --git a/data-canary/scripts/lib/register_npc_type.lua b/data/scripts/lib/register_npc_type.lua
similarity index 100%
rename from data-canary/scripts/lib/register_npc_type.lua
rename to data/scripts/lib/register_npc_type.lua
diff --git a/data-otservbr-global/scripts/lib/register_spells.lua b/data/scripts/lib/register_spells.lua
similarity index 100%
rename from data-otservbr-global/scripts/lib/register_spells.lua
rename to data/scripts/lib/register_spells.lua
diff --git a/data-otservbr-global/scripts/lib/shops.lua b/data/scripts/lib/shops.lua
similarity index 100%
rename from data-otservbr-global/scripts/lib/shops.lua
rename to data/scripts/lib/shops.lua
diff --git a/src/canary_server.cpp b/src/canary_server.cpp
index 9e13e8b05fd..1a2454a9ad0 100644
--- a/src/canary_server.cpp
+++ b/src/canary_server.cpp
@@ -349,7 +349,8 @@ void CanaryServer::loadModules() {
logger.debug("Loading core scripts on folder: {}/", coreFolder);
// Load first core Lua libs
modulesLoadHelper((g_luaEnvironment().loadFile(coreFolder + "/core.lua", "core.lua") == 0), "core.lua");
- modulesLoadHelper(g_scripts().loadScripts(coreFolder + "/scripts", false, false), "/data/scripts");
+ modulesLoadHelper(g_scripts().loadScripts(coreFolder + "/scripts/lib", true, false), coreFolder + "/scripts/libs");
+ modulesLoadHelper(g_scripts().loadScripts(coreFolder + "/scripts", false, false), coreFolder + "/scripts");
// Second XML scripts
modulesLoadHelper(g_vocations().loadFromXml(), "XML/vocations.xml");
@@ -363,7 +364,6 @@ void CanaryServer::loadModules() {
modulesLoadHelper((g_npcs().load(true, false)), "npclib");
logger.debug("Loading datapack scripts on folder: {}/", datapackName);
- modulesLoadHelper(g_scripts().loadScripts(datapackFolder + "/scripts/lib", true, false), datapackFolder + "/scripts/libs");
// Load scripts
modulesLoadHelper(g_scripts().loadScripts(datapackFolder + "/scripts", false, false), datapackFolder + "/scripts");
// Load monsters
diff --git a/src/creatures/npcs/npc.cpp b/src/creatures/npcs/npc.cpp
index 5602f145807..7fe61491efd 100644
--- a/src/creatures/npcs/npc.cpp
+++ b/src/creatures/npcs/npc.cpp
@@ -405,24 +405,23 @@ void Npc::onPlayerSellItem(std::shared_ptr player, uint16_t itemId, uint
}
}
- if (toRemove != 0) {
- g_logger().error("[Npc::onPlayerSellItem] - Problem while removing items from player {} amount {} of items with id {} on shop for npc {}, the payment will be made based on amount of removed items.", player->getName(), toRemove, itemId, getName());
- }
-
auto totalRemoved = amount - toRemove;
auto totalCost = static_cast(sellPrice * totalRemoved);
- if (getCurrency() == ITEM_GOLD_COIN) {
- totalPrice += totalCost;
- if (g_configManager().getBoolean(AUTOBANK, __FUNCTION__)) {
- player->setBankBalance(player->getBankBalance() + totalCost);
+ g_logger().debug("[Npc::onPlayerSellItem] - Removing items from player {} amount {} of items with id {} on shop for npc {}", player->getName(), toRemove, itemId, getName());
+ if (totalRemoved > 0 && totalCost > 0) {
+ if (getCurrency() == ITEM_GOLD_COIN) {
+ totalPrice += totalCost;
+ if (g_configManager().getBoolean(AUTOBANK, __FUNCTION__)) {
+ player->setBankBalance(player->getBankBalance() + totalCost);
+ } else {
+ g_game().addMoney(player, totalCost);
+ }
+ g_metrics().addCounter("balance_increase", totalCost, { { "player", player->getName() }, { "context", "npc_sale" } });
} else {
- g_game().addMoney(player, totalCost);
- }
- g_metrics().addCounter("balance_increase", totalCost, { { "player", player->getName() }, { "context", "npc_sale" } });
- } else {
- std::shared_ptr- newItem = Item::CreateItem(getCurrency(), totalCost);
- if (newItem) {
- g_game().internalPlayerAddItem(player, newItem, true);
+ std::shared_ptr
- newItem = Item::CreateItem(getCurrency(), totalCost);
+ if (newItem) {
+ g_game().internalPlayerAddItem(player, newItem, true);
+ }
}
}
diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp
index 9a2e04af8b4..0a02122ff26 100644
--- a/src/creatures/players/player.cpp
+++ b/src/creatures/players/player.cpp
@@ -7023,6 +7023,11 @@ bool Player::saySpell(
// Forge system
void Player::forgeFuseItems(ForgeAction_t actionType, uint16_t firstItemId, uint8_t tier, uint16_t secondItemId, bool success, bool reduceTierLoss, bool convergence, uint8_t bonus, uint8_t coreCount) {
+ if (getFreeBackpackSlots() == 0) {
+ sendCancelMessage(RETURNVALUE_NOTENOUGHROOM);
+ return;
+ }
+
ForgeHistory history;
history.actionType = actionType;
history.tier = tier;
@@ -7261,6 +7266,11 @@ void Player::forgeFuseItems(ForgeAction_t actionType, uint16_t firstItemId, uint
}
void Player::forgeTransferItemTier(ForgeAction_t actionType, uint16_t donorItemId, uint8_t tier, uint16_t receiveItemId, bool convergence) {
+ if (getFreeBackpackSlots() == 0) {
+ sendCancelMessage(RETURNVALUE_NOTENOUGHROOM);
+ return;
+ }
+
ForgeHistory history;
history.actionType = actionType;
history.tier = tier;
diff --git a/src/game/game.cpp b/src/game/game.cpp
index 397695f822f..f1d02f38bd2 100644
--- a/src/game/game.cpp
+++ b/src/game/game.cpp
@@ -2152,11 +2152,23 @@ std::tuple Game::addItemBatch(const std::shared
}
if (!dropping) {
uint32_t remainderCount = 0;
- ret = internalCollectManagedItems(player, item, g_game().getObjectCategory(item), false);
- // If cannot place it in the obtain containers, will add it normally
- if (ret != RETURNVALUE_NOERROR) {
+ bool addedToAutoContainer = false;
+ // First, try adding to the autoContainer, if it is set
+ if (autoContainerId != 0) {
ret = internalAddItem(destination, item, CONST_SLOT_WHEREEVER, flags, false, remainderCount);
+ if (ret == RETURNVALUE_NOERROR) {
+ addedToAutoContainer = true;
+ }
+ }
+ // If it failed to add to the autoContainer, or it's not set, use the current logic
+ if (!addedToAutoContainer) {
+ ret = internalCollectManagedItems(player, item, g_game().getObjectCategory(item), false);
+ // If it can't place in the player's backpacks, add normally
+ if (ret != RETURNVALUE_NOERROR) {
+ ret = internalAddItem(destination, item, CONST_SLOT_WHEREEVER, flags, false, remainderCount);
+ }
}
+
if (remainderCount != 0) {
std::shared_ptr
- remainderItem = Item::CreateItem(item->getID(), remainderCount);
ReturnValue remaindRet = internalAddItem(destination->getTile(), remainderItem, INDEX_WHEREEVER, FLAG_NOLIMIT);
@@ -3068,6 +3080,11 @@ void Game::playerEquipItem(uint32_t playerId, uint16_t itemId, bool hasTier /* =
return;
}
+ if (player->getFreeBackpackSlots() == 0) {
+ player->sendCancelMessage(RETURNVALUE_NOTENOUGHROOM);
+ return;
+ }
+
const ItemType &it = Item::items[itemId];
Slots_t slot = getSlotType(it);
@@ -3075,6 +3092,7 @@ void Game::playerEquipItem(uint32_t playerId, uint16_t itemId, bool hasTier /* =
auto equipItem = searchForItem(backpack, it.id, hasTier, tier);
if (slotItem && slotItem->getID() == it.id && (!it.stackable || slotItem->getItemCount() == slotItem->getStackSize() || !equipItem)) {
internalMoveItem(slotItem->getParent(), player, CONST_SLOT_WHEREEVER, slotItem, slotItem->getItemCount(), nullptr);
+ g_logger().debug("Item {} was unequipped", slotItem->getName());
} else if (equipItem) {
if (it.weaponType == WEAPON_AMMO) {
auto quiver = player->getInventoryItem(CONST_SLOT_RIGHT);
@@ -3084,7 +3102,15 @@ void Game::playerEquipItem(uint32_t playerId, uint16_t itemId, bool hasTier /* =
}
}
- internalMoveItem(equipItem->getParent(), player, slot, equipItem, equipItem->getItemCount(), nullptr);
+ if (slotItem) {
+ internalMoveItem(slotItem->getParent(), player, INDEX_WHEREEVER, slotItem, slotItem->getItemCount(), nullptr);
+ g_logger().debug("Item {} was moved back to player", slotItem->getName());
+ }
+
+ auto ret = internalMoveItem(equipItem->getParent(), player, slot, equipItem, equipItem->getItemCount(), nullptr);
+ if (ret == RETURNVALUE_NOERROR) {
+ g_logger().debug("Item {} was equipped", equipItem->getName());
+ }
}
}