[QUEST RELEASE] Aukciós Ház (Yang és Aranyrög alapú)

Indította xxxHUNâ„¢, 2014-07-22, 21:52:42

2014-07-22, 21:52:42 Utolsó szerkesztés: 2014-07-26, 15:06:33 Szerző: xxxHUN™
Sziasztok!

Készítettem egy Aukciós Ház questet. Tesztelés közben felmerülő hibákat javítottam. Azt hiszem, kijelenthetem, hogy működőképes. :)

UI.: Először Yang alapút töltöttem fel, kérésre feltöltöttem az Aranyröggel működő verziót is. Ha az Aranyrögös questet akarja valaki használni, fontos, hogy item_proto-ban csoportosíthatóvá tegye azt.

A lényege, hogy eladhatsz, vásárolhatsz tárgyakat, illetve licitálhatsz tárgyakra.
Ha eladni akarsz, ráhúzod a tárgyat az NPC-re, megadod a kivásárlási árat, és egy árat, amiről a licit indul.
Ha licitálsz, a licit minimum-nál nagyobb ajánlatot kell tenned, ha a kivásárlási árnál is nagyobb az ajánlat, az egyenértékű a vásárlással.
Ha kivásárolsz egy tárgyat, az azonnal a te tulajdonodba kerül.
Ha lezárod a licitet egy adott tárgyadra, a tárgy a legnagyobb ajánlatot tevő játékos tulajdonába kerül, a pénz pedig hozzád.
Ha túllicitálnak, vagy a tulajdonosa visszaveszi a tárgyat, a pénzedet visszakapod.

Aukción Lévő Tárgyak: más játékos által eladni kívánt tárgyak
Aukción Lévő Tárgyaim: az általad eladni kívánt tárgyak
Megszerzett Tárgyaim: ide kerülnek a megvásárolt, visszavett tárgyak, illetve azok a tárgyak amit liciten nyersz
Megszerzett Pénz: innen veheted fel a hozzá került pénzeket

Nah, szerintem ennyi rizsa elég, térjünk a lényegre... :D

34k game fájlhoz írtam eredetileg a questet, de a végén leírom, mit kell megváltoztatni, hogy működjön 40k game fájllal., felrakom vanilla core-hoz is (tesztelve).
Szóval, lássunk hozzá... Szükséges dolgok:

1. MySQL Lib
[spoiler]db_user="root"
db_pass="franzi"
db_host="localhost"

function mysql_select(query,notselect)
    local tmp=number(11111111,99999999)
os.execute('mysql -h '..db_host..' -u '..db_user..' -p'..db_pass..' -N -e '..string.format("%q",query)..' 2>&1 > /tmp/'..tmp)

if not notselect then
local res,i={},1
local f,e=io.open("/tmp/"..tmp)
if f then
local line=f:read("*l")
while line do
res[i]={}
string.gsub(line,"([^\t]+)\t*", function(s)
table.insert(res[i],s)
end)
i=i+1
line=f:read("*l")
end
f:close()
os.execute("rm /tmp/"..tmp)
end
return res
end
end

function mysql_notselect(query)
return mysql_select(query,true)
end

mysql_query = mysql_select
[/spoiler]
Én például ATAG questlib-be való funkcióját használom, de mindenki használhatja azt ami neki szimpatikus. (Mijago féle tökéletes)

2. select3 (Mijago)
[spoiler]function select3(...)
arg.n = nil
local tp,max = arg,5
if type(tp[1]) == 'number' then
max = tp[1]
if type(tp[2]) == 'table' then
tp = tp[2]
else
table.remove(tp,1)
end
elseif type(tp[1]) == 'table' then
if type(tp[1][1]) == 'number' then
max = tp[1][1]
table.remove(tp[1],1)
tp = tp[1]
end
tp = tp[1]
end
local str = '{'
local tablen,act,incit = table.getn(tp),0,0
table.foreach(tp,function(i,l)
act = act + 1
if act == 1 then
str = str .. '{'..string.format('%q',l)
elseif act == max+1 and tablen > act+incit then
if tablen ~= act+incit+1 then
str = str..'},{'..string.format('%q',l)
else
str=str..','..string.format('%q',l)
end
incit = incit + max
act = 1
else
str=str..','..string.format('%q',l)
end
end)
local px = loadstring('return '..str ..'}}')()
local function copy_tab(t) local p= {} for i = 1,table.getn(t) do p[i] = t[i] end return p end
local pe = {}
for i = 1,table.getn(px) do pe [i] = copy_tab(px[i]) end
local function init(i,ip)
pe[i] = copy_tab(px[i])
local next,back,exit = 0,0,0
if i < table.getn(pe) and table.getn(pe) ~=1 then  table.insert(pe[i],table.getn(pe[i])+1,'Tovább a(z) '..(i+1)..'. oldalra'); next = table.getn(pe[i]) end
if i > 1 then table.insert(pe[i],table.getn(pe[i])+1,'Vissza a(z) '..(i-1)..'. oldalra'); back = table.getn(pe[i]) end
table.insert(pe[i],table.getn(pe[i])+1,'Kilépés '); exit = table.getn(pe[i])
if table.getn(pe) > 1 then
say('Oldal: '..i..'/'..table.getn(pe))
end
local e = select_table(pe[i])
if e == next then return init(i+1,ip+max)
elseif e == back then return init(i-1,ip-max)
elseif e == exit then return -1
else return e+ip,pe[i][e] end
end
return init(1,0) or -1
end
[/spoiler]

3. item2_pc2_lib (iMer)
[spoiler]
Idézhttp://www.elitepvpers.com/forum/metin2-pserver-guides-strategies/2875163-lib-item2-pc2-set_attr-get_attr-equip-set_level-und-mehr.html
[/spoiler]
Erre 34k game fájl esetén van szükség.

4. MySQL Táblák
aukcios_haz
[spoiler]-- ----------------------------
-- Table structure for `aukcios_haz`
-- ----------------------------
DROP TABLE IF EXISTS `aukcios_haz`;
CREATE TABLE `aukcios_haz` (
  `id` int(11) NOT NULL auto_increment,
  `owner` varchar(30) NOT NULL,
  `bidder` varchar(30) NOT NULL,
  `price` int(11) NOT NULL,
  `licitmin` int(11) NOT NULL,
  `vnum` int(11) NOT NULL,
  `count` int(3) NOT NULL,
  `st1` int(11) NOT NULL,
  `st2` int(11) NOT NULL,
  `st3` int(11) NOT NULL,
  `bt1` int(11) NOT NULL,
  `bv1` int(11) NOT NULL,
  `bt2` int(11) NOT NULL,
  `bv2` int(11) NOT NULL,
  `bt3` int(11) NOT NULL,
  `bv3` int(11) NOT NULL,
  `bt4` int(11) NOT NULL,
  `bv4` int(11) NOT NULL,
  `bt5` int(11) NOT NULL,
  `bv5` int(11) NOT NULL,
  `bt6` int(11) NOT NULL,
  `bv6` int(11) NOT NULL,
  `bt7` int(11) NOT NULL,
  `bv7` int(11) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=latin1;

[/spoiler]
aukcios_haz_item_reward
[spoiler]-- ----------------------------
-- Table structure for `aukcios_haz_item_reward`
-- ----------------------------
DROP TABLE IF EXISTS `aukcios_haz_item_reward`;
CREATE TABLE `aukcios_haz_item_reward` (
  `id` int(11) NOT NULL auto_increment,
  `owner` varchar(30) NOT NULL,
  `vnum` int(11) NOT NULL,
  `count` int(3) NOT NULL,
  `st1` int(11) NOT NULL,
  `st2` int(11) NOT NULL,
  `st3` int(11) NOT NULL,
  `bt1` int(11) NOT NULL,
  `bv1` int(11) NOT NULL,
  `bt2` int(11) NOT NULL,
  `bv2` int(11) NOT NULL,
  `bt3` int(11) NOT NULL,
  `bv3` int(11) NOT NULL,
  `bt4` int(11) NOT NULL,
  `bv4` int(11) NOT NULL,
  `bt5` int(11) NOT NULL,
  `bv5` int(11) NOT NULL,
  `bt6` int(11) NOT NULL,
  `bv6` int(11) NOT NULL,
  `bt7` int(11) NOT NULL,
  `bv7` int(11) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=11 DEFAULT CHARSET=latin1;
[/spoiler]
aukcios_haz_money_reward
[spoiler]-- ----------------------------
-- Table structure for `aukcios_haz_money_reward`
-- ----------------------------
DROP TABLE IF EXISTS `aukcios_haz_money_reward`;
CREATE TABLE `aukcios_haz_money_reward` (
  `id` int(11) NOT NULL auto_increment,
  `owner` varchar(30) NOT NULL,
  `amount` int(11) NOT NULL,
  `cause` text NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
[/spoiler]

5. Végül, de nem utolsó sorban:
[spoiler]A Questet csatolmányként raktam.  ;D[/spoiler]

Külön köszönet illeti:
- DonNodus
- Nzio
- Morpheus
Nekik köszönöm a segítséget. :)

Remélem tetszik, és lesz, aki hasznát veszi.  ;)

Üdv.: xxxHUN™

by Morpheus

2014-09-01, 19:31:13 #1 Utolsó szerkesztés: 2014-09-06, 20:47:24 Szerző: xxxHUN™
Elhoztam nektek a MySQL lekérések nélkül működő verziót.
A működési elv körülbelül ugyanaz, mint az előző verziónál.

A leginkább szembetűnő különbség a 2 között, hogy az új quest az adatokat globális változókban tárolja.
A változók tartalmát txt fájlokba lehet menteni, ez elsősorban biztonsági mentés céljából nagyon fontos.
Az adatok mentésére 3 különböző lehetőség van beépítve:
- GM karakter az erre kijelölt funkcióval végrehajtja a mentést-újratöltést.
- Minden jelentősebb mozzanatnál (vásárlás, eladás, stb) mentésre kerülnek az adatok.
- Adott időközönként automatikus mentés történik.
Azt, hogy melyik mentési módot akarjátok használni, ingame tudjátok beállítani.

Ahhoz, hogy az Aukciós Ház "aktív" állapotba kerüljön, GM karakternek a kijelölt NPC-nél rá kell mennie, hogy: "GM: Aukció Adatok Betöltése".
De, még ezt megelőzően nem árt, ha beállítasz egy limitet, hogy maximum hány tárgyat helyezhessenek az aukciós házba. Ha nem akarsz limitet, nem kell változtatni semmit, ha akarsz, érdemes valami ésszerű értéket beállítani, gyakorlatilag nincs annyi tárgy, amivel ki lehetne ütni a szervert, bár... nekem azért sikerült. A következő értékekkel teszteltem a limitet (nyugalom, programmal töltöttem fel az adatokat, nem húzgáltam minden egyes tárgyat az NPC-re :D ) :
- 100.000 tárgy, menteni tudta, betölteni tudta, menügenerálásnál lelőtte CH-t
- 25.000 tárgy, mentés-töltés tökéletes, menügenerálás kb. 1 perc
- 10.000 tárgy, ment-tölt, menügenerálás 2-3 mp, de ki az az állat, aki képes végiglapozni 2.000 oldalt? :D
- 5.000 tárgy, ment-tölt-generál, 1.000 oldal azért még mindig elég sok :D
- 1.000 tárgy, ez már azt hiszem elég elfogadható limit, bár szerintem 200 oldalt sem lapozna végig senki
Lényeg, ingame ezzel a paranccsal állíts be egy limitet, ha akarsz: /e aukcio_limit szám

Ami fontos, az az, hogy még akkor is, ha van bekapcsolva automatikus mentés, mielőtt reboot-olsz, reload, reload q, vagy akármi hasonlót csinálsz, GM karakter mindenképp mentse az adatokat az NPC-nél!
Automata mentésnél fontos, hogy ha időzített mentést akarsz, állítsd be ingame, hogy milyen időközönként történjen mentés, ezzel a paranccsal: /e aukcio_savecycle szám

Azt hiszem, a működéséről ennyit lehet mondani, a többi dolog úgy működik, mint az előző verziónál.

Ami még fontos, hogy az adatokat a változókból txt-kbe lehet menteni, a mellékelt txt-ket töltsétek fel a quest mappába, és adjatok nekik 777 engedélyt. (nem tudom, ez mennyire fontos, de biztos ami biztos)
Illetve a quest-ben, ha esetleg a quest mappa elérése nem egyezne a megadottal, akkor azt javítsátok ki.

Ami még egy érdekes változás az előzőhöz képest, hogy ezzel a globális változóval nem igazán tudunk dűlőre jutni. Nem tudjuk biztosra, hogy pl.: ha CH1-n egy játékos berak egy tárgyat, akkor azt CH2-n fogják-e látni. Erről még folynak a viták, tanácskozások.
Egyelőre azt tudom mondani, hogy az a biztos, ha CH99-en lehet csak használni az Aukciós Házat.
(Igen, tudom, ez elég nagy hiba, de ha rájöttem/rájöttünk, hogyan lehetne biztosra megoldani a többi CH-ra is, javítom majd.)

34k game fájl esetén iMer item2_pc2 libjére továbbra is szükség van, illetve Mijago select3 funkciójára mindenképp.
Egy dologról elfeledkeztem... split funkció... Akinek esetleg nincs hozzá lib-je:
function split(str, delim, maxNb)
if str == nil then return str end
if string.find(str, delim) == nil then return { str } end
if maxNb == nil or maxNb < 1 then maxNb = 0 end
local result = {}
local pat = "(.-)" .. delim .. "()"
local nb = 0
local lastPos
for part, pos in string.gfind(str, pat) do
nb = nb + 1
result[nb] = part
lastPos = pos
if nb == maxNb then break end
end
if nb ~= maxNb then result[nb + 1] = string.sub(str, lastPos) end
return result
end

Jah még annyi, hogy most csak Yang alapút töltöm fel, Aranyrög-ösre még eddig nem volt alkalmam megváltoztatni, de aki nagyon akarja, az előző verziónak és ennek a birtokában már össze tudja hozni magának is valószínűleg, de amint időm lesz, megcsinálom és felrakom azt is.
Feldobtam Aranyrög alapút is, ahogy ígértem. :)

A kódon kicsit változtattam, ezzel áttekinthetőbbé vált 1-2 funkció, köszönöm a javaslatot ATAG-nak.

Egyelőre ennyi lenne.

Üdv.: xxxHUN™

by Morpheus