Files
metin2-client/tools/server/ava2-items/tests/test_items.py
T
shenleiandClaude Opus 5.5 178fcf48fe AVA2 unlock P1/P2: treasure boxes/keys and stone/Boss stones usable
Keep ITEM_TREASURE_BOX/KEY and METIN_NORMAL rows; APPLY_ATTBONUS_STONE 139 /
APPLY_ATTBONUS_BOSS 140 in ItemData.h, item module and tooltip (mt_applies).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 11:05:20 +09:00

47 lines
3.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_ATTBONUS_BOSS','5']) # ported apply kept
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_treasure_box_and_key_kept(self):
for vnum,t in ((77918,'ITEM_TREASURE_BOX'),(77921,'ITEM_TREASURE_KEY')):
s,c,kept=m.convert(row(vnum,t,'0',values=('3','0','0','0','0','0')),self.E,set())
self.assertTrue(kept);self.assertEqual(s[2:4],[t,'0']);self.assertEqual(s[24],'3') # key value0 == box value0 opens it
self.assertEqual(c[1],self.E['type'].index(t))
def test_stone_and_boss_stones_kept(self):
s,c,kept=m.convert(row(28444,'ITEM_METIN','METIN_NORMAL',flags='ITEM_STACKABLE',wear='WEAR_WEAPON',
applies=('APPLY_ATTBONUS_STONE','8','APPLY_NONE','0','APPLY_NONE','0'),values=('0','0','0','0','0','31')),self.E,set())
self.assertTrue(kept);self.assertEqual(s[7],'WEAR_WEAPON');self.assertEqual(s[18:20],['APPLY_ATTBONUS_STONE','8'])
self.assertEqual(c[17:19],[139,8]) # AVA2 numbering, shared with the server and client enums
self.assertEqual(self.E['apply'].index('APPLY_ATTBONUS_BOSS'),140);self.assertEqual(s[29],'31')
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()