Files
metin2-client/src/platform/ScriptLib/DisplayScript.inc
T
shenandshen 507e687867 feat: add MeshPort overlay networking, item actions window, and AVA2 client enhancements
- add MeshPort peer-to-peer overlay networking SDK, C++ integration, and Python bindings
- add item actions quick use/split/delete/lock overlay window (mt_item_actions)
- add shop name range and NPC name visibility settings to system display options
- support battlepass ticket activation and month validation in mt_battlepass
- support boss tracking teleport destination button in mt_bosses
- support asynchronous account registration cancellation and pending login cancellation
- update AVA2 item conversion for attr lock scrolls and battlepass tickets
- update .gitignore for local build outputs and caches
2026-10-16 01:29:57 -07:00

154 lines
6.4 KiB
C++

// PORT: AVA2-style display options (ENABLE_GRAPHIC_ON_OFF effect level, HIDE_OBJECTS tree/cloud parts),
// client-only. The effect level is systemSetting.SetEffectLevel (CInstanceBase::__UpdateEffectShown deactivates
// attached effects); trees and clouds use the original background.SetVisiblePart; names and damage numbers
// are shortcuts to the original game options. See docs/AVA2-DISPLAY.md.
static const char c_szDisplayScript[] = R"PY(# -*- coding: utf-8 -*-
import background
import game
import grp
import systemSetting
import ui
import weakref
from mt_biolog import Action, Text, L
from mt_wiki import B
g_window=None
g_entry=None
CONFIG='mt_display.cfg'
LEVELS=(u'全部特效',u'只看怪物特效',u'只看玩家特效',u'只看自己特效',u'关闭全部特效')
LEVEL_HINTS=('显示所有角色的特效','隐藏其他玩家和NPC的特效,保留自己和怪物的','隐藏怪物和NPC的特效,保留玩家的',
'只保留自己的特效','连自己的特效也隐藏')
class Options(object):
def __init__(self):self.effect=0;self.tree=True;self.cloud=True;self.shopRange=0;self.npcNames=True
def Load(self,text):
words=text.split()
if len(words) not in (3,5) or not all(w.isdigit() and len(w)==1 for w in words):return
effect,tree,cloud=[int(w) for w in words[:3]]
shop,names=[int(w) for w in words[3:]] if len(words)==5 else (0,1)
if effect<len(LEVELS) and tree in (0,1) and cloud in (0,1) and shop<5 and names in (0,1):
self.effect=effect;self.tree=tree==1;self.cloud=cloud==1;self.shopRange=shop;self.npcNames=names==1
def Dump(self):return '%d %d %d %d %d'%(self.effect,int(self.tree),int(self.cloud),self.shopRange,int(self.npcNames))
def Apply(self):
systemSetting.SetEffectLevel(self.effect)
systemSetting.SetShopNamesRange(self.shopRange)
systemSetting.SetShopNameStatus(self.npcNames)
background.SetVisiblePart(background.PART_TREE,int(self.tree))
background.SetVisiblePart(background.PART_CLOUD,int(self.cloud))
def LoadConfig(options):
try:
f=open(CONFIG,'r');text=f.read();f.close();options.Load(text)
except (IOError,OSError):pass
def SaveConfig(options):
try:
f=open(CONFIG,'w');f.write(options.Dump());f.close()
except (IOError,OSError):pass
def Mark(text,on):return L(B(u'【%s】'%text if on else text))
class DisplayWindow(ui.Window):
def __init__(self,options):
ui.Window.__init__(self);self.SetWindowName('DisplayWindow');self.AddFlag('float');self.AddFlag('movable')
self.options=options;self.SetSize(332,456)
self.heading=Text(self,18,18,'显示设置',0xffffd68b)
self.closeButton=Action(self,256,6,60,'关闭',self.Hide)
self.effectText=Text(self,18,54,'特效',0xffc3b7a1)
self.levelButtons=[Action(self,18+(i%2)*152,76+(i//2)*52,144,'',lambda level=i:self.SetLevel(level)) for i in range(len(LEVELS))]
self.sceneText=Text(self,18,238,'场景和文字',0xffc3b7a1)
self.treeButton=Action(self,18,260,144,'',self.ToggleTree)
self.cloudButton=Action(self,170,260,144,'',self.ToggleCloud)
self.nameButton=Action(self,18,312,144,'',self.ToggleName)
self.damageButton=Action(self,170,312,144,'',self.ToggleDamage)
self.rangeButton=Action(self,18,364,144,'',self.NextRange)
self.npcButton=Action(self,170,364,144,'',self.ToggleNPC)
self.status=Text(self,18,428,'',0xffc3b7a1)
self.Refresh();self.Hide()
def Buttons(self):return [self.closeButton,self.treeButton,self.cloudButton,self.nameButton,self.damageButton,self.rangeButton,self.npcButton]+self.levelButtons
def Open(self):self.Refresh();self.SetCenterPosition();self.Show();self.SetTop()
def Changed(self):self.options.Apply();SaveConfig(self.options);self.Refresh()
def SetLevel(self,level):self.options.effect=level;self.Changed()
def ToggleTree(self):self.options.tree=not self.options.tree;self.Changed()
def ToggleCloud(self):self.options.cloud=not self.options.cloud;self.Changed()
def NextRange(self):self.options.shopRange=(self.options.shopRange+1)%5;self.Changed()
def ToggleNPC(self):self.options.npcNames=not self.options.npcNames;self.Changed()
# Names and damage numbers are the original game options (saved by the client config on exit).
def ToggleName(self):systemSetting.SetAlwaysShowNameFlag(not systemSetting.IsAlwaysShowName());self.Refresh()
def ToggleDamage(self):systemSetting.SetShowDamageFlag(not systemSetting.IsShowDamage());self.Refresh()
def Refresh(self):
o=self.options
for i,button in enumerate(self.levelButtons):button.SetText(Mark(LEVELS[i],i==o.effect))
self.treeButton.SetText(Mark(u'显示树木',o.tree));self.cloudButton.SetText(Mark(u'显示云',o.cloud))
self.nameButton.SetText(Mark(u'总是显示名字',systemSetting.IsAlwaysShowName()))
self.damageButton.SetText(Mark(u'显示伤害数字',systemSetting.IsShowDamage()))
self.rangeButton.SetText(L(B(u'摊位范围 %d 米'%((100,60,40,20,10)[o.shopRange]))))
self.npcButton.SetText(Mark(u'显示NPC名称',o.npcNames))
self.status.SetText(L(LEVEL_HINTS[o.effect]))
def OnRender(self):
x,y=self.GetGlobalPosition();grp.SetColor(0xf51b1916);grp.RenderBar(x,y,self.GetWidth(),self.GetHeight());grp.SetColor(0xff9b7b48);grp.RenderBox(x,y,self.GetWidth(),self.GetHeight())
def OnPressEscapeKey(self):self.Hide();return True
def Destroy(self):
self.Hide()
for b in self.Buttons():b.event=None
class Entry(Action):
def __init__(self,window):
Action.__init__(self,None,0,0,64,'显示',Toggle)
self.minimap=weakref.proxy(window.interface.wndMiniMap);self.SetWindowName('DisplayEntry');self.OnUpdate()
def OnUpdate(self):
x,y=self.minimap.GetGlobalPosition();self.SetPosition(max(4,x-68),y+252)
g_options=Options()
LoadConfig(g_options)
systemSetting.SetEffectLevel(g_options.effect)
def Toggle():
if g_window:
if g_window.IsShow():g_window.Hide()
else:g_window.Open()
_open=game.GameWindow.Open
_close=game.GameWindow.Close
def Open(self):
global g_window,g_entry
_open(self);g_options.Apply();g_window=DisplayWindow(g_options);g_entry=Entry(self)
def Close(self):
global g_window,g_entry
if g_entry:g_entry.Hide();g_entry.event=None;g_entry=None
if g_window:g_window.Destroy();g_window=None
_close(self)
game.GameWindow.Open=Open
game.GameWindow.Close=Close
)PY";