Ir para conteúdo

Guild Vaults


Omega

Posts Recomendados

Informações

  • Esse NPC cria um depot compartilhado por toda a guilda. Você pode depositar os itens com ele, que ficam salvos em uma variável (que depois é passada para o banco de dados);
  • Para pegar os itens você deve dizer "withdraw". Caso existam itens depositados por sua guilda, o NPC irá abrir uma janela de trade. Nessa janela, todos os itens aparecerão como custando 1gp, mas é apenas representativo. Apesar da opção de pegar mais itens do que existem depositados aparecer, o NPC não permitirá, avisando que a guilda não tem estoque desse item;
  • A qualquer momento um membro da guilda pode dizer "list" para receber uma listagem com todos os itens depositados e suas respectivas quantidades;
  • Para depositar um item, o jogador deve dizer "deposit quantidade nome do item". Por exemplo, para depositar duas leather armors "deposit 2 leather armor";
  • O NPC explica o funcionamento caso o jogador peça "instructions";
  • Um número máximo de itens depositados é permitido. Esse limite não se dá por quantidade, mas sim por variedade. Por exemplo, podem existir infinitos great health potion depositados, mas apenas 10 (configurável) itens diferentes;
  • O NPC passa o valor da variável periodicamente para o banco de dados, salvando os guild vaults. Recomendo que esse valor seja próximo ao do global save para evitar problemas;
  • Os valores configuráveis ficam nas duas primeiras linhas do guild_vaults.lua.

Segue um pequeno vídeo ilustrando o funcionamento.



 

 

Aviso

Apesar de ter testado laboriosamente, ainda podem existir erros no código. Teste por si mesmo e, caso encontre algum problema, volte com o erro e como o erro aconteceu.

Códigos
Para que o código funcione, é necessário adicionar uma tabela no banco de dados pela seguinte query:

CREATE TABLE guild_items (
		guild_id INT NOT NULL default 0,
		itemid INT NOT NULL default 0,
		amount INT NOT NULL default 0
		);

data/npcs/scripts/guild_vaults.lua

local updateDelay = 10 -- Tempo em minutos para atualizar o sistema (salvar no banco de dados)
local max_slots = 10 -- Máximo de itens diferentes por guild vault

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

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

function countTable(tab)
	local k = 0
	for _ in pairs(tab) do
		k = k + 1
	end
	return k
end

function doRefreshGuildVaults()	
	local refresh_storage = 995
	local query_func = db.query or db.executeQuery
	if guild_vault_changes then
		for guildId, item_list in pairs(guild_vault_changes) do
			for itemId, info in pairs(item_list) do
				if info.insert then
					query_func("INSERT INTO guild_items VALUES("..guildId..", "..itemId..", "..info.amount..");")
				else
					query_func("UPDATE guild_items SET amount = "..info.amount.." WHERE guild_id = "..guildId.." AND itemid = "..itemId..";")
				end
			end
		end
		query_func("DELETE FROM guild_items WHERE amount = 0;")
		guild_vault_changes = {}
		print(os.date("[%X] > Guild Vaults have been updated."))
	end
	addEvent(doRefreshGuildVaults, updateDelay * 1000 * 60)
	setGlobalStorageValue(refresh_storage, os.time())
	return true
end

function doStartGuildVaults()
	local query = db.getResult("SELECT * FROM guild_items;")
	if query:getID() ~= -1 then
		repeat
			local guildId, itemid, amount = query:getDataInt("guild_id"), query:getDataInt("itemid"), query:getDataInt("amount")
			if not guild_vault[guildId] then
				guild_vault[guildId] = {}
			end
			guild_vault[guildId][itemid] = {name = getItemNameById(itemid), id = itemid, buy = 1, sell = false, count = amount}
		until not query:next()
		query:free()
	end
	setGlobalStorageValue(995, os.time())
	addEvent(doRefreshGuildVaults, updateDelay * 1000 * 60)
end

if not guild_vault then
	guild_vault = {}
	guild_vault_changes = {}
	doStartGuildVaults()
end

local function doPlayerRemoveItemsNS(cid, itemId, amount)
	local k = 0
	if isItemStackable(itemId) then
		if doPlayerRemoveItem(cid, itemId, amount) then
			return amount
		end
	else
		for i = 1, amount do
			if not doPlayerRemoveItem(cid, itemId, 1) then
				break
			end
			k = k + 1
		end
	end
	return k > 0 and k or false
end

function creatureSayCallback(cid, type, msg)
	if(not npcHandler:isFocused(cid)) then
		return false
	end

	local talkUser = NPCHANDLER_CONVBEHAVIOR == CONVERSATION_DEFAULT and 0 or cid	
	
	local guild = getPlayerGuildId(cid)

	local function onBuy(cid, item, subType, amount, ignoreCap, inBackpacks)
		local weight = getItemWeightById(item)
		local guild = getPlayerGuildId(cid)
		if not guild_vault_changes[guild] then
			guild_vault_changes[guild] = {}
		end
		if getPlayerFreeCap(cid) > weight * amount then
			if guild_vault[guild][item] and guild_vault[guild][item].count >= amount then
				if isItemStackable(item) then
					doPlayerAddItem(cid, item, amount, true)
				else
					for i = 1, amount do
						doPlayerAddItem(cid, item, 1, true)
					end
				end
				guild_vault[guild][item].count = guild_vault[guild][item].count - amount
				if guild_vault_changes[guild][item] then
					guild_vault_changes[guild][item].amount = guild_vault[guild][item].count
				else
					guild_vault_changes[guild][item] = {amount = guild_vault[guild][item].count, insert = false}
				end
				if guild_vault[guild][item].count == 0 then
					selfSay("Now your guild has no more of that item in stock.", cid)
					guild_vault[guild][item] = nil
				else
					selfSay("Now your guild has only ".. guild_vault[guild][item].count .. " of that item in stock.", cid)
				end
			else
				selfSay("Your guild doesn't have that many items in stock.", cid)
			end
		else
			selfSay("It is too heavy for you", cid)
		end
	end

	local function onSell(cid, item, subType, amount, ignoreCap, inBackpacks)		
		return false
	end
	
	if guild and guild > 0 then
		if not guild_vault[guild] then
			guild_vault[guild] = {}
		end
		if not guild_vault_changes[guild] then
			guild_vault_changes[guild] = {}
		end
		if msgcontains(msg, "instructions") then
			selfSay("I manage the guild vaults. A guild vault is a safe in which you can store your items so that all your guild can have access to them.", cid)
			selfSay("To access your guild's vault, you can say {withdraw} or {deposit amount item name} to deposit an item.", cid)
			selfSay("As an example, if you wish to deposit a dragon scale mail, say 'deposit 1 dragon scale mail'.", cid)
		elseif msgcontains(msg, "withdraw") then
			if countTable(guild_vault[guild]) > 0 then
				openShopWindow(cid, guild_vault[guild], onBuy, onSell)
				selfSay("These are your guild's stored items.", cid)
			else
				selfSay("Your guild vault is empty.", cid)
			end
		elseif msgcontains(msg, "deposit") then
			local str = string.explode(msg, " ")
			if str[1] and tonumber(str[2]) and str[3] then
				local item_name = str[3]
				if #str > 3 then
					for i = 4, #str do
						item_name = string.format("%s %s", item_name, str[i])
					end
				end
				local item_id = getItemIdByName(item_name, false)
				if item_id then
					if not guild_vault[guild][item_id] and countTable(guild_vault[guild]) >= max_slots then
						selfSay("I'm sorry, but it appears that your guild vault has reached its maximum capacity.", cid)
						return true
					end
					local amount_removed = doPlayerRemoveItemsNS(cid, item_id, tonumber(str[2]))
					if amount_removed then
						if guild_vault[guild][item_id] then
							guild_vault[guild][item_id].count = guild_vault[guild][item_id].count + amount_removed
							if guild_vault_changes[guild][item_id] then
								guild_vault_changes[guild][item_id].amount = guild_vault_changes[guild][item_id].amount + amount_removed
							else
								guild_vault_changes[guild][item_id] = {amount = guild_vault[guild][item_id].count, insert = false}
							end
						else
							guild_vault[guild][item_id] = {name = item_name, id = item_id, buy = 1, sell = false, count = amount_removed}
							guild_vault_changes[guild][item_id] = {amount = amount_removed, insert = true}							
						end
						item_name = amount_removed > 1 and getItemPluralNameById(item_id) or item_name
						selfSay(string.format("You have successfully deposited %d %s.", amount_removed, item_name), cid)
					else
						selfSay("You do not have that item.", cid)
					end
				else
					selfSay("What item do you want to deposit?", cid)
				end
			else							
				selfSay("That was not a valid request. Please ask for {instructions} if you don't know what to do.", cid)
			end
		elseif msgcontains(msg, "list") then
			local item_table = guild_vault[guild]
			if countTable(item_table) > 0 then
				local str = "   Guild Vault Item List\n"
				for itemid, info in pairs(item_table) do
					if info.count > 0 then
						str = string.format("%s\n%s (%d)", str, info.name, info.count)
					end
				end
				if str:len() > 30 then
					doPlayerPopupFYI(cid, str)
					selfSay("Here you go.", cid)
				else
					selfSay("Your guild's vault is empty", cid)
				end
			else
				selfSay("Your guild's vault is empty", cid)
			end
		end
	else
		selfSay("I manage the guild vaults and I cannot help you unless you're already in a guild.", cid)
	end
	return true
end

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

 

data/lib/npcs/Frederic.xml

 

 

<?xml version="1.0" encoding="UTF-8"?>
<npc name="Frederic" script="data/npc/scripts/guild_vaults.lua" walkinterval="3000" floorchange="0">
	<health now="100" max="100"/>
	<look type="129" head="115" body="95" legs="113" feet="0" addons="3"/>
	<parameters>
  <parameter key="message_greet" value="Would you like to manage your guild's vault? You can see an item {list}, {withdraw}, {deposit} or get some {instructions}."/>
  <parameter key="message_farewell" value="May your adventures be sucessful, |PLAYERNAME|."/>
  <parameter key="message_walkaway" value="See ya..."/>
  </parameters>
</npc>

 

 

Link para o comentário
Compartilhar em outros sites

×
×
  • Criar Novo...