• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Lua Xikini's Free Scripting Service TFS 1.4.2

Xikini

I whore myself out for likes
Senator
Joined
Nov 17, 2010
Messages
6,830
Solutions
586
Reaction score
5,413
Request whatever you want, within reason.

Please do not request for things that require source editing or database queries.

------------------------------------
If I've reacted to your post, it means I've read it. 👍😍🤣😲🙁😡🤔😉

------------------------------------
Completed Requests

A boss that randomly creates effects on tiles, that when stepped on, gives the player increased damage/mitigation to that boss.
Kill monster and gain X% extra loot chance or Y% extra experience for Z minutes
A pack of 6 useful simple scripts.
-> (1) Simple quest npc
-> (2,3,4,5) use levers in specific order / stand with 4 players / use 4 objects / place items -> to open wall
-> (6) use lever to add/remove/replace objects
Wave type spell, with multiple effects
-> Same spell, but with default combat system
House market system. (owner places price on blackboard and object on the ground, other players buy with a lever)
Respawn System (closest anchor (like darks souls bonfire) / tavern / temple)
Vocation Death Protection (protect the noobs!)
Spell that shows area it will damage, before it strikes.
RAID SYSTEM - rebuilt in Lua, with some more features.
Modal Window - Teleport Item with saving/deleting of positions
Show top 3 Online Players (outfit, name, level) (as monsters, in set positions)
onLook function showing kill count of player.
Modal Window - Use Item -> choose reward.
Talkaction - !backpacks - to buy backpacks (or single items) anywhere. uses bank & current money on players
Quest/Event? Turn a bunch of objects with a monster, spawn portal.
Spawn Monsters, after they've all been killed, give global increased experience/loot in specific area's
Evolving Weapons - Kill X amount of specific creatures, evolve weapon and gain extra damage to those creatures.
Random Portals spawn at XX:XX time(s). (can exit 'off' portals, if you have the storage.)
Monster that adjusts speed based on target
Monster that increases damage output based on # of players nearby
Experience recovery Item. Die -> Use Item -> gain % of lost experience
Character Snapshot - Keeps track of all skills & level, for resetting later.
Fire Dagger - Physical Damage Melee Weapon, with % added damage
Players in specific level ranges don't lose skills/loot/experience, when they die.
Multiclient Limit Check - with admin account not being counted towards limit
Capacity Increasing Items
Upgradeable Protection Amulet - 10% to all elements
-> upgrade amulet, but for all items.
onKill - give reward to all players who dealt damage
-> example: give reward based on damage contribution
Quest Book - Record your quest progress into a book.
Stat System, using modal windows
Holy Tible (POI) - Require Item to use teleport tiles
Item Upgrade System
Skill Stages
-> individual stages for each skill type
-> talkaction to check rates (by @Extrodus)
Random Reward Item - gives different rewards based on vocation
Bounty Hunter System
NPC & Player Walk System (Follow Nodes to destination)
Health/Mana gain permanent - limited use items

------------------------------------
Support

If you have an issue with one of my scripts, I will attempt to help you, but not in this thread.
Make a thread in the support board.
Ensure to follow all rules of the support board.
Without all necessary information it's impossible to help you.

------------------------------------
I will only be scripting for TFS 1.4.2

Not TFS 1.1 / 1.2
Not OTServBR / OTX
and certainly not TFS 0.4

When requesting a script, don't ask for "this script I saw on super popular OT".

I don't care where the idea came from.
I don't want to see a video of the script in action.

Just describe what the script is supposed to do, and I'll try to make it.

Any script that I make in response to a request from this thread will be shared publicly, here, in this thread.

I'm not going to make anything in private, so post your request in this thread only.
Please, for the love of god, don't pm me asking to make a script.
I will actually add you to my ignore list if you do that.
--------------

Anyways!

Thanks for coming by and checking the thread out.
If you think there is a better way to script something, feel free to let me know.
I'm here to learn.

Cheers,

Xikini
---------

P.S.
I've been doing free scripting service's on/off for awhile.
And if you want to see the previous threads, go check them here.

 
Last edited by a moderator:
View attachment 81898

data/script/evolvingWeapons.lua
Lua:
local evolvingWeapons = {
    [2376] = {
        ["Gobblin' These Nuts"] = {
            evolve = {
                killsRequired = 20,
                newDescription = "With your wanton cravings out of whack, you gobble up all the nuts and deal increased damage.",
                monsters = {
                    ["goblin lord"] = {value = 20},
                    ["goblin"] = {value = 1},
                    ["goblin assassin"] = {value = 1}
                }
            },
            bonuses = {
                increasedDamagePercent = 100,
                affectedMonsters = {"goblin", "goblin assassin"}
            }
        },
        ["Dragon Poker"] = {
            evolve = {
                killsRequired = 20,
                newDescription = "Poking dragons bum for increased damage. :D",
                monsters = {
                    ["demodras"] = {value = 20},
                    ["dragon"] = {value = 1},
                    ["dragon lord"] = {value = 2}
                }
            },
            bonuses = {
                increasedDamagePercent = 100,
                affectedMonsters = {"dragon", "dragon lord"}
            }
        }      
    }
}

-- END OF CONFIG

local affectedMonsters = {}

for itemId, weapons in pairs(evolvingWeapons) do
    for weaponName, weaponDetails in pairs(weapons) do
        -- recreate monster table with lowercase letters
        local newMonsters = {}
        for monsterName, monsterDetails in pairs(weaponDetails.evolve.monsters) do
            newMonsters[monsterName:lower()] = monsterDetails
        end
        weaponDetails.evolve.monsters = newMonsters
        -- update all affected monster with lowercase letters
        if weaponDetails.bonuses and weaponDetails.bonuses.affectedMonsters then
            for i, monsterName in ipairs(weaponDetails.bonuses.affectedMonsters) do
                weaponDetails.bonuses.affectedMonsters[i] = monsterName:lower()
                affectedMonsters[weaponDetails.bonuses.affectedMonsters[i]] = 0
            end
        end
    end
end

local function sendDelayedMessage(creatureId, message)
    local creature = Creature(creatureId)
    if not creature then
        return
    end
    creature:sendTextMessage(MESSAGE_INFO_DESCR, message)
end


local creatureevent = CreatureEvent("onKill_evolvingWeapons")

function creatureevent.onKill(creature, target)
    if not target:isMonster() then
        return true
    end
  
    local weapon = creature:getSlotItem(CONST_SLOT_LEFT)
    if not weapon then
        return true
    end
  
    if weapon:getCustomAttribute("EVOLVED_WEAPON") then
        return true
    end
  
    local index = evolvingWeapons[weapon:getId()]
    if not index then
        return true
    end
  
    local monsterName = target:getName():lower()  
    local evolveEvents = {
        -- {evolveName = "", totalKills = 0}
    }
  
    for k, v in pairs(index) do
        local totalKills = weapon:getCustomAttribute(k)
        totalKills = totalKills and totalKills or 0
        if v.evolve.monsters[monsterName] then
            totalKills = totalKills + v.evolve.monsters[monsterName].value
            weapon:setCustomAttribute(k, totalKills)
        end
        if totalKills >= v.evolve.killsRequired then
            evolveEvents[#evolveEvents + 1] = {evolveName = k, totalKills = totalKills}
        end
    end
  
    table.sort(evolveEvents, function(a, b) return a.totalKills > b.totalKills end)
  
    if not evolveEvents[1] or evolveEvents[2] and evolveEvents[1].totalKills == evolveEvents[2].totalKills then
        return true
    end
  
    for k, _ in pairs(index) do
        if weapon:getCustomAttribute(k) then
            weapon:removeCustomAttribute(k)
        end
    end
  
    local itemName = ItemType(weapon:getId()):getName()
    local text = string.format("Your %s evolved into %s!", itemName, evolveEvents[1].evolveName)
    addEvent(sendDelayedMessage, 0, creature:getId(), text)
    weapon:setAttribute(ITEM_ATTRIBUTE_NAME, evolveEvents[1].evolveName)
    weapon:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, index[evolveEvents[1].evolveName].evolve.newDescription)
    weapon:setCustomAttribute("EVOLVED_WEAPON", evolveEvents[1].evolveName)
    return true
end

creatureevent:register()


local creatureevent = CreatureEvent("onLogin_evolvingWeapons")

function creatureevent.onLogin(player)
    player:registerEvent("onKill_evolvingWeapons")
    return true
end

creatureevent:register()



local creatureevent = CreatureEvent("onHealthChange_evolvingWeapons")

function creatureevent.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
    if not isPlayer(attacker) then
        return primaryDamage, primaryType, secondaryDamage, secondaryType
    end
  
    local weapon = attacker:getSlotItem(CONST_SLOT_LEFT)
    if not weapon then
        return primaryDamage, primaryType, secondaryDamage, secondaryType
    end
  
    local evolvedWeapon = weapon:getCustomAttribute("EVOLVED_WEAPON")
    if not evolvedWeapon then
        return primaryDamage, primaryType, secondaryDamage, secondaryType
    end
  
    local index = evolvingWeapons[weapon:getId()][evolvedWeapon].bonuses
    if not table.contains(index.affectedMonsters, creature:getName():lower()) then
        return primaryDamage, primaryType, secondaryDamage, secondaryType
    end
  
    primaryDamage = primaryDamage * ((index.increasedDamagePercent + 100) / 100)
    secondaryDamage = secondaryDamage * ((index.increasedDamagePercent + 100) / 100)
    return primaryDamage, primaryType, secondaryDamage, secondaryType
end

creatureevent:register()



local eventCallback = EventCallback

function eventCallback.onSpawn(creature, position, startup, artificial)
    if affectedMonsters[creature:getName():lower()] then
        creature:registerEvent("onHealthChange_evolvingWeapons")
    end
    return true
end

eventCallback:register(-666)
is it possible to put a talkaction to this or something to see how many mobs left etc?
 
is it possible to put a talkaction to this or something to see how many mobs left etc?
That would be tough, since each weapon can evolve in multiple different ways, depending on the monsters you are hunting..

mm alright, I think got something cooking.

Untested.
Put into same file.

Lua:
local talkaction = TalkAction("!checkEvolution")

function talkaction.onSay(player, words, param, type)
	local slotItem = player:getSlotItem(CONST_SLOT_LEFT)
	if not slotItem then
		player:sendTextMessage(MESSAGE_STATUS_SMALL, "No weapon equipped in left hand.")
		return false
	end
	
	local slotItem_itemId = slotItem:getId()
	local weaponIndex = evolvingWeapons[slotItem_itemId]
	if not weaponIndex then
		player:sendTextMessage(MESSAGE_STATUS_SMALL, "This weapon has no evolutions.")
		return false
	end
	
	if slotItem:getCustomAttribute("EVOLVED_WEAPON") then
		player:sendTextMessage(MESSAGE_STATUS_SMALL, "This weapon has already evolved.")
        return false
    end
	
	local text = ""
	for k, v in pairs(weaponIndex) do
		local totalKills = slotItem:getCustomAttribute(k)
        totalKills = totalKills and totalKills or 0
		if text ~= "" then
			text = text .. "\n\n"
		end
		text = text .. "Evolution: " .. k .. "\n"
		text = text .. "Requirement: " .. v.evolve.killsRequired .. "\n"
		text = text .. "Current: " .. totalKills
	end
	
	player:showTextDialog(slotItem_itemId, text)
	return false
end

talkaction:separator(" ")
talkaction:register()
 
That would be tough, since each weapon can evolve in multiple different ways, depending on the monsters you are hunting..

mm alright, I think got something cooking.

Untested.
Put into same file.

Lua:
local talkaction = TalkAction("!checkEvolution")

function talkaction.onSay(player, words, param, type)
    local slotItem = player:getSlotItem(CONST_SLOT_LEFT)
    if not slotItem then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, "No weapon equipped in left hand.")
        return false
    end
   
    local slotItem_itemId = slotItem:getId()
    local weaponIndex = evolvingWeapons[slotItem_itemId]
    if not weaponIndex then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, "This weapon has no evolutions.")
        return false
    end
   
    if slotItem:getCustomAttribute("EVOLVED_WEAPON") then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, "This weapon has already evolved.")
        return false
    end
   
    local text = ""
    for k, v in pairs(weaponIndex) do
        local totalKills = slotItem:getCustomAttribute(k)
        totalKills = totalKills and totalKills or 0
        if text ~= "" then
            text = text .. "\n\n"
        end
        text = text .. "Evolution: " .. k .. "\n"
        text = text .. "Requirement: " .. v.evolve.killsRequired .. "\n"
        text = text .. "Current: " .. totalKills
    end
   
    player:showTextDialog(slotItem_itemId, text)
    return false
end

talkaction:separator(" ")
talkaction:register()
it works but there are some stuff missing, it doesnt show what mobs to kill also when i finish the first tier on weapon then it wont upgrade it to next tier etc.

so this script works but for 1 upgrade only not for multiple upgrades if i wanted so.
 
it works but there are some stuff missing, it doesnt show what mobs to kill also when i finish the first tier on weapon then it wont upgrade it to next tier etc.

so this script works but for 1 upgrade only not for multiple upgrades if i wanted so.
correct.
 
so this script is just for 1 upgrade and not more and the idea is to maybe choose witch upgrade i am going to make?
The original idea as far as I can remember, was to have hidden evolutions for weapons for the players to find.
It was a very rpg server.

But yes, it's built that only a single transformation can take place, per item.
 
The original idea as far as I can remember, was to have hidden evolutions for weapons for the players to find.
It was a very rpg server.

But yes, it's built that only a single transformation can take place, per item.
i see then this idea with talkaction is unnecessary as i taught that it was possible to upgrade 1 wep many stages.

doesnt it take much to convert it to many stages and maybe even put some extra attributes to it as fire, earth and ice so on as extra attack?
 
Would be possible to duplicate or double the spawn amount if player amount login surpasses certain amount of players online? If players surpasses 59 online players double the spawn amount if 100 triplicate it and so on? If so could you give me an exampleor tell me which functions to use? Thank
 
Hi @Xikini might I ask a script? I need something for this piece of map
1716013895786.png

The idea is that the players must stand on the tiles surrounding the lever, and the lever can be pulled only if Ghazbaran is alive. Is there a method to check if the boss is alive and make the lever be pulled only if it is? You crafted this system before, probably could be used with this one. [1.X] Boss system (with checker, auto-respawn and day configuration) (https://otland.net/threads/1-x-boss-system-with-checker-auto-respawn-and-day-configuration.281920/#post-2701975)

Then, when you pull the lever players should be teleported to the big north area, to fight the boss. Doesn't matter if 1 or 8 players pull the lever, they should be able to enter as long the boss is alive. If there could be a chance to teleport each player to a random position from the north area, would be nice, but, if is better to set a single coordinate for each one (like player1 goes to xyz, then player 2 goes to xyz...) it's fine!

So when you kill the boss, it actually activates this system https://otland.net/threads/1-x-boss-system-with-checker-auto-respawn-and-day-configuration.281920/#post-2701975 making Ghazbaran appear after "x" minutes of being killed. Would be possible that this "x" minutes while Ghazbaran is respawning again, a portal appears to exit the north room, and also, make the lever stop working? (since the boss is death).

The last thing I would like to add to all this, is that player's can only pull the lever if the north area is without players, or empty of players, so more teams can't just come and spawn inside while another team is making the boss. If any other information is needed please let me know!

PS: As north area I refer to the area that is passing the magic walls.

Thanks in advance!
Hope it can be possible :)
 
For me this code works, @ralke
Lua:
local ghazarea = {x=,y=,z=}     -- center position of area 
local ghazspectators = {}
local ghazspectators = getSpectators(ghazarea, 30, 30, FALSE) -- scan radius
if ghazspectators then
        for _, pid in ipairs(ghazspectators) do
            n = getCreatureName(pid):lower()
            if n == "ghazbaran" then
                  -- RUN LEVER         
            else
                  -- cancel message
            end
        end 
else
    -- cancel message
end
 
Hi @Xikini might I ask a script? I need something for this piece of map

The idea is that the players must stand on the tiles surrounding the lever, and the lever can be pulled only if Ghazbaran is alive. Is there a method to check if the boss is alive and make the lever be pulled only if it is? You crafted this system before, probably could be used with this one. [1.X] Boss system (with checker, auto-respawn and day configuration) (https://otland.net/threads/1-x-boss-system-with-checker-auto-respawn-and-day-configuration.281920/#post-2701975)

Then, when you pull the lever players should be teleported to the big north area, to fight the boss. Doesn't matter if 1 or 8 players pull the lever, they should be able to enter as long the boss is alive. If there could be a chance to teleport each player to a random position from the north area, would be nice, but, if is better to set a single coordinate for each one (like player1 goes to xyz, then player 2 goes to xyz...) it's fine!

So when you kill the boss, it actually activates this system https://otland.net/threads/1-x-boss-system-with-checker-auto-respawn-and-day-configuration.281920/#post-2701975 making Ghazbaran appear after "x" minutes of being killed. Would be possible that this "x" minutes while Ghazbaran is respawning again, a portal appears to exit the north room, and also, make the lever stop working? (since the boss is death).

The last thing I would like to add to all this, is that player's can only pull the lever if the north area is without players, or empty of players, so more teams can't just come and spawn inside while another team is making the boss. If any other information is needed please let me know!

PS: As north area I refer to the area that is passing the magic walls.

Thanks in advance!
Hope it can be possible :)

If no boss spawned, lever cannot be activated.
If players enter the boss chamber, and do not interact with the boss for 5 minutes, they will be kicked out.
When boss dies, a portal appears to exit.
If players refuse to leave, they will automatically be kicked out 10 seconds before the next Boss is summoned.
When all players have exited, the portal disappears, and lever resets.

Removed 90% of the raidBossInformation table, as you really don't need that many examples.

Suffice to say, just make sure marker in this table and matches the next script.
Lua:
raidBossInformation = {
	{
		marker = 6,		
		dayToSpawn = "Saturday",
		position = Position(861, 890, 12),
		monsterName = "Ghazbaran",
		respawnTime = 4, -- hours
		messageOnSpawn = "Ghazbaran is awakening... demonic entities are entering the mortal realm in the Hrodmir mines.",
		messageOnDeath = "Ghazbaran has been defeated, the demon master will reveal himself in Hrodimir in 4 hours.",
		creatureId = 0, -- don't touch
		lastKilledTime = 0, -- don't touch
		lastDamagedTime = 0 -- don't touch
	},
	{
		marker = nil,	
		dayToSpawn = "Any",
		position = Position(1299, 834, 15),
		monsterName = "Condesa Tristeza",
		respawnTime = 1, -- hour
		messageOnSpawn = "Countess Sorrow is awakening... demonic entities are spawning in the Bazir's throneroom.",
		messageOnDeath = "Countess Sorrow has been defeated, this demonic spawn will reveal himself in Bazir's throneroom in 1 hour.",
		creatureId = 0, -- don't touch
		lastKilledTime = 0, -- don't touch
		lastDamagedTime = 0 -- don't touch
	},
}

local day = " .. (day or os.date('%A')) .."-- don't touch

local function respawnBoss(index)
	local spawn = raidBossInformation[index]
	local monster = Game.createMonster(spawn.monsterName, spawn.position, false, true)
	if monster then
		spawn.creatureId = monster:getId()
		monster:setMasterPosition(spawn.position)
		monster:registerEvent("raidBossDeath")
		monster:registerEvent("raidBossHealthChange")
		Game.broadcastMessage(spawn.messageOnSpawn, MESSAGE_EVENT_ADVANCE)
	else
		print("Failed to respawn index: " .. index .. " -> " .. spawn.monsterName .. "")
	end
end

local globalevent = GlobalEvent("raidBosses")

function globalevent.onStartup()
	day = os.date('%A')
	for index, spawn in pairs(raidBossInformation) do
		if spawn.dayToSpawn == day or spawn.dayToSpawn == "Any" then
			local monster = Game.createMonster(spawn.monsterName, spawn.position, false, true)
			if monster then
				spawn.creatureId = monster:getId()
				monster:setMasterPosition(spawn.position)
				monster:registerEvent("raidBossDeath")
				monster:registerEvent("raidBossHealthChange")
			else
				print("Failed to spawn index: " .. index .. " -> " .. spawn.monsterName .. "")
			end
		end
	end
	return true
end

globalevent:register()


local creatureevent = CreatureEvent("raidBossHealthChange")

function creatureevent.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
	local bossId = creature:getId()
	for i = 1, #raidBossInformation do
		if raidBossInformation[i].creatureId == bossId then
			if attacker and attacker:isPlayer() then
				raidBossInformation[i].lastDamagedTime = os.time()
			end
			return primaryDamage, primaryType, secondaryDamage, secondaryType
		end
	end
	print("Something went wrong in raidBossHealthChange script.")
	return primaryDamage, primaryType, secondaryDamage, secondaryType
end

creatureevent:register()


local creatureevent = CreatureEvent("raidBossDeath")

function creatureevent.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
	local bossId = creature:getId()
	for i = 1, #raidBossInformation do
		if raidBossInformation[i].creatureId == bossId then
			raidBossInformation[i].creatureId = 0
			raidBossInformation[i].lastKilledTime = os.time()
			Game.broadcastMessage(raidBossInformation[i].messageOnDeath, MESSAGE_EVENT_ADVANCE)
			addEvent(respawnBoss, 1000 * 60 * 60 * raidBossInformation[i].respawnTime, i)
			return true
		end
	end
	print("Something went wrong in raidBossDeath script.")
	return true
end

creatureevent:register()


local talk = TalkAction("/bosscheck", "!bosscheck")

function talk.onSay(player, words, param)
	local text = ""
	for i = 1, #raidBossInformation do
		if text ~= "" then
			text = text .. "\n"
		end
		text = text .. raidBossInformation[i].monsterName
		text = text .. " " .. (raidBossInformation[i].dayToSpawn == "Any" and " [" .. day .. "]" or " [" .. raidBossInformation[i].dayToSpawn .. "]") .. "\n    "
		if raidBossInformation[i].creatureId == 0 then
			if raidBossInformation[i].lastKilledTime == 0 then
				text = text .. "Unavailable"
			else
				text = text .. "Dead -> respawning in " .. os.date("!%Hh %Mm %Ss", (raidBossInformation[i].lastKilledTime + (60 * 60 * raidBossInformation[i].respawnTime)) - os.time())
			end
		else
			text = text .. "Alive"
		end
	end
	player:showTextDialog(2239, text, false)
	return false
end

talk:separator(" ")
talk:register()
Lua:
-- this script does not function on it's own, and requires the previous script. They work in tandem.
local config = {
	marker = 6, -- must match the marker in the boss table
	actionId = 45001, -- to put on lever
	teleportId = 1387,
	teleportPosition = Position(1000, 1000, 7),
	leverId = {
		left = 1945,
		right = 1946
	},
	leverPosition = Position(1000, 1000, 7),
	playerPositions = {
		Position(1000, 1000, 7), -- positions around lever
		Position(1000, 1000, 7),
		Position(1000, 1000, 7),
		Position(1000, 1000, 7),
		Position(1000, 1000, 7),
		Position(1000, 1000, 7),
		Position(1000, 1000, 7),
		Position(1000, 1000, 7)
	},
	bossArea = {
		from = Position(1000, 1000, 7), -- top left corner
		to = Position(1000, 1000, 7),   -- bottom right corner
	},
	exitPosition = Position(1000, 1000, 7),
	bossIndex = 0, -- don't touch
	players = {} -- don't touch
}

local function resetArea()
	local tile = Tile(config.teleportPosition)
	local teleport = tile:getItemById(config.teleportId)
	if teleport then
		teleport:remove()
	end
	tile = Tile(config.leverPosition)
	local lever = tile:getItemById(config.leverId.right)
	if lever then
		lever:transform(config.leverId.left)
	end
	for i = #config.players, 1, -1 do
		local player = Player(config.players[i].playerId)
		if player then
			player:teleportTo(config.exitPosition)
		end
	end
	config.players = {}
end

local function monitorPlayers(bossId)
	for i = #config.players, 1, -1 do
		local player = Player(config.players[i].playerId)
		if not player then
			table.remove(config.players, i)
		end
	end
	
	local index = raidBossInformation[config.bossIndex]
	local tile = Tile(config.teleportPosition)
	local teleport = tile:getItemById(config.teleportId)
	
	if not next(config.players) then
		resetArea()
		return
	end

	if index.creatureId ~= 0 and index.creatureId ~= bossId then
		resetArea()
		return
	end
	if index.creatureId ~= bossId then
		if not teleport then
			teleport = Game.createItem(config.teleportId, 1, config.teleportPosition)
			teleport:setActionId(config.actionId)
		end
		
		local respawnTime = index.lastKilledTime + (60 * 60 * index.respawnTime)
		local currentTime = os.time()
		if respawnTime - currentTime <= 10 then
			resetArea()
		else
			addEvent(monitorPlayers, 2000, bossId)
		end
		return
	end
	if (index.lastDamagedTime + 300) > os.time() then
		addEvent(monitorPlayers, 2000, bossId)
		return
	end
	resetArea()
end

local action = Action()

function action.onUse(player, item, fromPosition, target, toPosition, isHotkey)
	if item:getId() == config.teleportId then
		return false
	end
	if item:getId() == config.leverId.right then
		return false
	end
	if config.bossIndex == 0 then
		return true
	end
	local index = raidBossInformation[config.bossIndex]
	if index.creatureId == 0 then
		return true
	end
	if next(config.players) then
		return true
	end
	item:transform(config.leverId.right)
	for i = 1, #config.playerPositions do
		local tile = Tile(config.playerPositions[i])
		if tile then
			local topCreature = tile:getTopVisibleCreature(player)
			if topCreature and topCreature:isPlayer() then
				config.players[#config.players + 1] = {playerId = topCreature:getId()}
				local teleport = false
				while teleport == false do
					local teleportPosition = Position(math.random(config.bossArea.from.x, config.bossArea.to.x), math.random(config.bossArea.from.y, config.bossArea.to.y), math.random(config.bossArea.from.z, config.bossArea.to.z))
					local teleportTile = Tile(teleportPosition)
					if teleportTile and teleportTile:isWalkable() then
						topCreature:teleportTo(teleportPosition)
						teleport = true
					end
				end
			end
		end
	end
	index.lastDamagedTime = os.time()
	monitorPlayers(index.creatureId)
	return true
end

action:aid(config.actionId)
action:register()


local moveevent = MoveEvent()

function moveevent.onStepIn(creature, item, position, fromPosition)
	if item:getId() ~= config.teleportId then
		return true
	end
	if not creature:isPlayer() then
		return true
	end
	local creatureId = creature:getId()
	for i = #config.players, 1, -1 do
		if config.players[i].playerId == creatureId then
			table.remove(config.players, i)
			break
		end
	end
	creature:teleportTo(config.exitPosition)
	return true
end

moveevent:aid(config.actionId)
moveevent:register()


local function loadMarker(attempts)
	if not raidBossInformation then
		if attempts < 60 then
			addEvent(loadMarker, 1000, attempts + 1)
		else
			print("Error: Unable to find raidBossInformation table. (Marker: " .. config.marker .. ")")
		end
		return
	end
	for i = 1, #raidBossInformation do
		if raidBossInformation[i].marker then
			if raidBossInformation[i].marker == config.marker then
				config.bossIndex = i
				return
			end
		end
	end
	print("Error: Unable to find matching boss marker in raidBossInformation table. (Marker: " .. config.marker .. ")")
end

local globalevent = GlobalEvent("onStartUp_raidBoss_" .. config.actionId)

function globalevent.onStartup()
	addEvent(loadMarker, 1000, 0)
	return true
end

globalevent:register()


local creatureevent = CreatureEvent("onLogin_raidBoss_" .. config.actionId)

function creatureevent.onLogin(player)
	if player:getPosition():isInRange(config.bossArea.from, config.bossArea.to) then
		player:teleportTo(config.exitPosition)
	end
	return true
end

creatureevent:register()
 
View attachment 82245


data/scripts/eventcallbacks/player/default_onLook.lua

add to very top
Lua:
local conditions = {
    "life increase",
    "mana increase",
    "speed",
    "magic",
    "melee",
    "fist",
    "club",
    "sword",
    "axe",
    "distance",
    "shield",
    "fishing",
    "critical hit chance",
    "critical hit damage",
    "life leech chance",
    "life leech amount",
    "mana leech chance",
    "mana leech amount",
    "life increase percent",
    "mana increase percent",
    "magic percent",
    "melee percent",
    "fist percent",
    "club percent",
    "sword percent",
    "axe percent",
    "distance percent",
    "shield percent",
    "fishing percent",
    "life regen",
    "mana regen",
    "soul regen"
}
add under local description = "You see " .. thing:getDescription(distance)
Lua:
    if thing:isItem() then
        for i = 1, #conditions do
            local currentStatAmount = thing:getCustomAttribute(conditions[i])
            currentStatAmount = currentStatAmount and currentStatAmount or 0
            if currentStatAmount > 0 then
                description = description .. "\n" .. conditions[i] .. ": " .. currentStatAmount
            end
        end
    end
data/scripts/itemUpgradeSystem.lua
Lua:
local conditionSubId = 45083 -- must be a unique subId not used for other buffs in your server
local config = {
    ["statMain"] = {
        -- flat_bonus_stats
        {statType = "life increase"},
        {statType = "mana increase"},
        {statType = "magic"},
        {statType = "fist"},
        {statType = "melee"},
        {statType = "distance"},
        {statType = "shield"},
        {statType = "fishing"},
        {statType = "critical hit chance"},
        {statType = "critical hit damage"},
        {statType = "life leech chance"},
        {statType = "life leech amount"},
        {statType = "mana leech chance"},
        {statType = "mana leech amount"}
    },
    ["statSpeed"] = {
        {statType = "speed"}
    },
    ["statRegen"] = {
        {statType = "life regen", ticks = 1000}, -- ticks in milliseconds}
        {statType = "mana regen", ticks = 1000}  -- can't go lower then 1000
    },
    ["statSoulRegen"] = {
        {statType = "soul regen", ticks = 1000}
    },
 
    maxUpgradesPerItem = 5,
    upgradeItems = {
        [8302] = {statType = "reset item"},
        [8303] = {statType = "life increase", value = 100},
    },
    specialDisallowedItems = {} -- any items that shouldn't be upgradeable, add them here
}

-- Choose Flat or Percentage stats. Cannot use both.

-- Flat Stats
--[[
    ["statMain"] = {
        -- flat_bonus_stats
        {statType = "life increase"},
        {statType = "mana increase"},
        {statType = "magic"},
        {statType = "fist"},
        {statType = "melee"},
        {statType = "distance"},
        {statType = "shield"},
        {statType = "fishing"},
        {statType = "critical hit chance"},
        {statType = "critical hit damage"},
        {statType = "life leech chance"},
        {statType = "life leech amount"},
        {statType = "mana leech chance"},
        {statType = "mana leech amount"}
    },
    ["statSpeed"] = {
        {statType = "speed"}
    },
    ["statRegen"] = {
        {statType = "life regen", ticks = 5000}, -- ticks in milliseconds}
        {statType = "mana regen", ticks = 5000}  -- can't go lower then 1000
    },
    ["statSoulRegen"] = { -- you can remove entire categories
        {statType = "soul regen", ticks = 5000} -- or individual stats, if you don't want to use them
    },
]]--


-- Percent Stats
--[[
    ["statMain"] = {
        -- percent_bonus_stats
        {statType = "life increase percent"},
        {statType = "mana increase percent"},
        {statType = "magic percent"},
        {statType = "fist percent"},
        {statType = "melee percent"},
        {statType = "distance percent"},
        {statType = "shield percent"},
        {statType = "fishing percent"},
        {statType = "critical hit chance"},
        {statType = "critical hit damage"},
        {statType = "life leech chance"},
        {statType = "life leech amount"},
        {statType = "mana leech chance"},
        {statType = "mana leech amount"}
    },
    ["statSpeed"] = {
        {statType = "speed"}
    },
    ["statRegen"] = {
        {statType = "life regen", ticks = 5000}, -- ticks in milliseconds}
        {statType = "mana regen", ticks = 5000}  -- can't go lower then 1000
    },
    ["statSoulRegen"] = {
        {statType = "soul regen", ticks = 5000}
    },
]]--


-- END OF CONFIG

local choiceDictionary = {}

local conditions = {
    ["life increase"] = {CONDITION_PARAM_STAT_MAXHITPOINTS},
    ["mana increase"] = {CONDITION_PARAM_STAT_MAXMANAPOINTS},
    ["speed"] = {CONDITION_PARAM_SPEED},
    ["magic"] = {CONDITION_PARAM_STAT_MAGICPOINTS},
    ["melee"] = {CONDITION_PARAM_SKILL_MELEE},
    ["fist"] = {CONDITION_PARAM_SKILL_FIST},
    ["club"] = {CONDITION_PARAM_SKILL_CLUB},
    ["sword"] = {CONDITION_PARAM_SKILL_SWORD},
    ["axe"] = {CONDITION_PARAM_SKILL_AXE},
    ["distance"] = {CONDITION_PARAM_SKILL_DISTANCE},
    ["shield"] = {CONDITION_PARAM_SKILL_SHIELD},
    ["fishing"] = {CONDITION_PARAM_SKILL_FISHING},
    ["critical hit chance"] = {CONDITION_PARAM_SPECIALSKILL_CRITICALHITCHANCE},
    ["critical hit damage"] = {CONDITION_PARAM_SPECIALSKILL_CRITICALHITAMOUNT},
    ["life leech chance"] = {CONDITION_PARAM_SPECIALSKILL_LIFELEECHCHANCE},
    ["life leech amount"] = {CONDITION_PARAM_SPECIALSKILL_LIFELEECHAMOUNT},
    ["mana leech chance"] = {CONDITION_PARAM_SPECIALSKILL_MANALEECHCHANCE},
    ["mana leech amount"] = {CONDITION_PARAM_SPECIALSKILL_MANALEECHAMOUNT},
    ["life increase percent"] = {CONDITION_PARAM_STAT_MAXHITPOINTSPERCENT},
    ["mana increase percent"] = {CONDITION_PARAM_STAT_MAXMANAPOINTSPERCENT},
    ["magic percent"] = {CONDITION_PARAM_STAT_MAGICPOINTSPERCENT},
    ["melee percent"] = {CONDITION_PARAM_SKILL_MELEEPERCENT},
    ["fist percent"] = {CONDITION_PARAM_SKILL_FISTPERCENT},
    ["club percent"] = {CONDITION_PARAM_SKILL_CLUBPERCENT},
    ["sword percent"] = {CONDITION_PARAM_SKILL_SWORDPERCENT},
    ["axe percent"] = {CONDITION_PARAM_SKILL_AXEPERCENT},
    ["distance percent"] = {CONDITION_PARAM_SKILL_DISTANCEPERCENT},
    ["shield percent"] = {CONDITION_PARAM_SKILL_SHIELDPERCENT},
    ["fishing percent"] = {CONDITION_PARAM_SKILL_FISHINGPERCENT},
    ["life regen"] = {CONDITION_PARAM_HEALTHGAIN, CONDITION_PARAM_HEALTHTICKS},
    ["mana regen"] = {CONDITION_PARAM_MANAGAIN, CONDITION_PARAM_MANATICKS},
    ["soul regen"] = {CONDITION_PARAM_SOULGAIN, CONDITION_PARAM_SOULTICKS}
}

local main_attributes = {CONDITION_ATTRIBUTES, CONDITION_HASTE, CONDITION_REGENERATION, CONDITION_SOUL}
local main_stats = {"statMain", "statSpeed", "statRegen", "statSoulRegen"}

local function updateStatBonus(playerId)
    local player = Player(playerId)
    if not player then
        return
    end
 
    -- remove all previous buffs
    for i = 1, 4 do
        if player:getCondition(main_attributes[i], conditionSubId) then
            player:removeCondition(main_attributes[i], conditionSubId)
        end
    end
 
    local equippedItems = {}
    for slot = 1, 10 do
        local slotItem = player:getSlotItem(slot)
        if slotItem then
            equippedItems[#equippedItems + 1] = slotItem
        end
    end
 
    -- add all buffs
    for i = 1, 4 do
        local statCategory = main_stats[i]
        if config[statCategory] then
            local condition = Condition(main_attributes[i], conditionSubId)
            condition:setParameter(CONDITION_PARAM_TICKS, -1)
            for _, stat in ipairs(config[statCategory]) do
                local statValue = 0
                for i = 1, #equippedItems do
                    local itemValue = equippedItems[i]:getCustomAttribute(stat.statType)
                    statValue = itemValue and itemValue + statValue or statValue
                end
                if statValue > 0 then
                    for conditionParam = 1, #conditions[stat.statType] do
                        condition:setParameter(conditions[stat.statType][conditionParam], statValue)
                    end
                    player:addCondition(condition)
                end
            end
        end
    end
    return true
end


local slotTypes = {
    48, -- weapon or shield
    49, -- helmet
    50, -- amulet
    52, -- backpack
    56, -- armor
    112, -- legs
    176, -- boots
    304, -- ring
    560, -- ammo
    2096 -- two handed
}

local function isItemUpgradeable(item)
    if not item:isItem() then
        return false
    end
    local itemType = ItemType(item:getId())
    if not table.contains(slotTypes, itemType:getSlotPosition()) then
        return false
    end
    if itemType:isStackable() then
        return false
    end
    if table.contains(config.specialDisallowedItems, item:getId()) then
        return false
    end
    return true
end



local action = Action()

function action.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if not isItemUpgradeable(target) then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, "Not a valid item to apply upgrades too.")
        player:getPosition():sendMagicEffect(CONST_ME_POFF, player)
        return true
    end
 
    local itemIndex = config.upgradeItems[item:getId()]
    local itemUpgradeCount = target:getCustomAttribute("Upgrade Counter")
    itemUpgradeCount = itemUpgradeCount and itemUpgradeCount or 0
 
    if itemIndex.statType == "reset item" then
        if itemUpgradeCount == 0 then
            player:sendTextMessage(MESSAGE_STATUS_SMALL, "Item has no upgrades to reset.")
            target:getPosition():sendMagicEffect(CONST_ME_POFF, player)
            return true
        end
        for k, v in pairs(conditions) do
            target:removeCustomAttribute(k)
        end
        target:removeCustomAttribute("Upgrade Counter")
        target:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE, player)
        player:sendTextMessage(MESSAGE_STATUS_SMALL, "All upgrades have been removed from this item.")
        item:remove(1)
        if toPosition.x == CONTAINER_POSITION and toPosition.y <= 10 then
            addEvent(updateStatBonus, 0, player:getId())
        end
        return true
    end
 
    if itemUpgradeCount >= config.maxUpgradesPerItem then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, "Item has reached max upgrades.")
        target:getPosition():sendMagicEffect(CONST_ME_POFF, player)
        return true
    end
 
    local currentStatAmount = target:getCustomAttribute(itemIndex.statType)
    currentStatAmount = currentStatAmount and currentStatAmount or 0
    target:setCustomAttribute(itemIndex.statType, currentStatAmount + itemIndex.value)
    target:setCustomAttribute("Upgrade Counter", itemUpgradeCount + 1)
 
    target:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN, player)
    player:sendTextMessage(MESSAGE_STATUS_SMALL, "Item has been upgraded.")
    item:remove(1)
 
    if toPosition.x == CONTAINER_POSITION and toPosition.y <= 10 then
        addEvent(updateStatBonus, 0, player:getId())
    end
    return true
end

for itemId, _ in pairs(config.upgradeItems) do
    action:id(itemId)
end
action:register()


local creatureevent = CreatureEvent("onLogin_updateItemStatBonus")

function creatureevent.onLogin(player)
    updateStatBonus(player:getId())
    return true
end

creatureevent:register()


local ec = EventCallback

ec.onMoveItem = function(self, item, count, fromPosition, toPosition, fromCylinder, toCylinder)
    if not (toPosition.x == CONTAINER_POSITION and toPosition.y <= 10 or fromPosition.x == CONTAINER_POSITION and fromPosition.y <= 10) then
        return RETURNVALUE_NOERROR
    end
    addEvent(updateStatBonus, 0, self:getId())
    return RETURNVALUE_NOERROR
end

ec:register()
Post automatically merged:


Lua:
local skillStages = {
    [SKILL_FIST] = {
        [{  1,   8}] = {multiplier = 5},
        [{  9,  20}] = {multiplier = 4},
        [{ 21,  50}] = {multiplier = 3},
        [{ 51, 100}] = {multiplier = 2},
        [{101}]      = {multiplier = 1}
    },
    [SKILL_CLUB] = {
        [{  1,   8}] = {multiplier = 5},
        [{  9,  20}] = {multiplier = 4},
        [{ 21,  50}] = {multiplier = 3},
        [{ 51, 100}] = {multiplier = 2},
        [{101}]      = {multiplier = 1}
    },
    [SKILL_SWORD] = {
        [{  1,   8}] = {multiplier = 5},
        [{  9,  20}] = {multiplier = 4},
        [{ 21,  50}] = {multiplier = 3},
        [{ 51, 100}] = {multiplier = 2},
        [{101}]      = {multiplier = 1}
    },
    [SKILL_AXE] = {
        [{  1,   8}] = {multiplier = 5},
        [{  9,  20}] = {multiplier = 4},
        [{ 21,  50}] = {multiplier = 3},
        [{ 51, 100}] = {multiplier = 2},
        [{101}]      = {multiplier = 1}
    },
    [SKILL_DISTANCE] = {
        [{  1,   8}] = {multiplier = 5},
        [{  9,  20}] = {multiplier = 4},
        [{ 21,  50}] = {multiplier = 3},
        [{ 51, 100}] = {multiplier = 2},
        [{101}]      = {multiplier = 1}
    },
    [SKILL_SHIELD] = {
        [{  1,   8}] = {multiplier = 5},
        [{  9,  20}] = {multiplier = 4},
        [{ 21,  50}] = {multiplier = 3},
        [{ 51, 100}] = {multiplier = 2},
        [{101}]      = {multiplier = 1}
    },
    [SKILL_FISHING] = {
        [{  1,   8}] = {multiplier = 5},
        [{  9,  20}] = {multiplier = 4},
        [{ 21,  50}] = {multiplier = 3},
        [{ 51, 100}] = {multiplier = 2},
        [{101}]      = {multiplier = 1}
    },
    [SKILL_MAGLEVEL] = {
        [{  1,   8}] = {multiplier = 5},
        [{  9,  20}] = {multiplier = 4},
        [{ 21,  50}] = {multiplier = 3},
        [{ 51, 100}] = {multiplier = 2},
        [{101}]      = {multiplier = 1}
    }
}


local ec = EventCallback

ec.onGainSkillTries = function(self, skill, tries)
    if not skillStages[skill] then
        return tries
    end
    local playerLevel = skill == SKILL_MAGLEVEL and self:getMagicLevel() or self:getSkillLevel(skill)
    for k, v in pairs(skillStages[skill]) do
        if playerLevel >= k[1] then
            if not k[2] or playerLevel <= k[2] then
                tries = tries * v.multiplier
            end
        end
    end 
    return tries
end

ec:register()
Post automatically merged:


Added.

Go to the post and find the uploaded script, as per usual. lol
I was wondering if it would be too complicated to add, protection of elements, physical, fire, ice, earth, holy, death, energy.
and also increased damage by elements. <3
 
Back
Top