tools/server/ava2-items stages the 478 items referenced by the AVA2 drop tables that 203 does not have: server item_proto/item_names rows, a client item_proto/item_list/itemdesc patch over the biolog tables, and the AVA2 icons, ground models (BitKnit gr2 via sdk/gr2) and their textures, packed as ava2items ahead of biolog. Materials, quest items, chests, the guardian weapons and shoes keep their meaning; items of AVA2-only systems (pets, pendants, new rings, mounts, sashes, costume enchants, talisman items, new skill books) become plain ITEM_NONE items until those systems are ported. Names are translated in names_zh.tsv. item_proto_patch is the full-record successor of biolog_proto_patch, with --dump for checking conversions against the shipped table. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
36 lines
2.5 KiB
Python
36 lines
2.5 KiB
Python
import sys,unittest
|
|
from pathlib import Path
|
|
HERE=Path(__file__).resolve().parents[1];sys.path.insert(0,str(HERE))
|
|
import make_items as m
|
|
READER=HERE.parents[3]/'metin2-server/src/server/db/src/ProtoReader.cpp'
|
|
|
|
def row(vnum,t,st,anti='NONE',flags='NONE',wear='NONE',applies=('APPLY_NONE','0')*3,values=('0',)*6,refine=('0','0')):
|
|
return [str(vnum),'x',t,st,'1',anti,flags,wear,'NONE','10','20',refine[0],refine[1],'0','LEVEL','120','LIMIT_NONE','0',*applies,*values,'0','0','-1','']
|
|
|
|
@unittest.skipUnless(READER.is_file(),'needs ../metin2-server')
|
|
class ConvertTests(unittest.TestCase):
|
|
E=m.enums(READER) if READER.is_file() else None
|
|
def test_weapon_kept_without_unknown_flags(self):
|
|
s,c,kept=m.convert(row(320,'ITEM_WEAPON','WEAPON_SWORD','ANTI_MUDANG | ANTI_WOLFMAN','ITEM_TUNABLE','WEAR_WEAPON',
|
|
('APPLY_ATT_SPEED','18','APPLY_ATTBONUS_BOSS','5','APPLY_NONE','0'),refine=('321','81')),self.E,{320})
|
|
self.assertTrue(kept);self.assertEqual(s[5],'ANTI_MUDANG');self.assertEqual(s[7],'WEAR_WEAPON')
|
|
self.assertEqual(s[18:22],['APPLY_ATT_SPEED','18','APPLY_NONE','0'])
|
|
self.assertEqual(s[11:13],['0','0']) # the +1 item is not imported
|
|
self.assertEqual(c[1:3],[self.E['type'].index('ITEM_WEAPON'),0]);self.assertEqual(c[4],1<<self.E['anti'].index('ANTI_MUDANG'))
|
|
self.assertEqual(len(s),33);self.assertEqual(len(c),31)
|
|
def test_costume_enchant_is_locked(self):
|
|
s,c,kept=m.convert(row(54001,'ITEM_USE','USE_CHANGE_ATTRIBUTE',flags='ITEM_STACKABLE',values=('23','10','2','0','0','0')),self.E,set())
|
|
self.assertFalse(kept);self.assertEqual(s[2:4],['ITEM_NONE','0']);self.assertEqual(s[24:30],['0']*6)
|
|
self.assertEqual(c[1:3],[0,0]);self.assertEqual(c[5],1<<self.E['flag'].index('ITEM_STACKABLE'))
|
|
def test_unknown_type_and_stackable_anti(self):
|
|
s,_,kept=m.convert(row(55010,'ITEM_PET','PET_SKILL','ITEM_STACKABLE','LOG','WEAR_PENDANT'),self.E,set())
|
|
self.assertFalse(kept);self.assertEqual(s[5:8],['NONE','LOG | ITEM_STACKABLE','NONE'])
|
|
def test_quest_subtype(self):
|
|
s,c,kept=m.convert(row(30400,'ITEM_QUEST','QUEST_NONE',values=('APPLY_NONE','0','0','0','0','0')),self.E,set())
|
|
self.assertTrue(kept);self.assertEqual(s[3],'0');self.assertEqual(s[24],'0')
|
|
def test_names_cover_ranges(self):
|
|
n=m.names();self.assertEqual(len(n),478);self.assertEqual(n[54100],'武器外观强化石')
|
|
self.assertTrue(all(len(v.encode('gbk'))<=24 for v in n.values()))
|
|
|
|
if __name__=='__main__':unittest.main()
|