Jump to content
Poccnn

system Sistema avançado de Quest

Recommended Posts

Olá Homo-Sapiens.

 

Resolvi trazer para vocês esse sistema de Quest que eu criei para resolver alguns inconvenientes em meu ot serv.

 

Quais são as características dele?

 

  1. Ele é totalmente inserido através do mapper sem precisar criar scripts.
  2. Ele contém um sistema de parâmetros que podem ser usados para determinar a quem pode receber o prêmio.
  3. Ele não usa marcação por storage evitando assim conflitos com outros scripts que usam storage como marcação.
  4. Com esse sistema inserido vocês podem criar quest por vocação única, promovidos, mages ou kinas/palas.

  5. Como ela pode usar os items dentro do baú como items obtiveis de quest, ela aceita qualquer tipo de item inserido, mesmo keys e runas.

 

Implementação

 

 

Em actions.xml adicione:


<!-- Quests baus -->
	<action fromid="1740" toid="1741" event="script" value="quests/quests.lua"/>
	<action fromid="1747" toid="1749" event="script" value="quests/quests.lua"/>
	<action fromid="1410" toid="1420" event="script" value="quests/quests.lua"/>
	<action actionid="2000" event="script" value="quests/quests.lua"/>

 

Agora em scripts/quests crie ou modifique seu quests.lua para esse:

--[[
	autor = Marcryzius
	data = segunda-feira, 28 de Dezembro de 2015
	>> Alguns parametros de uso.
	item.uid = itemid << id do item que será ganho - caso o item esteja 'inside' no baú, não se faz nescessario usar o id do item na uid - para habilitar o bau com os items como sendo uma quest se faz necessario acrescentar uma AID.
	actionid = validação << o baú só será usado na forma de quest se tiver alguma aid. pode usar marcação de vocação como na instrução abaixo ou setar aid 2000 para validar o baú como uma quest.
	actionid = quantidade << desde que ela seja maior que 100 e menor que 200 (150 = 50 items, 200 = 100 items)
	actionid = vocação << o primeiro numero diz que é uma quest de vocação; o segundo habilita que, as vocações promovidas também podem fazer a quest; os dois ultimos numero é da vocação em questão.
		exemplo 1 = 1201 << sorceres e master sorceres -- promovidos
		exemplo 2 = 1200 << kina e EK -- promovidos
		exemplo 3 = 1102 << apenas druids e não elder druids -- vocação especifica
		exemplo 4 = 1000 << apenas knights e paladins.
		exemplo 5 = 1100 << apenas sorcerers e druids.
	inside = varios items << todos os items que forem colocados dentro do bau será usado como referencia do premio da quest; pode-se tambem usar aid para determinar a vocação nescessaria dessa quest.
	-- ### --
	Com o uso da nova função, não está mais sendo "setado" no player a store da "quest" usando setPlayerStorageValue().
]]

function onUse(cid,item,pos) 
	if(item.actionid >= 1000 and item.actionid < 3000)then 
		if(item.actionid == 1000 and not(isPaladin(cid) or isKnight(cid)))then -- somente kina ou pala recebem o item
			return true,doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "It is locked.")
		elseif(item.actionid-1000 == 100 and not(isSorcerer(cid) or isDruid(cid)))then -- somente mages recebem o item
			return true,doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "It is locked.")	
		elseif(item.actionid-1000 > 0 and item.actionid-1000 < 100 and not(getPlayerVocation(cid) == item.actionid-1000))then -- vocação especifica - kina pala.
			return true,doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "It is locked.")
		elseif(item.actionid-1000 > 100 and item.actionid-1000 < 200 and not(getPlayerVocation(cid) == item.actionid-1100))then -- vocação especifica - mages.
			return true,doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "It is locked.")
		elseif(item.actionid-1000 >= 200 and item.actionid-1000 < 300 and not(getPlayerVocation(cid) % 4 == item.actionid-1200))then -- vocações promovidas.
			return true,doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "It is locked.")
		end
	elseif(item.uid > 12000 and item.actionid == 0)then -- um baú qualquer
		return false -- abre o baú para pegarem os items 'inside' sem marcar nada, como se fosse abrir um baú qualquer sem ser de quest.
	end
	
local quests_quant = (item.actionid-100 < 1) and 1 or (item.actionid-100  > 100) and 100 or  item.actionid-100--Defini a quantidade de items.
local playerCap,cap = getPlayerFreeCap(cid),getItemWeightById(item.uid,quests_quant) or 0
	if(item.uid > 1000 and cap > 0)then -- quest por uid
		if(getSaveQuestsInfor(item.uid,cid))then --Função não usa marcação (getPlayerStore...)
			if(playerCap >= cap)then
				if(item.uid == 2493)then setPlayerStorageValue(cid,2493,1) end -- compatibilidade, verificar uso > ???...D:::H...???
				doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, 'You have found a '..((quests_quant == 1) and '' or quests_quant)..' '..getItemNameById(item.uid)..'.')
				saveQuestsInfor(item.uid,getItemNameById(item.uid),cid,"Quest system by uid.")
				doPlayerAddItemEx(cid,doCreateItemEx(item.uid, quests_quant),true)
			else 
				return false,doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, 'You have found a '..(quests_quant == 1 and '' or quests_quant)..' '..getItemNameById(item.uid)..' weighing '..math.floor(cap)..' oz it\'s too heavy.')
			end
		else--caso o player já tenha feito a quest, abri-se o baú de forma convencional, podendo obter os items que estejam dentro dele.
			return false 
		end
		return true
	end
	
	local size,texto,rewards,peso	= isContainer(item.uid) and getContainerSize(item.uid) or 0,'You have found a ',{},0
	if(size > 0)then 
		for i = size,0,-1 do
			local tmp = getContainerItem(item.uid, i)
			if(tmp.itemid > 0) then
				if(isItemContainer(tmp.itemid))then -- só é possível adicionar mais um inside. ou seja, uma bolsa com algo dentro desde que não tenha outra bolsa com mais coisas dentro, dentro dessa bolsa primária.
					table.insert(rewards,1,{[tmp.itemid] = {}})
					texto = texto..' a '..getItemNameById(tmp.itemid)..''..(i+1<size and ',' or '.')
					for insize = getContainerSize(tmp.uid),0,-1 do
					local newtmp = getContainerItem(tmp.uid, insize)
						table.insert(rewards[1][tmp.itemid],{id=newtmp.itemid, val=(newtmp.actionid > 0 and newtmp.actionid or newtmp.type)})
					end
				else
				--Foi feito dessa forma para não haver conflito com items do mesmo tipo.
					table.insert(rewards,{[tmp.itemid]=(tmp.actionid > 0 and tmp.actionid or tmp.type)})
					if(tmp.type > 0)then
						texto = texto..' '..(tmp.type > 0 and tmp.type..' charges of ' or 1)..' '..getItemNameById(tmp.itemid)..''..(i+1<size and ',' or '.')
					elseif(tmp.actionid > 0)then
						texto = texto..' '..(tmp.type > 0 and tmp.type..' charges of ' or 1)..' '..getItemNameById(tmp.itemid)..''..(i+1<size and ',' or '.')
					else			
						texto = texto..' '..getItemNameById(tmp.itemid)..''..(i+1<size and ',' or '.')	
					end
				end
				peso = peso + getItemWeight(tmp.uid)
			end
		end
		if(getSaveQuestsInfor(tonumber(pos.x..''..pos.y..''..pos.z),cid))then --Função não usa marcação (getStore...))
			if(playerCap >= peso)then
				for _,reward in pairs(rewards) do
					for item,valor in pairs(reward) do
						if(type(valor) == "table")then
						local bag = doCreateItemEx(item)
							for _,value in pairs(valor) do 
								if(value and value.id > 0)then doAddContainerItemEx(bag,doCreateItemEx(value.id,(value.val<=0 and 1 or value.val))) end
							end
							doPlayerAddItemEx(cid,bag,true) 
						elseif(isInArray(KEYS_DOOR,item))then -- se o item for uma key
						local ch = doCreateItemEx(item,1)
							doItemSetAttribute(ch,'aid',valor)
							doPlayerAddItemEx(cid,ch)
						else
							doPlayerAddItemEx(cid,doCreateItemEx(item, valor),true)							
						end
					end
				end
				doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, texto)
				saveQuestsInfor(tonumber((pos.x)..''..(pos.y)..''..(pos.z)),getItemNameById(table.maxn(rewards)),cid,"Quest system by Inside.")
			else
				doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, texto..' weighing '..math.floor(peso)..' oz it\'s too heavy.' )			
			end
		else
			doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "It is locked.")
		end
	else
		return false, doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "It is empty.")
	end
	return true
end 

 

 

Em lib/050-functions.lua adicione:

 


function getSaveQuestsInfor(uid,cid) --[[( Marcryzius )]]--
local str = false

	if not(db.executeQuery("SELECT * FROM `server_quests`;"))then -- caso a table não exista, será criada
		db.executeQuery("CREATE TABLE `server_quests` (`uid` INTEGER, `name` VARCHAR(255), `name_player` VARCHAR(255), `pos` VARCHAR(255), `other` TEXT);")
		return getSaveQuestsInfor(uid,cid)
	end

	if(tonumber(uid))then
		str = db.getResult("SELECT * FROM `server_quests` WHERE `uid` = '"..uid.."' AND `name_player` = ".. db.escapeString(getCreatureName(cid))..";")
	elseif(type(uid) == 'string')then
		str = db.getResult("SELECT * FROM `server_quests` WHERE `name_player` = " ..db.escapeString(getCreatureName(cid)).. " AND `name` = '"..uid.."';")
	else
		return false,print('getSaveQuestInfor: tipo de uid invalido > '..tostring(type(uid)))
	end
	return (str:getID() == -1) and true or false 
end

function saveQuestsInfor(uid,name,cid,other) --[[( Marcryzius )]]--
--[[
	uid = Item.uid usado no bau(entre outros) para receber o item da Quest
	name = nome do item dado ao player ou nome da quest
	cid = identificacao do player
	other = informacoes adicionais para serem salvas junto a quest
]]--

if not(db.executeQuery("SELECT * FROM `server_quests`;"))then -- caso a table não exista, será criada
	db.executeQuery("CREATE TABLE `server_quests` (`uid` INTEGER, `name` VARCHAR(255), `name_player` VARCHAR(255), `pos` VARCHAR(255), `other` TEXT);")
end

-- caso o parametro uid seja numero, pega-se a posição do item ou, caso não, pega-se a posição do player.
local other,pos2 = other or '',''
local pos = type(uid) == 'number' and getThingPos(uid) or getCreaturePosition(cid)
	pos2 = 'x='..pos.x..', y='..pos.y..', z='..pos.z
	
	-- verifica se tudo está correto.
	if not(type(name) == 'string') or not(tonumber(cid))then 
		return false, print('Funcao requer parametros: name,cid') 
	end
	
	-- salva as informações na database.
	db.executeQuery("INSERT INTO `server_quests` (`uid`, `name`, `name_player`,`pos`,`other`) VALUES ("..(uid or tonumber(pos.x..''..pos.y..''..pos.z))..",'"..name.."', '"..getCreatureName(cid).."','"..pos2.."','"..other.."');")
	return true
end

 

Exemplos de uso do sistema

Quest na qual dá o prêmio de 100 gps:

Citar

AID = 200 -- quantidade

UID = 2148 -- ID do item

Quest na qual dá o prêmio apenas para knights (e não para EKs e outras promoções de knight):

Citar

AID = 1004 -- 4 é a vocação requerida
UID = ID do item

Quest na qual dá o prêmio apenas para paladins e suas promotions:

Ressalva: Caso queira fazer para knights use o id 0 (zero) e não 4 (quatro).

Citar

AID = 1203 -- O 2 diz que é uma quest de vocações promovidas, o 3 diz qual é a vocação requerida, nesse caso 3 = paladin

UID = ID do item

Quest na qual dá o prêmio apenas para todos:

Nesse caso você pode usar AID 0 (zero) ou AID (2000).

Citar

AID = 0 ou 2000
UID = ID do item

Caso usem o metodo 'inside' de items no baú pode-se também usar esses mesmos parâmetros para estabelecer a quem pode ganhar os items inseridos no baú. Lembre-se que em quests 'insides' não se usa UID, mantenha ela em 0 (zero):

Citar

AID = 1100 -- Quest apenas para mages (sorcerers e druids)

UID = 0

Utilizando o metodo 'inside' ela só se tornará uma quest caso tenha alguma AID para válidar como quest. Então para fazer uma validação na qual qualquer player possa obter os itens 'inside' como sendo uma quest, adicione a AID 2000 ao baú:

Citar

AID = 2000 -- Todos poderão obter os items inseridos no baú como sendo uma quest
UID = 0

 

Bem, é isso pessoal.

Para finalizar, aqui vai uma crítica ao xtibia. MELHOREM ESSE SISTEMA DE EDIÇÃO DE TEXTO.

Link to post
Share on other sites
Em 15/10/2020 em 14:39, Deadpool disse:

agora sim, eu ja adicionei e vou usar com certeza, valeu mesmo kk salvou demais 

Originalmente esse script também faz quest por level, porém omite essa parte ao trazer para cá devida a questão de compatibilidade.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.


    Administrador |  Diretor |  Coordenador |  Moderador |  Suporter |  Estagiário |  Herói
  • Similar Content

    • By Poccnn
      Hail Xtibianos.
       
      Esse script eu criei a pedido de um membro do fórum e resolvi posta-lo para vocês.
       
      Ele serve para que ao matarem um determinado monstros, somente os players que tiverem uma certa quantidade de participação (em porcentagem) na morte do monstro é que receberam algo (configurável).
       
      Em creaturescripts.xml adicione:
      <event type="statschange" name="stats" script="statsMonster.lua"/> <event type="death" name="deathMonster" script="deathMonster.lua"/>  
      Em creaturescripts/scripts crie um arquivo lua com o nome statsMonster e adicione:
      --[[ autor = Marcryzius data = sexta-feira, 05 de fevereiro de 2016 tipo = 1 (um) é ataque, 0 (zero) é healing. query para ser adicionada no monstro: <script> <event name = "stats"/> <event name = "deathMonster"/> </script> ]] M = {} function getDamageInMonster(monster,cid) local monster,cid,m_life,p_dano = tonumber(monster),tonumber(cid),0,0 if not(monster or cid)then return 0,error('function getDamageInMonster(): monster or cid, not number') end if not(isCreature(monster))then return 0,error('function getDamageInMonster(): variavel monster nao e monstro.') end for k,v in pairs(M[monster]) do if(k == cid)then p_dano = v end m_life = m_life + v end return math.floor(p_dano/(m_life/100)) end function onStatsChange(cid, attacker, tipo, combat, value) if not(M[cid])then M[cid] = {} end if not(tipo == 1)then return true end if(isPlayer(attacker))then if not(M[cid][attacker])then M[cid][attacker] = 0 end M[cid][attacker] = M[cid][attacker] + value elseif(isMonster(attacker))then -- caso seja um monstro o atacante local get = getCreatureMaster(attacker) -- averigua se não é um summon que está atacando if(tonumber(get) and isPlayer(get))then -- caso o summon seja de um player, adiciona o dano como se fosse o player if not(M[cid][get])then M[cid][get] = 0 end M[cid][get] = M[cid][get] + value end end return true end  
      Agora crie outro arquivo lua na mesma pasta e nomeie para deathMonster e adicione:
      function onDeath(cid, corpse, deathList) --[[> Marcryzius <]] for _,player in pairs(deathList) do local player = isCreature(player) and getCreatureMaster(player) or player if(isPlayer(player) and isPlayerOn(player))then if(getDamageInMonster(cid,player) >= 50)then -- quantidade de danos em % --[[ aqui é a parte onde dar ao player seu premio por ter consegue tantos % de danos ao monstro ]]-- -- exemplos de ações doRemoveItem(getThingfromPos(Full_Items[getCreatureName(cid):lower()]).uid) doCreateItem(2283,1,getCreaturePosition(cid)) doCreateItem(4810,1,Full_Items[getCreatureName(cid):lower()]) setPlayerStorageValue(player,getStoreString('fullitems'),0) end if(M[player])then table.remove(M,player) end end end end  
      No monstro que tu queira usar esse sistema, adicione no xml dele essas duas tags:
      <script> <event name = "stats"/> <event name = "deathMonster"/> </script>  
      Pronto.
      Qualquer duvida, erro e etc, deixe nos comentários. 
    • By Marcos VMA
      Boa tarde, vim fazer um pedido pra quem puder me ajudar, a colocar um sistema de gender tipico do otpokemon..
       
      Como é o sistema?
       
      Os pokemons summon e dos player que for do [SEXO MALE] ficar com o nome com a cor azul
      Os pokemons summon e dos player que for do [SEXO FEMALE] ficar com o nome com cor rosa
       
      Caso não puder ajudar, se puder falar onde fica esse tipo de sistema, irei atrás de bases com esse sistema e tentar pega-los.. Obrigado a todos ❤️
    • By gabrieloli
      Galera deixa o like e e inscreve lá - Dando dicas totalmente de graça para ajudar a sua experiencia como mapper ou tendo um servidor.
       
    • By Marcos VMA
      Boa noite povo do xTibia vim fazer pedido sobre o Level System, queria saber se alguém poderia me ajudar a adicionar Level System básico
       
      Como seria esse Level system básico?
       
      Fica mostrando level nos Pokémons summon e nos próprios pokémons do jogadores
       
      Ele fica ganhando XP a cada pokémon matado e fica mostrando no chat quantos xp ganhou e quantos precisa pra subir de nível
       
      Assim que upa de nível apareça tipo uma mensagem falando q o povo subir de nível e qual foi o nível
       
      [Obs : se puder colocar pra cada vez q upa o nível adicionar uma % de vida ou força]
       
      Agradeço pela atenção, quem puder ou não puder ajuda não tem problema, Obrigado a todos pela atenção.
       
    • By Vinnyzinho
      Olá, estou contratando algum programador que consiga fazer o sistema e a module do PVP DO GLA.
      Que não seja caro, crise tá foda, rs.

      Bom o sistema é simples, porém a module no OTC é muito bonita e bem feita.
       
      Basicamente o sistema funciona assim:
      Você clica em uma aba no Cliente e abre a module onde aparece Player vs Player & Torneio.
      Eu por enquanto só quero a parte Player vs Player.

       Na parte de player vs player aparece um ranking ordenado por quem tem mais vitórias, e aparece suas derrotas e seu winrate. Para buscar partida precisaria clicar em "Buscar por grupo" onde iniciaria um Matchmaking com outras pessoas que estavam na fila. Ao encontrar outro jogador os 2 players seriam levado para uma arena livre e começariam o Duelo até 1 morrer. Quando 1 player conseguir vencer o outro vai aparecer Victory na tela assim:
       
      E também iria aparecer uma mensagem para todos do jogo assim:

      Como vocês perceberam há um contador de tempo mas para mim não é necessário.


      Lembrando meu servidor ainda não comecei, ou seja não tenho base nenhuma ainda, e isso é para um servidor de poketibia, então se vocês se sentirem mais a vontade com certa base para fazer o sistema sintam-se a vontade e eu utilizarei essa base.
       
×
×
  • Create New...