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

[Release] RPG Smith

Varus

الله أكبر
Joined
May 19, 2012
Messages
60
Reaction score
8
Location
Earth
I'd take no credits for this script this script was offically made by jkotni6,and I'm not sure if there is something like this.

Add this like to data/actions/actions.xml
HTML:
<action uniqueid="1337" script="smith.lua" />
You may change the uniqueid if you do want so.

Next, create a file in data/actions/scripts/ and name it smith.lua
PHP:
function getItemsfromPos(position)
	local toret = { }

	if position.stackpos == nil then
		position.stackpos = 1
	end

	while true do
		local thing = getThingfromPos(position)
		if thing.itemid == 0 then
			break
		end
		if thing.type <= 0 then
			thing.type = 1
		end
		table.insert(toret, {position.stackpos, thing.itemid, thing.type})
		position.stackpos = position.stackpos + 1
	end

	return toret
end

function smith(array, pos1, pos2, pos3, createdItem, createdCount)
	-- lever pos, items pos, anvil pos
	t = getItemsfromPos({x=pos2.x, y=pos2.y, z=pos2.z, stackpos=0})
	local y = { }
	local delete = true
	local txt = ''
	for q = 1, #t do
		for w = 1, #array do
			if array[w][2] == t[q][2] and array[w][1] <= t[q][3] then
				table.insert(y, {t[q][1], t[q][2], t[q][3]})
			end
		end
	end
	for x = 1, #array do
		for z = 1, #y do
			if array[x][2] ~= y[z][2] or array[x][1] > y[z][3] then
				delete = false
			end
			if array[x][2] == y[z][2] and array[x][1] <= y[z][3] and delete == true then
				thing = getThingfromPos({x=pos2.x, y=pos2.y, z=pos2.z, stackpos=y[z][1]})
				doRemoveItem(thing.uid, array[x][1])
				doSendMagicEffect(pos2, 15)
				create = true
			end
		end
	end
	if create == true then
		doCreateItem(createdItem, createdCount, {x=pos3.x, y=pos3.y, z=pos3.z, stackpos=1})
		create = false
		doSendMagicEffect(pos1, 3)
		doSendMagicEffect(pos3, 11)
		doSendAnimatedText(pos3, 'BANG!', 12)
	end
end

local ITEMS = {
	{
		{2, 2152, ''}, 
		{2, 2148, ''}, 
		{1, 2000, ''}
	}, 
	{
		{100, 2152, ''}, 
		{10, 2160, ''}
	}
}

function onUse(cid, item, frompos, item2, topos)
	if item.uid == 1337 and item.itemid == 1945 then
		smith(ITEMS[1], {x=85, y=28, z=9}, {x=85, y=27, z=9}, {x=85, y=29, z=9}, 2408, 1)
		doTransformItem(item.uid, item.itemid+1)
	elseif item.uid == 1337 and item.itemid == 1946 then
		doTransformItem(item.uid, item.itemid-1)
	end
end
Let me explain some things.
1. The first function is made by myself, I used a script from here as a template!
2. The second function is made totaly by myself, I've been working hard to get that few lines working.
3. There is an ITEMS array with sub-arrays. Here you will configure it like this:
The first number is the count of the item that should be smithed.
The second number is the item ID.
The third value is the item name (optional).
PHP:
local ITEMS = {
	{
		{2, 2152, ''}, 
		{2, 2148, ''}, 
		{1, 2000, ''}
	}, 
	{
		{100, 2152, ''}, 
		{10, 2160, ''}
	}
}
This example array is made to smith 2 items. To add more items just dublicate the first line, but do not go over 7 items because it might lag the server after 7.
Example:
Old:
PHP:
local ITEMS = {
	{
		{2, 2152, ''}, 
		{2, 2148, ''}, 
		{1, 2000, ''}
	}, 
	{
		{100, 2152, ''}, 
		{10, 2160, ''}
	}
}
New:
PHP:
local ITEMS = {
	{
		{1, 1756, ''}, 
		{2, 2152, ''}, 
		{2, 2148, ''}, 
		{1, 2000, ''}
	}, 
	{
		{100, 2152, ''}, 
		{10, 2160, ''}
	}
}
Also if you want more items to be smithed dublicate the first sub-array.
Example:
Old:
PHP:
local ITEMS = {
	{
		{2, 2152, ''}, 
		{2, 2148, ''}, 
		{1, 2000, ''}
	}, 
	{
		{100, 2152, ''}, 
		{10, 2160, ''}
	}
}
New:
PHP:
local ITEMS = {
	{
		{2, 2152, ''}, 
		{2, 2148, ''}, 
		{1, 2000, ''}
	}, 
	{
		{1, 1457, ''}, 
		{1, 2684, ''}, 
		{1, 1836, ''}
	}, 
	{
		{100, 2152, ''}, 
		{10, 2160, ''}
	}
}
Woah, we're already at the onUse function! More to go. ^^
PHP:
function onUse(cid, item, frompos, item2, topos)
	if item.uid == 1337 and item.itemid == 1945 then
		smith(ITEMS[1], {x=85, y=28, z=9}, {x=85, y=27, z=9}, {x=85, y=29, z=9}, 2408, 1)
		doTransformItem(item.uid, item.itemid+1)
	elseif item.uid == 1337 and item.itemid == 1946 then
		doTransformItem(item.uid, item.itemid-1)
	end
end
This is it how it looks like. I'll explain the smith() function now a bit detailed.
The first attribute is the array that should be used. In this case it's the 1st sub array. The second attribute is the level position, the third the required item field and the fourth the position where the item should be created. The last 2 attributes are the item ID of the item that should be created and the item count.

YAY! We're done with the action script. Let's go to the NPC.

In data/npc/ create a file named Blacksmith Reider (you can change it if you want):
HTML:
<?xml version="1.0"?>
<npc name="Blacksmith Reider" script="data/npc/scripts/smith.lua" access="5" autowalk="25" floorchange="0" lookdir="2" level="1" maglevel="1">
  <health now="120" max="120" />
  <mana now="35" max="35" />
  <look type="160" head="95" body="106" legs="87" feet="116"  />
  <parameters>
    <parameter key="message_greet" value="Ohh... hello |PLAYERNAME|. What brings you to this place?" />
    <parameter key="module_keywords" value="1" />
    <parameter key="keywords" value="job;name" />
    <parameter key="keyword_reply1" value="I'm a smith as you can see. I can teach you how to smith the best items you've ever dreamt off." />
    <parameter key="keyword_reply2" value="My name... it's Reider of course!" />
    <parameter key="message_farewell" value="Good bye young adventurer. Visit me sometime again." />
  </parameters>
</npc>

Now we come to the next part. In data/npc/scripts/ create a file named smith.lua:
PHP:
function readAndStoreIt(startPhrase, middlePhrase1, middlePhrase2, endPhrase, array)
	phrase = startPhrase
	for q = 1, #array do
		if array[q][1] == 1 then
			middlePhrase = middlePhrase1
		else
			middlePhrase = middlePhrase2
		end
		phrase = phrase .. array[q][1] .. middlePhrase .. array[q][2]
		if q == (#array - 1) then
			phrase = phrase .. ' and '
		elseif q < (#array - 1) then
			phrase = phrase .. ', '
		end
	end
	phrase = phrase .. endPhrase
	return phrase
end

function getPlayerItemCountArray(cid, array)
	v = true
	for q = 1, #array do
		if getPlayerItemCount(cid, array[q][3]) < array[q][1] then
			v = false
		end
	end
	return v
end

function doPlayerTakeItemArray(cid, array)
	v = true
	for q = 1, #array do
		if doPlayerTakeItem(cid, array[q][3], array[q][1]) ~= 0 then
			v = false
		end
	end
	return v
end

talkState = 0
req = ''

local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)

-- OTServ event handling functions start
function onCreatureAppear(cid)				npcHandler:onCreatureAppear(cid) end
function onCreatureDisappear(cid) 			npcHandler:onCreatureDisappear(cid) end
function onCreatureSay(cid, type, msg) 	npcHandler:onCreatureSay(cid, type, msg) end
function onThink() 						npcHandler:onThink() end
-- OTServ event handling functions end

function creatureSayCallback(cid, type, msg)
	if(npcHandler.focus ~= cid) then
		return false
	end

	local welcome = 'I have written down your name into my book. When you are ready for an advance just come and I will find a task for you.'
	local cancel = 'Maybe next time.'
	local levelup = 'You brought all the items. Would you like to get a better smith?'
	local done = 'Thank you very much for the items. If you would like to get even better just ask me for more lessons.'
	local removeError = 'Sorry, but could not remove all items. Please contact the owner!'

	local req1 = 'Please come back when you get '
	local req2 = ' piece of '
	local req3 = ' pieces of '
	local req4 = '.'

	local advance = {'advance', 'learn', 'lesson', 'teach'}
	local task = {'task', 'mission', 'item', 'items'}
	local stat = {'status', 'skill', 'level'}

	local item = {
		{
			{50, 'iron ore', 2148}, 
			{200, 'some ore', 2152}, 
			{1000, 'gold', 2160}
		}, 
		{
			{50, 'iron ore', 2148}, 
			{200, 'some ore', 2152}, 
			{1000, 'gold', 2160}
		}, 
		{
			{50, 'iron ore', 2148}, 
			{200, 'some ore', 2152}, 
			{1000, 'gold', 2160}
		}, 
		{
			{50, 'iron ore', 2148}, 
			{200, 'some ore', 2152}, 
			{1000, 'gold', 2160}
		}, 
		{
			{50, 'iron ore', 2148}, 
			{200, 'some ore', 2152}, 
			{1000, 'gold', 2160}
		}
	}

	local strgVal = 667
	local status = getPlayerStorageValue(cid, strgVal)

	if msgInArray(stat, msg) then
		if status < 0 then
			selfSay('Your smithing skill is currently at ' .. status .. req4)
		else
			selfSay('Sorry, but you can not smith yet. Shall I teach you?')
		end
		talkState = 0
	elseif msgInArray(task, msg) then
		if (status + 1) <= #item then
			req = readAndStoreIt('To get a better smith you should bring me ', ' piece of ', ' pieces of ', '.', item[status + 1])
			selfSay(req)
			talkState = 0
		else
			selfSay('Sorry, but currently I have no tasks for you.')
		end
	end

	if status < 0 then
		if msgInArray(advance, msg) then
			selfSay('Do you realy want to learn how to smith items?')
			talkState = 1
		elseif msgcontains(msg, 'yes') and talkState == 1 then
			selfSay(welcome)
			talkState = 0
			setPlayerStorageValue(cid, strgVal, 0)
		elseif msgcontains(msg, 'no') and talkState == 1 then
			selfSay(cancel)
			talkState = 0
		end
	elseif status == 0 then
		if msgInArray(advance, msg) then
			if getPlayerItemCountArray(cid, item[1]) then
				selfSay(levelup)
				talkState = 1
			else
				req = readAndStoreIt(req1, req2, req3, req4, item[1])
				selfSay(req)
				talkState = 0
			end
		elseif msgcontains(msg, 'yes') and talkState == 1 then
			if getPlayerItemCountArray(cid, item[1]) then
				if doPlayerTakeItemArray(cid, item[1]) then
					selfSay(done)
					setPlayerStorageValue(cid, strgVal, 1)
				else
					selfSay(removeError)
				end
			else
				req = readAndStoreIt(req1, req2, req3, req4, item[1])
				selfSay(req)
			end
			talkState = 0
		elseif msgcontains(msg, 'no') and talkState == 1 then
			selfSay(cancel)
			talkState = 0
		end
	elseif status == 1 then
		if msgInArray(advance, msg) then
			if getPlayerItemCountArray(cid, item[2]) then
				selfSay(levelup)
				talkState = 1
			else
				req = readAndStoreIt(req1, req2, req3, req4, item[2])
				selfSay(req)
				talkState = 0
			end
		elseif msgcontains(msg, 'yes') and talkState == 1 then
			if getPlayerItemCountArray(cid, item[2]) then
				if doPlayerTakeItemArray(cid, item[2]) then
					selfSay(done)
					setPlayerStorageValue(cid, strgVal, 2)
				else
					selfSay(removeError)
				end
			else
				req = readAndStoreIt(req1, req2, req3, req4, item[2])
				selfSay(req)
			end
			talkState = 0
		elseif msgcontains(msg, 'no') and talkState == 1 then
			selfSay(cancel)
			talkState = 0
		end
	elseif status == 2 then
		if msgInArray(advance, msg) then
			if getPlayerItemCountArray(cid, item[3]) then
				selfSay(levelup)
				talkState = 1
			else
				req = readAndStoreIt(req1, req2, req3, req4, item[3])
				selfSay(req)
				talkState = 0
			end
		elseif msgcontains(msg, 'yes') and talkState == 1 then
			if getPlayerItemCountArray(cid, item[3]) then
				if doPlayerTakeItemArray(cid, item[3]) then
					selfSay(done)
					setPlayerStorageValue(cid, strgVal, 3)
				else
					selfSay(removeError)
				end
			else
				req = readAndStoreIt(req1, req2, req3, req4, item[3])
				selfSay(req)
			end
			talkState = 0
		elseif msgcontains(msg, 'no') and talkState == 1 then
			selfSay(cancel)
			talkState = 0
		end
	elseif status == 3 then
		if msgInArray(advance, msg) then
			if getPlayerItemCountArray(cid, item[4]) then
				selfSay(levelup)
				talkState = 1
			else
				req = readAndStoreIt(req1, req2, req3, req4, item[4])
				selfSay(req)
				talkState = 0
			end
		elseif msgcontains(msg, 'yes') and talkState == 1 then
			if getPlayerItemCountArray(cid, item[4]) then
				if doPlayerTakeItemArray(cid, item[4]) then
					selfSay(done)
					setPlayerStorageValue(cid, strgVal, 4)
				else
					selfSay(removeError)
				end
			else
				req = readAndStoreIt(req1, req2, req3, req4, item[4])
				selfSay(req)
			end
			talkState = 0
		elseif msgcontains(msg, 'no') and talkState == 1 then
			selfSay(cancel)
			talkState = 0
		end
	elseif status == 4 then
		if msgInArray(advance, msg) then
			if getPlayerItemCountArray(cid, item[5]) then
				selfSay(levelup)
				talkState = 1
			else
				req = readAndStoreIt(req1, req2, req3, req4, item[5])
				selfSay(req)
				talkState = 0
			end
		elseif msgcontains(msg, 'yes') and talkState == 1 then
			if getPlayerItemCountArray(cid, item[5]) then
				if doPlayerTakeItemArray(cid, item[5]) then
					selfSay(done)
					setPlayerStorageValue(cid, strgVal, 5)
				else
					selfSay(removeError)
				end
			else
				req = readAndStoreIt(req1, req2, req3, req4, item[5])
				selfSay(req)
			end
			talkState = 0
		elseif msgcontains(msg, 'no') and talkState == 1 then
			selfSay(cancel)
			talkState = 0
		end
	elseif status == 5 then
		if msgInArray(advance, msg) then
			selfSay('Sorry, but I taught you every thing I do know.')
		end
	end
	return true
end

npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())


Let's go to the configure part.
PHP:
	local welcome = 'I have written down your name into my book. When you are ready for an advance just come and I will find a task for you.'
	local cancel = 'Maybe next time.'
	local levelup = 'You brought all the items. Would you like to get a better smith?'
	local done = 'Thank you very much for the items. If you would like to get even better just ask me for more lessons.'
	local removeError = 'Sorry, but could not remove all items. Please contact the owner!'

	local req1 = 'Please come back when you get '
	local req2 = ' piece of '
	local req3 = ' pieces of '
	local req4 = '.'

	local advance = {'advance', 'learn', 'lesson', 'teach'}
	local task = {'task', 'mission', 'item', 'items'}
	local stat = {'status', 'skill', 'level'}

	local item = {
		{
			{50, 'iron ore', 2148}, 
			{200, 'some ore', 2152}, 
			{1000, 'gold', 2160}
		}, 
		{
			{50, 'iron ore', 2148}, 
			{200, 'some ore', 2152}, 
			{1000, 'gold', 2160}
		}, 
		{
			{50, 'iron ore', 2148}, 
			{200, 'some ore', 2152}, 
			{1000, 'gold', 2160}
		}, 
		{
			{50, 'iron ore', 2148}, 
			{200, 'some ore', 2152}, 
			{1000, 'gold', 2160}
		}, 
		{
			{50, 'iron ore', 2148}, 
			{200, 'some ore', 2152}, 
			{1000, 'gold', 2160}
		}
	}

	local strgVal = 667
	local status = getPlayerStorageValue(cid, strgVal)

I believe that I don't have to explain the string configuration. I'll start with the arrays. The first, advance is the array of keywords the player should say to advance to the next smithing level. The next, task, is the array of keywords with which the player can check what he has to bring for the next level-up. The third contains keywords, that can tell you the smithing level (stat).
And now to the last, item.
PHP:
	local item = {
		{
			{50, 'iron ore', 2148}, 
			{200, 'some ore', 2152}, 
			{1000, 'gold', 2160}
		}, 
		{
			{50, 'iron ore', 2148}, 
			{200, 'some ore', 2152}, 
			{1000, 'gold', 2160}
		}, 
		{
			{50, 'iron ore', 2148}, 
			{200, 'some ore', 2152}, 
			{1000, 'gold', 2160}
		}, 
		{
			{50, 'iron ore', 2148}, 
			{200, 'some ore', 2152}, 
			{1000, 'gold', 2160}
		}, 
		{
			{50, 'iron ore', 2148}, 
			{200, 'some ore', 2152}, 
			{1000, 'gold', 2160}
		}
	}
It's the same as with the actions, there are sub-arrays, so I don't have to explain the sub array thing once more.

Last thing... add this to data/npc/scripts/lib/npc.lua:
PHP:
function msgInArray(array, msg)
	local v = false
	msg = string.lower(msg)
	for a = 1, #array do
		if msgcontains(msg, array[a]) then
			v = true
		end
	end
	return v
end
Yay! we're finaly done! Please not that this isn't the finished script so you'll have to add a party with get/setPlayerStorageValue to the smith.lua files.

Also one more thing. The items that are required for the smithing of an item must be in the exact order as they are listed in the array! The first is on the top, the last on the bottom!

If you have any question, feel free to ask.

------------------------------------------------
How to smith?
So here we are. Add these lines
PHP:
    elseif msgInArray({'smith', 'create'}, msg) then
        selfSay('You may smith one of the following items: ITEM LIST HERE')
		talkState = 1
between
PHP:
    if msgInArray(stat, msg) then
        if status < 0 then
            selfSay('Your smithing skill is currently at ' .. status .. req4)
        else
            selfSay('Sorry, but you can not smith yet. Shall I teach you?')
        end
        talkState = 0
    elseif msgInArray(task, msg) then
        if (status + 1) <= #item then
            req = readAndStoreIt('To get a better smith you should bring me ', ' piece of ', ' pieces of ', '.', item[status + 1])
            selfSay(req)
            talkState = 0
        else
            selfSay('Sorry, but currently I have no tasks for you.')
        end
and
PHP:
    end
Also add these lines for each item that can be smithed.
PHP:
    elseif msgInArray({'item name', 'teh name'}, msg) and talkState == 1 then
        selfSay('You may smith ITEM NAME HERE at the smithing place.')
		setPlayerStorageValue(cid, STORAGE_VALUE_HERE, VALUE_HERE_DIFFERENT_FOR_DIFFERENT_ITEMS1)
		talkState = 0
    elseif msgInArray({'item name2', 'teh name2'}, msg) and talkState == 1 then
        selfSay('You may smith ITEM NAME HERE at the smithing place.')
		setPlayerStorageValue(cid, STORAGE_VALUE_HERE, VALUE_HERE_DIFFERENT_FOR_DIFFERENT_ITEMS2)
		talkState = 0
    elseif msgInArray({'item name3', 'teh name3'}, msg) and talkState == 1 then
        selfSay('You may smith ITEM NAME HERE at the smithing place.')
		setPlayerStorageValue(cid, STORAGE_VALUE_HERE, VALUE_HERE_DIFFERENT_FOR_DIFFERENT_ITEMS3)
		talkState = 0
Now it shouldn't be all to hard to add the items to the smith.lua action file...
PHP:
function onUse(cid, item, frompos, item2, topos)
    if item.uid == 1337 and item.itemid == 1945 then
        smith(ITEMS[1], {x=85, y=28, z=9}, {x=85, y=27, z=9}, {x=85, y=29, z=9}, 2408, 1)
        doTransformItem(item.uid, item.itemid+1)
    elseif item.uid == 1337 and item.itemid == 1946 then
        doTransformItem(item.uid, item.itemid-1)
    end
end
This part:
PHP:
        smith(ITEMS[1], {x=85, y=28, z=9}, {x=85, y=27, z=9}, {x=85, y=29, z=9}, 2408, 1)
        doTransformItem(item.uid, item.itemid+1)
would become something like this:
PHP:
        if getPlayerStorageValue(cid, STORAGE_VALUE_HERE) == VALUE_HERE_DIFFERENT_FOR_DIFFERENT_ITEMS1 then
			smith(ITEMS[1], {x=85, y=28, z=9}, {x=85, y=27, z=9}, {x=85, y=29, z=9}, 2408, 1)
        elseif getPlayerStorageValue(cid, STORAGE_VALUE_HERE) == VALUE_HERE_DIFFERENT_FOR_DIFFERENT_ITEMS2 then
			smith(ITEMS[2], {x=85, y=28, z=9}, {x=85, y=27, z=9}, {x=85, y=29, z=9}, 2408, 1)
        elseif getPlayerStorageValue(cid, STORAGE_VALUE_HERE) == VALUE_HERE_DIFFERENT_FOR_DIFFERENT_ITEMS3 then
			smith(ITEMS[3], {x=85, y=28, z=9}, {x=85, y=27, z=9}, {x=85, y=29, z=9}, 2408, 1)
		end
 
Yes could you please add a quick explination! I don't want to read through all the codes just to work out what it does :(
 
Back
Top