Histórico de Curtidas
-
Flavio S recebeu reputação de Heitorzera13 em Map size: 48422x47676 KilledMemória Ram/Processador insuficiente.
-
Flavio S recebeu reputação de Xekzy em [TFS 1.1] Monster TasksEsse npc permite escolher qual task o player irá fazer :
Adonai.xml
<?xml version="1.0" encoding="UTF-8"?> <npc name="Adonai" script="tasks.lua" walkinterval="2000" speed ="0" floorchange="0"> <health now="100" max="100"/> <look type="433" head="58" body="113" legs="50" feet="78" addons="1" mount="688"/> </npc>
tasks.lua
local keywordHandler = KeywordHandler:new() local npcHandler = NpcHandler:new(keywordHandler) NpcSystem.parseParameters(npcHandler) local xmsg = {} 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 local storage = 62003 local monsters = { ["Dragons"] = {storage = 5010, mstorage = 19000, amount = 10, exp = 5000, items = {{id = 2157, count = 1}, {id = 2160, count = 3}}}, ["Dragon Lords"] = {storage = 5011, mstorage = 19001, amount = 10, exp = 10000, items = {{id = 2492, count = 1}, {id = 2160, count = 5}}}, ["Hydras"] = {storage = 5012, mstorage = 19002, amount = 10, exp = 18000, items = {{id = 2195, count = 1}, {id = 2157, count = 8}}}, ["Demons"] = {storage = 5013, mstorage = 19003, amount = 10, exp = 20000, items = {{id = 2520, count = 1}, {id = 2160, count = 10}}} } local function getItemsFromTable(itemtable) local text = "" for v = 1, #itemtable do count, info = itemtable[v].count, ItemType(itemtable[v].id) local ret = ", " if v == 1 then ret = "" elseif v == #itemtable then ret = " and " end text = text .. ret text = text .. (count > 1 and count or info:getArticle()).." "..(count > 1 and info:getPluralName() or info:getName()) end return text end local function Cptl(f, r) return f:upper()..r:lower() end function creatureSayCallback(cid, type, msg) local player, cmsg = Player(cid), msg:gsub("(%a)([%w_']*)", Cptl) if not npcHandler:isFocused(cid) then if msg == "hi" or msg == "hello" then npcHandler:addFocus(cid) if player:getStorageValue(storage) == -1 then local text, n = "", 0 for k, x in pairs(monsters) do if player:getStorageValue(x.mstorage) < x.amount then n = n + 1 text = text .. ", " text = text .. ""..x.amount.." {"..k.."}" end end if n > 1 then npcHandler:say("I have several tasks for you to kill monsters"..text..", which one do you choose? I can also show you a {list} with rewards and you can {stop} a task if you want.", cid) npcHandler.topic[cid] = 1 xmsg[cid] = msg elseif n == 1 then npcHandler:say("I have one last task for you"..text..".", cid) npcHandler.topic[cid] = 1 else npcHandler:say("You already did all tasks, I have nothing for you to do anymore, good job though.", cid) end elseif player:getStorageValue(storage) == 1 then for k, x in pairs(monsters) do if player:getStorageValue(x.storage) == 1 then npcHandler:say("Did you kill "..x.amount.." "..k.."?", cid) npcHandler.topic[cid] = 2 xmsg[cid] = k end end end else return false end elseif monsters[cmsg] and npcHandler.topic[cid] == 1 then if player:getStorageValue(monsters[cmsg].storage) == -1 then npcHandler:say("Good luck, come back when you killed "..monsters[cmsg].amount.." "..cmsg..".", cid) player:setStorageValue(storage, 1) player:setStorageValue(monsters[cmsg].storage, 1) else npcHandler:say("You already did the "..cmsg.." mission.", cid) end npcHandler.topic[cid] = 0 elseif msgcontains(msg, "yes") and npcHandler.topic[cid] == 2 then local x = monsters[xmsg[cid]] if player:getStorageValue(x.mstorage) >= x.amount then npcHandler:say("Good job, here is your reward, "..getItemsFromTable(x.items)..".", cid) for g = 1, #x.items do player:addItem(x.items[g].id, x.items[g].count) end player:addExperience(x.exp) player:setStorageValue(x.storage, 2) player:setStorageValue(storage, -1) npcHandler.topic[cid] = 3 else npcHandler:say("You didn't kill them all, you still need to kill "..x.amount -(player:getStorageValue(x.mstorage) + 1).." "..xmsg[cid]..".", cid) end elseif msgcontains(msg, "task") and npcHandler.topic[cid] == 3 then local text, n = "", 0 for k, x in pairs(monsters) do if player:getStorageValue(x.mstorage) < x.amount then n = n + 1 text = text .. (n == 1 and "" or ", ") text = text .. "{"..k.."}" end end if text ~= "" then npcHandler:say("Want to do another task? You can choose "..text..".", cid) npcHandler.topic[cid] = 1 else npcHandler:say("You already did all tasks.", cid) end elseif msgcontains(msg, "no") and npcHandler.topic[cid] == 1 then npcHandler:say("Ok then.", cid) npcHandler.topic[cid] = 0 elseif msgcontains(msg, "stop") then local text, n = "", 0 for k, x in pairs(monsters) do if player:getStorageValue(x.mstorage) < x.amount then n = n + 1 text = text .. (n == 1 and "" or ", ") text = text .. "{"..k.."}" if player:getStorageValue(x.storage) == 1 then player:setStorageValue(x.storage, -1) end end end if player:getStorageValue(storage) == 1 then npcHandler:say("Alright, let me know if you want to continue an other task, you can still choose "..text..".", cid) else npcHandler:say("You didn't start any new task yet, if you want to start one, you can choose "..text..".", cid) end player:setStorageValue(storage, -1) npcHandler.topic[cid] = 1 elseif msgcontains(msg, "list") then local text = "Tasks\n\n" for k, x in pairs(monsters) do if player:getStorageValue(x.mstorage) < x.amount then text = text ..k .." ["..(player:getStorageValue(x.mstorage) + 1).."/"..x.amount.."]:\n Rewards:\n "..getItemsFromTable(x.items).."\n "..x.exp.." experience \n\n" else text = text .. k .." [DONE]\n" end end player:showTextDialog(1949, "" .. text) npcHandler:say("Here you are.", cid) elseif msgcontains(msg, "bye") then npcHandler:say("Bye.", cid) npcHandler:releaseFocus(cid) else npcHandler:say("What?", cid) end return true end npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
creaturescripts.xml
<event type="kill" name="Tasks" script="killtasks.lua"/>
login.lua
player:registerEvent("Tasks")
killtasks.lua
local config = { ['dragon'] = {amount = 10, storage = 19000, startstorage = 5010, startvalue = 1}, ['dragon lord'] = {amount = 10, storage = 19001, startstorage = 5011, startvalue = 1}, ['hydra'] = {amount = 10, storage = 19002, startstorage = 5012, startvalue = 1}, ['demon'] = {amount = 10, storage = 19003, startstorage = 5013, startvalue = 1} } function onKill(player, target) local monster = config[target:getName():lower()] if target:isPlayer() or not monster or target:getMaster() then return true end local stor = player:getStorageValue(monster.storage)+1 if stor < monster.amount and player:getStorageValue(monster.startstorage) >= monster.startvalue then player:setStorageValue(monster.storage, stor) player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, 'Task message: '..(stor +1)..' of '..monster.amount..' '..target:getName()..'s killed.') end if (stor +1) == monster.amount then player:sendTextMessage(MESSAGE_INFO_DESCR, 'Congratulations, you have killed '..(stor +1)..' '..target:getName()..'s and completed the '..target:getName()..'s mission.') player:setStorageValue(monster.storage, stor +1) end return true end
___________________________________________________________________________________________
Como funciona ?
O NPC oferece-lhe várias task, você pode escolher qual você deseja fazer. Se você não matar todos os monstros, o NPC irá dizer-lhe quantos você ainda tem que matar.
Você pode para ver a lista de recompensa e as tasks que você já fez.
Você pode parar com as tasks e ir fazer outra e depois continuar a antiga.
Ao terminar as task elas não serão mais mencionados pelo NPC mas será mostrado como terminado na lista.
Quando terminar as task o npc, dirá que todas foram completadas.
Créditos : Limos, Summ
-
Flavio S recebeu reputação de LionM em [TFS 1.1] Monster TasksEsse npc permite escolher qual task o player irá fazer :
Adonai.xml
<?xml version="1.0" encoding="UTF-8"?> <npc name="Adonai" script="tasks.lua" walkinterval="2000" speed ="0" floorchange="0"> <health now="100" max="100"/> <look type="433" head="58" body="113" legs="50" feet="78" addons="1" mount="688"/> </npc>
tasks.lua
local keywordHandler = KeywordHandler:new() local npcHandler = NpcHandler:new(keywordHandler) NpcSystem.parseParameters(npcHandler) local xmsg = {} 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 local storage = 62003 local monsters = { ["Dragons"] = {storage = 5010, mstorage = 19000, amount = 10, exp = 5000, items = {{id = 2157, count = 1}, {id = 2160, count = 3}}}, ["Dragon Lords"] = {storage = 5011, mstorage = 19001, amount = 10, exp = 10000, items = {{id = 2492, count = 1}, {id = 2160, count = 5}}}, ["Hydras"] = {storage = 5012, mstorage = 19002, amount = 10, exp = 18000, items = {{id = 2195, count = 1}, {id = 2157, count = 8}}}, ["Demons"] = {storage = 5013, mstorage = 19003, amount = 10, exp = 20000, items = {{id = 2520, count = 1}, {id = 2160, count = 10}}} } local function getItemsFromTable(itemtable) local text = "" for v = 1, #itemtable do count, info = itemtable[v].count, ItemType(itemtable[v].id) local ret = ", " if v == 1 then ret = "" elseif v == #itemtable then ret = " and " end text = text .. ret text = text .. (count > 1 and count or info:getArticle()).." "..(count > 1 and info:getPluralName() or info:getName()) end return text end local function Cptl(f, r) return f:upper()..r:lower() end function creatureSayCallback(cid, type, msg) local player, cmsg = Player(cid), msg:gsub("(%a)([%w_']*)", Cptl) if not npcHandler:isFocused(cid) then if msg == "hi" or msg == "hello" then npcHandler:addFocus(cid) if player:getStorageValue(storage) == -1 then local text, n = "", 0 for k, x in pairs(monsters) do if player:getStorageValue(x.mstorage) < x.amount then n = n + 1 text = text .. ", " text = text .. ""..x.amount.." {"..k.."}" end end if n > 1 then npcHandler:say("I have several tasks for you to kill monsters"..text..", which one do you choose? I can also show you a {list} with rewards and you can {stop} a task if you want.", cid) npcHandler.topic[cid] = 1 xmsg[cid] = msg elseif n == 1 then npcHandler:say("I have one last task for you"..text..".", cid) npcHandler.topic[cid] = 1 else npcHandler:say("You already did all tasks, I have nothing for you to do anymore, good job though.", cid) end elseif player:getStorageValue(storage) == 1 then for k, x in pairs(monsters) do if player:getStorageValue(x.storage) == 1 then npcHandler:say("Did you kill "..x.amount.." "..k.."?", cid) npcHandler.topic[cid] = 2 xmsg[cid] = k end end end else return false end elseif monsters[cmsg] and npcHandler.topic[cid] == 1 then if player:getStorageValue(monsters[cmsg].storage) == -1 then npcHandler:say("Good luck, come back when you killed "..monsters[cmsg].amount.." "..cmsg..".", cid) player:setStorageValue(storage, 1) player:setStorageValue(monsters[cmsg].storage, 1) else npcHandler:say("You already did the "..cmsg.." mission.", cid) end npcHandler.topic[cid] = 0 elseif msgcontains(msg, "yes") and npcHandler.topic[cid] == 2 then local x = monsters[xmsg[cid]] if player:getStorageValue(x.mstorage) >= x.amount then npcHandler:say("Good job, here is your reward, "..getItemsFromTable(x.items)..".", cid) for g = 1, #x.items do player:addItem(x.items[g].id, x.items[g].count) end player:addExperience(x.exp) player:setStorageValue(x.storage, 2) player:setStorageValue(storage, -1) npcHandler.topic[cid] = 3 else npcHandler:say("You didn't kill them all, you still need to kill "..x.amount -(player:getStorageValue(x.mstorage) + 1).." "..xmsg[cid]..".", cid) end elseif msgcontains(msg, "task") and npcHandler.topic[cid] == 3 then local text, n = "", 0 for k, x in pairs(monsters) do if player:getStorageValue(x.mstorage) < x.amount then n = n + 1 text = text .. (n == 1 and "" or ", ") text = text .. "{"..k.."}" end end if text ~= "" then npcHandler:say("Want to do another task? You can choose "..text..".", cid) npcHandler.topic[cid] = 1 else npcHandler:say("You already did all tasks.", cid) end elseif msgcontains(msg, "no") and npcHandler.topic[cid] == 1 then npcHandler:say("Ok then.", cid) npcHandler.topic[cid] = 0 elseif msgcontains(msg, "stop") then local text, n = "", 0 for k, x in pairs(monsters) do if player:getStorageValue(x.mstorage) < x.amount then n = n + 1 text = text .. (n == 1 and "" or ", ") text = text .. "{"..k.."}" if player:getStorageValue(x.storage) == 1 then player:setStorageValue(x.storage, -1) end end end if player:getStorageValue(storage) == 1 then npcHandler:say("Alright, let me know if you want to continue an other task, you can still choose "..text..".", cid) else npcHandler:say("You didn't start any new task yet, if you want to start one, you can choose "..text..".", cid) end player:setStorageValue(storage, -1) npcHandler.topic[cid] = 1 elseif msgcontains(msg, "list") then local text = "Tasks\n\n" for k, x in pairs(monsters) do if player:getStorageValue(x.mstorage) < x.amount then text = text ..k .." ["..(player:getStorageValue(x.mstorage) + 1).."/"..x.amount.."]:\n Rewards:\n "..getItemsFromTable(x.items).."\n "..x.exp.." experience \n\n" else text = text .. k .." [DONE]\n" end end player:showTextDialog(1949, "" .. text) npcHandler:say("Here you are.", cid) elseif msgcontains(msg, "bye") then npcHandler:say("Bye.", cid) npcHandler:releaseFocus(cid) else npcHandler:say("What?", cid) end return true end npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
creaturescripts.xml
<event type="kill" name="Tasks" script="killtasks.lua"/>
login.lua
player:registerEvent("Tasks")
killtasks.lua
local config = { ['dragon'] = {amount = 10, storage = 19000, startstorage = 5010, startvalue = 1}, ['dragon lord'] = {amount = 10, storage = 19001, startstorage = 5011, startvalue = 1}, ['hydra'] = {amount = 10, storage = 19002, startstorage = 5012, startvalue = 1}, ['demon'] = {amount = 10, storage = 19003, startstorage = 5013, startvalue = 1} } function onKill(player, target) local monster = config[target:getName():lower()] if target:isPlayer() or not monster or target:getMaster() then return true end local stor = player:getStorageValue(monster.storage)+1 if stor < monster.amount and player:getStorageValue(monster.startstorage) >= monster.startvalue then player:setStorageValue(monster.storage, stor) player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, 'Task message: '..(stor +1)..' of '..monster.amount..' '..target:getName()..'s killed.') end if (stor +1) == monster.amount then player:sendTextMessage(MESSAGE_INFO_DESCR, 'Congratulations, you have killed '..(stor +1)..' '..target:getName()..'s and completed the '..target:getName()..'s mission.') player:setStorageValue(monster.storage, stor +1) end return true end
___________________________________________________________________________________________
Como funciona ?
O NPC oferece-lhe várias task, você pode escolher qual você deseja fazer. Se você não matar todos os monstros, o NPC irá dizer-lhe quantos você ainda tem que matar.
Você pode para ver a lista de recompensa e as tasks que você já fez.
Você pode parar com as tasks e ir fazer outra e depois continuar a antiga.
Ao terminar as task elas não serão mais mencionados pelo NPC mas será mostrado como terminado na lista.
Quando terminar as task o npc, dirá que todas foram completadas.
Créditos : Limos, Summ
-
Flavio S recebeu reputação de Pedro. em [TFS 1.1] Monster TasksEsse npc permite escolher qual task o player irá fazer :
Adonai.xml
<?xml version="1.0" encoding="UTF-8"?> <npc name="Adonai" script="tasks.lua" walkinterval="2000" speed ="0" floorchange="0"> <health now="100" max="100"/> <look type="433" head="58" body="113" legs="50" feet="78" addons="1" mount="688"/> </npc>
tasks.lua
local keywordHandler = KeywordHandler:new() local npcHandler = NpcHandler:new(keywordHandler) NpcSystem.parseParameters(npcHandler) local xmsg = {} 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 local storage = 62003 local monsters = { ["Dragons"] = {storage = 5010, mstorage = 19000, amount = 10, exp = 5000, items = {{id = 2157, count = 1}, {id = 2160, count = 3}}}, ["Dragon Lords"] = {storage = 5011, mstorage = 19001, amount = 10, exp = 10000, items = {{id = 2492, count = 1}, {id = 2160, count = 5}}}, ["Hydras"] = {storage = 5012, mstorage = 19002, amount = 10, exp = 18000, items = {{id = 2195, count = 1}, {id = 2157, count = 8}}}, ["Demons"] = {storage = 5013, mstorage = 19003, amount = 10, exp = 20000, items = {{id = 2520, count = 1}, {id = 2160, count = 10}}} } local function getItemsFromTable(itemtable) local text = "" for v = 1, #itemtable do count, info = itemtable[v].count, ItemType(itemtable[v].id) local ret = ", " if v == 1 then ret = "" elseif v == #itemtable then ret = " and " end text = text .. ret text = text .. (count > 1 and count or info:getArticle()).." "..(count > 1 and info:getPluralName() or info:getName()) end return text end local function Cptl(f, r) return f:upper()..r:lower() end function creatureSayCallback(cid, type, msg) local player, cmsg = Player(cid), msg:gsub("(%a)([%w_']*)", Cptl) if not npcHandler:isFocused(cid) then if msg == "hi" or msg == "hello" then npcHandler:addFocus(cid) if player:getStorageValue(storage) == -1 then local text, n = "", 0 for k, x in pairs(monsters) do if player:getStorageValue(x.mstorage) < x.amount then n = n + 1 text = text .. ", " text = text .. ""..x.amount.." {"..k.."}" end end if n > 1 then npcHandler:say("I have several tasks for you to kill monsters"..text..", which one do you choose? I can also show you a {list} with rewards and you can {stop} a task if you want.", cid) npcHandler.topic[cid] = 1 xmsg[cid] = msg elseif n == 1 then npcHandler:say("I have one last task for you"..text..".", cid) npcHandler.topic[cid] = 1 else npcHandler:say("You already did all tasks, I have nothing for you to do anymore, good job though.", cid) end elseif player:getStorageValue(storage) == 1 then for k, x in pairs(monsters) do if player:getStorageValue(x.storage) == 1 then npcHandler:say("Did you kill "..x.amount.." "..k.."?", cid) npcHandler.topic[cid] = 2 xmsg[cid] = k end end end else return false end elseif monsters[cmsg] and npcHandler.topic[cid] == 1 then if player:getStorageValue(monsters[cmsg].storage) == -1 then npcHandler:say("Good luck, come back when you killed "..monsters[cmsg].amount.." "..cmsg..".", cid) player:setStorageValue(storage, 1) player:setStorageValue(monsters[cmsg].storage, 1) else npcHandler:say("You already did the "..cmsg.." mission.", cid) end npcHandler.topic[cid] = 0 elseif msgcontains(msg, "yes") and npcHandler.topic[cid] == 2 then local x = monsters[xmsg[cid]] if player:getStorageValue(x.mstorage) >= x.amount then npcHandler:say("Good job, here is your reward, "..getItemsFromTable(x.items)..".", cid) for g = 1, #x.items do player:addItem(x.items[g].id, x.items[g].count) end player:addExperience(x.exp) player:setStorageValue(x.storage, 2) player:setStorageValue(storage, -1) npcHandler.topic[cid] = 3 else npcHandler:say("You didn't kill them all, you still need to kill "..x.amount -(player:getStorageValue(x.mstorage) + 1).." "..xmsg[cid]..".", cid) end elseif msgcontains(msg, "task") and npcHandler.topic[cid] == 3 then local text, n = "", 0 for k, x in pairs(monsters) do if player:getStorageValue(x.mstorage) < x.amount then n = n + 1 text = text .. (n == 1 and "" or ", ") text = text .. "{"..k.."}" end end if text ~= "" then npcHandler:say("Want to do another task? You can choose "..text..".", cid) npcHandler.topic[cid] = 1 else npcHandler:say("You already did all tasks.", cid) end elseif msgcontains(msg, "no") and npcHandler.topic[cid] == 1 then npcHandler:say("Ok then.", cid) npcHandler.topic[cid] = 0 elseif msgcontains(msg, "stop") then local text, n = "", 0 for k, x in pairs(monsters) do if player:getStorageValue(x.mstorage) < x.amount then n = n + 1 text = text .. (n == 1 and "" or ", ") text = text .. "{"..k.."}" if player:getStorageValue(x.storage) == 1 then player:setStorageValue(x.storage, -1) end end end if player:getStorageValue(storage) == 1 then npcHandler:say("Alright, let me know if you want to continue an other task, you can still choose "..text..".", cid) else npcHandler:say("You didn't start any new task yet, if you want to start one, you can choose "..text..".", cid) end player:setStorageValue(storage, -1) npcHandler.topic[cid] = 1 elseif msgcontains(msg, "list") then local text = "Tasks\n\n" for k, x in pairs(monsters) do if player:getStorageValue(x.mstorage) < x.amount then text = text ..k .." ["..(player:getStorageValue(x.mstorage) + 1).."/"..x.amount.."]:\n Rewards:\n "..getItemsFromTable(x.items).."\n "..x.exp.." experience \n\n" else text = text .. k .." [DONE]\n" end end player:showTextDialog(1949, "" .. text) npcHandler:say("Here you are.", cid) elseif msgcontains(msg, "bye") then npcHandler:say("Bye.", cid) npcHandler:releaseFocus(cid) else npcHandler:say("What?", cid) end return true end npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
creaturescripts.xml
<event type="kill" name="Tasks" script="killtasks.lua"/>
login.lua
player:registerEvent("Tasks")
killtasks.lua
local config = { ['dragon'] = {amount = 10, storage = 19000, startstorage = 5010, startvalue = 1}, ['dragon lord'] = {amount = 10, storage = 19001, startstorage = 5011, startvalue = 1}, ['hydra'] = {amount = 10, storage = 19002, startstorage = 5012, startvalue = 1}, ['demon'] = {amount = 10, storage = 19003, startstorage = 5013, startvalue = 1} } function onKill(player, target) local monster = config[target:getName():lower()] if target:isPlayer() or not monster or target:getMaster() then return true end local stor = player:getStorageValue(monster.storage)+1 if stor < monster.amount and player:getStorageValue(monster.startstorage) >= monster.startvalue then player:setStorageValue(monster.storage, stor) player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, 'Task message: '..(stor +1)..' of '..monster.amount..' '..target:getName()..'s killed.') end if (stor +1) == monster.amount then player:sendTextMessage(MESSAGE_INFO_DESCR, 'Congratulations, you have killed '..(stor +1)..' '..target:getName()..'s and completed the '..target:getName()..'s mission.') player:setStorageValue(monster.storage, stor +1) end return true end
___________________________________________________________________________________________
Como funciona ?
O NPC oferece-lhe várias task, você pode escolher qual você deseja fazer. Se você não matar todos os monstros, o NPC irá dizer-lhe quantos você ainda tem que matar.
Você pode para ver a lista de recompensa e as tasks que você já fez.
Você pode parar com as tasks e ir fazer outra e depois continuar a antiga.
Ao terminar as task elas não serão mais mencionados pelo NPC mas será mostrado como terminado na lista.
Quando terminar as task o npc, dirá que todas foram completadas.
Créditos : Limos, Summ
-
Flavio S recebeu reputação de Cricket em [TFS 1.1] Monster TasksEsse npc permite escolher qual task o player irá fazer :
Adonai.xml
<?xml version="1.0" encoding="UTF-8"?> <npc name="Adonai" script="tasks.lua" walkinterval="2000" speed ="0" floorchange="0"> <health now="100" max="100"/> <look type="433" head="58" body="113" legs="50" feet="78" addons="1" mount="688"/> </npc>
tasks.lua
local keywordHandler = KeywordHandler:new() local npcHandler = NpcHandler:new(keywordHandler) NpcSystem.parseParameters(npcHandler) local xmsg = {} 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 local storage = 62003 local monsters = { ["Dragons"] = {storage = 5010, mstorage = 19000, amount = 10, exp = 5000, items = {{id = 2157, count = 1}, {id = 2160, count = 3}}}, ["Dragon Lords"] = {storage = 5011, mstorage = 19001, amount = 10, exp = 10000, items = {{id = 2492, count = 1}, {id = 2160, count = 5}}}, ["Hydras"] = {storage = 5012, mstorage = 19002, amount = 10, exp = 18000, items = {{id = 2195, count = 1}, {id = 2157, count = 8}}}, ["Demons"] = {storage = 5013, mstorage = 19003, amount = 10, exp = 20000, items = {{id = 2520, count = 1}, {id = 2160, count = 10}}} } local function getItemsFromTable(itemtable) local text = "" for v = 1, #itemtable do count, info = itemtable[v].count, ItemType(itemtable[v].id) local ret = ", " if v == 1 then ret = "" elseif v == #itemtable then ret = " and " end text = text .. ret text = text .. (count > 1 and count or info:getArticle()).." "..(count > 1 and info:getPluralName() or info:getName()) end return text end local function Cptl(f, r) return f:upper()..r:lower() end function creatureSayCallback(cid, type, msg) local player, cmsg = Player(cid), msg:gsub("(%a)([%w_']*)", Cptl) if not npcHandler:isFocused(cid) then if msg == "hi" or msg == "hello" then npcHandler:addFocus(cid) if player:getStorageValue(storage) == -1 then local text, n = "", 0 for k, x in pairs(monsters) do if player:getStorageValue(x.mstorage) < x.amount then n = n + 1 text = text .. ", " text = text .. ""..x.amount.." {"..k.."}" end end if n > 1 then npcHandler:say("I have several tasks for you to kill monsters"..text..", which one do you choose? I can also show you a {list} with rewards and you can {stop} a task if you want.", cid) npcHandler.topic[cid] = 1 xmsg[cid] = msg elseif n == 1 then npcHandler:say("I have one last task for you"..text..".", cid) npcHandler.topic[cid] = 1 else npcHandler:say("You already did all tasks, I have nothing for you to do anymore, good job though.", cid) end elseif player:getStorageValue(storage) == 1 then for k, x in pairs(monsters) do if player:getStorageValue(x.storage) == 1 then npcHandler:say("Did you kill "..x.amount.." "..k.."?", cid) npcHandler.topic[cid] = 2 xmsg[cid] = k end end end else return false end elseif monsters[cmsg] and npcHandler.topic[cid] == 1 then if player:getStorageValue(monsters[cmsg].storage) == -1 then npcHandler:say("Good luck, come back when you killed "..monsters[cmsg].amount.." "..cmsg..".", cid) player:setStorageValue(storage, 1) player:setStorageValue(monsters[cmsg].storage, 1) else npcHandler:say("You already did the "..cmsg.." mission.", cid) end npcHandler.topic[cid] = 0 elseif msgcontains(msg, "yes") and npcHandler.topic[cid] == 2 then local x = monsters[xmsg[cid]] if player:getStorageValue(x.mstorage) >= x.amount then npcHandler:say("Good job, here is your reward, "..getItemsFromTable(x.items)..".", cid) for g = 1, #x.items do player:addItem(x.items[g].id, x.items[g].count) end player:addExperience(x.exp) player:setStorageValue(x.storage, 2) player:setStorageValue(storage, -1) npcHandler.topic[cid] = 3 else npcHandler:say("You didn't kill them all, you still need to kill "..x.amount -(player:getStorageValue(x.mstorage) + 1).." "..xmsg[cid]..".", cid) end elseif msgcontains(msg, "task") and npcHandler.topic[cid] == 3 then local text, n = "", 0 for k, x in pairs(monsters) do if player:getStorageValue(x.mstorage) < x.amount then n = n + 1 text = text .. (n == 1 and "" or ", ") text = text .. "{"..k.."}" end end if text ~= "" then npcHandler:say("Want to do another task? You can choose "..text..".", cid) npcHandler.topic[cid] = 1 else npcHandler:say("You already did all tasks.", cid) end elseif msgcontains(msg, "no") and npcHandler.topic[cid] == 1 then npcHandler:say("Ok then.", cid) npcHandler.topic[cid] = 0 elseif msgcontains(msg, "stop") then local text, n = "", 0 for k, x in pairs(monsters) do if player:getStorageValue(x.mstorage) < x.amount then n = n + 1 text = text .. (n == 1 and "" or ", ") text = text .. "{"..k.."}" if player:getStorageValue(x.storage) == 1 then player:setStorageValue(x.storage, -1) end end end if player:getStorageValue(storage) == 1 then npcHandler:say("Alright, let me know if you want to continue an other task, you can still choose "..text..".", cid) else npcHandler:say("You didn't start any new task yet, if you want to start one, you can choose "..text..".", cid) end player:setStorageValue(storage, -1) npcHandler.topic[cid] = 1 elseif msgcontains(msg, "list") then local text = "Tasks\n\n" for k, x in pairs(monsters) do if player:getStorageValue(x.mstorage) < x.amount then text = text ..k .." ["..(player:getStorageValue(x.mstorage) + 1).."/"..x.amount.."]:\n Rewards:\n "..getItemsFromTable(x.items).."\n "..x.exp.." experience \n\n" else text = text .. k .." [DONE]\n" end end player:showTextDialog(1949, "" .. text) npcHandler:say("Here you are.", cid) elseif msgcontains(msg, "bye") then npcHandler:say("Bye.", cid) npcHandler:releaseFocus(cid) else npcHandler:say("What?", cid) end return true end npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
creaturescripts.xml
<event type="kill" name="Tasks" script="killtasks.lua"/>
login.lua
player:registerEvent("Tasks")
killtasks.lua
local config = { ['dragon'] = {amount = 10, storage = 19000, startstorage = 5010, startvalue = 1}, ['dragon lord'] = {amount = 10, storage = 19001, startstorage = 5011, startvalue = 1}, ['hydra'] = {amount = 10, storage = 19002, startstorage = 5012, startvalue = 1}, ['demon'] = {amount = 10, storage = 19003, startstorage = 5013, startvalue = 1} } function onKill(player, target) local monster = config[target:getName():lower()] if target:isPlayer() or not monster or target:getMaster() then return true end local stor = player:getStorageValue(monster.storage)+1 if stor < monster.amount and player:getStorageValue(monster.startstorage) >= monster.startvalue then player:setStorageValue(monster.storage, stor) player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, 'Task message: '..(stor +1)..' of '..monster.amount..' '..target:getName()..'s killed.') end if (stor +1) == monster.amount then player:sendTextMessage(MESSAGE_INFO_DESCR, 'Congratulations, you have killed '..(stor +1)..' '..target:getName()..'s and completed the '..target:getName()..'s mission.') player:setStorageValue(monster.storage, stor +1) end return true end
___________________________________________________________________________________________
Como funciona ?
O NPC oferece-lhe várias task, você pode escolher qual você deseja fazer. Se você não matar todos os monstros, o NPC irá dizer-lhe quantos você ainda tem que matar.
Você pode para ver a lista de recompensa e as tasks que você já fez.
Você pode parar com as tasks e ir fazer outra e depois continuar a antiga.
Ao terminar as task elas não serão mais mencionados pelo NPC mas será mostrado como terminado na lista.
Quando terminar as task o npc, dirá que todas foram completadas.
Créditos : Limos, Summ
-
Flavio S recebeu reputação de davidvietro em [TFS 1.1] Healer/blessings NPCbless_heal.lua
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 onPlayerEndTrade(cid) npcHandler:onPlayerEndTrade(cid) end function onPlayerCloseChannel(cid) npcHandler:onPlayerCloseChannel(cid) end function creatureSayCallback(cid, type, msg) if(not npcHandler:isFocused(cid)) then return false end local talkUser = cid local p = Player(cid) local heal = false local hp = p:getHealth() if msgcontains(msg, "heal") then if getCreatureCondition(cid, CONDITION_FIRE) then selfSay("You are burning. I will help you.", cid) doRemoveCondition(cid, CONDITION_FIRE) heal = true elseif getCreatureCondition(cid, CONDITION_POISON) then selfSay("You are poisoned. I will cure you.", cid) doRemoveCondition(cid, CONDITION_POISON) heal = true elseif getCreatureCondition(cid, CONDITION_ENERGY) then selfSay("You are electrificed. I will help you.", cid) doRemoveCondition(cid, CONDITION_ENERGY) heal = true elseif getCreatureCondition(cid, CONDITION_PARALYZE) then selfSay("You are paralyzed. I will cure you.", cid) doRemoveCondition(cid, CONDITION_PARALYZE) heal = true elseif getCreatureCondition(cid, CONDITION_DROWN) then selfSay("You are drowing. I will help you.", cid) doRemoveCondition(cid, CONDITION_DROWN) heal = true elseif getCreatureCondition(cid, CONDITION_FREEZING) then selfSay("You are cold! I will help you.", cid) doRemoveCondition(cid, CONDITION_FREEZING) heal = true elseif getCreatureCondition(cid, CONDITION_BLEEDING) then selfSay("You are bleeding! I will help you.", cid) doRemoveCondition(cid, CONDITION_BLEEDING) heal = true elseif getCreatureCondition(cid, CONDITION_DAZZLED) then selfSay("You are dazzled! Do not mess with holy creatures anymore!", cid) doRemoveCondition(cid, CONDITION_DAZZLED) heal = true elseif getCreatureCondition(cid, CONDITION_CURSED) then selfSay("You are cursed! I will remove it.", cid) doRemoveCondition(cid, CONDITION_CURSED) heal = true elseif hp < 65 then selfSay("You are looking really bad. Let me heal your wounds.", cid) p:addHealth(65 - hp) heal = true elseif hp < 2000 then selfSay("I did my best to fix your wounds.", cid) p:addHealth(2000 - hp) heal = true end if heal then p:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE) else local msgheal = { "You aren't looking really bad, " .. getCreatureName(cid) .. ". I only help in cases of real emergencies. Raise your health simply by eating {food}.", "Seriously? It's just a scratch", "Don't be a child. You don't need any help with your health.", "I'm not an expert. If you need help find a medic.", "Don't even waste my time, I have bigger problems than your scratched armor." } selfSay("" .. msgheal[math.random(1, #msgheal)] .. "", cid) end return true end if msgcontains(msg, "yes") and talkState[talkUser] > 90 and talkState[talkUser] < 96 then if getPlayerBlessing(cid, talkState[talkUser] - 90) then selfSay("You already have this blessing!", cid) else b_price = (2000 + ((math.min(130, getPlayerLevel(cid)) - 30) * 200)) if b_price < 2000 then b_price = 2000 end if doPlayerRemoveMoney(cid, b_price) then selfSay("You have been blessed by one of the five gods!", cid) doPlayerAddBlessing(cid, talkState[talkUser] - 90) doSendMagicEffect(getThingPos(cid), CONST_ME_MAGIC_BLUE) else selfSay("I'm sorry. We need money to keep this temple up.", cid) end end talkState[talkUser] = 0 return true end if msgcontains(msg, "yes") and talkState[talkUser] == 96 then havebless = {} for i = 1, 5 do if(getPlayerBlessing(cid, i)) then table.insert(havebless,i) end end if #havebless == 5 then selfSay('You already have all available blessings.',cid) talkState[talkUser] = 0 return true end b_price = (2000 + ((math.min(130, getPlayerLevel(cid)) - 30) * 200)) if b_price < 2000 then b_price = 2000 end b_price = ((5 - #havebless) * b_price) if doPlayerRemoveMoney(cid, b_price) then selfSay("You have been blessed by the five gods!", cid) for i = 1, 5 do doPlayerAddBlessing(cid, i) end doSendMagicEffect(getThingPos(cid), CONST_ME_MAGIC_BLUE) else selfSay("I'm sorry. We need money to keep this temple up.", cid) end talkState[talkUser] = 0 return true end if msgcontains(msg, "all") then havebless = {} b_price = (2000 + ((math.min(130, getPlayerLevel(cid)) - 30) * 200)) if b_price < 2000 then b_price = 2000 end for i = 1, 5 do if(getPlayerBlessing(cid, i)) then table.insert(havebless,i) end end b_price = ((5 - #havebless) * b_price) if b_price == 0 then selfSay('You already have all available blessings.',cid) talkState[talkUser] = 0 return true end selfSay('Do you want to receive all blessings for ' .. b_price .. ' gold?',cid) talkState[talkUser] = 96 return true end local blesskeywords = {'wisdom', 'spark', 'fire', 'spiritual', 'embrace'} local blessnames = {'Wisdom of Solitude', 'Spark of The Phoenix', 'Fire of Two Suns', 'Spiritual Shielding', 'The Embrace'} for i = 1, #blesskeywords do if msgcontains(msg, blesskeywords[i]) then b_price = (2000 + ((math.min(130, getPlayerLevel(cid)) - 30) * 200)) if b_price < 2000 then b_price = 2000 end selfSay('Do you want me to grant you ' .. blessnames[i] .. ' blessing for ' .. b_price .. ' gold?',cid) talkState[talkUser] = 90 + i return true end end return true end npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) npcHandler:addModule(FocusModule:new())
XML :
<?xml version="1.0" encoding="UTF-8"?> <npc name="NPCNAME" script="bless_heal.lua" walkinterval="2000" floorchange="0" speechbubble="1"> <health now="100" max="100"/> <look type="138" head="58" body="114" legs="87" addons="3"/> <parameters> <parameter key="module_keywords" value="1" /> <parameter key="keywords" value="bless;blessings" /> <parameter key="keyword_reply1" value="I can grant you blessings such as {Wisdom} {of} {Solitude}, {Spark} {of} {The} {Phoenix}, our {Fire} {of} {Two} {Suns}, {Spiritual} {Shielding} and {The Embrace}. I can also grant you {all} of these blessings, just ask me." /> <parameter key="keyword_reply2" value="I can grant you blessings such as {Wisdom} {of} {Solitude}, {Spark} {of} {The} {Phoenix}, our {Fire} {of} {Two} {Suns}, {Spiritual} {Shielding} and {The Embrace}. I can also grant you {all} of these blessings, just ask me." /> </parameters> </npc>
Créditos : zbisu.
-
Flavio S recebeu reputação de Summ em Atualizar a pagina utilizando GETOlá pessoal, estou aqui para resolver um probleminha que tenho encontrado principalmente no meu curso, então estou criando esse tópico para facilitar um pouco a vida dessas pessoas que estão boiando na maionese. É o seguinte:
Para facilitar um pouco nosso trabalho, utilizamos GET para obter o valor de uma váriavel na url para que possa abrir uma determinada pagina sem atualiza o site por completo.
O pessoal do meu curso está utilizando o GET dessa forma:
Código HTML: <?php if(isset($_GET['pagina']) == ' '){ // Se ?pagina= nao for definido nao faça nada, caso tenha um valor procura no switch esse valor e executa-o. }else{ $pagina = $_GET['pagina']; switch($pagina){ case 'home': include 'home.php'; break; default: echo 'pagina nao encontrada'; } } ?> Isso está errado ?
Não, isto não está errado, mas imagine o seguinte, você tem a pagina home,registro,download, e várias outras, ou seja, vc teria de adicionar uma por uma no switch() para que ele possa saber o que fazer com aquele valor.
Enfim, isso daria um problemão pra cabeça, então eu recomendo vocês fazerem o seguinte:
Código HTML: if(!isset($_GET['pagina']) == ' '){ //Se ?pagina= for diferente de não definido $abrir = $_GET['pagina']; // Abrir obtém seu valor ou seja se for ?pagina=home, $abrir passa a valer home $local = $abrir.'.php'; // $local = home.php if(file_exists($local)){ // Se home.php existir include $local; // inclui home.php }else{ // se não echo 'pagina não encontra'; // pagina não encontrada } } É basicamente a mesma coisa a única diferença é que ao invés dele procurar no switch() ele vai verificar se o arquivo existe file_exists(), se existir vai abrir ele, se não, mostrar uma mensagem de pagina não encontrada !
abrçs!!!
-
Flavio S recebeu reputação de Duduph em [TFS 1.1] Healer/blessings NPCbless_heal.lua
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 onPlayerEndTrade(cid) npcHandler:onPlayerEndTrade(cid) end function onPlayerCloseChannel(cid) npcHandler:onPlayerCloseChannel(cid) end function creatureSayCallback(cid, type, msg) if(not npcHandler:isFocused(cid)) then return false end local talkUser = cid local p = Player(cid) local heal = false local hp = p:getHealth() if msgcontains(msg, "heal") then if getCreatureCondition(cid, CONDITION_FIRE) then selfSay("You are burning. I will help you.", cid) doRemoveCondition(cid, CONDITION_FIRE) heal = true elseif getCreatureCondition(cid, CONDITION_POISON) then selfSay("You are poisoned. I will cure you.", cid) doRemoveCondition(cid, CONDITION_POISON) heal = true elseif getCreatureCondition(cid, CONDITION_ENERGY) then selfSay("You are electrificed. I will help you.", cid) doRemoveCondition(cid, CONDITION_ENERGY) heal = true elseif getCreatureCondition(cid, CONDITION_PARALYZE) then selfSay("You are paralyzed. I will cure you.", cid) doRemoveCondition(cid, CONDITION_PARALYZE) heal = true elseif getCreatureCondition(cid, CONDITION_DROWN) then selfSay("You are drowing. I will help you.", cid) doRemoveCondition(cid, CONDITION_DROWN) heal = true elseif getCreatureCondition(cid, CONDITION_FREEZING) then selfSay("You are cold! I will help you.", cid) doRemoveCondition(cid, CONDITION_FREEZING) heal = true elseif getCreatureCondition(cid, CONDITION_BLEEDING) then selfSay("You are bleeding! I will help you.", cid) doRemoveCondition(cid, CONDITION_BLEEDING) heal = true elseif getCreatureCondition(cid, CONDITION_DAZZLED) then selfSay("You are dazzled! Do not mess with holy creatures anymore!", cid) doRemoveCondition(cid, CONDITION_DAZZLED) heal = true elseif getCreatureCondition(cid, CONDITION_CURSED) then selfSay("You are cursed! I will remove it.", cid) doRemoveCondition(cid, CONDITION_CURSED) heal = true elseif hp < 65 then selfSay("You are looking really bad. Let me heal your wounds.", cid) p:addHealth(65 - hp) heal = true elseif hp < 2000 then selfSay("I did my best to fix your wounds.", cid) p:addHealth(2000 - hp) heal = true end if heal then p:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE) else local msgheal = { "You aren't looking really bad, " .. getCreatureName(cid) .. ". I only help in cases of real emergencies. Raise your health simply by eating {food}.", "Seriously? It's just a scratch", "Don't be a child. You don't need any help with your health.", "I'm not an expert. If you need help find a medic.", "Don't even waste my time, I have bigger problems than your scratched armor." } selfSay("" .. msgheal[math.random(1, #msgheal)] .. "", cid) end return true end if msgcontains(msg, "yes") and talkState[talkUser] > 90 and talkState[talkUser] < 96 then if getPlayerBlessing(cid, talkState[talkUser] - 90) then selfSay("You already have this blessing!", cid) else b_price = (2000 + ((math.min(130, getPlayerLevel(cid)) - 30) * 200)) if b_price < 2000 then b_price = 2000 end if doPlayerRemoveMoney(cid, b_price) then selfSay("You have been blessed by one of the five gods!", cid) doPlayerAddBlessing(cid, talkState[talkUser] - 90) doSendMagicEffect(getThingPos(cid), CONST_ME_MAGIC_BLUE) else selfSay("I'm sorry. We need money to keep this temple up.", cid) end end talkState[talkUser] = 0 return true end if msgcontains(msg, "yes") and talkState[talkUser] == 96 then havebless = {} for i = 1, 5 do if(getPlayerBlessing(cid, i)) then table.insert(havebless,i) end end if #havebless == 5 then selfSay('You already have all available blessings.',cid) talkState[talkUser] = 0 return true end b_price = (2000 + ((math.min(130, getPlayerLevel(cid)) - 30) * 200)) if b_price < 2000 then b_price = 2000 end b_price = ((5 - #havebless) * b_price) if doPlayerRemoveMoney(cid, b_price) then selfSay("You have been blessed by the five gods!", cid) for i = 1, 5 do doPlayerAddBlessing(cid, i) end doSendMagicEffect(getThingPos(cid), CONST_ME_MAGIC_BLUE) else selfSay("I'm sorry. We need money to keep this temple up.", cid) end talkState[talkUser] = 0 return true end if msgcontains(msg, "all") then havebless = {} b_price = (2000 + ((math.min(130, getPlayerLevel(cid)) - 30) * 200)) if b_price < 2000 then b_price = 2000 end for i = 1, 5 do if(getPlayerBlessing(cid, i)) then table.insert(havebless,i) end end b_price = ((5 - #havebless) * b_price) if b_price == 0 then selfSay('You already have all available blessings.',cid) talkState[talkUser] = 0 return true end selfSay('Do you want to receive all blessings for ' .. b_price .. ' gold?',cid) talkState[talkUser] = 96 return true end local blesskeywords = {'wisdom', 'spark', 'fire', 'spiritual', 'embrace'} local blessnames = {'Wisdom of Solitude', 'Spark of The Phoenix', 'Fire of Two Suns', 'Spiritual Shielding', 'The Embrace'} for i = 1, #blesskeywords do if msgcontains(msg, blesskeywords[i]) then b_price = (2000 + ((math.min(130, getPlayerLevel(cid)) - 30) * 200)) if b_price < 2000 then b_price = 2000 end selfSay('Do you want me to grant you ' .. blessnames[i] .. ' blessing for ' .. b_price .. ' gold?',cid) talkState[talkUser] = 90 + i return true end end return true end npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) npcHandler:addModule(FocusModule:new())
XML :
<?xml version="1.0" encoding="UTF-8"?> <npc name="NPCNAME" script="bless_heal.lua" walkinterval="2000" floorchange="0" speechbubble="1"> <health now="100" max="100"/> <look type="138" head="58" body="114" legs="87" addons="3"/> <parameters> <parameter key="module_keywords" value="1" /> <parameter key="keywords" value="bless;blessings" /> <parameter key="keyword_reply1" value="I can grant you blessings such as {Wisdom} {of} {Solitude}, {Spark} {of} {The} {Phoenix}, our {Fire} {of} {Two} {Suns}, {Spiritual} {Shielding} and {The Embrace}. I can also grant you {all} of these blessings, just ask me." /> <parameter key="keyword_reply2" value="I can grant you blessings such as {Wisdom} {of} {Solitude}, {Spark} {of} {The} {Phoenix}, our {Fire} {of} {Two} {Suns}, {Spiritual} {Shielding} and {The Embrace}. I can also grant you {all} of these blessings, just ask me." /> </parameters> </npc>
Créditos : zbisu.
-
Flavio S recebeu reputação de Herculesp em [TFS 1.1] Monster TasksEsse npc permite escolher qual task o player irá fazer :
Adonai.xml
<?xml version="1.0" encoding="UTF-8"?> <npc name="Adonai" script="tasks.lua" walkinterval="2000" speed ="0" floorchange="0"> <health now="100" max="100"/> <look type="433" head="58" body="113" legs="50" feet="78" addons="1" mount="688"/> </npc>
tasks.lua
local keywordHandler = KeywordHandler:new() local npcHandler = NpcHandler:new(keywordHandler) NpcSystem.parseParameters(npcHandler) local xmsg = {} 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 local storage = 62003 local monsters = { ["Dragons"] = {storage = 5010, mstorage = 19000, amount = 10, exp = 5000, items = {{id = 2157, count = 1}, {id = 2160, count = 3}}}, ["Dragon Lords"] = {storage = 5011, mstorage = 19001, amount = 10, exp = 10000, items = {{id = 2492, count = 1}, {id = 2160, count = 5}}}, ["Hydras"] = {storage = 5012, mstorage = 19002, amount = 10, exp = 18000, items = {{id = 2195, count = 1}, {id = 2157, count = 8}}}, ["Demons"] = {storage = 5013, mstorage = 19003, amount = 10, exp = 20000, items = {{id = 2520, count = 1}, {id = 2160, count = 10}}} } local function getItemsFromTable(itemtable) local text = "" for v = 1, #itemtable do count, info = itemtable[v].count, ItemType(itemtable[v].id) local ret = ", " if v == 1 then ret = "" elseif v == #itemtable then ret = " and " end text = text .. ret text = text .. (count > 1 and count or info:getArticle()).." "..(count > 1 and info:getPluralName() or info:getName()) end return text end local function Cptl(f, r) return f:upper()..r:lower() end function creatureSayCallback(cid, type, msg) local player, cmsg = Player(cid), msg:gsub("(%a)([%w_']*)", Cptl) if not npcHandler:isFocused(cid) then if msg == "hi" or msg == "hello" then npcHandler:addFocus(cid) if player:getStorageValue(storage) == -1 then local text, n = "", 0 for k, x in pairs(monsters) do if player:getStorageValue(x.mstorage) < x.amount then n = n + 1 text = text .. ", " text = text .. ""..x.amount.." {"..k.."}" end end if n > 1 then npcHandler:say("I have several tasks for you to kill monsters"..text..", which one do you choose? I can also show you a {list} with rewards and you can {stop} a task if you want.", cid) npcHandler.topic[cid] = 1 xmsg[cid] = msg elseif n == 1 then npcHandler:say("I have one last task for you"..text..".", cid) npcHandler.topic[cid] = 1 else npcHandler:say("You already did all tasks, I have nothing for you to do anymore, good job though.", cid) end elseif player:getStorageValue(storage) == 1 then for k, x in pairs(monsters) do if player:getStorageValue(x.storage) == 1 then npcHandler:say("Did you kill "..x.amount.." "..k.."?", cid) npcHandler.topic[cid] = 2 xmsg[cid] = k end end end else return false end elseif monsters[cmsg] and npcHandler.topic[cid] == 1 then if player:getStorageValue(monsters[cmsg].storage) == -1 then npcHandler:say("Good luck, come back when you killed "..monsters[cmsg].amount.." "..cmsg..".", cid) player:setStorageValue(storage, 1) player:setStorageValue(monsters[cmsg].storage, 1) else npcHandler:say("You already did the "..cmsg.." mission.", cid) end npcHandler.topic[cid] = 0 elseif msgcontains(msg, "yes") and npcHandler.topic[cid] == 2 then local x = monsters[xmsg[cid]] if player:getStorageValue(x.mstorage) >= x.amount then npcHandler:say("Good job, here is your reward, "..getItemsFromTable(x.items)..".", cid) for g = 1, #x.items do player:addItem(x.items[g].id, x.items[g].count) end player:addExperience(x.exp) player:setStorageValue(x.storage, 2) player:setStorageValue(storage, -1) npcHandler.topic[cid] = 3 else npcHandler:say("You didn't kill them all, you still need to kill "..x.amount -(player:getStorageValue(x.mstorage) + 1).." "..xmsg[cid]..".", cid) end elseif msgcontains(msg, "task") and npcHandler.topic[cid] == 3 then local text, n = "", 0 for k, x in pairs(monsters) do if player:getStorageValue(x.mstorage) < x.amount then n = n + 1 text = text .. (n == 1 and "" or ", ") text = text .. "{"..k.."}" end end if text ~= "" then npcHandler:say("Want to do another task? You can choose "..text..".", cid) npcHandler.topic[cid] = 1 else npcHandler:say("You already did all tasks.", cid) end elseif msgcontains(msg, "no") and npcHandler.topic[cid] == 1 then npcHandler:say("Ok then.", cid) npcHandler.topic[cid] = 0 elseif msgcontains(msg, "stop") then local text, n = "", 0 for k, x in pairs(monsters) do if player:getStorageValue(x.mstorage) < x.amount then n = n + 1 text = text .. (n == 1 and "" or ", ") text = text .. "{"..k.."}" if player:getStorageValue(x.storage) == 1 then player:setStorageValue(x.storage, -1) end end end if player:getStorageValue(storage) == 1 then npcHandler:say("Alright, let me know if you want to continue an other task, you can still choose "..text..".", cid) else npcHandler:say("You didn't start any new task yet, if you want to start one, you can choose "..text..".", cid) end player:setStorageValue(storage, -1) npcHandler.topic[cid] = 1 elseif msgcontains(msg, "list") then local text = "Tasks\n\n" for k, x in pairs(monsters) do if player:getStorageValue(x.mstorage) < x.amount then text = text ..k .." ["..(player:getStorageValue(x.mstorage) + 1).."/"..x.amount.."]:\n Rewards:\n "..getItemsFromTable(x.items).."\n "..x.exp.." experience \n\n" else text = text .. k .." [DONE]\n" end end player:showTextDialog(1949, "" .. text) npcHandler:say("Here you are.", cid) elseif msgcontains(msg, "bye") then npcHandler:say("Bye.", cid) npcHandler:releaseFocus(cid) else npcHandler:say("What?", cid) end return true end npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
creaturescripts.xml
<event type="kill" name="Tasks" script="killtasks.lua"/>
login.lua
player:registerEvent("Tasks")
killtasks.lua
local config = { ['dragon'] = {amount = 10, storage = 19000, startstorage = 5010, startvalue = 1}, ['dragon lord'] = {amount = 10, storage = 19001, startstorage = 5011, startvalue = 1}, ['hydra'] = {amount = 10, storage = 19002, startstorage = 5012, startvalue = 1}, ['demon'] = {amount = 10, storage = 19003, startstorage = 5013, startvalue = 1} } function onKill(player, target) local monster = config[target:getName():lower()] if target:isPlayer() or not monster or target:getMaster() then return true end local stor = player:getStorageValue(monster.storage)+1 if stor < monster.amount and player:getStorageValue(monster.startstorage) >= monster.startvalue then player:setStorageValue(monster.storage, stor) player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, 'Task message: '..(stor +1)..' of '..monster.amount..' '..target:getName()..'s killed.') end if (stor +1) == monster.amount then player:sendTextMessage(MESSAGE_INFO_DESCR, 'Congratulations, you have killed '..(stor +1)..' '..target:getName()..'s and completed the '..target:getName()..'s mission.') player:setStorageValue(monster.storage, stor +1) end return true end
___________________________________________________________________________________________
Como funciona ?
O NPC oferece-lhe várias task, você pode escolher qual você deseja fazer. Se você não matar todos os monstros, o NPC irá dizer-lhe quantos você ainda tem que matar.
Você pode para ver a lista de recompensa e as tasks que você já fez.
Você pode parar com as tasks e ir fazer outra e depois continuar a antiga.
Ao terminar as task elas não serão mais mencionados pelo NPC mas será mostrado como terminado na lista.
Quando terminar as task o npc, dirá que todas foram completadas.
Créditos : Limos, Summ
-
Flavio S recebeu reputação de Nazz.dhan em [TFS 1.1] Monster TasksEsse npc permite escolher qual task o player irá fazer :
Adonai.xml
<?xml version="1.0" encoding="UTF-8"?> <npc name="Adonai" script="tasks.lua" walkinterval="2000" speed ="0" floorchange="0"> <health now="100" max="100"/> <look type="433" head="58" body="113" legs="50" feet="78" addons="1" mount="688"/> </npc>
tasks.lua
local keywordHandler = KeywordHandler:new() local npcHandler = NpcHandler:new(keywordHandler) NpcSystem.parseParameters(npcHandler) local xmsg = {} 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 local storage = 62003 local monsters = { ["Dragons"] = {storage = 5010, mstorage = 19000, amount = 10, exp = 5000, items = {{id = 2157, count = 1}, {id = 2160, count = 3}}}, ["Dragon Lords"] = {storage = 5011, mstorage = 19001, amount = 10, exp = 10000, items = {{id = 2492, count = 1}, {id = 2160, count = 5}}}, ["Hydras"] = {storage = 5012, mstorage = 19002, amount = 10, exp = 18000, items = {{id = 2195, count = 1}, {id = 2157, count = 8}}}, ["Demons"] = {storage = 5013, mstorage = 19003, amount = 10, exp = 20000, items = {{id = 2520, count = 1}, {id = 2160, count = 10}}} } local function getItemsFromTable(itemtable) local text = "" for v = 1, #itemtable do count, info = itemtable[v].count, ItemType(itemtable[v].id) local ret = ", " if v == 1 then ret = "" elseif v == #itemtable then ret = " and " end text = text .. ret text = text .. (count > 1 and count or info:getArticle()).." "..(count > 1 and info:getPluralName() or info:getName()) end return text end local function Cptl(f, r) return f:upper()..r:lower() end function creatureSayCallback(cid, type, msg) local player, cmsg = Player(cid), msg:gsub("(%a)([%w_']*)", Cptl) if not npcHandler:isFocused(cid) then if msg == "hi" or msg == "hello" then npcHandler:addFocus(cid) if player:getStorageValue(storage) == -1 then local text, n = "", 0 for k, x in pairs(monsters) do if player:getStorageValue(x.mstorage) < x.amount then n = n + 1 text = text .. ", " text = text .. ""..x.amount.." {"..k.."}" end end if n > 1 then npcHandler:say("I have several tasks for you to kill monsters"..text..", which one do you choose? I can also show you a {list} with rewards and you can {stop} a task if you want.", cid) npcHandler.topic[cid] = 1 xmsg[cid] = msg elseif n == 1 then npcHandler:say("I have one last task for you"..text..".", cid) npcHandler.topic[cid] = 1 else npcHandler:say("You already did all tasks, I have nothing for you to do anymore, good job though.", cid) end elseif player:getStorageValue(storage) == 1 then for k, x in pairs(monsters) do if player:getStorageValue(x.storage) == 1 then npcHandler:say("Did you kill "..x.amount.." "..k.."?", cid) npcHandler.topic[cid] = 2 xmsg[cid] = k end end end else return false end elseif monsters[cmsg] and npcHandler.topic[cid] == 1 then if player:getStorageValue(monsters[cmsg].storage) == -1 then npcHandler:say("Good luck, come back when you killed "..monsters[cmsg].amount.." "..cmsg..".", cid) player:setStorageValue(storage, 1) player:setStorageValue(monsters[cmsg].storage, 1) else npcHandler:say("You already did the "..cmsg.." mission.", cid) end npcHandler.topic[cid] = 0 elseif msgcontains(msg, "yes") and npcHandler.topic[cid] == 2 then local x = monsters[xmsg[cid]] if player:getStorageValue(x.mstorage) >= x.amount then npcHandler:say("Good job, here is your reward, "..getItemsFromTable(x.items)..".", cid) for g = 1, #x.items do player:addItem(x.items[g].id, x.items[g].count) end player:addExperience(x.exp) player:setStorageValue(x.storage, 2) player:setStorageValue(storage, -1) npcHandler.topic[cid] = 3 else npcHandler:say("You didn't kill them all, you still need to kill "..x.amount -(player:getStorageValue(x.mstorage) + 1).." "..xmsg[cid]..".", cid) end elseif msgcontains(msg, "task") and npcHandler.topic[cid] == 3 then local text, n = "", 0 for k, x in pairs(monsters) do if player:getStorageValue(x.mstorage) < x.amount then n = n + 1 text = text .. (n == 1 and "" or ", ") text = text .. "{"..k.."}" end end if text ~= "" then npcHandler:say("Want to do another task? You can choose "..text..".", cid) npcHandler.topic[cid] = 1 else npcHandler:say("You already did all tasks.", cid) end elseif msgcontains(msg, "no") and npcHandler.topic[cid] == 1 then npcHandler:say("Ok then.", cid) npcHandler.topic[cid] = 0 elseif msgcontains(msg, "stop") then local text, n = "", 0 for k, x in pairs(monsters) do if player:getStorageValue(x.mstorage) < x.amount then n = n + 1 text = text .. (n == 1 and "" or ", ") text = text .. "{"..k.."}" if player:getStorageValue(x.storage) == 1 then player:setStorageValue(x.storage, -1) end end end if player:getStorageValue(storage) == 1 then npcHandler:say("Alright, let me know if you want to continue an other task, you can still choose "..text..".", cid) else npcHandler:say("You didn't start any new task yet, if you want to start one, you can choose "..text..".", cid) end player:setStorageValue(storage, -1) npcHandler.topic[cid] = 1 elseif msgcontains(msg, "list") then local text = "Tasks\n\n" for k, x in pairs(monsters) do if player:getStorageValue(x.mstorage) < x.amount then text = text ..k .." ["..(player:getStorageValue(x.mstorage) + 1).."/"..x.amount.."]:\n Rewards:\n "..getItemsFromTable(x.items).."\n "..x.exp.." experience \n\n" else text = text .. k .." [DONE]\n" end end player:showTextDialog(1949, "" .. text) npcHandler:say("Here you are.", cid) elseif msgcontains(msg, "bye") then npcHandler:say("Bye.", cid) npcHandler:releaseFocus(cid) else npcHandler:say("What?", cid) end return true end npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
creaturescripts.xml
<event type="kill" name="Tasks" script="killtasks.lua"/>
login.lua
player:registerEvent("Tasks")
killtasks.lua
local config = { ['dragon'] = {amount = 10, storage = 19000, startstorage = 5010, startvalue = 1}, ['dragon lord'] = {amount = 10, storage = 19001, startstorage = 5011, startvalue = 1}, ['hydra'] = {amount = 10, storage = 19002, startstorage = 5012, startvalue = 1}, ['demon'] = {amount = 10, storage = 19003, startstorage = 5013, startvalue = 1} } function onKill(player, target) local monster = config[target:getName():lower()] if target:isPlayer() or not monster or target:getMaster() then return true end local stor = player:getStorageValue(monster.storage)+1 if stor < monster.amount and player:getStorageValue(monster.startstorage) >= monster.startvalue then player:setStorageValue(monster.storage, stor) player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, 'Task message: '..(stor +1)..' of '..monster.amount..' '..target:getName()..'s killed.') end if (stor +1) == monster.amount then player:sendTextMessage(MESSAGE_INFO_DESCR, 'Congratulations, you have killed '..(stor +1)..' '..target:getName()..'s and completed the '..target:getName()..'s mission.') player:setStorageValue(monster.storage, stor +1) end return true end
___________________________________________________________________________________________
Como funciona ?
O NPC oferece-lhe várias task, você pode escolher qual você deseja fazer. Se você não matar todos os monstros, o NPC irá dizer-lhe quantos você ainda tem que matar.
Você pode para ver a lista de recompensa e as tasks que você já fez.
Você pode parar com as tasks e ir fazer outra e depois continuar a antiga.
Ao terminar as task elas não serão mais mencionados pelo NPC mas será mostrado como terminado na lista.
Quando terminar as task o npc, dirá que todas foram completadas.
Créditos : Limos, Summ
-
Flavio S recebeu reputação de lango rullez em [AJUDA] Erro nesse scriptTroca :
local tile = toPosition:getTile() por :
local tile = Player(cid):getTile() -
Flavio S recebeu reputação de Volnei02 em (Resolvido)SCRIPT DESBUG AJUDATroque seu código por esse :
local time = 30 -- minutos function onUse(cid, item, frompos, item2, topos) if getPlayerStorageValue(cid, 5489) <= os.time() then if doPlayerRemoveMoney(cid,500000) == 1 and getPlayerLevel(cid) >= 200 then addLevel(cid,1) doSendMagicEffect(topos,14) doPlayerSay(cid,"Level Desbugado",16) setPlayerStorageValue(cid, 5489, (60*time) + os.time()) else doPlayerSay(cid,"Sorry Custa 50 Gold",16) doPlayerSendCancel(cid,"Sorry no have Lvl 500!") end else doPlayerSendCancel(cid,"Você tem que esperar" .. (getPlayerStorageValue(cid, 5489) - os.time()) / 60 .. "minuto(s) para desbugar novamente.") end return true end -
Flavio S recebeu reputação de exhon em (Resolvido)Ajuda com Database MysqlMarque o post, que mais te ajudou como melhor resposta, pro tópico ficar como resolvido.
-
Flavio S deu reputação a Bruno Minervino em [10.90] Vanaheim Global Opensource - TFS 1.2Um método diferente de agir. Escolhas diferentes, um projeto surpreendente, e o melhor é opensource. Sim, você pode ter acesso a este servidor que estou desenvolvendo em parceria com a Serversoft para você.
Um servidor com uma mega estrutura para suportar seus jogadores online sem nenhum problema como: debug, bug de clonagem, instabilidade entre diversos outros dos servidores free's disponíveis para download nessa vasta internet tibiana.
Uma inovação no ramo de OTservers, distribuindo não só a datapack como as sourcers e os sistemas, absolutamente tudo que você procura. Basta baixar, compilar... Mas eu não sei compilar. Não há problema nisso, o OTPanel da Serversoft faz tudo isso para você. Basta clicar num botão de "play" e ver a mágica acontecer.
O projeto Vanaheim, foi criado com o intuito de ser inteiramente grátis para toda a comunidade. Um servidor no qual a diversão é o fator principal, um projeto com viabilidade absoluta por todos os tibianos.
O projeto conta com uma área exclusiva no GitHub para que todos possam acompanhar a evolução do mesmo, dia a dia, diversas atualizações estarão disponíveis a todos. Desde uma action até uma modificação na source vocês terão acesso.
O servidor conta com um mapa Global Full, quando eu digo full, quero dizer que está 99.99% do mapa completo, sem bugs entre outros.
Um servidor que você escolhe a rate experience/skill que desejar, ele vai se adaptar! Você pode escolher se quer ou não que as quests tenham as missões originais 100%!
E o melhor? Além do servidor estar disponível para download ele está online para quem quiser conhecer o projeto, ajudar de alguma forma e o melhor de tudo, se divertir.
Venha se divertir: http://www.vanaheimglobal.com
RATES
Level 8 - 50: 300x
Level 51 - 80: 200x
Level 81 - 100: 150x
Level 101 - 140: 90x
Level 141 - 160: 70x
Level 161 - 180: 60x
Level 181 - 200: 50x
Level 201 - 230: 40x
Level 231 - 260: 30x
Level 261 - 290: 20x
Level 291 - 310: 15x
Level 311 - 340: 10x
Level 341 - 350: 8x
Level 351 - 380: 6x
Level 381 - 430: 4x
Level 431 - 450: 2x
Level 451+: 1x
Skill: 40x
Magic: 8x
Loot: 3x
EVENTOS
Em Breve.
IMAGENS
Em Breve.
GITHUB
Para acompanhar e baixar o servidor atualizado, segue o link do nosso projeto no GitHub:
DOWNLOADS
Servidor
Mapa
Yasir
Scan
CRÉDITOS
TFS Team
Orts Project
Bruno Minervino
-
Flavio S deu reputação a Pedro. em [GESIOR] Task Shop TFS 1.0Olá, venho trazer para vocês um sistema de Task que vi em um servidor e nunca tinha encontrado em nenhum lugar antes e achei bem interessante.
Como funciona? Você completa a task, ganha direito matar o boss/exp/itens 'editavel' e ganha pontos para usar no Shopping do servidor.
Bom, vamos ao sistema:
Em data/globalevents/scripts crie um arquivo chamado shoptask.lua e adicione o code a seguir:
-- ### CONFIG ### -- message send to player by script "type" (types you can check in "global.lua") SHOP_MSG_TYPE = 18 -- time (in seconds) between connections to SQL database by shop script SQL_interval = 30 -- ### END OF CONFIG ### function onThink(interval, lastExecution) local result_plr = db.storeQuery("SELECT * FROM z_ots_shoptaskcomunication") if(result_plr ~= false) then repeat local id = tonumber(result.getDataInt(result_plr, "id")) local action = tostring(result.getDataString(result_plr, "action")) local delete = tonumber(result.getDataInt(result_plr, "delete_it")) local cid = getPlayerByName(tostring(result.getDataString(result_plr, "name"))) if(cid) then local itemtogive_id = tonumber(result.getDataInt(result_plr, "param1")) local itemtogive_count = tonumber(result.getDataInt(result_plr, "param2")) local container_id = tonumber(result.getDataInt(result_plr, "param3")) local container_count = tonumber(result.getDataInt(result_plr, "param4")) local add_item_type = tostring(result.getDataString(result_plr, "param5")) local add_item_name = tostring(result.getDataString(result_plr, "param6")) local received_item = 0 local full_weight = 0 if(add_item_type == 'container') then container_weight = getItemWeight(container_id, 1) if(isItemRune(itemtogive_id)) then items_weight = container_count * getItemWeight(itemtogive_id, 1) else items_weight = container_count * getItemWeight(itemtogive_id, itemtogive_count) end full_weight = items_weight + container_weight else full_weight = getItemWeight(itemtogive_id, itemtogive_count) if(isItemRune(itemtogive_id)) then full_weight = getItemWeight(itemtogive_id, 1) else full_weight = getItemWeight(itemtogive_id, itemtogive_count) end end local free_cap = getPlayerFreeCap(cid) if(full_weight <= free_cap) then if(add_item_type == 'container') then local new_container = doCreateItemEx(container_id, 1) local iter = 0 while(iter ~= container_count) do doAddContainerItem(new_container, itemtogive_id, itemtogive_count) iter = iter + 1 end received_item = doPlayerAddItemEx(cid, new_container) else local new_item = doCreateItemEx(itemtogive_id, itemtogive_count) received_item = doPlayerAddItemEx(cid, new_item) end if(type(received_item) == "number" and received_item == RETURNVALUE_NOERROR) then doPlayerSendTextMessage(cid, SHOP_MSG_TYPE, 'You received >> '.. add_item_name ..' << from OTS shop.') db.query("DELETE FROM `z_ots_comunication` WHERE `id` = " .. id .. ";") db.query("UPDATE `z_shop_history_item` SET `trans_state`='realized', `trans_real`=" .. os.time() .. " WHERE id = " .. id .. ";") else doPlayerSendTextMessage(cid, SHOP_MSG_TYPE, '>> '.. add_item_name ..' << from OTS shop is waiting for you. Please make place for this item in your backpack/hands and wait about '.. SQL_interval ..' seconds to get it.') end else doPlayerSendTextMessage(cid, SHOP_MSG_TYPE, '>> '.. add_item_name ..' << from OTS shop is waiting for you. It weight is '.. full_weight ..' oz., you have only '.. free_cap ..' oz. free capacity. Put some items in depot and wait about '.. SQL_interval ..' seconds to get it.') end end until not result.next(result_plr) result.free(result_plr) end return true end Em data/globalevents/globalevents.xml adicione a seguinte tag:
<globalevent name="Shop" interval="60000" script="shoptask.lua" /> Pronto. A parte do servidor ta safo, vamos adicionar a database os codigos a seguir:
ALTER TABLE `accounts` ADD `task_points` INTEGER(11) NOT NULL DEFAULT 0; ALTER TABLE `accounts` ADD `task_points_stats` INT NOT NULL DEFAULT '0'; CREATE TABLE `z_shoptask_offer` ( `id` int(11) NOT NULL auto_increment, `points` int(11) NOT NULL default '0', `itemid1` int(11) NOT NULL default '0', `count1` int(11) NOT NULL default '0', `itemid2` int(11) NOT NULL default '0', `count2` int(11) NOT NULL default '0', `offer_type` varchar(255) default NULL, `offer_description` text NOT NULL, `offer_name` varchar(255) NOT NULL, `pid` INT(11) NOT NULL DEFAULT '0', PRIMARY KEY (`id`)) CREATE TABLE `z_shoptask_history_item` ( `id` int(11) NOT NULL auto_increment, `to_name` varchar(255) NOT NULL default '0', `to_account` int(11) NOT NULL default '0', `from_nick` varchar(255) NOT NULL, `from_account` int(11) NOT NULL default '0', `price` int(11) NOT NULL default '0', `offer_id` int(11) NOT NULL default '0', `trans_state` varchar(255) NOT NULL, `trans_start` int(11) NOT NULL default '0', `trans_real` int(11) NOT NULL default '0', PRIMARY KEY (`id`)) CREATE TABLE `z_shoptask_history_pacc` ( `id` int(11) NOT NULL auto_increment, `to_name` varchar(255) NOT NULL default '0', `to_account` int(11) NOT NULL default '0', `from_nick` varchar(255) NOT NULL, `from_account` int(11) NOT NULL default '0', `price` int(11) NOT NULL default '0', `pacc_days` int(11) NOT NULL default '0', `trans_state` varchar(255) NOT NULL, `trans_start` int(11) NOT NULL default '0', `trans_real` int(11) NOT NULL default '0', PRIMARY KEY (`id`)) CREATE TABLE IF NOT EXISTS `z_ots_shoptaskcomunication` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `type` varchar(255) NOT NULL, `action` varchar(255) NOT NULL, `param1` varchar(255) NOT NULL, `param2` varchar(255) NOT NULL, `param3` varchar(255) NOT NULL, `param4` varchar(255) NOT NULL, `param5` varchar(255) NOT NULL, `param6` varchar(255) NOT NULL, `param7` varchar(255) NOT NULL, `delete_it` int(2) NOT NULL DEFAULT '1', PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=13107; Pronto, terminamos quase tudo né? Servidor, Database.. Falta Web.
Irei deixar a vocês uma php pronto para download, mas se vocês quiserem usar o de vocês basta trocar.
shop_system para shoptask_system
premium_points para shoptask_points
premium points para shoptask points
z_shop_offer para z_shoptask_offer
shopsystem para shoptask
z_shop_history_pacc para z_shoptask_history_pacc
z_shop_history_item para z_shoptask_history_item
z_ots_comunication para z_ots_shoptaskcomunication
shoptask.php
Agora é só adicionar no seu layout. Vá em layouts.php adicione abaixo de buypoints:
<a href='?subtopic=shoptask'> <div id='submenu_shoptask' class='Submenuitem' onMouseOver='MouseOverSubmenuItem(this)'onMouseOut='MouseOutSubmenuItem(this)'> <div class='LeftChain' style='background-image:url(<?PHP echo $layout_name; ?>/images/general/chain.gif);'></div> <div id='ActiveSubmenuItemIcon_shoptask' class='ActiveSubmenuItemIcon'style='background-image:url(<?PHP echo $layout_name; ?>/images/menu/icon-activesubmenu.gif);'></div> <div class='SubmenuitemLabel'>Shop Task</div> <div class='RightChain' style='background-image:url(<?PHP echo $layout_name; ?>/images/general/chain.gif);'></div> </div> </a>
Bem é isso, é meio similar ao Guild Shop, porém ele usa o sistema de task. Então vamos ao sistema.
Vamos em data/creaturescript/creaturescript.xml e adicione as seguintes Tags;
<event type="modalwindow" name="taskw" script="task_window.lua"/> <event type="kill" name="KillingInTheNameOf" script="task.lua"/> Em seguida vá em scripts e adicione.
Crie um task.lua e adicione.
local questCreatures = { ["troll"] = {questStarted = 65000, questStorage = 65100, creatureStorage = 15000, killsRequired = 100, raceName = "Trolls"}, ["frost troll"] = {questStarted = 65000, questStorage = 65100, creatureStorage = 15001, killsRequired = 100, raceName = "Trolls"}, ["furious troll"] = {questStarted = 65000, questStorage = 65100, creatureStorage = 15002, killsRequired = 100, raceName = "Trolls"}, ["island troll"] = {questStarted = 65000, questStorage = 65100, creatureStorage = 15003, killsRequired = 100, raceName = "Trolls"}, ["swamp troll"] = {questStarted = 65000, questStorage = 65100, creatureStorage = 15004, killsRequired = 100, raceName = "Trolls"}, ["troll champion"] = {questStarted = 65000, questStorage = 65100, creatureStorage = 15005, killsRequired = 100, raceName = "Trolls"}, ["troll legionnaire"] = {questStarted = 65000, questStorage = 65100, creatureStorage = 15006, killsRequired = 100, raceName = "Trolls"}, ["goblin"] = {questStarted = 65001, questStorage = 65101, creatureStorage = 15007, killsRequired = 5, raceName = "Goblins"}, ["goblin assassin"] = {questStarted = 65001, questStorage = 65101, creatureStorage = 15008, killsRequired = 5, raceName = "Goblins"}, ["goblin leader"] = {questStarted = 65001, questStorage = 65101, creatureStorage = 15009, killsRequired = 5, raceName = "Goblins"}, ["goblin scavenger"] = {questStarted = 65001, questStorage = 65101, creatureStorage = 15010, killsRequired = 5, raceName = "Goblins"}, ["rotworm"] = {questStarted = 65002, questStorage = 65102, creatureStorage = 15011, killsRequired = 300, raceName = "Rotworms"}, ["carriom worm"] = {questStarted = 65002, questStorage = 65102, creatureStorage = 15012, killsRequired = 300, raceName = "Rotworms"}, ["cyclops"] = {questStarted = 65003, questStorage = 65103, creatureStorage = 15013, killsRequired = 500, raceName = "Cyclops"}, ["cyclops smith"] = {questStarted = 65003, questStorage = 65103, creatureStorage = 15014, killsRequired = 500, raceName = "Cyclops"}, ["cyclops drone"] = {questStarted = 65003, questStorage = 65103, creatureStorage = 15015, killsRequired = 500, raceName = "Cyclops"}, ["crocodile"] = {questStarted = 14007, questStorage = 14107, creatureStorage = 15016, killsRequired = 300, raceName = "Crocodiles"}, ["tarantula"] = {questStarted = 14008, questStorage = 14108, creatureStorage = 15017, killsRequired = 300, raceName = "Tarantulas"}, ["carniphila"] = {questStarted = 14009, questStorage = 14109, creatureStorage = 15018, killsRequired = 150, raceName = "Carniphilas"}, ["stone golem"] = {questStarted = 14010, questStorage = 14110, creatureStorage = 15019, killsRequired = 200, raceName = "Stone Golems"}, ["mammoth"] = {questStarted = 14011, questStorage = 14111, creatureStorage = 15020, killsRequired = 300, raceName = "Mammoths"}, ["ice golem"] = {questStarted = 14012, questStorage = 14112, creatureStorage = 15021, killsRequired = 300, raceName = "Ice Golems"}, ["quara predator scout"] = {questStarted = 14013, questStorage = 14113, creatureStorage = 15022, killsRequired = 300, raceName = "Quaras Scout"}, ["quara constrictor scout"] = {questStarted = 14013, questStorage = 14113, creatureStorage = 15023, killsRequired = 300, raceName = "Quaras Scout"}, ["quara hydromancer scout"] = {questStarted = 14013, questStorage = 14113, creatureStorage = 15024, killsRequired = 300, raceName = "Quaras Scout"}, ["quara mantassin scout"] = {questStarted = 14013, questStorage = 14113, creatureStorage = 15025, killsRequired = 300, raceName = "Quaras Scout"}, ["quara pincher scout"] = {questStarted = 14013, questStorage = 14113, creatureStorage = 15026, killsRequired = 300, raceName = "Quaras Scout"}, ["quara predator"] = {questStarted = 14014, questStorage = 14114, creatureStorage = 15027, killsRequired = 300, raceName = "Quaras"}, ["quara constrictor"] = {questStarted = 14014, questStorage = 14114, creatureStorage = 15028, killsRequired = 300, raceName = "Quaras"}, ["quara hydromancer"] = {questStarted = 14014, questStorage = 14114, creatureStorage = 15029, killsRequired = 300, raceName = "Quaras"}, ["quara mantassin"] = {questStarted = 14014, questStorage = 14114, creatureStorage = 15030, killsRequired = 300, raceName = "Quaras"}, ["quara pincher"] = {questStarted = 14014, questStorage = 14114, creatureStorage = 15031, killsRequired = 300, raceName = "Quaras"}, ["water elemental"] = {questStarted = 14015, questStorage = 14115, creatureStorage = 15032, killsRequired = 70, raceName = "Water Elementals"}, ["roaring water elemental"] = {questStarted = 14015, questStorage = 14115, creatureStorage = 15033, killsRequired = 70, raceName = "Water Elementals"}, ["slick water elemental"] = {questStarted = 14015, questStorage = 14115, creatureStorage = 15034, killsRequired = 70, raceName = "Water Elementals"}, ["massive water elemental"] = {questStarted = 14015, questStorage = 14115, creatureStorage = 15035, killsRequired = 70, raceName = "Water Elementals"}, ["earth elemental"] = {questStarted = 14016, questStorage = 14116, creatureStorage = 15036, killsRequired = 70, raceName = "Earth Elementals"}, ["jagged earth elemental"] = {questStarted = 14016, questStorage = 14116, creatureStorage = 15037, killsRequired = 70, raceName = "Earth Elementals"}, ["massive earth elemental"] = {questStarted = 14016, questStorage = 14116, creatureStorage = 15038, killsRequired = 70, raceName = "Earth Elementals"}, ["muddy earth elemental"] = {questStarted = 14016, questStorage = 14116, creatureStorage = 15039, killsRequired = 70, raceName = "Earth Elementals"}, ["energy elemental"] = {questStarted = 14017, questStorage = 14117, creatureStorage = 15040, killsRequired = 70, raceName = "Energy Elementals"}, ["charged energy elemental"] = {questStarted = 14017, questStorage = 14117, creatureStorage = 15041, killsRequired = 70, raceName = "Energy Elementals"}, ["massive energy elemental"] = {questStarted = 14017, questStorage = 14117, creatureStorage = 15042, killsRequired = 70, raceName = "Energy Elementals"}, ["overcharged energy elemental"] = {questStarted = 14017, questStorage = 14117, creatureStorage = 15043, killsRequired = 70, raceName = "Energy Elementals"}, ["fire elemental"] = {questStarted = 14018, questStorage = 14118, creatureStorage = 15044, killsRequired = 70, raceName = "Fire Elementals"}, ["blazing fire elemental"] = {questStarted = 14018, questStorage = 14118, creatureStorage = 15045, killsRequired = 70, raceName = "Fire Elementals"}, ["blistering fire elemental"] = {questStarted = 14018, questStorage = 14118, creatureStorage = 15046, killsRequired = 70, raceName = "Fire Elementals"}, ["massive fire elemental"] = {questStarted = 14018, questStorage = 14118, creatureStorage = 15047, killsRequired = 70, raceName = "Fire Elementals"}, ["mutated rat"] = {questStarted = 14019, questStorage = 14119, creatureStorage = 15048, killsRequired = 200, raceName = "Mutated Rats"}, ["giant spider"] = {questStarted = 14020, questStorage = 14120, creatureStorage = 15049, killsRequired = 500, raceName = "Giant Spiders"}, ["hydra"] = {questStarted = 14021, questStorage = 14121, creatureStorage = 15050, killsRequired = 500, raceName = "Hydras"}, ["sea serpent"] = {questStarted = 14001, questStorage = 14101, creatureStorage = 15051, killsRequired = 500, raceName = "Sea Serpents"}, ["behemoth"] = {questStarted = 14022, questStorage = 14122, creatureStorage = 15052, killsRequired = 500, raceName = "Behemoths"}, ["serpent spawn"] = {questStarted = 14002, questStorage = 14102, creatureStorage = 15053, killsRequired = 375, raceName = "Serpents Spawn"}, ["green djinn"] = {questStarted = 65022, questStorage = 65122, creatureStorage = 15054, killsRequired = 125, raceName = "Green Djinns"}, ["efreet"] = {questStarted = 65022, questStorage = 65122, creatureStorage = 15055, killsRequired = 125, raceName = "Green Djinns"}, ["blue djinn"] = {questStarted = 65023, questStorage = 65123, creatureStorage = 15056, killsRequired = 125, raceName = "Blue Djinns"}, ["marid"] = {questStarted = 65023, questStorage = 65123, creatureStorage = 15057, killsRequired = 125, raceName = "Blue Djinns"}, ["pirate buccaneer"] = {questStarted = 65024, questStorage = 65124, creatureStorage = 15058, killsRequired = 300, raceName = "Pirates"}, ["pirate corsair"] = {questStarted = 65024, questStorage = 65124, creatureStorage = 15059, killsRequired = 300, raceName = "Pirates"}, ["pirate cutthroat"] = {questStarted = 65024, questStorage = 65124, creatureStorage = 15060, killsRequired = 300, raceName = "Pirates"}, ["pirate ghost"] = {questStarted = 65024, questStorage = 65124, creatureStorage = 15061, killsRequired = 300, raceName = "Pirates"}, ["pirate marauder"] = {questStarted = 65024, questStorage = 65124, creatureStorage = 15062, killsRequired = 300, raceName = "Pirates"}, ["pirate skeleton"] = {questStarted = 65024, questStorage = 65124, creatureStorage = 15063, killsRequired = 300, raceName = "Pirates"}, ["minotaur"] = {questStarted = 14004, questStorage = 14104, creatureStorage = 15070, killsRequired = 500, raceName = "Minotaurs"}, ["necromancer"] = {questStarted = 14003, questStorage = 14103, creatureStorage = 15071, killsRequired = 1000, raceName = "Magicians"}, ["priestess"] = {questStarted = 14003, questStorage = 14103, creatureStorage = 15072, killsRequired = 1000, raceName = "Magicians"}, ["dragon"] = {questStarted = 65030, questStorage = 65130, creatureStorage = 15065, killsRequired = 500, raceName = "Dragons"}, ["dragon lord"] = {questStarted = 65030, questStorage = 65130, creatureStorage = 15066, killsRequired = 500, raceName = "Dragons"}, ["frost dragon"] = {questStarted = 65030, questStorage = 65130, creatureStorage = 15067, killsRequired = 500, raceName = "Dragons"}, ["ghastly dragon"] = {questStarted = 65030, questStorage = 65130, creatureStorage = 15068, killsRequired = 500, raceName = "Dragons"}, ["undead dragon"] = {questStarted = 65030, questStorage = 65130, creatureStorage = 15069, killsRequired = 500, raceName = "Dragons"}, ["demon"] = {questStarted = 14023, questStorage = 14123, creatureStorage = 15075, killsRequired = 6666, raceName = "Demons"} } local msgType = MESSAGE_STATUS_CONSOLE_ORANGE function onKill(cid, target, lastHit) local creature = questCreatures[getCreatureName(target):lower()] if creature then if isPlayer(target) then return true end if getCreatureStorage(cid, creature.questStarted) > 0 then if getCreatureStorage(cid, creature.questStorage) < creature.killsRequired then if getCreatureStorage(cid, creature.questStorage) < 0 then doCreatureSetStorage(cid, creature.questStorage, 0) end if (not isSummon(target)) then if getCreatureStorage(cid, creature.creatureStorage) < 0 then doCreatureSetStorage(cid, creature.creatureStorage, 0) end doCreatureSetStorage(cid, creature.questStorage, getCreatureStorage(cid, creature.questStorage) + 1) doCreatureSetStorage(cid, creature.creatureStorage, getCreatureStorage(cid, creature.creatureStorage) + 1) doPlayerSendTextMessage(cid, msgType, "[Mission]: " .. getCreatureStorage(cid,creature.questStorage) .. "/" .. creature.killsRequired .. " " .. creature.raceName .. " defeated.") end end end end return true end depois task_window e adicione;
function onModalWindow(cid, modalWindowId, buttonId, choiceId) if modalWindowId ~= 1900 then return false end local rank = getCreatureStorage(cid, rankStorage) if rank < 0 then doCreatureSetStorage(cid, rankStorage, 0) end local r_string = function() if tasks[choiceId].repeatable then return "repeatable" end return "not repeatable" end local r_article_string = function (id, amount) task_item_word = "" if amount > 1 then task_item_word = task_item_word .. amount .. "x " .. getItemName(id) else if ItemType(itemId):getArticle() == "" then task_item_word = task_item_word .. getItemName(id) else task_item_word = task_item_word .. ItemType(itemId):getArticle() .. " " .. getItemName(id) end end return task_item_word end local storage_string = {[80000] = "The Snapper", [80001] = "Demodras", [80002] = "The Hide", [80003] = "The Bloodtusk", [80004] = "The Shardhead", [80005] = "Thul", [80006] = "Esmeralda", [80007] = "The Old Widow", [80008] = "The Many", [80009] = "The Leviathan", [80010] = "The Stonecracker", [80011] = "The Noxious Spawn", [80012] = "Merikh The Slaughterer", [80013] = "Fahim The Wise", [80014] = "pirate leader", [80015] = "The Horned Fox", [80016] = "Necropharus" } if buttonId == 1 then -- confirm task if getCreatureStorage(cid, tasks[choiceId].questStarted) < 1 then doCreatureSetStorage(cid, tasks[choiceId].questStarted, 1) doCreatureSetStorage(cid, tasks[choiceId].questStorage, 0) doCreatureSay(taskNPCuid, "In this mission you have to hunt " .. tasks[choiceId].killsRequired .. " " .. tasks[choiceId].raceName .. " down. Good luck!", TALKTYPE_PRIVATE_NP, false, cid, getThingPos(taskNPCuid)) else if getCreatureStorage(cid, tasks[choiceId].questStarted) == 1 then if tasks[choiceId].killsRequired > getCreatureStorage(cid, tasks[choiceId].questStorage) then doPlayerPopupFYI(cid,"Status: Active\nKills: " .. getCreatureStorage(cid, tasks[choiceId].questStorage) .. "/" .. tasks[choiceId].killsRequired .. " (" .. tasks[choiceId].killsRequired - getCreatureStorage(cid, tasks[choiceId].questStorage) .. " left)\n\nThis mission is " .. r_string() .. ".") sendTaskWindow(cid) else doCreatureSetStorage(cid, tasks[choiceId].questStarted, 2) task_reward_str = "Reward(s):\n" for i = 1, table.maxn(tasks[choiceId].rewards) do if(tasks[choiceId].rewards[i].enable) then if isInArray({"boss", "teleport", 1}, tasks[choiceId].rewards[i].type) then doTeleportThing(cid, tasks[choiceId].rewards[i].values) task_reward_str = task_reward_str .. "You have been teleported.\n" elseif isInArray({"exp", "experience", 2}, tasks[choiceId].rewards[i].type) then doPlayerAddExperience(cid, tasks[choiceId].rewards[i].values) task_reward_str = task_reward_str .. "+ " .. tasks[choiceId].rewards[i].values .. " exp\n" elseif isInArray({"item", 3}, tasks[choiceId].rewards[i].type) then doPlayerAddItem(cid, tasks[choiceId].rewards[i].values[1], tasks[choiceId].rewards[i].values[2]) task_reward_str = task_reward_str .. r_article_string(tasks[choiceId].rewards[i].values[1], tasks[choiceId].rewards[i].values[2]) .. "\n" elseif isInArray({"money", 4}, tasks[choiceId].rewards[i].type) then doPlayerAddMoney(cid, tasks[choiceId].rewards[i].values) task_reward_str = task_reward_str .. "+ " .. tasks[choiceId].rewards[i].values .. " gp\n" elseif isInArray({"storage", "stor", 5}, tasks[choiceId].rewards[i].type) then doCreatureSetStorage(cid, tasks[choiceId].rewards[i].values[1], tasks[choiceId].rewards[i].values[2]) task_reward_str = task_reward_str .. "Chance to duel " .. storage_string[tasks[choiceId].rewards[i].values[1]] .. ".\n" elseif isInArray({"points", "rank", 2}, tasks[choiceId].rewards[i].type) then db.query("UPDATE `accounts` SET `task_points` = `task_points` + " .. tasks[choiceId].rewards[i].values .. " WHERE `id` = " .. getPlayerAccountId(cid) .. ";") doCreatureSetStorage(cid, rankStorage, getCreatureStorage(cid, rankStorage) + tasks[choiceId].rewards[i].values) task_reward_str = task_reward_str .. "+ " .. tasks[choiceId].rewards[i].values .. " rank points.\n" else print("[Warning - Npc::KillingInTheNameOf] Wrong reward type: " .. (tasks[choiceId].rewards[i].type or "nil") .. ", reward could not be loaded.") end end end if task_reward_str == "Reward(s):\n" then doPlayerPopupFYI(cid,task_reward_str .. "none") else doPlayerPopupFYI(cid,task_reward_str) end doCreatureSay(taskNPCuid, "Great job" .. (((rank > 4 and rank < 10) and (", Huntsman") or (rank > 9 and rank < 20) and (", Ranger") or (rank > 19 and rank < 30) and (", Big Game Hunter") or (rank > 29 and rank < 50) and (", Trophy Hunter") or (rank > 49) and (", Elite Hunter")) or ", my Beginner") .. "! Here is your reward. Keep hunting and good luck!", TALKTYPE_PRIVATE_NP, false, cid, getThingPos(taskNPCuid)) end else if tasks[choiceId].repeatable then for i = 1, table.maxn(tasks[choiceId].rewards) do if isInArray({"storage", "stor", 5}, tasks[choiceId].rewards[i].type) then doPlayerPopupFYI(cid,"To repeat this mission again, fight with " .. storage_string[tasks[choiceId].rewards[i].values[1]] .. " first.") break end if i == table.maxn(tasks[choiceId].rewards) then doPlayerPopupFYI(cid,"You can't repeat this mission.") end end else doPlayerPopupFYI(cid,"You can't repeat this mission.") end sendTaskWindow(cid) end end elseif buttonId == 255 then doPlayerPopupFYI(cid,"Please use a button.") sendTaskWindow(cid) end return true end Agora vamos até data\lib e crie e adicione;
rankStorage = 32150 THESNAPPER = {80000, 1} DEMODRAS = {80001, 1} HIDE = {80002, 1} THEBLOODTUSK = {80003, 1} SHARDHEAD = {80004, 1} THUL = {80005, 1} ESMERALDA = {80006, 1} THEOLDWIDOW = {80007, 1} THEMANY = {80008, 1} LEVIATHAN = {80009, 1} STONECRACKER = {80010, 1} THENOXIUSSPAWN = {80011, 1} MERIKHTHESLAUGHTERER = {80012, 1} FAHIMTHEWISE = {80013, 1} RANDOMPIRATEBOSS = {80014, 1} THEHORNEDFOX = {80015, 1} NECROPHARUS = {80016, 1} tasks = { [1] = {questStarted = 65000, questStorage = 65100, killsRequired = 100, raceName = "Trolls", repeatable = false, rewards = {{enable = true, type = "exp", values = 40000}, {enable = true, type = "money", values = 4000}}}, [2] = {questStarted = 65001, questStorage = 65101, killsRequired = 150, raceName = "Goblins", repeatable = false, rewards = {{enable = true, type = "exp", values = 70000}, {enable = true, type = "money", values = 5000}}}, [3] = {questStarted = 65002, questStorage = 65102, killsRequired = 300, raceName = "Rotworms", repeatable = false, rewards = {{enable = true, type = "exp", values = 100000}, {enable = true, type = "money", values = 6000}}}, [4] = {questStarted = 65003, questStorage = 65103, killsRequired = 500, raceName = "Cyclops", repeatable = false, rewards = {{enable = true, type = "exp", values = 150000}, {enable = true, type = "money", values = 8000}}}, [5] = {questStarted = 14007, questStorage = 14107, killsRequired = 300, raceName = "Crocodiles", repeatable = true, rewards = {{enable = true, type = "exp", values = 100000}, {enable = true, type = "storage", values = THESNAPPER}, {enable = true, type = "points", values = 2}}}, [6] = {questStarted = 14008, questStorage = 14108, killsRequired = 300, raceName = "Tarantulas", repeatable = true, rewards = {{enable = true, type = "exp", values = 150000}, {enable = true, type = "storage", values = HIDE}, {enable = true, type = "points", values = 2}}}, [7] = {questStarted = 14009, questStorage = 14109, killsRequired = 150, raceName = "Carniphilas", repeatable = false, rewards = {{enable = true, type = "exp", values = 250000}, {enable = true, type = "money", values = 15000}}}, [8] = {questStarted = 14010, questStorage = 14110, killsRequired = 200, raceName = "Stone Golems", repeatable = false, rewards = {{enable = true, type = "exp", values = 200000}, {enable = true, type = "money", values = 15000}}}, [9] = {questStarted = 14011, questStorage = 14111, killsRequired = 300, raceName = "Mammoths", repeatable = true, rewards = {{enable = true, type = "exp", values = 150000}, {enable = true, type = "storage", values = THEBLOODTUSK}, {enable = true, type = "points", values = 2}}}, [10] = {questStarted = 14012, questStorage = 14112, killsRequired = 300, raceName = "Ice Golems", repeatable = true, rewards = {{enable = true, type = "exp", values = 150000}, {enable = true, type = "storage", values = SHARDHEAD}, {enable = true, type = "points", values = 2}}}, [11] = {questStarted = 14013, questStorage = 14113, killsRequired = 300, raceName = "Quaras Scout", repeatable = true, rewards = {{enable = true, type = "exp", values = 250000}, {enable = true, type = "money", values = 25000}}}, [12] = {questStarted = 14014, questStorage = 14114, killsRequired = 300, raceName = "Quaras", repeatable = true, rewards = {{enable = true, type = "exp", values = 300000}, {enable = true, type = "storage", values = THUL}, {enable = true, type = "points", values = 2}}}, [13] = {questStarted = 14015, questStorage = 14115, killsRequired = 70, raceName = "Water Elementals", repeatable = false, rewards = {{enable = true, type = "exp", values = 200000}, {enable = true, type = "money", values = 20000}}}, [14] = {questStarted = 14016, questStorage = 14116, killsRequired = 70, raceName = "Earth Elementals", repeatable = false, rewards = {{enable = true, type = "exp", values = 200000}, {enable = true, type = "money", values = 20000}}}, [15] = {questStarted = 14017, questStorage = 14117, killsRequired = 70, raceName = "Energy Elementals", repeatable = false, rewards = {{enable = true, type = "exp", values = 200000}, {enable = true, type = "money", values = 20000}}}, [16] = {questStarted = 14018, questStorage = 14118, killsRequired = 70, raceName = "Fire Elementals", repeatable = false, rewards = {{enable = true, type = "exp", values = 200000}, {enable = true, type = "money", values = 20000}}}, [17] = {questStarted = 14019, questStorage = 14119, killsRequired = 200, raceName = "Mutated Rats", repeatable = true, rewards = {{enable = true, type = "exp", values = 150000}, {enable = true, type = "storage", values = ESMERALDA}, {enable = true, type = "points", values = 2}}}, [18] = {questStarted = 14020, questStorage = 14120, killsRequired = 500, raceName = "Giant Spiders", repeatable = true, rewards = {{enable = true, type = "exp", values = 250000}, {enable = true, type = "storage", values = THEOLDWIDOW}, {enable = true, type = "points", values = 2}}}, [19] = {questStarted = 14021, questStorage = 14121, killsRequired = 500, raceName = "Hydras", repeatable = true, rewards = {{enable = true, type = "storage", values = THEMANY}, {enable = true, type = "points", values = 4}}}, [20] = {questStarted = 14001, questStorage = 14101, killsRequired = 500, raceName = "Sea Serpents", repeatable = true, rewards = {{enable = true, type = "storage", values = LEVIATHAN}, {enable = true, type = "points", values = 4}}}, [21] = {questStarted = 14022, questStorage = 14122, killsRequired = 500, raceName = "Behemoths", repeatable = true, rewards = {{enable = true, type = "storage", values = STONECRACKER}, {enable = true, type = "points", values = 4}}}, [22] = {questStarted = 14002, questStorage = 14102, killsRequired = 375, raceName = "Serpents Spawn", repeatable = true, rewards = {{enable = true, type = "storage", values = THENOXIOUSSPAWN}, {enable = true, type = "points", values = 4}}}, [23] = {questStarted = 65022, questStorage = 65122, killsRequired = 125, raceName = "Green Djinns", repeatable = true, rewards = {{enable = true, type = "exp", values = 230000}, {enable = true, type = "money", values = 5000}, {enable = true, type = "storage", values = MERIKHTHESLAUGHTERER}}}, [24] = {questStarted = 65023, questStorage = 65123, killsRequired = 125, raceName = "Blue Djinns", repeatable = true, rewards = {{enable = true, type = "exp", values = 230000}, {enable = true, type = "money", values = 5000}, {enable = true, type = "storage", values = FAHIMTHEWISE}}}, [25] = {questStarted = 65024, questStorage = 65124, killsRequired = 300, raceName = "Pirates", repeatable = false, rewards = {{enable = true, type = "exp", values = 300000}, {enable = true, type = "money", values = 40000}, {enable = true, type = "storage", values = RANDOMPIRATEBOSS}}}, [26] = {questStarted = 14004, questStorage = 14104, killsRequired = 500, raceName = "Minotaurs", repeatable = false, rewards = {{enable = true, type = "storage", values = THEHORNEDFOX}}}, [27] = {questStarted = 14003, questStorage = 14103, killsRequired = 1000, raceName = "Magicians", repeatable = false, rewards = {{enable = true, type = "storage", values = NECROPHARUS}}}, [28] = {questStarted = 65030, questStorage = 65130, killsRequired = 500, raceName = "Dragons", repeatable = true, rewards = {{enable = true, type = "storage", values = DEMODRAS}, {enable = true, type = "exp", values = 400000}}}, [29] = {questStarted = 14023, questStorage = 14123, killsRequired = 6666, raceName = "Demons", repeatable = false, rewards = {{enable = true, type = "exp", values = 1000000}, {enable = true, type = "item", values = {10305,1}}}}} function getTasksStarted(cid) local tmp = {} for k, v in pairs(tasks) do if getCreatureStorage(cid, v.questStarted) == 1 then table.insert(tmp, k) end end return tmp end function getTaskByName(name) for k, v in pairs(tasks) do if v.raceName:lower() == name:lower() then return k end end return false end function sendTaskWindow(cid) taskWindow = ModalWindow(1900, "Mission Management", "Select a task:") local task_status = {} if taskWindow:getId() == 1900 then taskWindow:addButton(1, "Select") taskWindow:setDefaultEnterButton(1) taskWindow:addButton(2, "Cancel") taskWindow:setDefaultEscapeButton(2) for i = 1, #tasks do if getCreatureStorage(cid, tasks[i].questStarted) == 2 then task_status[i] = "[completed]" else if getCreatureStorage(cid, tasks[i].questStarted) == 1 then task_status[i] = "[" .. getCreatureStorage(cid, tasks[i].questStorage) .. "/" .. tasks[i].killsRequired .. "]" else if getCreatureStorage(cid, tasks[i].questStarted) < 1 then task_status[i] = tasks[i].killsRequired else task_status[i] = tasks[i].killsRequired .. " [unknown]" end end end if getCreatureStorage(cid, tasks[i].questStarted) == 1 and getCreatureStorage(cid, tasks[i].questStorage) >= tasks[i].killsRequired then taskWindow:addChoice(i, tasks[i].raceName .. " [click for reward]") else taskWindow:addChoice(i, tasks[i].raceName .. ", " .. task_status[i]) end end end taskWindow:sendToPlayer(cid) return true end Agora vamos até data\npc crie Victor.xml e adicione
<?xml version="1.0" encoding="UTF-8"?> <npc name="Victor" script="Victor.lua" walkinterval="2000" floorchange="0"> <health now="150" max="150" /> <look type="131" head="76" body="20" legs="116" feet="1" addons="1" /> <parameters> <parameter key="message_greet" value="Ola, eu posso te ajudar com algumas missões, e como recompensa te darei exp e direito a matar alguns bosses diga {task}"/> </parameters> </npc> agora vamos até scripts crie Victor.lua e adicione
local choose = {} 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 creatureSayCallback(cid, type, msg) if(not npcHandler:isFocused(cid)) then return false end local talkUser = NPCHANDLER_CONVBEHAVIOR == CONVERSATION_PRIVATE and 0 or cid if isInArray({"task", "tasks"}, msg:lower()) then selfSay("Here.", cid) taskNPCuid = getNpcCid() if getPlayerStorageValue(cid, 32150) < 0 then setPlayerStorageValue(cid, 32150, 0) end return sendTaskWindow(cid) end return true end npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) npcHandler:addModule(FocusModule:new())
Caso vocês queiram adicionar a recompensa no próprio sistema de task de vocês basta adicionar na recompensa a seguinte query.
db.query("UPDATE `accounts` SET `task_points` = `task_points` + " .. tasks[choiceId].rewards[i].values .. " WHERE `id` = " .. getPlayerAccountId(cid) .. ";") Pronto, terminamos.
Créditos: Jobs.
Tópico exclusivo para o TK.
-
Flavio S deu reputação a Snowsz em (Resolvido)[PEDIDO] Porta com requisitosEssa verificação:
if(item.uid == 2500 É totalmente desnecessária, só faz custar mais ao servidor, mesmo que seja pouco, de grão em grão a galinha enche o papo...
Não é necessário colocar () nisso, ficaria até melhor sem , e está faltando return true no final do script, para ele poder abrir a porta caso tenha o skill.
Também poderia fazer assim:
function onUse(cid, item, fromPosition, itemEx, toPosition) return getPlayerSkillLevel(cid, SKILL_SWORD) < 20 and doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You need 20 sword fighting to open this door.") or true end -
Flavio S deu reputação a dezon em Atualizar a pagina utilizando GETInteressante esse código, mas mesmo assim ainda contém uma vulnerabilidade, porque ele checa se há o arquivo .php e assim carrega ele.
Já usei muito nos meus sistemas dessa forma que você fez, mas já tive problemas, a melhor solução que eu desenvolvi foi assim:
<?php header("Content-Type: text/html; charset=UTF-8", true); $pagina = $_GET['pagina']; $extensao = '.php'; $items = array('index', 'teste', 'contato'); if( in_array($pagina, $items) && file_exists($pagina.$extensao) ) { // Ok, a gente inclui a página include_once $pagina.$extensao; } else { // Erro, ou damos a mensagem ou incluimos uma página padrão exit('A página solicitada não existe!'); } ?> Dessa forma ele checa se o item passado pelo GET está dentro do vetor predefinido por você e ainda assim checa se há o arquivo, dessa maneira, evitamos que o "hacker" force o sistema a incluir arquivos do servidor.
-
Flavio S deu reputação a Wakon em [TFS 0.4] Quest unica.Fala ai galerinha do Tk, estou trazendo hoje meu 1 script, não posso dizer que é 100% meu pois tive ajuda da lista de funções do Matheus e tirei a ideia do RadBr, então vou colocar 1 credito a eles.
O script é de uma quest unica que para acessa-la você deve clicar em uma placa no caso, você pode mudar para outro item se quiser!
Funciona da seguinte maneira:
O player clica na placa, se ele nunca tiver feito a quest e tiver o level necessario para faze-la ele é teleportado para posição inicial da quest, porém se ele já fez a quest ou não tem o level necessario para fazer ele é teleportado para o templo ou para a posição que você desejar !
Para adicionar você deve ir até data/actions/scripts, copiar e colar um arquivo .lua e renomear ele para questunica.lua, depois apague tudo dentro do arquivo e cole isso:
function onUse(cid, item, fromPos, itemEx, toPos) pos = {x = 160, y = 54, z = 7} -- Local da quest caso nunca tenha feito. pos2 = {x = 160, y = 56, z = 7} -- Local para teleportar, caso já tenha feito. local storage = 13909 -- Storage da placa, se for mudar não se esqueça de mudar também no script questunicabau.lua !! local plevel = 16 -- Level minimo para fazer a quest. if getPlayerStorageValue(cid,storage) == -1 then if getPlayerLevel(cid) >= plevel then doTeleportThing(cid,pos) doSendMagicEffect(toPos,2) -- Efeito ao teleportar para a quest, para ver mais efeitos diga /z e o numero do efeito, se quiser mudar é só alterar no valor 2 doSendMagicEffect(fromPos,2) else doPlayerSendTextMessage(cid,25,"Voce precisa ser level "..plevel.." para fazer essa quest.") end else doTeleportThing(cid,pos2) doPlayerSendCancel(cid, "Voce ja fez essa quest!") doSendMagicEffect(pos2,29) -- Efeito ao teleportar para fora da quest, para ver mais efeitos diga /z e o numero do efeito, se quiser mudar é só alterar no valor 2 doSendMagicEffect(fromPos,2) return 1 end end
Agora vá em data/actions e abra o actions.xml, depois adicione essa linha:
<action uniqueid="13909" script="questunica.lua"/> Então terminamos de adicionar a uniqueid que da acesso a quest, agora vamos adicionar o baú da quest.
Vá até data/actions/scripts, copiae e cole um arquivo .lua e renomeie ele para questunicabau.lua, depois apague tudo dentro do arquivo e cole isso:
function onUse(cid, item, frompos, item2, topos) storage = 13910 -- Storage do baú da quest. premio = 2393 -- ID do premio da quest. storageplaca = 13909 -- Storage da placa para entrar na quest. Não se esqueça de mudar nos 2 scripts, caso queira mudar. nome = "Demon Helmet" if item.uid == storage then if getPlayerStorageValue(cid,storage) == -1 then doPlayerSendTextMessage(cid,25,"You have found a "..nome..".") doPlayerAddItem(cid,2493,1) setPlayerStorageValue(cid,storage,1) setPlayerStorageValue(cid,storageplaca,1) else doPlayerSendTextMessage(cid,25,"The is empty.") return true end end end Agora vá em data/actions e abra o actions.xml, depois adicione essa linha:
<action uniqueid="13910" script="questunicabau.lua"/>
Agora para montar a quest no seu OT, você coloca o uniqueid 13909 na placa ou em outro objeto para teleportar o player até a quest e o uniqueid 13910 no baú no final da quest, assim quando ele clicar no baú não poderá fazer novamente a quest.
Bom é isso, espero que gostem do script, se tiver algo errado, algo faltando ou até mesmo algo que facilite o uso de outros membros, é só me dizer que eu tento arrumar.
Creditos:
RadBr 5% - Pela ideia da quest!
Matheus 10% - Pela lista de funções, sem ela não teria o script oakpsk.
-
Flavio S recebeu reputação de luanluciano93 em Atualizar a pagina utilizando GETOlá pessoal, estou aqui para resolver um probleminha que tenho encontrado principalmente no meu curso, então estou criando esse tópico para facilitar um pouco a vida dessas pessoas que estão boiando na maionese. É o seguinte:
Para facilitar um pouco nosso trabalho, utilizamos GET para obter o valor de uma váriavel na url para que possa abrir uma determinada pagina sem atualiza o site por completo.
O pessoal do meu curso está utilizando o GET dessa forma:
Código HTML: <?php if(isset($_GET['pagina']) == ' '){ // Se ?pagina= nao for definido nao faça nada, caso tenha um valor procura no switch esse valor e executa-o. }else{ $pagina = $_GET['pagina']; switch($pagina){ case 'home': include 'home.php'; break; default: echo 'pagina nao encontrada'; } } ?> Isso está errado ?
Não, isto não está errado, mas imagine o seguinte, você tem a pagina home,registro,download, e várias outras, ou seja, vc teria de adicionar uma por uma no switch() para que ele possa saber o que fazer com aquele valor.
Enfim, isso daria um problemão pra cabeça, então eu recomendo vocês fazerem o seguinte:
Código HTML: if(!isset($_GET['pagina']) == ' '){ //Se ?pagina= for diferente de não definido $abrir = $_GET['pagina']; // Abrir obtém seu valor ou seja se for ?pagina=home, $abrir passa a valer home $local = $abrir.'.php'; // $local = home.php if(file_exists($local)){ // Se home.php existir include $local; // inclui home.php }else{ // se não echo 'pagina não encontra'; // pagina não encontrada } } É basicamente a mesma coisa a única diferença é que ao invés dele procurar no switch() ele vai verificar se o arquivo existe file_exists(), se existir vai abrir ele, se não, mostrar uma mensagem de pagina não encontrada !
abrçs!!!
-
Flavio S recebeu reputação de Ceos em Atualizar a pagina utilizando GETOlá pessoal, estou aqui para resolver um probleminha que tenho encontrado principalmente no meu curso, então estou criando esse tópico para facilitar um pouco a vida dessas pessoas que estão boiando na maionese. É o seguinte:
Para facilitar um pouco nosso trabalho, utilizamos GET para obter o valor de uma váriavel na url para que possa abrir uma determinada pagina sem atualiza o site por completo.
O pessoal do meu curso está utilizando o GET dessa forma:
Código HTML: <?php if(isset($_GET['pagina']) == ' '){ // Se ?pagina= nao for definido nao faça nada, caso tenha um valor procura no switch esse valor e executa-o. }else{ $pagina = $_GET['pagina']; switch($pagina){ case 'home': include 'home.php'; break; default: echo 'pagina nao encontrada'; } } ?> Isso está errado ?
Não, isto não está errado, mas imagine o seguinte, você tem a pagina home,registro,download, e várias outras, ou seja, vc teria de adicionar uma por uma no switch() para que ele possa saber o que fazer com aquele valor.
Enfim, isso daria um problemão pra cabeça, então eu recomendo vocês fazerem o seguinte:
Código HTML: if(!isset($_GET['pagina']) == ' '){ //Se ?pagina= for diferente de não definido $abrir = $_GET['pagina']; // Abrir obtém seu valor ou seja se for ?pagina=home, $abrir passa a valer home $local = $abrir.'.php'; // $local = home.php if(file_exists($local)){ // Se home.php existir include $local; // inclui home.php }else{ // se não echo 'pagina não encontra'; // pagina não encontrada } } É basicamente a mesma coisa a única diferença é que ao invés dele procurar no switch() ele vai verificar se o arquivo existe file_exists(), se existir vai abrir ele, se não, mostrar uma mensagem de pagina não encontrada !
abrçs!!!
-
Flavio S recebeu reputação de Slaake em [TFS 1.x] /addplayersonline item, quantidadeScript simples mas pode ser útil, para os ot admin.
data/talkactions/scripts addplayersonline.lua :
function onSay(player, words, param) if not player:getGroup():getAccess() then return true end if player:getAccountType() < ACCOUNT_TYPE_GOD then return false end local v = param:split(",") if #v ~= 2 then player:sendCancelMessage("Insufficient parameters.") return false end local item, count = tonumber(v[1]), tonumber(v[2]) for _, pid in pairs(Game.getPlayers()) do pid:addItem(item, count) end broadcastMessage("A equipe acaba de mandar "..count.." "..ItemType(item):getName().." para todos os player online!", MESSAGE_STATUS_WARNING) return false end tag.XML :
<talkaction words="/addplayersonline" separator=" " script="addplayersonline.lua" /> -
Flavio S deu reputação a Tricoder em RPG - Rock Island (100% custom "Rookgaard")Tamanho: 271 KB
Categoria: Mapa.
Versão: 10.31
Créditos: Slec
Anexos: Scan | Download
Screenshot;
-
Flavio S deu reputação a Caronte em Lib 000-ConstOlá pessoal, venho mais uma vez trazer um tutorial simples, e tentar explicar tudo claramente, esse tutorial pode ficar grande dependendo do desenrolar dele, pois é um pack de tutoriais, então vou usar spoilers para ajudar na formatação do tópico.
Nota: as informações usadas abaixo, podem ser tanto usadas com o nome, quanto com o número, e podem ser encontradas na pasta lib no arquivo 000-const
https://pastebin.com/0FfPcg7y
line4
Coordenadas:
Tutorial feito e formatado por Caronte o + gato do fórum, avaliações do perfil são bem-vindas.
Explicando:
doMoveCreature(cid, direction): Serve para mover tanto o player quanto o monstro.
Combate:
Tutorial feito e formatado por Caronte o + gato do fórum, avaliações do perfil são bem-vindas.
Parâmetros de condição:
Condições:
Slots:
Tutorial feito e formatado por Caronte o + gato do fórum, avaliações do perfil são bem-vindas.
Participação: xWhiteWolf
Const_ani e Const_me:
Tutorial feito e formatado por Caronte o + gato do fórum, avaliações do perfil são bem-vindas.
Talktypes and message types:
[title][/title]
Tutoriais concluídos por ordem de formatação (podem ser alterados assim mesmo):
Coordenadas, e suas direções. Combat (ainda há coisas a serem adicionadas). Slots. CONST_ME and CONST_ANI
Os assuntos do tópico poderão se diminuídos ou aumentados de acordo com o desenrolar do tempo,
gostaria de apoio, e não me incomodaria se alguém se propusesse fazer algum tutorial, eles serão supervisionados por mim e formatados por mim, para serem postados neste tópico.
Esse tópico demorou e vai demorar muito para fazer
cada tutorial, então eu não me importo com um obrigado e REP+,
OBS.: Um obrigado vale bem mais do que um REP+
-
Flavio S recebeu reputação de Snowsz em Ponteiros em C/C++Estou estudando C/C++, e esse tutorial sobre ponteiros me tirou várias dúvidas e pensei em compartilhar ele com vocês.
Todo os créditos ficam a C0d3r__.
Audiência
Você tem dificuldades entendendo ponteiros? Tem problemas no uso de ponteiros? Até mesmo não tem menor idéia do que é um ponteiro? Se a resposta for SIM para uma das perguntas anteriores, então esse tutorial é para você, também se vc tiver uma idéia legal sobre ponteiros, quem sabe esse tutorial não pode aumentar o seu nàvel de conhecimento, então continue a lêr.
Requerimentos
Interesse em aprender, e um pouco de conhecimento sobre C ou C++ desenvolvido ou não. É necessario lêr as sessões do comeco ao fim sem pular nenhuma sessão pq o conhecimento no assunto de ponteiros sera construido sequencialmente, quero dizer uma sessão irí lhe dar o alicerce para a proxima sessão.
O que são ponteiros
Ponteiros são variaveis, isso mesmo um ponteiro é uma variavel, mas vc pode se perguntar: "oq é uma variavel?", a resposta seria, uma variavel é um tipo de dados que é armazenado na memoria do computador em um determinado endereço. Onde tipos de dados são como os inteiros, caracteres, números fracionarios, e o endereço é um número que representa a posiçao na memoria onde se encontra a variavel.
exemplo:
int MeuInt;
Como vc pode observar acima na declaracao de uma variavel em C, o int é o tipo da variavel que é inteiros, e o MeuInt é chamado de label, ou nome da variavel, onde internamente é associado ao nome da variavel o seu determinado endereço na memoria, "mas oq eu faco com o endereço e como obtenho?" com o endereco vc consegue referenciar a uma variavel, e pra se obter o endereco na programacao em C existe o operador &, que retorna o endereço na memoria de uma variavel. "Operador, que isso?" "Quem vai operar quem?" um operador da linguaguem C ou C++ é uma palavra-chave, que faz uma operacao então a operacao que o operador & faz é simplesmente retornar o endereço de uma variavel, vejamos:
#include <stdio> #include <stdlib> int main(void) { int MeuInteiro = 0; /* Declara um inteiro */ /* Usa o %p ou specificador de formato p para mostrar o endereço em hexadecimal da variavel que estara na lista de argumento de printf() onde temos &MeuInteiro */ printf("%#p", &MeuInteiro); /* Pausa */ system("pause"); return 0; }
Compilando o codigo acima em um compilador de C ou C++ vc vera que o programa irí mostrar na tela o endereço da variavel MeuInteiro, onde o operador & foi usado para se obter o endereço.
também se vc não sabe, números hexadecimais são números de base 16, a base 16 são 16 possiveis números e letras para um digito, os números são: de 0 a 9, e de A a F as letras. Se vc contar da 16, então o valor 0xABCD e um número hexadecimal, veja que cada digito, 4 digitos "ABCD" tem uma letra. também no exemplo acima foi usado o modificador de formato # antes de p que e para dizer a printf() que coloque o prefixo 0x defrente do número hexadecimal, pq 0x representa números hexadecimais.
Então logo depois que revisamos oq é uma variavel, e aprendemos que todas variaveis tem um endereco que e geralmente representado em hexadecimal, posso lhe dizer que um ponteiro é uma variavel que contém o endereço de uma outra variavel na memoria.
Da mesma forma que variaveis normais contem um valor, digamos:
int Inteiro = 10;
E dado a variavel Inteiro o valor 10.
Ponteiros também tem um valor, que e um endereço na memoria de outra variavel.
Também como toda variavel tem um endereço, o ponteiro também tem um endereço de localizacao na memoria.
#include <stdio> #include <stdlib> int main(void) { int MeuInteiro = 0; /* Declara um inteiro */ int *MeuPonteiro = &MeuInteiro; /* Declara um ponteiro para um inteiro que esta recebendo o endereço de um inteiro */ /* Acessando o conteudo de um ponteiro, ou seja 5 e copiado para MeuInteiro */ *MeuPonteiro = 5; /* Mostra o valor de MeuInteiro */ printf("MeuInteiro = %d\n", MeuInteiro); /* pausa */ system("pause"); return 0; } Como vc pode observar acima e usado o operador * para se acessar oq o ponteiro esta apontando, ou seja: na variavel que MeuPonteiro aponta copie o valor 5, então e mostrado o valor da variavel MeuInteiro que foi acessada apartir de MeuPonteiro.
Pra vc ver que ponteiros também possuem seu endereço na memoria compile o codigo fonte abaixo:
#include <stdio> #include <stdlib> int main(void) { int MeuInteiro = 0; /* Declara um inteiro */ int *MeuPonteiro = &MeuInteiro; /* Declara um ponteiro para um inteiro que esta recebendo o endereço de um inteiro */ /* Acessando o conteudo de um ponteiro, ou seja 5 e copiado para MeuInteiro */ *MeuPonteiro = 5; /* Mostra o endereço do ponteiro */ printf("endereço do ponteiro = %#p\n", &MeuPonteiro); /* O que o ponteiro tem (Um endereço pra um inteiro) */ printf("MeuPonteiro = %#p\n", MeuPonteiro); /* Mostre MeuInteiro atravez do ponteiro */ printf("MeuInteiro = %d\n", *MeuPonteiro); /* pausa */ system("pause"); return 0; } Como vc pode observar com o operador * acessamos oq o ponteiro esta apontando, no caso acima acessamos a variavel MeuInteiro, onde usando o operador de copia = e copiado um valor atravez do ponteiro para a variavel, e também usando o *MeuPonteiro como na linha:
printf("MeuInteiro = %d\n", *MeuPonteiro);
e mostrado oq MeuInteiro possui atravez de MeuPonteiro.
Vale apena salientar que se o operador * não e usado em um ponteiro o valor do ponteiro e acessado que e obvio um endereço, vejamos:
printf("MeuPonteiro = %#p\n", MeuPonteiro);
E mostrado o endereço de MeuInteiro que esta dentro da variavel MeuPonteiro.
também aplicando o operador & ao ponteiro pegamos o seu endereço de localizacao na memoria, vejamos:
printf("endereço do ponteiro = %#p\n", &MeuPonteiro);
você Sabia: desde que ponteiros tem enderecos, e possivel se criar um ponteiro para um ponteiro, ou uma variavel que possui o endereço de outro ponteiro.
Para que servem os ponteiros
Os ponteiros servem para adicionar flexibilidade na programacao, onde apartir de um ponteiro e possivel se acessar variaveis pra lêr oq as mesmas contem ou pra se modificar oq as mesmas contem.
? Ponteiros são usados com memoria dinamica, com arrays, com variaveis, ou com estruturas. Onde um ponteiro pode conter um determinado endereço de um valor dentro de um grupo de memoria, apartir dai usando aritimetica de ponteiros, e possivel se andar por absolutamente todos os bytes de um grupo de memoria, indepedente do tipo de dados. Funcoes de manipulacao de string abusam do uso de parametros que são ponteiros, simplesmente pq e impossivel fazer uma manipulacao de uma variavel de dentro de uma funcao e modificar a variavel se ela foi passada como parametro sem que um ponteiro pra variavel seja usado; Veremos mais detalhes sobre isso na sessão de funcoes.
? Ponteiros são usados com funcoes de varias formas: funcoes que tem parametros que são ponteiros, funcoes que retornam um ponteiro, ponteiro para funcoes.
Todas essas formas de ponteiros seram analizadas nas sessões a seguir.
Ponteiros e memoria dinamica
Memoria dinamica e toda memoria alocada dinamicamente ou seja na hora de execucao do programa de acordo com algum evento que satisfaca a necessidade de variacao, exemplo:
Em um programa de redes, cliente/servidor, um cliente pode requisitar(pedir) informacoes ao servidor usando bytes, o mesmo que dados, que são chamados de cabecalhos, então imagine a seguinte situacao: um cliente envia um cabecalho que define o tamanho da requisicao de dados que irí seguir ou seja o tamanho dos dados, o tamanho que e enviado inicialmente pelo cliente seria uma variavel inteiro, que ira dizer ao servidor a quantidade de bytes o servidor deve alocar para se guardar o requisito de informacao, onde essa quantidade de bytes varia. O servidor quando recebe esse tamanho que pode ser variado, aloca memoria no lado do servidor de acordo com esse tamanho de uma forma dinamica ao invez de constante como seria no caso de uma declaracao de uma variavel.
Onde o ponteiro entra em acao? O ponteiro e utilizado pra apontar para o inicio da memoria recem alocada; Funcoes como malloc(), calloc(), realloc(), são funcoes da livraria padrao da linguaguem C que retornam ponteiros.
também os operadores new e delete em C++ são exemplos que alocam memoria e retornam um ponteiro.
Vejamos um exemplo em C:
#include <stdio> #include <stdlib> int main(void) { /* Declara um ponteiro pra um inteiro */ int *p = NULL; /* Usa malloc pra alocar memoria */ p = malloc(sizeof(int)); /* Abaixo se p == NULL memoria não foi alocada */ /* Pq 0 se torna 1 com o ! entao o bloco do if e executado */ if (!p) { fputs("Erro: sem memoria disponivel!", stderr); return 1; } /* Acesse memoria dinamica */ *p = 1234; /* Mostre memoria dinamica */ printf("%i\n", *p); system("pause"); return 0; } Compile o codigo acima, e vera como e facil alocar memoria dinamica e usar o ponteiro pra essa memoria.
Observe que no codigo acima p e inicializado para NULL, onde NULL e um define dentro de stdlib.h que esta dessa forma:
#define NULL (void *)0
O NULL e o mesmo que 0 internamente, o casting (void *) siguinifica que 0 pode ser copiado para qualquer tipo de ponteiro usando o operador de atribuicao =.
E importante SEMPRE inicializar os nossos ponteiros para NULL e depois checar depois da rotina de alocacao de memoria se o ponteiro aponta pra algo diferente de NULL, senao problemas graves em projetos podem ocorrer onde o programa apenas e encerrado pelo sistema operacional pq o mesmo tentou manipular memoria protegida, lembra dos Read access violation, Write access violation, isso, esses 2 erros podem ser evitados inicializando os ponteiros para NULL, e sempre que vc for manipular os ponteiros verifique antes, se o mesmo realmente aponta pra memoria valida, memoria diferente de NULL e liberada para leitura/escrita pelo sistema.
Ponteiros e arrays
O que e uma array? Uma array e um grupo de variaveis em sequencia, exemplo:
char MinhaArray[50];
A declaracao acima aloca uma array chamada MinhaArray de tamanho 50, em outras palavras um grupo de 50 chars e alocado.
Existe um relacionamento entre ponteiros e arrays, pelo simples fato, sabemos que um ponteiro e uma variavel que aponta pra outra variavel, ja uma array e um grupo de variaveis no qual o NOME da array "MinhaArray" aponta pro primeiro item ou elemento da array. vejamos:
#include <stdio> #include <stdlib> int main(void) { /* Grupo de 50 chars */ char MinhaArray[50]; /* Desde que MinhaArray aponta pro primeiro elemento podemos usar o operador * e acessar o primeiro elemento */ *MinhaArray = 10; /* Agora conferimos */ printf("Primeiro elemento = %i\n", *MinhaArray); /* Comprovamos */ printf("MinhaArray aponta pra = %#X\n", MinhaArray); system("pause"); return 0; } não confunda! apesar de existir um relacionamento com ponteiros o nome da array não e um ponteiro, porem por ser associado o nome ao endereço do primeiro elemento, onde o nome e simplesmente um label linhas como:
*MinhaArray = 10;
Se tornam possivel, por que * funciona da mesma forma com nomes de array como com nomes de ponteiros.
No entanto linhas como:
*MinhaArray++;
ou
*++MinhaArray;
não são permitidos, por que MinhaArray não possui um espaco unico na memoria, então:
MinhaArray += sizeof(TIPO_DE_OBJETO);
ou
MinhaArray = MinhaArray + sizeof(TIPO_DE_OBJETO);
Onde tipo de objeto pode ser qualquer tipo suportado, não são permitidos; Observe que desde que MinhaArray não possui o seu espaco na memoria não e possivel assinar a mesma valores.
O operador ++ faz a operacao de incrementacao por 1, então:
x++;
e o mesmo que:
x = x + 1;
e
++x;
também e:
x = x +1;
Logo desde que não podemos salvar a posiçao de um determinado elemento dentro do nome da array, usamos ponteiros, logo observe:
char MinhaArray[50];
char *MeuPonteiro;
MeuPonteiro = MinhaArray;
E dado ao MeuPonteiro o endereço do primeiro elemento da array MinhaArray. Declarando um ponteiro temos um espaco na memoria, onde podemos manter o endereço de um determinado byte, no caso de um char, dentro da array, dessa forma podemos andar ou pecorrer os items da array; Vejamos:
#include <stdio> #include <stdlib> int main(void) { /* O grupo de bytes */ char MinhaArray[50]; /* Coloca o endereço do primeiro elemento da array dentro de MeuPonteiro */ char *MeuPonteiro = MinhaArray; /* Mantem a posiçao atual e evita que ultrapassemos o tamanho da array que e 50. */ int Count = 0; /* Esse loop irí pecorrer a array de chars de 0 a 49 que são 50 elementos e irí copiar o valor atual de Count + 1 dentro de um determinado elemento usando ponteiro. */ while (Count < 50) { *(MeuPonteiro + Count) = Count + 1; Count++; } /* Reseta Count */ Count = 0; /* O loop abaixo irí pecorrer a array usando o ponteiro e irí mostrar na tela oq a array contem. */ while (Count < 50) { printf("%d ", *(MeuPonteiro + Count)); Count++; } system("pause"); return 0; } A linha abaixo faz o seguinte:
*(MeuPonteiro + Count) = Count + 1;
O valor de MeuPonteiro que e um endereço e obtido depois e somado com Count, e depois o operador * irí permitir que acessemos esse endereço, onde e copiado usando o operador =, Count + 1.
A linha acima poderia ser substituida por:
*MeuPonteiro++ = Count + 1;
E o ponteiro seria resetado assim:
MeuPonteiro = MeuPonteiro - 50;
Onde MeuPonteiro++ e o mesmo que: MeuPonteiro = MeuPonteiro + 1; dessa forma pecorremos os bytes da array incremetando o endereço do primeiro byte que faz com que o ponteiro aponte pro segundo byte mas note que MeuPonteiro depois da expressao irí apontar para o endereço + 1, por que MeuPonteiro++ e o mesmo que MeuPonteiro = MeuPonteiro + 1, observe o operador =, por isso e necessario resetar o ponteiro, se vc deseja passar pelos bytes iniciais, porque em outras palavras o operador ++ modifica o seu operando; Um exemplo mais simples segue:
#include <stdio> #include <stdlib> int main(void) { /* Grupo de bytes inicializado, e terminado por 0 */ char MinhaString[] = "Ola mundo!"; /* Coloca o endereço do primeiro elemento da array em MeuPonteiro */ char *MeuPonteiro = MinhaString; /* Enquanto o byte apontado por MeuPonteiro não e 0 */ while (*MeuPonteiro != '\0') { /* Mostre o determinado byte */ putchar(*MeuPonteiro); /* Depois que mostrou o byte aponte pro proximo */ MeuPonteiro++; } /* Nova linha */ putchar('\n'); system("pause"); return 0; } Compile o exemplo acima e vera que uma string e mostrada na tela usando ponteiros.
Se vc não esta lembrado uma string e uma array de characteres terminada por um 0. Quando vc cria uma string:
char MinhaString[] = "Ola mundo!"; o 0 e colocado depois do sinal de !. Observe também que na linha:
MeuPonteiro++
Acontece:
MuPonteiro = MeuPonteiro + sizeof(TIPO_DE_OBJETO);
Dessa forma apontamos pro proximo byte da string.
Vale apena salientar que MeuPonteiro++ pode variar de acordo com o tipo de ponteiro, se for um ponteiro para character então e somado sizeof(char) ao endereço, se for um ponteiro pra um inteiro e somado o tamanho do inteiro, sizeof(int), se for um ponteiro para um float e somado sizeof(float), e ser for um ponteiro para um double e somado sizeof(double).
Utilizando operadores aritimeticos como +, -, com ponteiros e chamado de aritimetica com ponteiros que de acordo com o tipo de ponteiro tem um efeito diferente, observe o exemplo abaixo:
#include <stdio> #include <stdlib> int main(void) { /* Declaracao de uma array de inteiros Smile */ int MinhaArrayDeInteiros[50]; /* Nosso ponteiro apontando pro inicio da array */ int *MeuPonteiroPraInteiros = MinhaArrayDeInteiros; /* Mostra oq o ponteiro contem */ printf("endereço que ponteiro contem = %#X\n", MeuPonteiroPraInteiros); /* Aqui incremente o endereço de MeuPonteiroPraInteiros por sizeof(int) ou seja o endereço do ponteiro inicial e somando por sizeof(int), e não por 1, pq não estamos lidando com 1 byte; Assim apontamos pro proximo inteiro, e acessamos o mesmo colocando 10 nele. */ *++MeuPonteiroPraInteiros = 10; /* Mostra oq o ponteiro no momento contem */ printf("Agora endereço que ponteiro contem = %#X\n", MeuPonteiroPraInteiros); /* Mostra a diferenca do endereço final em relacao ao endereço inicial */ printf("Diferenca = %d\n", (int)MeuPonteiroPraInteiros - (int)MinhaArrayDeInteiros); /* Usa indexacao [] para se acessa minha array que foi modificada apartir do ponteiro*/ printf("%d\n", MinhaArrayDeInteiros[1]); system("pause"); return 0; } sizeof() se vc estiver esquecido retorna o tamanho de um tipo de dado.
E possivel tambem se ter arrays de ponteiros ou seja uma array onde todos os seus elementos sao ponteiros, vejamos:
char *MinhaArraydePonteiros[10];
Na declaracao acima uma array de 10 ponteiros pra characteres e criada, ou seja uma array de 10 elementos que sao enderecos de memoria.
O uso de uma array de ponteiro e bem eficaz e dinamico, muitas vezes precisamos de mais de 1 ponteiro em nossos programas para apontar para variaveis que muitas vezes nao sabemos oq seram ou quantas seram, observemos o caso de um suposto programa editor de texto; Sabemos que a cada caractere que o usuario tecla esse caractere deve ser gravado em um buffer ou em uma alocacao de memoria, entao digamos que implementamos uma funcao que se obtenha uma sequencia de caracteres, quando o usuario pressiona enter sabemos que temos uma linha, em um programa de texto haveram varias linhas, entao entra-se em questao, onde guardar essas linhas, e como se ter controle de todas essas linhas, se a cada chamada de uma suposta funcao EntreLinha() 1 buffer seria preenchido, onde estaria esse buffer? voce poderia fazer uma array multidimensional porem memoria seria altamente disperdicada se o usuario precisa-se somente de umas 10 linhas e voce aloca-se espaco para 1000, por isso e usado uma array de ponteiros para charactere, lembra da sessao de memoria dinamica e ponteiros, o dinamismo do ponteiro resolve o problema, EntreLinha() retornaria um ponteiro para uma linha que foi alocada na memoria dinamicamente e esse ponteiro seria copiado para a array de ponteiros e um inteiro de posicao da array seria incrementado, nesse caso por simplicidade e tambem pq como tudo e limitado a array de ponteiros teria de ter um tamanho predeterminado e limitado digamos 1000 linhas, entao imagine que em um determinado momento o usuario do programa precisa procurar por uma string dentro das linhas, simplesmente seria pecorrida a array de ponteiros acessando-se a memoria em que os ponteiros aponta; Se nao fosse com uma array de ponteiros como ordenaria-mos as linhas sequencialmente, assim?
#define TAMANHO_DA_LINHA 200
buf1[TAMANHO_DA_LINHA]
buf2[TAMANHO_DA_LINHA]
buf3[TAMANHO_DA_LINHA]
...
...
...
Com certeza nao!
Talvez assim?
#define MAXIMO_DE_LINHAS 1000
buf[MAXIMO_DE_LINHAS][TAMANHO_DA_LINHA]
Com certeza nao!
Voce ver no procedimento acima array multidimensional, seria alocado MAXIMO_DE_LINHAS(1000) * TAMANHO_DA_LINHA(200) que no caso seria 200,000 bytes que e disperdicio desde que vc nao sabe se o usuario somente precisa de 10 linhas ou seja 10 * 200 que e igual a 2,000 bytes.
Entao a solucao e:
char *MinhaArraydePonteiros[MAXIMO_DE_LINHAS];
Pq ai memoria e alocada de acordo com a necessidade de linhas, onde custariamos espaco inicialmente somente para os ponteiros ou sizeof(char *) * 1,000 que e igual a 4,000 bytes, e quando 10 linhas fossem tecladas, 10 * 200 teriamos 2,000, ao todo estariamos tomando 4,000 + 2,000 que e 6,000 bytes que comparado com a array multidimensional 200,000 bytes e absurdamente mais flexivel.
Observe um exemplo:
Leia o exemplo abaixo atenciosamente, e compile.
#include <stdio> /* Para IO*/ #include <stdlib> /* Para rotinas em geral */ #include <time> /* Calendario */ /* Definicao do limite de linhas */ #define NUMERO_DE_LINHAS 1000 /* Definicao do tamanho de uma linha */ #define TAMANHO_DA_LINHA 200 /* Definicao de uma string de error */ #define ERR_SEM_MEMORIA "Erro: sem memoria suficiente." /* A definicao de uma Array de Ponteiros para characteres observe a sintaxe */ char *Linhas[NUMERO_DE_LINHAS] = {NULL}; /* Inicializada pra NULL */ /* Index de linha, representa a linha atual dentro de Linhas.*/ int NumLinhas = 0; /* Mostra sugestoes sobre um texto que voce possa escrever */ void MostreUmaSugestao(void); /* Entrada de uma linha pelo teclado */ char *EntreLinha(void); /* Mostra todas as linhas em LinhasParam na quantidade exata */ void MostreLinhas(char *LinhasParam[], int QuantasLinhas); /* Limpa todas as linhas em LinhasParam na quantidade exata */ void LimpeLinhas(char *LinhasParam[], int QuantasLinhas); /* Funcao inicial */ int main(void) { /* Mostra um titulo de programa amigavel */ puts("Usuario(a), bem vindo ao editor de texto," " para terminar digite '.' ponto, no comeco de uma" " linha e pressione [ENTER]."); puts(""); /* Mostra uma sugestao, veja declaracao da funcao logo abaixo */ MostreUmaSugestao(); /* Enquanto nao passamos do limite de linhas */ while (NumLinhas < NUMERO_DE_LINHAS) { /* EntreLinha() retorna um ponteiro para uma linha para dentro de Linhas */ Linhas[NumLinhas] = EntreLinha(); /* Se o primeiro charactere de Linhas em uma determinada linha for . saia */ if (Linhas[NumLinhas][0] == '.') break; /* Proxima linha */ NumLinhas++; } puts(""); printf("Voce escreveu %d linha(as).\n", NumLinhas); puts("Mostrando toda(as) a(as) linha(as)..."); puts(""); /* Declaracao abaixo */ MostreLinhas(Linhas, NumLinhas); /* Declaracao abaixo */ LimpeLinhas(Linhas, NumLinhas); puts("O fim."); puts(""); system("PAUSE"); return 0; } /* Mostra uma sugestao declaracao */ void MostreUmaSugestao() { /* Todas as sugestoes */ /* Observe que Sugestoes, abaixo e uma array multidimensional de 2 dimensoes, inicializada com todas as possiveis sugestoes, saiba tambem que e alocado em bytes 10 * 60 = 600 bytes. */ char Sugestoes[10][60] = { "Historia da sua vida", "Melhor dia da sua vida", "Sua primeira vez", "Pior dia da sua vida", "Um fato traumatico", "Um objetivo a ser alcancado para o futuro", "Relacionamento familiar", "Melhores amigos(as)", "Ponteiros", "Arrays de ponteiros" }; /* Numero que representa a data e hora do sistema */ time_t t; puts("Escreva sobre: "); /* Inicializa a funcao rand() para pegar uma sugestao aleatoriamente */ srand(time(&t)); /* Pega uma sugestao aleatoriamente */ printf("%s.\n\n", Sugestoes[rand() % 10]); } /* Entra uma linha pelo teclado */ char *EntreLinha(void) { /* Esse buf e temporario ira segura a linha por um momento */ char Buf[TAMANHO_DA_LINHA]; /* Esse e um ponteiro para a linha que sera alocada */ char *Linha = NULL; /* Abaixo Pega uma linha para dentro de buf, note fgets() coloca '\n' que representa uma nova linha, dentro de buf. */ fgets(Buf, TAMANHO_DA_LINHA, stdin); /* Abaixo e alocado memoria para Linha de acordo com o tamanho de "caracteres" em Buf. strlen(Buf) + 1 + 1 e necessario para se reservar espaco para o NULL. */ Linha = (char *)malloc((strlen(Buf) + 1) * sizeof(char)); /* Alocou memoria ok? senao mostre erro, e saia. */ if (!Linha) { puts(ERR_SEM_MEMORIA); exit(EXIT_FAILURE); } /* Copie Buf para dentro da Memoria alocada apontada por Linha */ strcpy(Linha, Buf); /* Retorne um ponteiro para a memoria alocada para a linha que e copiado para dentro da array de ponteiro de caracteres depois. */ return Linha; } /* Mostre linhas no console */ void MostreLinhas(char *LinhasParam[], int QuantasLinhas) { int i; /* Observe que LinhasParam[x] retorna um endereco para uma linha */ for (i = 0; i < QuantasLinhas; i++) if (LinhasParam[i]) /* Nao pode ser NULL */ printf(LinhasParam[i]); /* E diferente de NULL acesse endereco */ } /* Libera memoria alocada para as linhas */ void LimpeLinhas(char *LinhasParam[], int QuantasLinhas) { int i; /* Observe que LinhasParam[x] retorna um endereco para uma linha */ for (i = 0; i <QuantasLinhas> ou operador seta, vejamos: PonteiroPraMinhaStruct = &InstanciaMinhaStruct; PonteiroPraMinhaStruct -> Campo1 = 10; printf("%i\n", PonteiroPraMinhaStruct -> Campo1); Observe como o operador -> e usado para acessar os campos de uma estrutura, também e possivel utilizar a seguinte sintaxe:
(*PonteiroPraMinhaStruct).Campo1;
Onde os parenteses são necessarios para com oq a estrutura seja acessada apartir do ponteiro primeiro, depois o operador . e aplicado e Campo1 pode ser acessado dentro da estrutura apontada por PonteiroPraMinhaStruct.
Vejamos um exemplo:
#include <stdio> #include <stdlib> int main(void) { /* Declara uma struct dentro de main */ struct MinhaStruct { int Campo1; int Campo2; }; /* Inicializa a struct na memoria */ struct MinhaStruct InstanciaMinhaStruct; /* Declara um ponteiro para uma estrutura */ struct MinhaStruct *PonteiroPraMinhaStruct; /* Ponteiro pra estrutura aponta pra instancia na memoria */ PonteiroPraMinhaStruct = &InstanciaMinhaStruct; /* Acesse o campo1 usando -> */ PonteiroPraMinhaStruct -> Campo1 = 10; /* Acesse o campo1 pra mostrar na tela */ printf("%i\n", PonteiroPraMinhaStruct -> Campo1); /* Acesse o campo2 usando sintaxe normal de ponteiros */ /* Note a necessidade dos parenteses por causa que ponto tem precedencia maior */ (*PonteiroPraMinhaStruct).Campo2 = 20; /* Acesse o campo2 pra mostrar na tela */ printf("%i\n", (*PonteiroPraMinhaStruct).Campo2); system("pause"); return 0; } não e facil usar ponteiros com estruturas? Smile não tem segredo.
Ponteiros e parametros de funcoes
Muitas vezes em nossos programas precisamos passar parametros para uma funcao, se vc não sabe oq e uma funcao ou não esta tao confiante aqui vai uma revisao:
Tipo-de-retorno Nome-da-funcao(Tipo-de-parametro Nome-do-parametro, ...);
Acima o formato de uma funcao em C/C++ o Tipo-de-retorno e oq a funcao retorna podendo ser qualquer dos tipos suportados na linguaguem C/C++, o Nome-da-funcao vc escolhe, e o Tipo-de-parametro Nome-do-parametro, e a declaracao de um parametro para uso dentro da funcao, exemplo:
void Tabuada(int De, int Ate);
Seria uma funcao que retorna nada(void) chamada Tabuada e que pega 2 parametros o inteiro De, e o inteiro Ate, onde qualquer linha de codigo chamando a funcao passara os parametros por valor, ou seja valores seram passados nos dois parametros ou variaveis que contenham um valor que seja do mesmo tipo excluindo ponteiros.
então oq acontece se eu fizer:
Tabuada(1, 10);
Estaria passando os valores que programaticamente e chamado: Parametros passados por valor.
ou
int x = 1;
int y = 10;
Tabuada(x, y);
Seria a mesma coisa: Parametros passados por valor.
Quando um parametro e passado por valor, e feita uma copia do mesmo na stack, a stack e um lugar onde as variaveis do seu programa em C/C++ que não são globais, ficam armazenadas. então essa copia do valor fica na stack e não tem nenhum relacionamento com as variaveis x, e y fora da funcao, exemplo:
#include <stdio> #include <stdlib> /* A funcao exemplo pega 2 parametros inteiros. E depois pras respectivas copias de a e b que foram passadas pra funcao que estao na stack e escrito 10 e 90, então se 10 e 90 e escrito para as copias as variaveis que foram passadas por valor não são afetadas, somente as copias. */ void Exemplo(int a, int { a = 10; b = 90; } int main(void) { int x = 1, y = 2; /* Chama a funcao Exemplo() no qual e feita uma copia de x e y na stack. */ Exemplo(x, y); /* x continua 1 e y continua 2 */ printf("X = %d, Y = %d\n", x, y); system("pause"); return 0; } Então aqui e onde ponteiros entram em acao, e utilizado ponteiros para se modificar o valor de variaveis de dentro de uma funcao!!!
Ou seja, desde que, quando chamamos uma funcao passando parametros por valor, copias dos valores são feitas exclusivas para a funcao na stack, então se vc modifica o parametro da funcao vc não afeta as variaveis que foram usadas para se passar pra funcao, mas sim as copias que foram feitas automaticamente que estao na stack, então as variaveis que foram usadas pra se passar pra funcao ficam intocaveis, a solucao para esse problema: variaveis intocaveis, e o uso de ponteiros.
Vejamos:
#include <stdio> #include <stdlib> /* A funcao exemplo pega 2 ponteiros pra inteiros. E depois atravez dos ponteiros e acessado as respectivas variaveis que são passadas por referencia, ou seja os enderecos das variaveis são passados, então os valores 10 e 90 são escritos diretamente. */ void Exemplo(int *a, int * { *a = 10; *b = 90; } int main(void) { int x = 1, y = 2; /* Chama a funcao Exemplo() no qual e feita uma copia dos enderecos x e y na stack. */ Exemplo(&x, &y); /* X foi modificado e Y também */ printf("X = %d, Y = %d\n", x, y); system("pause"); return 0; } Se vc compilar o exemplo acima vera que x e y, variaveis dentro de main() são modificadas pela funcao Exemplo() que recebe o endereço das variaveis, que e chamado de: Parametros passados por referencia.
Lembra de:
scanf("%c", &MeuChar);
Isso mesmo e necessario uma chamada por referencia para com que a variavel MeuChar possa ser acessada por scanf; Onde o endereço da variavel e passado pra funcao e a mesma modifica a variavel, se voce nao passar o endereco, scanf() pegara o valor de MeuChar pensando que o mesmo e um endereco, no qual nao e, e scanf() tentara copiar um caractere para um espaco de memoria que possa estar protegido, e o sistema abortara o programa com erro de write access violation.
Isso vale para qualquer variavel que vc deseja modificar de dentro de uma funcao, arrays, estruturas, etc.
Observe o exemplo abaixo:
#include <stdio> #include <stdlib> /* Essa funcao troca o valor em x pelo de y */ void Troca(int x, int y) { int temp; temp = x; /* Guarda x*/ x = y; /* Troca por y */ y = temp; /* Troca por x */ printf("copia de x = %d e copia de y = %d\n", x, y); } int main(void) { int x, y; x = 10; y = 20; puts("x e y inicial: "); printf("x = %d e y = %d\n", x, y); /* Parametros passados por valor */ Troca(x, y); /* Continua o mesmo */ puts("Dentro de main:"); printf("x = %d e y = %d\n", x, y); system("pause"); return 0; } Analizando a chamada da funcao Troca(x, y), parametros sao passados por valor, oq siguinifica que de dentro da funcao nao ha como se referenciar as variaveis que foram declaradas dentro de main, entao siguinifica que apesar de Troca() trocar os valores, esses valores seram trocados usando as copias de x e y que foram feitas que estao na stack, por tanto quando a funcao retorna, x e y dentro de main continuam a mesma coisa.
Observe o exemplo abaixo:
#include <stdio> #include <stdlib> /* Essa funcao troca o valor em x pelo de y */ void Troca(int *x, int *y) { int temp; /* Observe o uso do operador * para acessar as variaveis */ temp = *x; /* Guarda x */ *x = *y; /* Troca por y */ *y = temp; /* Troca por x */ } int main(void) { int x, y; x = 10; y = 20; puts("x e y inicial: "); printf("x = %d e y = %d\n", x, y); /* Parametros passados por referencia */ Troca(&x, &y); /* Troca() modifica */ puts("Dentro de main:"); printf("x = %d e y = %d\n", x, y); system("pause"); return 0; } Chamando Troca() com parametros passados por referencia, e dado a funcao os enderecos das variaveis aonde se encontram os dados dessa forma de dentro da funcao e possivel se acessar esses dados, entao as variaveis de dentro de main() sao modificadas.
Funcoes que retornam um ponteiro
Funcoes que retornam um ponteiro são funcoes que retornam o endereço em memoria de uma variavel dessa forma e possivel manipular a variavel apartir do ponteiro, vejamos o exemplo:
#include <stdio> #include <stdlib> #include <string> /* Para usar strupr() */ /* A funcao abaixo pega 1 ponteiro pra um char então a funcao strupr() e chamada passando o parametro Str de StrMaiuscula(), e o retorno e um ponteiro pra um caractere em letra maiuscula que e retornado da strupr(). */ char *StrMaiuscula(char *Str) { return strupr(Str); } int main(void) { char String[] = "minha string Smile"; /* Chama a funcao StrMaiuscula() passando a string String como parametro depois printf() e chamado, desde que StrMaiuscula retorna o endereço de String o uso direto como abaixo e possivel. */ printf("%s\n", StrMaiuscula(String)); system("pause"); return 0; } Como vc pode observar strupr() retorna um ponteiro pra um char por isso:
return strupr(Str);
E aceitavel. Pq estamos retornando oq strupr() retornou um ponteiro para um caractere.
também e necessario lembrar que String, o nome da array e um label que associa o nome String a um endereço, e esse endereço e o endereço do primeiro caractere na memoria, por isso vc não ve o operador & antes de String nas chamadas de funcao, simplesmente pq String ja representa o endereço do primeiro elemento da array, no entanto &String[0] também e possivel.
Ponteiro pra funcoes
Se vc não sabe e possivel se declarar um ponteiro pra uma funcao, da seguinte forma:
Tipo-de-retorno-da-funcao (*Nome-do-ponteiro-pra-funcao)(Tipo-de-parametro Nome-de-parametro, ...);
Logo um ponteiro pra uma funcao que retorne um inteiro e pega nada seria:
int (*PonteiroPraFuncao)(void);
um Ponteiro pra uma funcao que retorna nada e pega um ponteiro pra um inteiro seria:
void (*PonteiroPraFuncao)(int *);
Quando obtemos um ponteiro apenas fazemos o mesmo apontar para o endereço de algo, nesse caso o endereço de uma funcao.
Para se obter o endereço de uma funcao e usado o nome da funcao ou label, o operador & não e necessario, e ilegal, vejamos:
void (*PonteiroPraFuncao)(int *);
PonteiroPraFuncao = NomeDaMinhaFuncao;
Dessa forma podemos chamar uma funcao apartir de seu ponteiro, observe:
int Inteiro;
(*PonteiroPraFuncao)(&Inteiro);
Acima e chamada a funcao void NomeDaMinhaFuncao(int *x) apartir do ponteiro pra funcao, onde parametros são passados.
Exemplo:
#include <stdio> #include <stdlib> /* Funcao que retorna nada e pega um ponteiro para um inteiro */ void Funcao(int *PonteiroInt) { /* O mesmo que *PonteiroInt = (*PonteiroInt) * 2 */ *PonteiroInt *= 2; } int main(int argc, char *argv[]) { /* Declara uma variavel x */ int x = 10; /* Declara um ponteiro para uma funcao que retorne nada e pega int * */ void (*PonteiroPraFuncao)(int *); /* Faz com oq PonteiroPraFuncao aponte pra Funcao */ PonteiroPraFuncao = Funcao; /* Chama funca(&x) apartir de PonteiroPraFuncao */ (*PonteiroPraFuncao)(&x); /* x = 20 */ printf("x = %d\n", x); system("PAUSE"); return 0; } Ponteiros para ponteiros
Lembra quando escrevi que ponteiros sao variaveis? Toda variavel possui um endereco de localizacao na memoria, entao ponteiros por serem variaveis possuem seu endereco na memoria, no qual ironicamente um ponteiro guarda um endereco de outra variavel, entao desde que ponteiros tem enderecos, pq nao ter como guardar o endereco de um ponteiro, logo temos ponteiros para ponteiros.
Um ponteiro para um ponteiro e uma variavel que guarda o endereco de outro ponteiro, dessa forma apartir do endereco de um ponteiro, ou seja o endereco onde um ponteiro se encontra, podemos acessar o mesmo para escrita e leitura, e ate acessar ao oq o mesmo aponta.
Para se declarar um ponteiro para um ponteiro e usada a seguinte sintaxe:
Tipo **NomeDoPonteiro;
Onde Tipo e qualquer tipo de dados da linguagem C/C++, os asteristicos, 2 no caso, representam que a variavel a ser declarada e um ponteiro para um ponteiro.
Como em,
char **pp;
Entao digamos se temos:
char MeuChar = '@';
char *PonteiroParaChar = &MeuChar;
Fazemos com oq PonteiroParaChar aponte para MeuChar. Logo depois:
char **PonteiroParaPonteiroParaChar = &PonteiroParaChar;
Observe que PonteiroParaPonteiroParaChar aponta para o PonteiroParaChar, oq siguinifica que PonteiroParaPonteiroParaChar contem o endereco onde se encontra o PonteiroParaChar.
Para se accessar oq o ponteiro dentro de PonteiroParaPonteiroParaChar aponta e utilizada a seguinte sintaxe, observe:
printf("%c\n", **PonteiroParaPonteiroParaChar);
Que retorna oq o ponteiro que o ponteiro para ponteiro aponta contem, que e o char arroba ou @.
Digamos que queira modificar esse char apartir do ponteiro para ponteiro, entao:
**PonteiroParaPonteiroParaChar = '*';
Agora MeuChar contem asterisco ou *.
Para se entender oq esta acontecendo considere essa explicacao:
O operador * retorna um valor de um tipo de dados em um endereco de memoria, ou seja quando usamos
o operador * com PonteiroParaPonteiroParaChar dessa forma: *PonteiroParaPonteiroParaChar desde que PonteiroParaPonteiroParaChar contem o endereco de um ponteiro, acessamos o determinado ponteiro; E o que acontece no caso de **PonteiroParaPonteiroParaChar, observe os parenteses em:
*(*PonteiroParaPonteiroParaChar) 1o e acessado o ponteiro, que claro contem o endereco de uma variavel, e 2o e por ultimo temos o seguinte *(Endereco de uma variavel), onde o operador asteristico acessa essa determinada variavel, logo no caso acessamos Meuchar.
Observe o exemplo com atencao e compile:
#include <stdio> #include <stdlib> int main(void) { char MeuChar = '@'; char *MeuPonteiro = &MeuChar; char **MeuPonteiroParaPonteiroParaChar = &MeuPonteiro; puts("Nome: MeuChar"); printf("Endereco: %#p\n", &MeuChar); printf("Valor: %c\n", MeuChar); puts(""); puts("Nome: MeuPonteiro"); printf("Endereco: %#p\n", &MeuPonteiro); printf("Valor: %#p\n", MeuPonteiro); printf("** Observe que o valor de MeuPonteiro e o endereco" " de MeuChar **\n"); printf("Acesse endereco: %c\n", *MeuPonteiro); puts(""); puts("Nome: MeuPonteiroParaPonteiroParaChar"); printf("Endereco: %#p\n", &MeuPonteiroParaPonteiroParaChar); printf("Valor: %#p\n", MeuPonteiroParaPonteiroParaChar); printf("** Observe que o valor de MeuPonteiroParaPonteiroParaChar e o endereco" " de MeuPonteiro **\n"); printf("Acesse endereco: %#p\n", *MeuPonteiroParaPonteiroParaChar); printf("** Observe que acessando o valor de MeuPonteiroParaPonteiroParaChar" " que e o endereco de MeuPonteiro, encontramos o endereco de MeuChar **\n"); printf("Acesse ponteiro para ponteiro: %c\n", **MeuPonteiroParaPonteiroParaChar); puts("** Encontramos o que o ponteiro apontado pelo ponteiro pra ponteiro aponta **"); puts(""); system("pause"); return 0; } Vejamos um dos usos de um ponteiro para um ponteiro; Digamos que voce queira fazer uma funcao que aloque memoria e que um ponteiro para essa memoria seja retornado, nao necessariamente voce precisa retornar esse ponteiro, por que nao passar um endereco de um ponteiro para a funcao, no qual quando voce chamar a funcao voce passa o endereco de um ponteiro do tipo de dados para a alocacao, onde apartir dai pelo endereco do ponteiro voce pode modificar o ponteiro que esta em algum lugar no seu programa, copiando para o mesmo o endereco dos bytes recem alocados, veja o exemplo:
#include <stdio> #include <stdlib> /* Recebe um endereco para um ponteiro */ void Exemplo(char **p) { /* Como p e o endereco de um ponteiro use o operador * para acessar esse endereco e copiar o endereco retornado por malloc(). */ *p = malloc(30); } int main(void) { char *p; /* Chamada por referencia */ Exemplo(&p); /* Memoria foi alocada copie dados */ strncpy(p, "Test 123\n", 30); /* Mostre na tela */ printf(p); system("pause"); return 0; } Um outro uso de ponteiro para ponteiro e com array de ponteiros; Da mesma forma que e possivel utilizar um ponteiro para se caminhar por uma array de um tipo, e possivel se usar um ponteiro para um ponteiro para se caminhar por todos os items de uma array de ponteiros que por sinal sao ponteiros, e nao e exatamente isso ao que um ponteiro para um ponteiro aponta.
Vejamos um exemplo:
#include <stdio> #include <stdlib> int main(int argc, char *argv[]) { char **pp = argv; while (argc-- > 0) printf("%s\n", *pp++); system("pause"); return 0; } E declarado um ponteiro para um ponteiro chamado pp, que e inicializado para o valor de argv, no qual e um endereco para um ponteiro, depois no while loop, pp e incrementado assim: pp += sizeof(char *); dessa forma o proximo endereco para um ponteiro e acessado, ja o operador * acessa os enderecos especificos onde e encontrado enderecos, que e o parametro para printf() mostrar uma string de argumento.
Ponteiros em C/C++
por: C0d3r__
-
Flavio S deu reputação a Orochi Elf em OTClient - Otui GeneratorSalve galera do TK, eu vim morar em outro estado por um tempo, e aqui a internet não é boa.. então eu passo muito tempo sem fazer nada, então tive uma ideia de criar um programa pra gerar a layout do módulo do OTClient, o famoso arquivo ".otui"
Então galerinha, o que acham? Quanto maior o feedback melhor.