Ingame CH váltó (m)

Started by Deadly2000, 2015-06-25, 14:19:07

http://metin2hungary.net/index.php/topic,190090.msg999991.html#msg999991
Ezt Pisit írta a Ingame CH Váltóról . Ezt beraktam meg minden ,de mikor beléptem akkor tudtam hol megnyitni . GOndolom valami gombnak kéne a taskbaron lennie ,de nincs . Pisti csak annyit írt rá ,hogy be kell pozicionálni ,de nem nagyon értek a pythonhoz . Valaki segítene :O ?

intrologin.py-ba beírtad ugye ezt az osztályt:

class ChannelChanger(ui.ScriptWindow):
def __init__(self):
ui.ScriptWindow.__init__(self)

self.__Init_ChannelChanger()
self.__Load_Gui()
self.__Fill_Up_ChannelList()

def __del__(self):
ui.ScriptWindow.__del__(self)

def Destroy(self):
self.Hide()
return TRUE

def __Init_ChannelChanger(self):
ServerStateChecker.Create(self)
self.SetSize(150, 175)
self.SetPosition(
(wndMgr.GetScreenWidth() / 2) - int(math.floor(self.GetWidth() / 2.)),
(wndMgr.GetScreenHeight() / 2) - int(math.floor(self.GetHeight() / 2.))
)
#self.AddFlag("movable")
self.AddFlag("float")
self.Show()

def __Load_Gui(self):
self.Board = ui.Board()
self.Board.SetParent(self)
self.Board.SetSize(self.GetWidth(), self.GetHeight())
self.Board.SetPosition(0, 0)
#self.Board.AddFlag("movable")
self.Board.AddFlag("float")
self.Board.Show()

self.TitleBar = ui.TitleBar()
self.TitleBar.SetParent(self.Board)
self.TitleBar.SetPosition(7, 7)
self.TitleBar.MakeTitleBar(self.GetWidth() - 2 * 7, 'bloodyblue')
self.TitleBar.SetCloseEvent(self.Close)
self.TitleBar.Show()

self.RefreshButton = ui.Button()
self.RefreshButton.SetParent(self.TitleBar)
self.RefreshButton.SetPosition(3, 3)
self.RefreshButton.SetUpVisual("d:/ymir work/ui/game/guild/refresh_button_01.sub")
self.RefreshButton.SetOverVisual("d:/ymir work/ui/game/guild/refresh_button_02.sub")
self.RefreshButton.SetDownVisual("d:/ymir work/ui/game/guild/refresh_button_03.sub")
self.RefreshButton.SetToolTipText("Frissítés", 0, - 23)
#   "Refresh"
self.RefreshButton.SetEvent(lambda : self.__Fill_Up_ChannelList())
self.RefreshButton.Show()

self.TitleText = ui.TextLine()
self.TitleText.SetParent(self.TitleBar)
self.TitleText.SetPosition(0, 4)
self.TitleText.SetText("CH - Választó")
#    "CH - Switcher"
self.TitleText.SetWindowHorizontalAlignCenter()
self.TitleText.SetHorizontalAlignCenter()
self.TitleText.Show()

self.ServerName = ui.TextLine()
self.ServerName.SetParent(self.TitleBar)
self.ServerName.SetPosition(0, self.TitleBar.GetHeight())
self.ServerName.SetText(str(net.GetServerInfo()).split(",")[0])
self.ServerName.SetWindowHorizontalAlignCenter()
self.ServerName.SetHorizontalAlignCenter()
self.ServerName.Show()

self.ChannelListBase = ui.SlotBar()
self.ChannelListBase.SetParent(self.Board)
self.ChannelListBase.SetSize(self.Board.GetWidth() - 2 * 16, 5 * 18 - 4)
self.ChannelListBase.SetPosition(16 , 7 + self.TitleBar.GetHeight() + 6 + 10)
self.ChannelListBase.Show()

self.ChannelList = ui.ListBox()
self.ChannelList.SetParent(self.ChannelListBase)
self.ChannelList.SetSize(self.ChannelListBase.GetWidth()- 20, self.ChannelListBase.GetHeight())
self.ChannelList.SetPosition(0, 0)
self.ChannelList.SetEvent(ui.__mem_func__(self.__OnSelectChannel))
self.ChannelList.Show()

self.ChangeButton = ui.Button()
self.ChangeButton.SetParent(self.Board)
self.ChangeButton.SetPosition(self.Board.GetWidth() / 2 - 44, self.Board.GetHeight() - 35)
self.ChangeButton.SetUpVisual('d:/ymir work/ui/public/Large_button_01.sub')
self.ChangeButton.SetOverVisual('d:/ymir work/ui/public/Large_button_02.sub')
self.ChangeButton.SetDownVisual('d:/ymir work/ui/public/Large_button_03.sub')
self.ChangeButton.SetEvent(lambda : self.__OnClickConnectButton())
self.ChangeButton.SetText("Mehet")
#   "Go"
self.ChangeButton.Show()
self.DisableChangeButton()

self.ChannelListScrollBar = ui.ScrollBar()
self.ChannelListScrollBar.SetParent(self.ChannelListBase)
self.ChannelListScrollBar.SetPosition(18, 3)
self.ChannelListScrollBar.SetScrollBarSize(83)
self.ChannelListScrollBar.SetWindowHorizontalAlignRight()
self.ChannelListScrollBar.SetScrollEvent(ui.__mem_func__(self.__OnScrollChannelList))
self.ChannelListScrollBar.Show()

def DisableChangeButton(self):
self.ChangeButton.Disable()
self.ChangeButton.Down()
self.ChangeButton.ButtonText.SetFontColor(0.4, 0.4, 0.4)

def EnableChangeButton(self):
self.ChangeButton.Enable()
self.ChangeButton.SetUp()
self.ChangeButton.ButtonText.SetFontColor(1, 1, 1)

def __GetRegionID(self):
return 0

def __GetServerID(self):
regionID = self.__GetRegionID()
for i in serverInfo.REGION_DICT[regionID].keys():
if serverInfo.REGION_DICT[regionID][i]["name"] == net.GetServerInfo().split(",")[0]:
serverID = int(i)
break

return serverID

def __Fill_Up_ChannelList(self):
self.__RequestServerStateList()
self.__RefreshServerStateList()
#self.ChannelList.SelectItem(0)

def __RequestServerStateList(self):
regionID = self.__GetRegionID()
serverID = self.__GetServerID()

try:
channelDict = serverInfo.REGION_DICT[regionID][serverID]["channel"]
except:
return

for id, channelDataDict in channelDict.items():
key=channelDataDict["key"]
ip=channelDataDict["ip"]
udp_port=channelDataDict["udp_port"]
ServerStateChecker.Request(key, ip, udp_port)

def __RefreshServerStateList(self):
regionID = self.__GetRegionID()
serverID = self.__GetServerID()
bakChannelID = self.ChannelList.GetSelectedItem()

self.ChannelList.ClearItem()

try:
channelDict = serverInfo.REGION_DICT[regionID][serverID]["channel"]
except:
return

for channelID, channelDataDict in channelDict.items():
channelName = channelDataDict["name"]
channelState = channelDataDict["state"]
self.ChannelList.InsertItem(channelID, "%s %s" % (channelName, channelState))

self.ChannelList.SelectItem(bakChannelID-1)

def NotifyChannelState(self, addrKey, state):
try:
stateName = serverInfo.STATE_DICT[state]
except:
stateName = serverInfo.STATE_NONE

regionID  = int(addrKey / 1000)
serverID  = int(addrKey / 10) % 100
channelID = addrKey % 10

try:
serverInfo.REGION_DICT[regionID][serverID]["channel"][channelID]["state"] = stateName
self.__RefreshChannelStateList()
except:
pass

def __IsSpecialMap(self):
dis_maps = [
"season1/metin2_map_oxevent",
"season2/metin2_map_guild_inside01",
"season2/metin2_map_empirewar01",
"season2/metin2_map_empirewar02",
"season2/metin2_map_empirewar03",
"metin2_map_dragon_timeattack_01",
"metin2_map_dragon_timeattack_02",
"metin2_map_dragon_timeattack_03",
"metin2_map_skipia_dungeon_boss",
"metin2_map_skipia_dungeon_boss2",
"metin2_map_devilsCatacomb",
"metin2_map_deviltower1",
"metin2_map_t1",
"metin2_map_t2",
"metin2_map_t3",
"metin2_map_t4",
"metin2_map_t5",
"metin2_map_wedding_01",
"metin2_map_duel"
]
if str(background.GetCurrentMapName()) in dis_maps:
return TRUE
return FALSE

def __OnSelectChannel(self):
if self.ChangeButton.IsDown():
self.EnableChangeButton()

##< Works but not need >##
#regionID = self.__GetRegionID()
#serverID = self.__GetServerID()
#channelID = self.ChannelList.GetSelectedItem()
#if self.__IsSpecialMap():
# self.DisableChangeButton()
# return
#elif serverInfo.REGION_DICT[regionID][serverID]["channel"][channelID]["state"] == serverInfo.STATE_NONE:
# self.DisableChangeButton()
# return

def __OnScrollChannelList(self):
viewItemCount = self.ChannelList.GetViewItemCount()
itemCount = self.ChannelList.GetItemCount()
pos = self.ChannelListScrollBar.GetPos() * (itemCount - viewItemCount)
self.ChannelList.SetBasePos(int(pos))

def __OnClickConnectButton(self):
regionID = self.__GetRegionID()
serverID = self.__GetServerID()
channelID = self.ChannelList.GetSelectedItem()
if not channelID:
chat.AppendChat(1, "Nem választotál ki csatornát!")
#    "You did not select a channel!"
return

try:
serverName = serverInfo.REGION_DICT[regionID][serverID]["name"]
channelName = serverInfo.REGION_DICT[regionID][serverID]["channel"][channelID]["name"]
addrKey = serverInfo.REGION_DICT[regionID][serverID]["channel"][channelID]["key"]
ip = serverInfo.REGION_DICT[regionID][serverID]["channel"][channelID]["ip"]
tcp_port = serverInfo.REGION_DICT[regionID][serverID]["channel"][channelID]["tcp_port"]
state = serverInfo.REGION_DICT[regionID][serverID]["channel"][channelID]["state"]

account_ip = serverInfo.REGION_AUTH_SERVER_DICT[regionID][serverID]["ip"]
account_port = serverInfo.REGION_AUTH_SERVER_DICT[regionID][serverID]["port"]

markKey = regionID * 1000 + serverID * 10
markAddrValue=serverInfo.MARKADDR_DICT[markKey]
net.SetMarkServer(markAddrValue["ip"], markAddrValue["tcp_port"])
app.SetGuildMarkPath(markAddrValue["mark"])
app.SetGuildSymbolPath(markAddrValue["symbol_path"])
except:
chat.AppendChat(1, "Hiba történt a csatlakozás közben!")
#    "An error occurred while connect!"
return

if state == serverInfo.STATE_NONE:
chat.AppendChat(1, "Sajnálom a kiválasztott csatorna nem elérhető!")
#    "Sorry the selected channel is offline!"
return
elif state == serverInfo.STATE_DICT[3]:
chat.AppendChat(1, "Sajnálom a kiválasztott csatorna telítve van!")
#    "Sorry the selected channel is full!"
return
elif net.GetServerInfo().strip().split(", ")[1] == self.ChannelList.textDict[self.ChannelList.selectedLine].strip().split(" ")[0]:
chat.AppendChat(1, "Te jelenleg is a kiválasztott csatornán tartózkodsz!")
#    "You are already on the selected channel!"
return
elif self.__IsSpecialMap():
chat.AppendChat(1, "Sajnálom ezen a területen nem válthatsz csatornát kilépés nélkül!")
#    "Sorry in this area you cannot change channel without logout!"
return

self.Close()
net.SetServerInfo("%s, %s" % (serverName, channelName))
self.DirectConnect(ip, tcp_port, account_ip, account_port)

def DirectConnect(self, ChannelIP, ChannelPort, AuthServerIP, AuthServerPort):
#net.SetLoginInfo("xPengii", "kiU2_w1A_q2olDle9")
net.SetLoginInfo(decode_string(net.ACCOUNT_ID), decode_string(net.ACCOUNT_PW))
net.ConnectToAccountServer(ChannelIP, ChannelPort, AuthServerIP, AuthServerPort)
net.DirectEnter(0)
net.SendSelectCharacterPacket(0)
net.SendEnterGamePacket()

def Show(self):
ui.ScriptWindow.Show(self)

def Close(self):
ServerStateChecker.Destroy(self)
self.Hide()
return TRUE

def OnPressEscapeKey(self):
self.Close()
return TRUE

def OnUpdate(self):
ServerStateChecker.Update()

iom = ChannelChanger()
iom.Show()
chat.AppendChat(1, "#DEV#{Succesfully loaded}")



Ebben az osztályban van a gomb meghatározva és a pozíció. Nem lenne nehéz kitalálni ebből, hogy Widht, Height, GetLeft, hogy micsoda. (Szélesség, magasság, bal irány.)


'ESC' gombbal jön elő és tűnik el az ablak. Ha lenyomod akkor elő kell jöjjön, ha nem tetted be rosszul...


Ennek a résznek kell lennie az elhelyezkedésért felelősnek:

self.SetPosition(
(wndMgr.GetScreenWidth() / 2) - int(math.floor(self.GetWidth() / 2.)),
(wndMgr.GetScreenHeight() / 2) - int(math.floor(self.GetHeight() / 2.))
)



De lehet ez az:

self.ChannelListBase = ui.SlotBar()
self.ChannelListBase.SetParent(self.Board)
self.ChannelListBase.SetSize(self.Board.GetWidth() - 2 * 16, 5 * 18 - 4)
[color=red] self.ChannelListBase.SetPosition(16 , 7 + self.TitleBar.GetHeight() + 6 + 10)[/color]
self.ChannelListBase.Show()




De ettől még nem fogsz tudni CH-t váltani.. csak a gombja lesz bent... Nekemis bentvan a szerverben.
cmd.cp:

   Ezután:
      ACMD(do_warp);
   ezt:
      ACMD(do_channel_switch);


   Ezután:
      { "mall_close", do_mall_close, 0, POS_DEAD, GM_PLAYER },
    ezt:
    { "channel", do_channel_switch, 0, POS_DEAD, GM_PLAYER },
   


cmd_general.cpp:
   
   Ezután:
      ACMD(do_set_run_mode)
{
ch->SetNowWalking(false);
ch->SetWalking(false);
}


   ezt:
      ACMD(do_channel_switch)
{
   
    char arg1[256];
    one_argument(argument, arg1, sizeof(arg1));

    if (!*arg1)
            return;
   
    int new_ch;
    str_to_number(new_ch, arg1);
    if( new_ch <1 || new_ch >4)   // REPLACE 2 WITH YOUR MAX_CHANNEL
        return;
    if (!ch->IsPC())
        return;
    ch->ChannelSwitch(new_ch);
   
}



char.h:
   
   Ezután:
      void StartWarpNPCEvent();

   ezt:
      void                            ChannelSwitch(int new_ch);




char.cpp:

   Ezután:
      EVENTFUNC(warp_npc_event)
{
char_event_info* info = dynamic_cast<char_event_info*>( event->info );
if ( info == NULL )
{
sys_err( "warp_npc_event> <Factor> Null pointer" );
return 0;
}

LPCHARACTER ch = info->ch;

if (ch == NULL) { // <Factor>
return 0;
}

if (!ch->GetSectree())
{
ch->m_pkWarpNPCEvent = NULL;
return 0;
}

FuncCheckWarp f(ch);
if (f.Valid())
ch->GetSectree()->ForEachAround(f);

return passes_per_sec / 2;
}



   ezt:
      void CHARACTER::ChannelSwitch(int new_ch){
    long lAddr;
    long lMapIndex;
    WORD wPort;
    long x = this->GetX();
    long y = this->GetY();

    if (!CMapLocation::instance().Get(x, y, lMapIndex, lAddr, wPort))
    {
            sys_err("cannot find map location index %d x %d y %d name %s", lMapIndex, x, y, GetName());
            return;
    }
    if(lMapIndex >= 10000){
        return;
    }
   
    std::map<WORD, int>micha;
   
    for(int i = 0; i < 4; i++){ //replace with maximum channels -1   actual 1300x - 1330x
        for(int i2 = 2; i2 < 9; i2++){ //replace with your core values actual  13x02 - 13x08
            micha[13*1000 + i*100 + i2] = i+1;
        }       
    }
    //micha[13002] = 1;
    int chan;
    if(micha.find(wPort) != micha.end()){
        chan = micha[wPort];
    }else{return;}
    Stop();
    Save();
   
    if(GetSectree()){
        GetSectree()->RemoveEntity(this);
        ViewCleanup();
        EncodeRemovePacket(this);
    }
    TPacketGCWarp p;

    p.bHeader = HEADER_GC_WARP;
    p.lX = x;
    p.lY = y;
    p.lAddr = lAddr;
    p.wPort = (wPort - 100*(chan-1) + 100*(new_ch-1));
   

    GetDesc()->Packet(&p, sizeof(TPacketGCWarp));
}

És persze a forrás, mielőtt bárki azt hinné, hogy ennyire megy neked a C.

http://metin2dev.org/board/index.php?/topic/7388-rls-ingame-channel-switcher-like-wom2/


De szerintem a Pisti féle gombos megoldás sokkal elegánsabb és kényelmesebb. Csak egyszerűbb egy esc-t nyomi meg 1-et 2-t kattintani, mint mindig beírogatni hogy /channel...
"Tisztelet a kivételnek! Mindig tisztelet a kivételnek!"
"KezdÅ' vagyok, ne nézz le... (:"

2015-09-21, 13:29:31 #4 Last Edit: 2015-09-21, 16:54:37 by endox93
Itt a forrásos ch váltónál nekem akadt 1 kis problémám hogy map 1/2-n müködnek de pl orkok sd2 be nem mi lehet a gond?

Üzenet összefésülés: 2015-09-21, 16:54:37

Rájöttem , akinek esetleg ugyan ez a problémája volt annyi a dolga hogy azokat a map indexeket hozzá kell adni a ch1-2 stb.. config fájlokhoz amiken szeretné hogy működjön.
Skype : Derota2

Huzsihun hozzászólása, a forrás alapú channel switcher-ről:
[spoiler]
Quote from: huzsihun1997 on 2015-06-25, 17:21:54
De ettől még nem fogsz tudni CH-t váltani.. csak a gombja lesz bent... Nekemis bentvan a szerverben.
cmd.cp:

   Ezután:
      ACMD(do_warp);
   ezt:
      ACMD(do_channel_switch);


   Ezután:
      { "mall_close", do_mall_close, 0, POS_DEAD, GM_PLAYER },
    ezt:
    { "channel", do_channel_switch, 0, POS_DEAD, GM_PLAYER },
   


cmd_general.cpp:
   
   Ezután:
      ACMD(do_set_run_mode)
{
ch->SetNowWalking(false);
ch->SetWalking(false);
}


   ezt:
      ACMD(do_channel_switch)
{
   
    char arg1[256];
    one_argument(argument, arg1, sizeof(arg1));

    if (!*arg1)
            return;
   
    int new_ch;
    str_to_number(new_ch, arg1);
    if( new_ch <1 || new_ch >4)   // REPLACE 2 WITH YOUR MAX_CHANNEL
        return;
    if (!ch->IsPC())
        return;
    ch->ChannelSwitch(new_ch);
   
}



char.h:
   
   Ezután:
      void StartWarpNPCEvent();

   ezt:
      void                            ChannelSwitch(int new_ch);




char.cpp:

   Ezután:
      EVENTFUNC(warp_npc_event)
{
char_event_info* info = dynamic_cast<char_event_info*>( event->info );
if ( info == NULL )
{
sys_err( "warp_npc_event> <Factor> Null pointer" );
return 0;
}

LPCHARACTER ch = info->ch;

if (ch == NULL) { // <Factor>
return 0;
}

if (!ch->GetSectree())
{
ch->m_pkWarpNPCEvent = NULL;
return 0;
}

FuncCheckWarp f(ch);
if (f.Valid())
ch->GetSectree()->ForEachAround(f);

return passes_per_sec / 2;
}



   ezt:
      void CHARACTER::ChannelSwitch(int new_ch){
    long lAddr;
    long lMapIndex;
    WORD wPort;
    long x = this->GetX();
    long y = this->GetY();

    if (!CMapLocation::instance().Get(x, y, lMapIndex, lAddr, wPort))
    {
            sys_err("cannot find map location index %d x %d y %d name %s", lMapIndex, x, y, GetName());
            return;
    }
    if(lMapIndex >= 10000){
        return;
    }
   
    std::map<WORD, int>micha;
   
    for(int i = 0; i < 4; i++){ //replace with maximum channels -1   actual 1300x - 1330x
        for(int i2 = 2; i2 < 9; i2++){ //replace with your core values actual  13x02 - 13x08
            micha[13*1000 + i*100 + i2] = i+1;
        }       
    }
    //micha[13002] = 1;
    int chan;
    if(micha.find(wPort) != micha.end()){
        chan = micha[wPort];
    }else{return;}
    Stop();
    Save();
   
    if(GetSectree()){
        GetSectree()->RemoveEntity(this);
        ViewCleanup();
        EncodeRemovePacket(this);
    }
    TPacketGCWarp p;

    p.bHeader = HEADER_GC_WARP;
    p.lX = x;
    p.lY = y;
    p.lAddr = lAddr;
    p.wPort = (wPort - 100*(chan-1) + 100*(new_ch-1));
   

    GetDesc()->Packet(&p, sizeof(TPacketGCWarp));
}

[/spoiler]

A forrás alapú ch választóhoz írtam python scriptet, hogy leltárban legyen neki gombja.

Leltárba gomb berakása:

1,
constinfo.py-t megnyitod!

Beleírod ezt:

switchbutton = 0



2,
uiinventory.py-t megnyitod!

Rákeresel erre:

def __init__(self):


Aláírod a listába:

self.Switch = None



Rákeresel erre:

self.costumeButton = self.GetChild2("CostumeButton")


Aláírod ezt:

self.SwitchButton = self.GetChild2("SwitchButton")




Rákeresel erre a tömbre:

# Costume Button
if self.costumeButton:
self.costumeButton.SetEvent(ui.__mem_func__(self.ClickCostumeButton))


Aláírod ezt:

# Switch channel
if self.SwitchButton:
self.SwitchButton.SetEvent(ui.__mem_func__(self.ClickSwitchButton))

         

         
Rákeresel erre:

def ClickCostumeButton(self):



Alá írod a funkciót:

def ClickSwitchButton(self):
import uiChannel
if constInfo.switchbutton == 0:
constInfo.switchbutton = 1
a = uiChannel.ChannelChanger()
a.Show()
elif constInfo.switchbutton == 1:
constInfo.switchbutton = 0
a = uiChannel.ChannelChanger()
a.Hide()




3,
inventorywindow.py-t megnyitod!   

MallButton rész fölé írod ezt:

##SwitchButton
{
"name" : "SwitchButton",
"type" : "button",

"x" : 114, # írd át
"y" : 90, # írd át

"tooltip_text" : "Csatorna választó ",

"default_image" : "d:/ymir work/ui/game/TaskBar/Mall_Button_01.tga",
"over_image" : "d:/ymir work/ui/game/TaskBar/Mall_Button_02.tga",
"down_image" : "d:/ymir work/ui/game/TaskBar/Mall_Button_03.tga",
},

2015-09-24, 13:28:30 #6 Last Edit: 2015-09-24, 17:55:07 by [MOD]Rasen
Ezt a funciot be teszitek + a csatolmányom És végeredményt látjátok képen :)
Quote from: Pisti95 on 2015-09-21, 17:24:13
[spoiler]
Leltárba gomb berakása:

1,
constinfo.py-t megnyitod!

Beleírod ezt:

switchbutton = 0



2,
uiinventory.py-t megnyitod!

Rákeresel erre:

def __init__(self):


Aláírod a listába:

self.Switch = None



Rákeresel erre:

self.costumeButton = self.GetChild2("CostumeButton")


Aláírod ezt:

self.SwitchButton = self.GetChild2("SwitchButton")




Rákeresel erre a tömbre:

# Costume Button
if self.costumeButton:
self.costumeButton.SetEvent(ui.__mem_func__(self.ClickCostumeButton))


Aláírod ezt:

# Switch channel
if self.SwitchButton:
self.SwitchButton.SetEvent(ui.__mem_func__(self.ClickSwitchButton))

         

         
Rákeresel erre:

def ClickCostumeButton(self):



Alá írod a funkciót:

def ClickSwitchButton(self):
import uiChannel
if constInfo.switchbutton == 0:
constInfo.switchbutton = 1
a = uiChannel.ChannelChanger()
a.Show()
elif constInfo.switchbutton == 1:
constInfo.switchbutton = 0
a = uiChannel.ChannelChanger()
a.Hide()




3,
inventorywindow.py-t megnyitod!   

MallButton rész fölé írod ezt:

##SwitchButton
{
"name" : "SwitchButton",
"type" : "button",

"x" : 114, # írd át
"y" : 90, # írd át

"tooltip_text" : "Csatorna választó ",

"default_image" : "d:/ymir work/ui/game/TaskBar/Mall_Button_01.tga",
"over_image" : "d:/ymir work/ui/game/TaskBar/Mall_Button_02.tga",
"down_image" : "d:/ymir work/ui/game/TaskBar/Mall_Button_03.tga",
},
[/spoiler]

Én még anyit hozzá tennék h ehhez a funciohoz nem kötelező forrást babrálni. Föleg ha szeretné valaki 34k hoz is használni :) ahol úgye nincs forrás :) csatoltam egy fájlt ha azt is be teszitek és meg írjátok python kodot hozzá akkor nem kell se forrás se semi :) csak Pisti95 leltár gombja :). Akinek nem sikerül python részt írni de szeretné használni írjon rám
dis_maps = [
"season1/metin2_map_oxevent",
"season2/metin2_map_guild_inside01",
"season2/metin2_map_empirewar01",
"season2/metin2_map_empirewar02",
"season2/metin2_map_empirewar03",
"metin2_map_dragon_timeattack_01",
"metin2_map_dragon_timeattack_02",
"metin2_map_dragon_timeattack_03",
"metin2_map_skipia_dungeon_boss",
"metin2_map_skipia_dungeon_boss2",
"metin2_map_devilsCatacomb",
"metin2_map_deviltower1",
"metin2_map_t1",
"metin2_map_t2",
"metin2_map_t3",
"metin2_map_t4",
"metin2_map_t5",
"metin2_map_wedding_01",
"metin2_map_duel",
"metin2_map_orclabyrinth",
"metin2_map_n_flame_dungeon_01",
"metin2_map_n_snow_dungeon_01"
]


Van a fájlban egy ilyen rész ebben részben tudod meg adni hogy hol is lehesen ch cserélni. Nekem jelenleg ezzek vannak meg adva. + úgye a fő városok alapból :).

Végeredmény :
Im Vivicsi<3~Aki nem keress annak nem is hiányzok ~