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

[LIB] Achievements Lib - 075-achievement.lua

Renusek

beton beton beton punk!
Joined
Jul 24, 2008
Messages
1,047
Reaction score
9
Location
Poland - Katowice/Ruda Śląska
Hi, I've made an Achievement Lib :D:D. If you want to install it, you must simply put it into data/lib/ folder
And the name 075-achievement.lua - I named it like that, because other files in lib folder are similarly named.
To TFS Developers: If you only want - you may add this lib into TFS (delete comments and clean some code, cause file looks dirty at the moment ;D) And rewrite something if you can do it better.
Many functions(some of them are useless), some constants and a table with achievements. All credits goes to me and only me <HUAHUAHUA>.
If you found any bugs, report it in this thread.
Note: This is only lib, you need to add giving storages in other scripts by yourself (like instruments, rust remover, fishing rod and other stuff).
Another Note: All Achievements in real Tibia are not discovered yet... I'm putting in script the known achievements.

I can't write in every achievement 'value', because it can be other on any server. List with achievements and how to get them is on Achievements - TibiaWiki - Quests, Items, Spells, and more

UPDATED 01 June 2011

Execute SQL query:
SQL:
CREATE TABLE `player_achievements`
(
	`player_id` INT NOT NULL DEFAULT 0,
	`id` INT NOT NULL DEFAULT 0,
	`grade` INT NOT NULL DEFAULT 0,
	`points` INT NOT NULL DEFAULT 0,
	`secret` BOOLEAN NOT NULL DEFAULT FALSE,
	KEY (`player_id`), UNIQUE (`player_id`, `id`),
	FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE
) ENGINE = InnoDB;

Then create a file: lib/075-achievements.lua:
Wklejka #539187 | Wklej.org
You know, it was too long for post it o_O (The text that you have entered is too long (65315 characters). Please shorten it to 37500 characters long.)

Then make a file creaturescripts/achievements.lua and paste it:
Lua:
function onThink(cid, interval)
    if isPlayer(cid) then
        for i = ACHIEVEMENT_FIRST, ACHIEVEMENT_LAST do
            local id = i - ACHIEVEMENT_BASE;
            if getCreatureStorage(cid, i) >= getAchievementStorageValue(id) then -- i == getAchievementStorageId(id)
                doPlayerAddAchievement(cid, id, true);
            end
        end
    end
    return true;
end

function onLogin(cid)
local added = 0;
    if isPlayer(cid) then
        for i = ACHIEVEMENT_FIRST, ACHIEVEMENT_LAST do
            local id = i - ACHIEVEMENT_BASE;
			if not getPlayerAchievement(cid, id) then
				doPlayerAddAchievement(cid, id, false); -- message will be not sent here.
				added = added + 1;
			end
        end
    end
    if added ~= 0 then
		local str = "Congratulations! You earned " .. added .. " achievement";
        doPlayerSendTextMessage(cid, MESSAGE_EVENT_ADVANCE, str .. added == 1 and "" or "s" .. "."); -- there will be message when gain > 1 achies.
    end
	return true;
end
XML:
<event type="login" name="AchievementLogin" event="script" value="Achievements.lua"/>
<event type="think" name="AchievementThink" event="script" value="Achievements.lua"/>

and paste to login.lua:
Lua:
registerCreatureEvent(cid, "AchievementLogin")
registerCreatureEvent(cid, "AchievementThink")

Post any bugs in this thread.​

Example of usage:

actions/other/partyhat.lua
Lua:
function onUse(cid, item, fromPosition, itemEx, toPosition)
	if(item.uid ~= getPlayerSlotItem(cid, CONST_SLOT_HEAD).uid) then
		return false
	end

	doCreatureSetStorage(cid, getAchievementStorageId(30), getCreatureStorage(cid, getAchievementStorageId(30)) + 1) -- value needed for achie is 200, onThink script will add achievement automatically
	doSendMagicEffect(getCreaturePosition(cid), CONST_ME_GIFT_WRAPS)
	return true
end

NOTE: THE ONLY THING YOU NEED TO DO BY YOURSELF IS CHANGE "VALUE = X" FOR YOUR VALUE (CAUSE IT MAY BE OTHER IN EACH SERVER)
 
Last edited:
Always a pleasure to see people working on the core aspects. =D
 
What are this do ?
If we use Rusty Remover we got archievement or what ?
 
@Lessaire
:)
@Fresh
In real Tibia, when you use(I don't remember how many times...) 1500x rust remover - you get achievement, or caught 1000 fishes or 250 fishes by ice fishing etc. Achievements are implemented in 8.60 :p
 
@up
Hm, I'm not sure, but yes, achievements are for account(you can see it on every char on website), but achievement points are for players(points are only for player which got achievement). So... I will leave it as it is, for now.
 
Code:
function getAchievementInfoByName(name)
	local name = string.lower(name)
	for i = ACHIEVEMENT_FIRST, ACHIEVEMENT_LAST do
		local id = i - ACHIEVEMENT_START
		if string.lower(getAchievementName(id)) == name then
			local achie = ACHIEVEMENT[id]
			return {
				id,
				storage = ACHIEVEMENT_START + id, -- storage = i
				value = achie.value,
				message = achie.message,
				grade = achie.grade,
				points = achie.points,
				secret = achie.secret
			}
		end
		[B][COLOR="red"]break[/COLOR][/B]
	end
	return false
end
Why would you break the loop on the first iteration?
 
buggq.png


then I change:
[83] = {name = "Herbicide", value = 1, message = "You're one of the brave heroes to face and defeat the mysterious demon oak and all the critters it threw in your face. Wielding your blessed axe no tree dares stand in your way - demonic or not.", grade = 3, points = , secret = true}

to:
[83] = {name = "Herbicide", value = 1, message = "You're one of the brave heroes to face and defeat the mysterious demon oak and all the critters it threw in your face. Wielding your blessed axe no tree dares stand in your way - demonic or not.", grade = 3, points = 5, secret = true}

and then:
bugg2l.png


so I change:
-- Functions
function getAchievementInfo(id)
local achie = ACHIEVEMENTS[id]
return {
name = achie.name,
storage = ACHIEVEMENT_START + id
value = achie.value,

message = achie.message,
grade = achie.grade,
points = achie.points,
secret = achie.secret
}
end


to
-- Functions
function getAchievementInfo(id)
local achie = ACHIEVEMENTS[id]
return {
name = achie.name,
storage = ACHIEVEMENT_START + id,
value = achie.value,
message = achie.message,
grade = achie.grade,
points = achie.points,
secret = achie.secret
}
end

so i get:
bugg3.png

and dont know how to fix
 
Last edited by a moderator:
Well, the code isn't the best, but nice try.
Use bitwise operators (band specifically) to create this using a single storage value (or even, do a sql connection, due to possible high values).

E.g:

Code:
local achievements = {
	ALLOW_COOKIES = 1, -- 2^0
	BEARHUGGER = 2, -- 2^1
	CHORISTER = 4, -- 2^2
	HUNTSMAN = 8 -- 2^3
	-- ...
}

-- That table must be global
acvEvents = {
	[ALLOW_COOKIES] = {
		name = "Allow Cookies?",
		msg = "With a perfectly harmless smile you fooled all of those wisecrackers into eating your Exploding Cookies. Consider a boy or girl scout outfit next time to make the trick even better.",
		grd = 1, pts = 1, secret = false,
	}
	[BEARHUGGER] = {
		name = "Bear Hugger",
		msg = "Warm, furry and cuddly - though that same bear you just hugged would probably rip you into pieces if he had been conscious, he reminded you of that old teddy bear which always slept in your bed when you were still small.",
		grd = 1, pts = 1, secret = false
	},
	[CHORISTER] = {
		name = "Chorister",
		msg = "Lalalala... you now know the cult's hymn sung in Liberty Bay by heart. Not that hard, considering that it mainly consists of two notes and repetitive lyrics.",
		grd = 1, pts = 1, secret = false
	},
	[HUNTSMAN] = {
		name = "Huntsman",
		msg = "You're familiar with hunting tasks and have carried out quite a few already. A bright career as hunter for the Paw & Fur society lies ahead!",
		grd = 1, pts = 1, secret = false
	},
	-- ...
	
}

So after that, using bitset band bits and comparing to each key of table acvEvents, you can get the achievements. Something like that:

Code:
STORAGE_ACHIEVEMENTS = 1000
function getPlayerAchievement(cid)
	local t = {}
	for _, bits in ipairs(achievements) do
		if ((getPlayerStorageValue(cid, STORAGE_ACHIEVEMENTS) band bits) == bits)
			table.insert(t, acvEvents[bits].name) -- in that case i am storing the name of achievements that the player has, you can do it different
		end
	end
end

If you see, it is like the flag calculator. Now it is your time, try to make doPlayerAddAchievement using that way.
Why? Because using a single storage value for N achievements (where N is a bigger value) can be bad.

Observation: maybe you will need to use LuaSQL to a new field (with bigger value storage) instead of using storages, since you can have big values (or maybe you can split achievements "enum" table).
 
now there is no bug until you login in :( alot of bugs at creaturescripts
Change these functions:
PHP:
function getAchievementName(id)
    local achie = ACHIEVEMENTS[id]
    return getAchievementInfo(achie).name
end
 
function getAchievementStorageId(id)
    local achie = ACHIEVEMENTS[id]
    return getAchievementInfo(achie).storage
end
 
function getAchievementStorageValue(id)
    local achie = ACHIEVEMENTS[id]
    return getAchievementInfo(achie).value
end
 
function getAchievementMessage(id)
    local achie = ACHIEVEMENTS[id]
    return getAchievementInfo(achie).message
end
 
function getAchievementGrade(id)
    local achie = ACHIEVEMENTS[id]
    return getAchievementInfo(achie).grade
end
 
function getAchievementPoints(id)
    local achie = ACHIEVEMENTS[id]
    return getAchievementInfo(achie).points
end
 
function isAchievementSecret(id)
    local achie = ACHIEVEMENTS[id]
    return getAchievementInfo(achie).secret
end
by these ones:
PHP:
function getAchievementName(id)
    return getAchievementInfo(id).name
end
 
function getAchievementStorageId(id)
    return getAchievementInfo(id).storage
end
 
function getAchievementStorageValue(id)
    return getAchievementInfo(id).value
end
 
function getAchievementMessage(id)
    return getAchievementInfo(id).message
end
 
function getAchievementGrade(id)
    return getAchievementInfo(id).grade
end
 
function getAchievementPoints(id)
    return getAchievementInfo(id).points
end
 
function isAchievementSecret(id)
    return getAchievementInfo(id).secret
end
 
:105 "attempt to index local 'achie' <a nil value>

:p

xampys version doesnt work
 
:105 "attempt to index local 'achie' <a nil value>

:p

xampys version doesnt work
You're doing something wrong, for me works fine...

I have an "end" on line 105...

Code:
# Achievement Lib
--TODO: complete ACHIEVEMENTS list
 
-- Table with Achievements
ACHIEVEMENTS = {
    -- tag 'secret' is used by Cipsoft Tibia on website to show image 'SECRET' next to the achievement name. There are 45 secret achievements.
    -- EXAMPLE: [0] = {name = "Test Achievement", storage = 20000, value = 3, message = "You are lucker! You win the lottery 3 times!", grade = 2, points = 5, secret = true}
    -- Grade 1: 1-3 points, Grade 2: 4-6 points, Grade 3: 7-9 points, Grade 4: 10 points
    -- At the moment, Real Tibia don't have Achievements with Grade 4, they will be added in next updates.
    -- YOU NEED TO EDIT MANY 'value' TAGS, and also I'm not sure about 'secret' tag correctness.
    [1] = {name = "Allow Cookies?", value = 1, message = "With a perfectly harmless smile you fooled all of those wisecrackers into eating your Exploding Cookies. Consider a boy or girl scout outfit next time to make the trick even better.", grade = 1, points = 1, secret = false}, [2] = {name = "Backpack Tourist", value = 1, message = "If someone lost a random thing in a random place, you're probably a good person to ask and go find it, even if you don't know what and where.", grade = 1, points = 1, secret = true},
    [3] = {name = "Bearhugger", value = 1, message = "Warm, furry and cuddly - though that same bear you just hugged would probably rip you into pieces if he had been conscious, he reminded you of that old teddy bear which always slept in your bed when you were still small.", grade = 1, points = 1, secret = false}, [4] = {name = "Bone Brother", value = 1, message = "You've joined the undead bone brothers - making death your enemy and your weapon as well. Devouring what's weak and leaving space for what's strong is your primary goal.", grade = 1, points = 1, secret = false},
    [5] = {name = "Chorister", value = 4, message = "Lalalala... you now know the cult's hymn sung in Liberty Bay by heart. Not that hard, considering that it mainly consists of two notes and repetitive lyrics.", grade = 1, points = 1, secret = false}, [6] = {name = "Fountain of Life", value = 1, message = "You found and took a sip from the Fountain of Life. Thought it didn't grant you eternal life, you feel changed and somehow at peace.", grade = 1, points = 1, secret = true},
    [7] = {name = "Here, Fishy Fishy!", value = 1000, message = "Ah, the smell of the sea! Standing at the shore and casting a line is one of your favourite activities. For you, fishing is relaxing - and at the same time, providing easy food. Perfect!", grade = 1, points = 1, secret = true}, [8] = {name = "Honorary Barbarian", value = 1, message = "You've hugged bears, pushed mammoths and proved your drinking skills. And even though you have a slight hangover, a partially fractured rib and some greasy hair on your tongue, you're quite proud to call yourself a honorary barbarian from now on.", grade = 1, points = 1, secret = false},
    [9] = {name = "Huntsman", value = 1, message = "You're familiar with hunting tasks and have carried out quite a few already. A bright career as hunter for the Paw & Fur society lies ahead!", grade = 1, points = 1, secret = false}, [10] = {name = "Just in Time", value = 1, message = "You're a fast runner and are good at delivering wares which are bound to decay just in the nick of time, even if you can't use any means of transportation or if your hands get cold or smelly in the process.", grade = 1, points = 1, secret = false},
    [11] = {name = "Matchmaker", value = 1, message = "You don't believe in romance to be a coincidence or in love at first sight. In fact - love potions, bouquets of flowers and cheesy poems do the trick much better than ever could. Keep those hormones flowing!", grade = 1, points = 1, secret = false}, [12] = {name = "Nightmare Knight", value = 1, message = "You follow the path of dreams and that of responsibility without self-centered power. Free from greed and selfishness, you help others without expecting a reward.", grade = 1, points = 1, secret = false},
    [13] = {name = "Party Animal", value = 200, message = "Oh my god, it's a paaaaaaaaaaaarty! You're always in for fun, friends and booze and love being the center of attention. There's endless reasons to celebrate! Woohoo!", grade = 1, points = 1, secret = true}, [14] = {name = "Secret Agent", value = 1, message = "Pack your spy gear and get ready for some dangerous missions in service of a secret agency. You've shown you want to - but can you really do it? Time will tell.", grade = 1, points = 1, secret = false},
    [15] = {name = "Talented Dancer", value = 1, message = "You're a lord or lady of the dance - and not afraid to use your skills to impress tribal gods. One step to the left, one jump to the right, twist and shout!", grade = 1, points = 1, secret = false}, [16] = {name = "Territorial", value = 1, message = "Your map is your friend - always in your back pocket and covered with countless marks of interesting and useful locations. One could say that you might be lost without it - but luckily there's no way to take it from you.", grade = 1, points = 1, secret = true},
    [17] = {name = "Worm Whacker", value = 1, message = "Weehee! Whack those worms! You sure know how to handle a big hammer.", grade = 1, points = 1, secret = true}, [18] = {name = "Allowance Collector", value = 50, message = "You certainly have your ways when it comes to acquiring money. Many of them are pink and paved with broken fragments of porcelain.", grade = 1, points = 2, secret = true},
    [19] = {name = "Amateur Actor", value = 1, message = "You helped bringing Princess Buttercup, Doctor Dumbness and Lucky the Wonder Dog to life - and will probably dream of them tonight, since you memorised your lines perfectly. What a .. special piece of.. screenplay.", grade = 1, points = 2, secret = false}, [20] = {name = "Animal Activist", value = 1, message = "You have a soft spot for little, weak animals, and you do everything in your power to protect them - even if you probably eat dragons for breakfast.", grade = 1, points = 2, secret = false},
    [21] = {name = "Beach Tamer", value = 1, message = "You re-enacted the Taming of the Shrew on a beach setting and proved that you can handle capricious girls quite well. With or without fish tails.", grade = 1, points = 2, secret = false}, [22] = {name = "Blessed!", value = 1, message = "You travelled the world for an almost meaningless prayer - but at least you don't have to do that again and can get a new blessed stake in the blink of an eye.", grade = 1, points = 2, secret = false},
    [23] = {name = "Exquisite Taste", value = 250, message = "You love fish - but preferably those caught in the cold north. Even though they're hard to come by you never get tired of picking holes in ice sheets and hanging your fishing rod in.", grade = 1, points = 2, secret = true}, [24] = {name = "Fireworks in the Sky", value = 250, message = "You love the moment right before your rocket takes off and explodes into beautiful colours - not only on new year's eve!", grade = 1, points = 2, secret = true},
    [25] = {name = "Greenhorn", value = 1, message = "You wiped out Orcus the Cruel in the Arena of Svargrond. You're still a bit green behind the ears, but there's some great potential.", grade = 1, points = 2, secret = false}, [26] = {name = "Jinx", value = 500, message = "Sometimes you feel there's a gremlin in there. So many lottery tickets, so many blanks? That's just not fair! Share your misery with the world.", grade = 1, points = 2, secret = true},
    [27] = {name = "Lucid Dreamer", value = 1, message = "Dreams - are your reality? Strange visions, ticking clocks, going to bed and waking up somewhere completely else - that was some trip, but you're almost sure you actually did enjoy it.", grade = 1, points = 2, secret = false}, [28] = {name = "Mathemagician", value = 1, message = "Sometimes the biggest secrets of life can have a simple solution.", grade = 1, points = 2, secret = false},
    [29] = {name = "Masquerader", value = 100, message = "You probably don't know anymore how you really look like - usually when you look into a mirror, some kind of monster stares back at you. On the other hand - maybe that's an improvement?", grade = 1, points = 2, secret = true}, [30] = {name = "Ministrel", value = 1, message = "You can handle any music instrument you're given - and actually manage to produce a pleasant sound with it. You're a welcome guest and entertainer in most taverns.", grade = 1, points = 2, secret = true},
    [31] = {name = "Poet Laureate", value = 1, message = "Poems, verses, songs and rhymes you've recited many times. You have passed the cryptic door, raconteur of ancient lore. Even elves you've left impressed, so it seems you're truly blessed.", grade = 1, points = 2, secret = true}, [32] = {name = "Quick as a Turtle", value = 2000, message = "There... is... simply... no... better... way - than to travel on the back of a turtle. At least you get to enjoy the beautiful surroundings of Laguna.", grade = 1, points = 2, secret = true},
    [33] = {name = "Sea Scout", value = 1, message = "Not even the hostile underwater environment stops you from doing your duty for the Explorer Society. Scouting the Quara realm is a piece of cake for you.", grade = 1, points = 2, secret = false}, [34] = {name = "Steampunked", value = 100, message = "Travelling with the dwarven steamboats through the underground rivers is your preferred way of crossing the lands. No pesky seagulls, and good beer on board!", grade = 1, points = 2, secret = true},
    [35] = {name = "Superstitios", value = 100, message = "Fortune tellers and horoscopes guide you through your life. And you probably wouldn't dare going on a big game hunt without your trusty voodoo skull giving you his approval for the day.", grade = 1, points = 2, secret = true}, [36] = {name = "The Milkman", value = 1, message = "Who's the milkman? You are!", grade = 1, points = 2, secret = false},
    [37] = {name = "Turncoat", value = 1, message = "You served Yalahar - but you didn't seem so sure whom to believe on the way. Both Azerus and Palimuth had good reasons for their actions, and thus you followed your gut instinct in the end, even if you helped either of them. May Yalahar prosper!", grade = 1, points = 2, secret = true}, [38] = {name = "Vive la Resistance", value = 1, message = "You've always been a rebel - admit it! Supplying prisoners, caring for outcasts, stealing from the rich and giving to the poor - no wait, that was another story.", grade = 1, points = 2, secret = false},
    [39] = {name = "Archpostman", value = 1, message = "Delivering letters and parcels has always been a secret passion of yours, and now you can officially put on your blue hat, blow your Post Horn and do what you like to do most. Beware of dogs!", grade = 1, points = 3, secret = false}, [40] = {name = "Clay Fighter", value = 1, message = "Sculpting Brog, the raging Titan, is your secret passion. Numerous perfect little clay statues with your name on them can be found everywhere around Tibia.", grade = 1, points = 3, secret = true},
    [41] = {name = "Efreet Ally", value = 1, message = "Even though the Efreet welcomed you only reluctantly and viewed you as \"only a human\" for quite some time, you managed to impress Malor and gained his respect and trade options with the green djinns.", grade = 1, points = 3, secret = false}, [42] = {name = "Ghostwisperer", value = 1, message = "You don't hunt them, you talk to them. You know that ghosts might keep secrets that have been long lost among the living, and you're skilled at talking them into revealing them to you.", grade = 1, points = 3, secret = false},
    [43] = {name = "His True Face", value = 1, message = "You're one of the few Tibians who Armenius chose to actually show his true face to - and he made you fight him. Either that means you're very lucky or very unlucky, but one thing's for sure - it's extremely rare.", grade = 1, points = 3, secret = true}, [44] = {name = "Ice Sculptor", value = 1, message = "You love to hang out in cold surroundings and consider ice the best material to be shaped. What a waste to use ice cubes for drinks when you can create a beautiful mammoth statue from it!", grade = 1, points = 3, secret = true},
    [45] = {name = "King Tibanus Fan", value = 1, message = "You're not sure what it is, but you feel drawn to royalty. Your knees are always a bit grazed from crawling around in front of thrones and you love hanging out in castles. Maybe you should consider applying as a guard?", grade = 1, points = 3, secret = false}, [46] = {name = "Marblelous", value = 1, message = "Your little statues of Tibiasula have become quite famous around Tibia and there's few people with similar skills when it comes to shaping marble.", grade = 1, points = 3, secret = true},
    [47] = {name = "Marid Ally", value = 1, message = "You've proven to be a valuable ally to the Marid, and Gabel welcomed you to trade with Haroun and Nah'Bob whenever you want to. Though the Djinn war has still not ended, the Marid can't fail with you on their side.", grade = 1, points = 3, secret = false}, [48] = {name = "Passionate Kisser", value = 1, message = "For you, a kiss is more than a simple touch of lips. You kiss maidens and deadbeats alike with unmatched affection and faced death and rebirth through the kiss of the banshee queen. Lucky are those who get to share such an intimate moment with you!", grade = 1, points = 3, secret = false},
    [49] = {name = "Perfect Fool", value = 1, message = "You love playing jokes on others and tricking them into looking a little silly. Wagging tongues say that the moment of realisation in your victims' eyes is the reward you feed on, but you're probably just kidding and having fun with them... right??", grade = 1, points = 3, secret = false}, [50] = {name = "Recognised Trader", value = 1, message = "You're a talented merchant who's able to handle wares with care, finds good offers and digs up rares every now and then. Never late to complete an order, you're a reliable trader - at least in Rashid's eyes.", grade = 1, points = 3, secret = false},
    [51] = {name = "Rockstar", value = 10000, message = "Music just comes to you naturally. You feel comfortable on any stage, at any time, and secretly hope that someday you will be able to defeat your foes by playing music only. Rock on!", grade = 1, points = 3, secret = true}, [52] = {name = "Scrapper", value = 1, message = "You put out the Spirit of Fire's flames in the arena of Svargrond. Arena fights are for you - fair, square, with simple rules and one-on-one battles.", grade = 1, points = 3, secret = false},
    [53] = {name = "Vanity", value = 300, message = "Aren't you just perfectly, wonderfully, beautifully gorgeous? You can't pass a mirror without admiring your looks. Or maybe doing a quick check whether something's stuck in your teeth, perhaps?", grade = 1, points = 3, secret = true}, [54] = {name = "Wayfarer", value = 1, message = "Dragon dreams are golden.", grade = 1, points = 3, secret = true},
    [55] = {name = "Champion of Chazorai", value = 1, message = "You won the merciless 2 vs. 2 team tournament on the Isle of Strife and wiped out wave after wave of fearsome opponents. Death or victory - you certainly chose the latter.", grade = 2, points = 4, secret = false}, [56] = {name = "Culinary Master", value = 1, message = "Simple hams and bread merely make you laugh. You're the master of the extra-ordinaire, melter of cheese, fryer of bat wings and shaker of shakes. Delicious!", grade = 2, points = 4, secret = false},
    [57] = {name = "Explorer", value = 1, message = "You've been to places most people don't even know the names of. Collecting botanic, zoologic and ectoplasmic samples is your daily business and you're always prepared to discover new horizons.", grade = 2, points = 4, secret = false}, [58] = {name = "Follower of Azerus", value = 1, message = "When you do something, you do it right. You have an opinion and you stand by it - and no one will be able to convince you otherwise. On a sidenote, you're a bit on the brutal and war-oriented side, but that's not a bad thing, is it?", grade = 2, points = 4, secret = false},
    [59] = {name = "Follower of Palimuth", value = 1, message = "You're a peacekeeper and listen to what the small people have to say. You've made up your mind and know who to help and for which reasons - and you do it consistently. Your war is fought with reason rather than weapons.", grade = 2, points = 4, secret = false}, [60] = {name = "Friend of the Apes", value = 1, message = "You know Banuta like the back of your hand and are good at destroying caskets and urns. The sight of giant footprints doesn't keep you from exploring unknown areas either.", grade = 2, points = 4, secret = false},
    [61] = {name = "Golem in the Gears", value = 1, message = "You're an aspiring mago-mechanic. Science and magic work well together in your eyes - and even though you probably delivered countless wrong charges while working for Telas, you might just have enough knowledge to build your own golem now.", grade = 2, points = 4, secret = false}, [62] = {name = "High-Flyer", value = 1000, message = "The breeze in your hair, your fingers clutching the rim of your Carpet - that's how you like to travel. Faster! Higher! And a looping every now and then.", grade = 2, points = 4, secret = true},
    [63] = {name = "Interior Decorator", value = 1000, message = "Your home is your castle - and the furniture in it is just as important. Your friends ask for your advice when decorating their Houses and your probably own every statue, rack and bed there is.", grade = 2, points = 4, secret = true}, [64] = {name = "Master Thief", value = 1, message = "Robbing, inviting yourself to VIP parties, faking contracts and pretending to be someone else - you're a jack of all trades when it comes to illegal activities. You take no prisoners, except for the occasional goldfish now and then.", grade = 2, points = 4, secret = false},
    [65] = {name = "Polisher", value = 1, message = "If you see a rusty item, you can't resist polishing it. There's always a little flask of rust remover in your inventory - who knows, there might be a golden armor beneath all that dirt!", grade = 2, points = 4, secret = true}, [66] = {name = "Potion Addict", value = 1, message = "Your local magic trader considers you one of his best customers - you usually buy large stocks of potions so you won't wake up in the middle of the night craving for more. Yet, you always seem to run out of them too fast. Cheers!", grade = 2, points = 4, secret = true},
    [67] = {name = "Ruthless", value = 1, message = "You've touched all thrones of the Ruthless Seven and absorbed some of their evil spirit. It may have changed you forever.", grade = 2, points = 5, secret = false}, [68] = {name = "Ship's Kobold", value = 1000, message = "You've probably never gotten seasick in your life - you love spending your free time on the ocean and covered quite a lot of miles with ships. Aren't you glad you didn't have to swim all that?", grade = 2, points = 4, secret = true}, 
    [69] = {name = "Top AVIN Agent", value = 1, message = "You've proven yourself as a worthy member of the 'family' and successfully carried out numerous spy missions for your 'uncle' to support the Venorean traders and their goals.", grade = 2, points = 4, secret = false}, [70] = {name = "Top CGB Agent", value = 1, message = "Girl power! Whether you're female or not, you've proven absolute loyalty and the willingness to put your life at stake for the girls brigade of Carlin.", grade = 2, points = 4, secret = false},
    [71] = {name = "Top TBI Agent", value = 1, message = "Conspiracies and open secrets are your daily bread. You've shown loyalty to the Thaian crown through your courage when facing enemies and completing spy missions. You're an excellent field agent of the TBI.", grade = 2, points = 4, secret = false}, [72] = {name = "Annihilator", value = 1, message = "You've daringly jumped into the infamous Annihilator and survived - taking home fame, glory and your reward.", grade = 2, points = 5, secret = false},
    [73] = {name = "Castlemania", value = 1, message = "You have an eye for suspicious places and love to read other people's diaries, especially those with vampire stories in it. You're also a dedicated token collector and explorer. Respect!", grade = 2, points = 5, secret = true}, [74] = {name = "Elite Hunter", value = 1, message = "You jump at every opportunity for a hunting challenge that's offered to you and carry out those tasks with deadly precision. You're a hunter at heart and a valuable member of the Paw & Fur Society.", grade = 2, points = 5, secret = false},
    [75] = {name = "High Inquisitor", value = 1, message = "You're the one who poses the questions around here, and you know how to get the answers you want to hear. Besides, you're a famous exorcist and slay a few vampires and demons here and there. You and your stake are a perfect team.", grade = 2, points = 5, secret = false}, [76] = {name = "Jamjam", value = 1, message = "When it comes to interracial understanding, you're an expert. You've mastered the language of the Chakoya and made someone really happy with your generosity. Achuq!", grade = 2, points = 5, secret = false},
    [77] = {name = "Lord of the Elements", value = 1, message = "You travelled the surreal realm of the elemental spheres, summoned and slayed the Lord of the Elements, all in order to retrieve neutral matter. And as brave as you were, you couldn't have done it without your team!", grade = 2, points = 5, secret = false}, [78] = {name = "Warlord of Svargrond", value = 1, message = "You sent the Obliverator into oblivion in the arena of Svargrond and defeated nine other dangerous enemies on the way. All hail the Warlord of Svargrond!", grade = 2, points = 5, secret = false},
    [79] = {name = "Master of the Nexus", value = 1, message = "You were able to fight your way through the countless hordes in the Demon Forge. Once more you proved that nothing is impossible.", grade = 2, points = 6, secret = false}, [80] = {name = "Razing!", value = 1, message = "People with sharp canine teeth better beware of you, especially at nighttime, or they might find a stake between their ribs. You're a merciless vampire hunter and have gathered numerous tokens as proof.", grade = 3, points = 7, secret = true},
    [81] = {name = "Dread Lord", value = 1, message = "You don't care for rules that others set up and shape the world to your liking. Having left behind meaningless conventions and morals, you prize only the power you wield. You're a master of your fate and battle to cleanse the world.", grade = 3, points = 8, secret = true}, [82] = {name = "Lord Protector", value = 1, message = "You proved yourself - not only in your dreams - and possess a strong and spiritual mind. Your valorous fight against demons and the undead plague has granted you the highest and most respected rank among the Nightmare Knights.", grade = 3, points = 8, secret = true},
    [83] = {name = "Herbicide", value = 1, message = "You're one of the brave heroes to face and defeat the mysterious demon oak and all the critters it threw in your face. Wielding your blessed axe no tree dares stand in your way - demonic or not.", grade = 3, points = 7, secret = true}
}
 
-- Storages
ACHIEVEMENT_FIRST = 20001
ACHIEVEMENT_START = ACHIEVEMENT_FIRST - 1 -- used in 'for' loops to get achievement ID
ACHIEVEMENT_LAST = ACHIEVEMENT_START + #ACHIEVEMENTS -- and if you will add/remove some achievements by yourself, constant will change automatically!
--
 
-- Functions
function getAchievementInfo(id)
    local achie = ACHIEVEMENTS[id]
    return {
        name = achie.name,
        storage = ACHIEVEMENT_START + id,
        value = achie.value,
        message = achie.message,
        grade = achie.grade,
        points = achie.points,
        secret = achie.secret
    }
end
 
function getAchievementName(id)
    return getAchievementInfo(id).name
end
 
function getAchievementStorageId(id)
    return getAchievementInfo(id).storage
end
 
function getAchievementStorageValue(id)
    return getAchievementInfo(id).value
end
 
function getAchievementMessage(id)
    return getAchievementInfo(id).message
end
 
function getAchievementGrade(id)
    return getAchievementInfo(id).grade
end
 
function getAchievementPoints(id)
    return getAchievementInfo(id).points
end
 
function isAchievementSecret(id)
    return getAchievementInfo(id).secret
end
 
function getPlayerAchievement(cid, id)
    return getCreatureStorage(cid, getAchievementStorageId(id)) >= getAchievementStorageValue(id)
end
 
function getAchievementInfoByName(name)
    local name = string.lower(name)
    for i = ACHIEVEMENT_FIRST, ACHIEVEMENT_LAST do
        local id = i - ACHIEVEMENT_START
        if string.lower(getAchievementName(id)) == name then
            local achie = ACHIEVEMENTS[id]
            return {
                id,
                storage = ACHIEVEMENT_START + id, -- storage = i
                value = achie.value,
                message = achie.message,
                grade = achie.grade,
                points = achie.points,
                secret = achie.secret
            }
        end
    end
    return false
end
 
function getAchievementId(name)
    return getAchievementInfoByName(name).id
end
 
function getAchievementStorageIdByName(name)
    return getAchievementInfoByName(name).storage
end
 
function getAchievementStorageValueByName(name)
    return getAchievementInfoByName(name).value
end
 
function getAchievementMessageByName(name)
    return getAchievementInfoByName(name).message
end
 
function getAchievementGradeByName(name)
    return getAchievementInfoByName(name).grade
end
 
function getAchievementPointsByName(name)
    return getAchievementInfoByName(name).points
end
 
function isAchievementSecretByName(name)
    return getAchievementInfoByName(name).secret
end
 
function getPlayerAchievementByName(name)
    return getPlayerAchievement(cid, getAchievementId(name))
end
 
function getPlayerAchievements(cid, names) -- if names == false then will return for example: {2, 47}, else: {"Backpack Tourist", "Marid Ally"}
    local done = {}
    local names = names or false
    for i = ACHIEVEMENT_FIRST, ACHIEVEMENT_LAST do
        local id = i - ACHIEVEMENT_START
        if getCreatureStorage(cid, i) >= getAchievementStorageValue(id) then
            if names then
                table.insert(done, getAchievementName(id))
            end
        end
    end
    return done
end
 
function getPlayerAchievementsNumber(cid) -- will return number of gained achivements
    local done = 0
    for i = ACHIEVEMENT_FIRST, ACHIEVEMENT_LAST do
        local id = i - ACHIEVEMENT_START
        if getCreatureStorage(cid, i) >= getAchievementStorageValue(id) then
            done = done + 1
        end
    end
    return done
end
 
function getPlayerSecretAchievements(cid, names) -- same as getPlayerAchievements, but will work only with secret achievements (have tag: secret = true)
    local done = {}
    local names = names or false
    for i = ACHIEVEMENT_FIRST, ACHIEVEMENT_LAST do
        local id = i - ACHIEVEMENT_START
        if isAchievementSecret(id) then
            if getCreatureStorage(cid, i) >= getAchievementStorageValue(id) then
                if names then
                    table.insert(done, getAchievementName(id))
                end
            end
        end
    end
    return done
end
 
function getPlayerSecretAchievementsNumber(cid) -- same as getPlayerAchievementNumber, but will work only with secret achievements
    local done = 0
    for i = ACHIEVEMENT_FIRST, ACHIEVEMENT_LAST do
        local id = i - ACHIEVEMENT_START
        if isAchievementSecret(id) then
            if getCreatureStorage(cid, i) >= getAchievementStorageValue(id) then
                done = done + 1
            end
        end
    end
    return done
end
 
function getPlayerAchievementPoints(cid)
    local points = 0
    for i = ACHIEVEMENT_FIRST, ACHIEVEMENT_LAST do
        local id = i - ACHIEVEMENT_START
        if getPlayerAchievement(cid, id) then
            points = points + getAchievementPoints(id)
        end
    end
    return points
end
 
function doPlayerAddAchievement(cid, achie) -- 'achie' may be an achievement ID or achievement NAME 
    if type(achie) == "string" then -- name
        --if not getPlayerAchievementByName(cid, achie) then
           -- doCreatureSetStorage(cid, getAchievementStorageIdByName(achie), getAchievementStorageValueByName(achie))
            doPlayerSendTextMessage(cid, MESSAGE_EVENT_ADVANCE, getAchievementMessageByName(achie))
        --end
    elseif type(achie) == "number" then-- id
        --if not getPlayerAchievement(cid, achie) then
          --  doCreatureSetStorage(cid, getAchievementStorageId(achie), getAchievementStorageValue(achie))
            doPlayerSendTextMessage(cid, MESSAGE_EVENT_ADVANCE, getAchievementMessage(achie))
        --end
    end
    return true
end
 
function doPlayerAddAllAchievements(cid)
    for i = ACHIEVEMENT_FIRST, ACHIEVEMENT_LAST do
        local id = i - ACHIEVEMENT_START
        if not getPlayerAchievement(cid, id) then
            local storage, value = getAchievementStorageId(id), getAchievementStorageValue(id)
            doCreatureSetStorage(cid, storage, value)
        end
    end
    doPlayerSendTextMessage(cid, MESSAGE_EVENT_ADVANCE, "You have gained all achievements!")
    return true
end
 
--
 
-- Compat
getAchievementStorageKey = getAchievementStorageId
getAchievementStorageKeyByName = getAchievementStorageIdByName
--
 
Last edited:
Back
Top