• 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!

CreatureEvent [TFS 1.1] Skill Points, modalwindow

Status
Not open for further replies.

zbizu

Legendary OT User
Joined
Nov 22, 2010
Messages
3,323
Solutions
26
Reaction score
2,694
Location
Poland
Spend skill points on skills/stats, configurable amount of points per level.
DF4hMqN.jpg


creaturescripts.xml:
Code:
    <event type="modalwindow" name="skillPoints_modal" script="sp.lua"/>
    <event type="advance" name="skillPoints_advance" script="sp.lua"/>
    <event type="login" name="skillPoints_register" script="sp.lua"/>

sp.lua Creaturescript
Code:
function onModalWindow(player, modalWindowId, buttonId, choiceId)
    player:skillWindowChoice(modalWindowId, buttonId, choiceId)
    return true
end

function onAdvance(player, skill, oldLevel, newLevel)
    if skill == SKILL_LEVEL then
        player:skillPointsAdvance(newLevel)
    end
    return true
end

function onLogin(player)
    player:registerEvent("skillPoints_advance")
    player:registerEvent("skillPoints_modal")
    return true
end

talkactions.xml:
Code:
    <talkaction words="!points" script="sp.lua"/>

sp.lua Talkaction
Code:
function onSay(player, words, param)
    player:sendSkillPointsWindow()
    return false
end

now the lib file:
- if you use this: [TFS 1.x] lib folder in "data" like 0.4, just create sp.lua and put it in data\lib folder
- if you don't use this, just create file sp.lua in data folder and put this in global.lua:
Code:
dofile('data/sp.lua')

sp.lua Lib
Code:
-- config
--promoted vocations included in function
local gainVoc = {
	[0] = {health = 10, mana = 10, magic = 1, skill = 1, cap = 10},
	[1] = {health = 10, mana = 10, magic = 1, skill = 1, cap = 10},
	[2] = {health = 10, mana = 10, magic = 1, skill = 1, cap = 10},
	[3] = {health = 10, mana = 10, magic = 1, skill = 1, cap = 10},
	[4] = {health = 10, mana = 10, magic = 1, skill = 1, cap = 10}
}

local skillStorage = 62490
local modalId = 4869
local TextModalId = 4870 -- so player may return to skill window
local skillPointsPerLevel = 3 -- points per level
local skillPointsAdvanceStorage = 62491 -- storage to avoid giving points twice for same level
local skillPointsTalkaction = "!points" -- so player knows command when he gets level up

local skills = {
-- name, get value, set value
	[1] = {'Health', function(player) return player:getMaxHealth() end, function(player) local gain = gainVoc[player:getBaseVocId()].health player:setMaxHealth(player:getMaxHealth() + gain) return gain end, 10},
	[2] = {'Mana', function(player) return player:getMaxMana() end, function(player) local gain = gainVoc[player:getBaseVocId()].mana player:setMaxMana(player:getMaxMana() + gain) return gain end, 10},
	[3] = {'Capacity', function(player) return player:getCapacity() / 100 end, function(player) local gain = gainVoc[player:getBaseVocId()].cap player:setCapacity(player:getCapacity() + (gain * 100)) return gain end, 10},
	[4] = {'Magic', function(player) return player:getBaseMagicLevel() end, function(player) local gain = gainVoc[player:getBaseVocId()].magic player:addSkillLevels(SKILL_MAGLEVEL, gain) return gain end, 10},
	[5] = {'Fist', function(player) return player:getSkillLevel(SKILL_FIST) end, function(player) local gain = gainVoc[player:getBaseVocId()].skill player:addSkillLevels(SKILL_FIST, gain) return gain end, 10},
	[6] = {'Club', function(player) return player:getSkillLevel(SKILL_CLUB) end, function(player) local gain = gainVoc[player:getBaseVocId()].skill player:addSkillLevels(SKILL_CLUB, gain) return gain end, 10},
	[7] = {'Sword', function(player) return player:getSkillLevel(SKILL_SWORD) end, function(player) local gain = gainVoc[player:getBaseVocId()].skill player:addSkillLevels(SKILL_SWORD, gain) return gain end, 10},
	[8] = {'Axe', function(player) return player:getSkillLevel(SKILL_AXE) end, function(player) local gain = gainVoc[player:getBaseVocId()].skill player:addSkillLevels(SKILL_AXE, gain) return gain end, 10},
	[9] = {'Distance', function(player) return player:getSkillLevel(SKILL_DISTANCE) end, function(player) local gain = gainVoc[player:getBaseVocId()].skill player:addSkillLevels(SKILL_DISTANCE, gain) return gain end, 10},
	[10] = {'Shielding', function(player) return player:getSkillLevel(SKILL_SHIELD) end, function(player) local gain = gainVoc[player:getBaseVocId()].skill player:addSkillLevels(SKILL_SHIELD, gain) return gain end, 10},
	[11] = {'Fishing', function(player) return player:getSkillLevel(SKILL_FISHING) end, function(player) local gain = gainVoc[player:getBaseVocId()].skill player:addSkillLevels(SKILL_FISHING, gain) return gain end, 10}
}

local skillForVoc = {
	[1] = {1, 2, 3, 4, 10, 11}, -- sorcerer
	[2] = {1, 2, 3, 4, 10, 11}, -- druid
	[3] = {1, 2, 3, 4, 9, 10, 11}, -- paladin
	[4] = {1, 2, 3, 5, 6, 7, 8, 10, 11}, -- knight
}

function Player:getBaseVocId()
	local basevoc = self:getVocation():getDemotion()
	if basevoc then
		return basevoc:getId()
	end
	return self:getVocation():getId()
end

function getExpForLevel(level)
	level = level - 1
	return ((50 * level * level * level) - (150 * level * level) + (400 * level)) / 3
end

function Player:addSkillLevels(skill, count)
	count = math.max(1, count or 1)
	
	if isInArray({SKILL_FIST, SKILL_CLUB, SKILL_SWORD, SKILL_AXE, SKILL_DISTANCE, SKILL_SHIELD, SKILL_FISHING}, skill) then
		for i = 1, count do
			local xp = math.ceil(self:getVocation():getRequiredSkillTries(skill, self:getSkillLevel(skill) + 1) / configManager.getNumber(configKeys.RATE_SKILL))
			self:addSkillTries(skill, xp)
		end
		return true
	end

	if skill == SKILL_MAGLEVEL then
		for i = 1, count do
			local xp = math.ceil(self:getVocation():getRequiredManaSpent(self:getBaseMagicLevel() + 1) / configManager.getNumber(configKeys.RATE_MAGIC))
			self:addManaSpent(xp)
		end
		return true
	end

	if skill == SKILL_LEVEL then
		for i = 1, count do
			local lv = self:getLevel()
			local xp = getExpForLevel(lv + 1) - getExpForLevel(lv)
			self:addExperience(xp, false)
		end
		return true
	end
	return false
end

function Player:sendSkillPointsWindow()
	local pts = self:getStorageValue(skillStorage)
	if pts < 0 then
		self:setStorageValue(skillStorage, 0)
		pts = 0
	end

	local window = ModalWindow(modalId, "Character Mastery", "Available points: [" .. pts .. "]")
	window:addButton(1, "Assign")
	window:addButton(2, "Exit")

	for i = 1, #skills do
		if isInArray(skillForVoc[self:getBaseVocId()], i) then
			window:addChoice(i, skills[i][1] .. ": [" .. skills[i][2](self) .. "][cost: " .. skills[i][4] .. "]")
		end
	end
	
	window:setDefaultEnterButton(1)
	window:setDefaultEscapeButton(2)
	window:sendToPlayer(self)
	return true
end

function Player:skillWindowChoice(windowId, buttonId, choiceId)
	if windowId == modalId then
		if buttonId == 1 then
			if not skills[choiceId] then
				local textWindow = ModalWindow(TextModalId, "Error", "No skill selected.")
				textWindow:addButton(1, "Ok")
				textWindow:setDefaultEnterButton(1)
				textWindow:setDefaultEscapeButton(1)
				textWindow:sendToPlayer(self)
				return true
			end
			local pts = self:getStorageValue(skillStorage)
			if pts < 0 then
				self:setStorageValue(skillStorage, 0)
				pts = 0
			end
			
			if pts - skills[choiceId][4] >= 0 then
				local textWindow = ModalWindow(TextModalId, "Point assigned.", skills[choiceId][1] .. " +" .. skills[choiceId][3](self))
				textWindow:addButton(1, "Ok")
				textWindow:setDefaultEnterButton(1)
				textWindow:setDefaultEscapeButton(1)
				textWindow:sendToPlayer(self)
				self:setStorageValue(skillStorage, pts - skills[choiceId][4])
				return true
			end

			local textWindow = ModalWindow(TextModalId, "Error", "Not enough points")
			textWindow:addButton(1, "Ok")
			textWindow:setDefaultEnterButton(1)
			textWindow:setDefaultEscapeButton(1)
			textWindow:sendToPlayer(self)
			return true
		end
		return false
	end
	
	if not (windowId == TextModalId) then
		return false
	end
		
	self:sendSkillPointsWindow()
	return false
end

function Player:addSkillPoints(count)
	count = math.max(1, count or 1)
	
	local pts = self:getStorageValue(skillStorage)
	if pts < 0 then
		self:setStorageValue(skillStorage, 0)
		pts = 0
	end
	
	return self:setStorageValue(skillStorage, pts + count)
end

function Player:skillPointsAdvance(nlevel)
	if self:getStorageValue(skillPointsAdvanceStorage) < nlevel then
		self:addSkillPoints(skillPointsPerLevel)
		self:setStorageValue(skillPointsAdvanceStorage, nlevel)
		self:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "New skill points available. Type " .. skillPointsTalkaction .. " to open character mastery window.")
	end
	return true
end
 
Last edited:
woooooooow did it works well? or have any troubles?
 
works well, I've tested skill and ml formulas
 
Last edited:
holy shit dude <3
would be cool for highrate servers if ya could do 1 points every 20 levels or so :p
maybe I can fix it by myself and post here when I got time
 
Is there anyway to change how much points each skill costs?
 
@calveron
add 4th value in skill tables, it will be skill cost, should look like this:
Code:
[1] = {'Health', function(player) return player:getMaxHealth() end, function(player) local gain = gainVoc[player:getBaseVocId()].health player:setMaxHealth(player:getMaxHealth() + gain) return gain end, 10},

replace
Code:
if pts > 0 then
to:
Code:
if pts - skills[choiceId][4] >= 0 then

replace:
Code:
self:setStorageValue(skillStorage, pts - 1)
to:
Code:
self:setStorageValue(skillStorage, pts - skills[i][4])

replace:
Code:
window:addChoice(i, skills[i][1] .. ": [" .. skills[i][2](self) .. "]")

to:
Code:
window:addChoice(i, skills[i][1] .. ": [" .. skills[i][2](self) .. "][cost: " .. skills[i][4] .. "]")

test it and let me know if it works
 
I managed to fix that, but Ill try your solution anyway.
Is there any chance you could help me add that you'll have a different window depending on your vocation? Im actually using a book that opens up a the modalwindow. And what I want is that if a sorcerer opens the book, he will open another window with only mana and magic level.
 
I managed to fix that, but Ill try your solution anyway.
Is there any chance you could help me add that you'll have a different window depending on your vocation? Im actually using a book that opens up a the modalwindow. And what I want is that if a sorcerer opens the book, he will open another window with only mana and magic level.

I'm posting from my phone now so can't explain it well now. I'll try, though.

Find this:
Code:
	for i = 1, #skills do
		window:addChoice(i, skills[i][1] .. ": [" .. skills[i][2](self) .. "]")
	end

Above addChoice put if isIArray(table, i) then
-- addChoice
end

Funcions you will need:
isInArray(table[voc], i)
player:getVocation():getId()
table = {
[vocid] = {statid1, statid2}
}

I hope you got it.

holy shit dude <3
would be cool for highrate servers if ya could do 1 points every 20 levels or so :p
maybe I can fix it by myself and post here when I got time

See my post above. You may set 1 point per level and cost 20.
 
If anyone would be super kind to help me adding that to the script I would be extremely glad!
 
I've already posted here all functions you need.
If you need help ask in support board.
 
@zbizu - I Believe the intention he mention of the vocation is to set different skills and costs depending on vocation.
The system is great, I did however had to put the cost to 15 Points as we don't want a Knight to gain a high magic lvl as for example. :)

It would be perfect if the cost would be different per skill per vocation, except that, great work! :)

Kind Regards,
Eldin.
 
Basicly what I want is when you open the modalwindow as a knight, you will only see Health, sword, axe, club and shielding. Making it only possible to upgrade those skills as a knight.
 
I know what you want. Curretly I'm working on another script and I had hope you get it working yourself.

When I complete my new stat system I'll add more features to this script.
 
@calveron
add 4th value in skill tables, it will be skill cost, should look like this:
Code:
[1] = {'Health', function(player) return player:getMaxHealth() end, function(player) local gain = gainVoc[player:getBaseVocId()].health player:setMaxHealth(player:getMaxHealth() + gain) return gain end, 10},

replace
Code:
if pts > 0 then
to:
Code:
if pts - skills[choiceId][4] >= 0 then

replace:
Code:
self:setStorageValue(skillStorage, pts - 1)
to:
Code:
self:setStorageValue(skillStorage, pts - skills[i][4])

replace:
Code:
window:addChoice(i, skills[i][1] .. ": [" .. skills[i][2](self) .. "]")

to:
Code:
window:addChoice(i, skills[i][1] .. ": [" .. skills[i][2](self) .. "][cost: " .. skills[i][4] .. "]")

test it and let me know if it works

Add it to your original script in the first pos, its only a + unless I missed something why people wouldn't want it? :)
Well done.

Kind Regards,
Eldin.
 
@calveron
add 4th value in skill tables, it will be skill cost, should look like this:
Code:
[1] = {'Health', function(player) return player:getMaxHealth() end, function(player) local gain = gainVoc[player:getBaseVocId()].health player:setMaxHealth(player:getMaxHealth() + gain) return gain end, 10},

replace
Code:
if pts > 0 then
to:
Code:
if pts - skills[choiceId][4] >= 0 then

replace:
Code:
self:setStorageValue(skillStorage, pts - 1)
to:
Code:
self:setStorageValue(skillStorage, pts - skills[i][4])

replace:
Code:
window:addChoice(i, skills[i][1] .. ": [" .. skills[i][2](self) .. "]")

to:
Code:
window:addChoice(i, skills[i][1] .. ": [" .. skills[i][2](self) .. "][cost: " .. skills[i][4] .. "]")

test it and let me know if it works

Tried this today, it adds the skill but it doesnt remove skill points.
 
I managed to fix that. Replaced
Code:
self:setStorageValue(skillStorage, pts - skills[i][4])
with
Code:
self:setStorageValue(skillStorage, pts - skills[choiceId][4])
 
I'm posting from my phone now so can't explain it well now. I'll try, though.

Find this:
Code:
    for i = 1, #skills do
        window:addChoice(i, skills[i][1] .. ": [" .. skills[i][2](self) .. "]")
    end

Above addChoice put if isIArray(table, i) then
-- addChoice
end

Funcions you will need:
isInArray(table[voc], i)
player:getVocation():getId()
table = {
[vocid] = {statid1, statid2}
}

I hope you got it.
Tried to add this but it just wont work. Anyone willing to work on this with me? :)
 
Status
Not open for further replies.
Back
Top