Hikayeler

Reklam vermek için turkmmo@gmail.com

[TRDE İLK] OYUN İÇİ GM EDİT PANELİ - VezirSOFT

aliceylancy

Level 1
Üye
Katılım
26 Nis 2025
Konular
2
Mesajlar
4
Online süresi
49594s
Reaksiyon Skoru
9
Altın Konu
0
Başarım Puanı
10
TM Yaşı
11 Ay 28 Gün
MmoLira
612
DevLira
6

Metin2 EP, Valorant VP dahil tüm oyun ürünlerini en uygun fiyatlarla bulabilir, Item ve Karakterlerinizi hızlıca satabilirsiniz. HEMEN TIKLA!

VezirSOFT — GM Edit Paneli Kurulum Rehberi







1) İşlem sırası (özet)
  • Sunucu: cmd.cpp → ön bildirim + cmd_info satırı → cmd_gm.cpp → derle
  • İstemci: uigmitempanel.py + gmpanel_item.py → interfacemodule.py → game.py → root paketle



2) Sunucu — cmd.cpp

Adım A1 — Ön bildirim

Ne yapıyoruz: Derleyiciye do_item_gm7 fonksiyonunun varlığını bildiriyoruz.

Ara:
Kod:
ACMD(do_item);

Bulacağın örnek:
Kod:
ACMD(do_item);
ACMD(do_mob);

Yap:
Kod:
ACMD(do_item);
satırının hemen altına ekle:
Kod:
ACMD(do_item_gm7);

Adım A2 — Komut tablosu
Ne yapıyoruz: Sohbette /item7 yazılınca hangi fonksiyon ve GM seviyesi çalışacak, cmd_info[] içine yazıyoruz.

Ara:
Kod:
{ "item",        do_item,

Bulacağın örnek:
Kod:
{ "item",        do_item,        0,            POS_DEAD,    GM_GOD        },
{ "mob",        do_mob,            0,            POS_DEAD,    GM_HIGH_WIZARD    },

Yap: item satırının altına ekle:
Kod:
{ "item7",        do_item_gm7,        0,            POS_DEAD,    GM_GOD        },
Not: GM seviyesini kendi sunucuna göre (ör. GM_IMPLEMENTOR) değiştirebilirsin.



3) Sunucu — cmd_gm.cpp

Ne yapıyoruz: /item7 gövdesi: vnum veya isim, adet, ITEM_ATTRIBUTE_MAX_NUM kadar (tip, değer) çifti, ITEM_SOCKET_MAX_NUM kadar socket, CreateItem, SetForceAttribute, SetSocket, AutoGiveItem, log.

Ara:
Kod:
ACMD(do_item)
— klasik GM item komutu (vnum + adet).

Nereye: do_item fonksiyonunun kapatan
Kod:
}
ile bir sonraki
Kod:
ACMD(do_...)
satırı arasına aşağıdaki bloğun tamamını yapıştır.

Kod:
ACMD(do_item_gm7)
{
    const char * line = argument;
    char arg[256];

    line = one_argument(line, arg, sizeof(arg));
    if (!*arg)
    {
        ch->ChatPacket(CHAT_TYPE_INFO, "Usage: item7 <vnum|name> <count> [tip0 val0] x7 [socket0 socket1 socket2] (tas vnum, 0=bos)");
        return;
    }

    DWORD dwVnum = 0;
    if (isnhdigit(*arg))
        str_to_number(dwVnum, arg);
    else if (!ITEM_MANAGER::instance().GetVnum(arg, dwVnum))
    {
        ch->ChatPacket(CHAT_TYPE_INFO, "Item bulunamadi: %s", arg);
        return;
    }

    line = one_argument(line, arg, sizeof(arg));
    int iCount = 1;
    if (*arg)
    {
        str_to_number(iCount, arg);
        iCount = MINMAX(1, iCount, g_bItemCountLimit);
    }

    long attr_type[ITEM_ATTRIBUTE_MAX_NUM];
    long attr_val[ITEM_ATTRIBUTE_MAX_NUM];
    memset(attr_type, 0, sizeof(attr_type));
    memset(attr_val, 0, sizeof(attr_val));

    for (int i = 0; i < ITEM_ATTRIBUTE_MAX_NUM; ++i)
    {
        line = one_argument(line, arg, sizeof(arg));
        if (!*arg)
            break;
        str_to_number(attr_type[i], arg);

        line = one_argument(line, arg, sizeof(arg));
        if (!*arg)
            break;
        str_to_number(attr_val[i], arg);
    }

    LPITEM item = ITEM_MANAGER::instance().CreateItem(dwVnum, iCount, 0, true);
    if (!item)
    {
        ch->ChatPacket(CHAT_TYPE_INFO, "item7: #%u olusturulamadi.", dwVnum);
        return;
    }

    for (int i = 0; i < ITEM_ATTRIBUTE_MAX_NUM; ++i)
        item->SetForceAttribute(i, (BYTE) attr_type[i], (short) attr_val[i]);

    long socket_val[ITEM_SOCKET_MAX_NUM];
    memset(socket_val, 0, sizeof(socket_val));
    for (int s = 0; s < ITEM_SOCKET_MAX_NUM; ++s)
    {
        line = one_argument(line, arg, sizeof(arg));
        if (*arg)
            str_to_number(socket_val[s], arg);
    }

    for (int s = 0; s < ITEM_SOCKET_MAX_NUM; ++s)
        item->SetSocket(s, socket_val[s]);

#ifdef __WJ_PICKUP_ITEM_EFFECT__
    ch->AutoGiveItem(item, false, true);
#else
    ch->AutoGiveItem(item, false);
#endif

    LogManager::instance().ItemLog(ch, item, "GM_ITEM7", item->GetName());
    ch->ChatPacket(CHAT_TYPE_INFO, "item7: %s verildi.", item->GetName());
}

Derleme: cmd_gm.cpp zaten projendeyse ekstra .cpp ekleme; game core’u yeniden derle.

Ek dosya: Birçok sürümde cmd.h içinde ayrıca tanım gerekmez; ön bildirimler cmd.cpp içindeki ACMD(...) satırlarıyla gider.



4) İstemci — uigmitempanel.py

Ne yapıyoruz: Panel mantığı: arama, 7 efsun + 3 taş, açılır liste (alt satır gizleme), /item7 satırını net.SendChatPacket ile gönderme.

Yol:
Kod:
pack/root/uigmitempanel.py

Yap: Aşağıdaki spoiler içindeki metni uigmitempanel.py dosyasına komple yapıştır (UTF-8 veya cp1254, sunucu diline göre).

Kod:
# -*- coding: utf-8 -*-
import ui
import net
import player
import chr
import chat
import app
import item
import localeInfo


def _wnd_text(s):
    """WndMgr genelde byte string ister; unicode kaynakli 'Nesne' kalmasini onler."""
    if s is None:
        return ""
    if isinstance(s, str):
        return s
    if isinstance(s, unicode):
        try:
            return s.encode("cp1254")
        except UnicodeEncodeError:
            return s.encode("utf-8", "replace")
    return str(s)


def _short_label(s):
    if not isinstance(s, basestring):
        s = str(s)
    if len(s) > 52:
        return s[:49] + "..."
    return s


COMBO_DROP_MAX_H = 240


class GmComboBox(ui.ComboBox):
    """Satirda acilir secilebilir liste (Metin2 ComboBox)."""

    MAX_DROP = COMBO_DROP_MAX_H

    def __init__(self):
        # ComboBox.__init__ listeyi TOP_MOST'ta acar; Board cocuklari UI katmaninda
        # sonra cizildigi icin liste gorunurde altta kalir. Liste UI katmaninda olmali.
        ui.Window.__init__(self)
        self.x = 0
        self.y = 0
        self.width = 0
        self.height = 0
        self.isSelected = False
        self.isOver = False
        self.isListOpened = False
        self.event = lambda *arg: None
        self.enable = True
        self.textLine = ui.MakeTextLine(self)
        self.textLine.SetText(localeInfo.UI_ITEM)
        self.listBox = ui.ComboBox.ListBoxWithBoard("UI")
        self.listBox.SetPickAlways()
        self.listBox.SetParent(self)
        self.listBox.SetEvent(ui.__mem_func__(self.OnSelectItem))
        self.listBox.Hide()
        self._gm_z_panel = None
        self._gm_z_kind = None
        self._gm_z_idx = 0
        try:
            self.listBox.AddFlag("float")
        except Exception:
            pass
        if app.ENABLE_MOUSEWHEEL_EVENT:
            try:
                self.listBox.SetMouseWheelScrollEvent(ui.__mem_func__(self._on_combo_list_wheel))
            except Exception:
                pass

    def SetGmDropdownShield(self, panel, kind, index):
        """kind: 'attr' | 'stone' — acilir liste acikken alt satirlar panel tarafindan gizlenir."""
        self._gm_z_panel = panel
        self._gm_z_kind = kind
        self._gm_z_idx = index

    def _on_combo_list_wheel(self, mode):
        if not self.isListOpened:
            return
        n = self.listBox.GetItemCount()
        v = max(1, self.listBox.GetViewItemCount())
        mx = max(0, n - v)
        if mx <= 0:
            return
        bp = getattr(self.listBox, "basePos", 0)
        if mode == "UP":
            bp = max(0, bp - 1)
        else:
            bp = min(mx, bp + 1)
        self.listBox.SetBasePos(bp)

    def CloseListBox(self):
        self.isListOpened = False
        p = getattr(self, "_gm_z_panel", None)
        if p:
            try:
                p.OnGmComboDropdownClose(self)
            except Exception:
                pass
        if self.listBox:
            self.listBox.Hide()

    def OnSelectItem(self, index, name):
        self.CloseListBox()
        self.SetCurrentItem(_wnd_text(_short_label(name)))
        self.event(index)

    def InsertItem(self, index, name):
        self.listBox.InsertItem(index, name)
        n = self.listBox.GetItemCount()
        step = getattr(self.listBox, "stepSize", 17)
        h = min(max(n * step, 17), self.MAX_DROP)
        self.listBox.SetSize(self.width, h)
        self.listBox._LocateItem()

    def OnMouseLeftButtonUp(self):
        if not self.enable:
            return
        self.isSelected = False
        if self.isListOpened:
            self.CloseListBox()
        else:
            if self.listBox.GetItemCount() > 0:
                p = getattr(self, "_gm_z_panel", None)
                if p:
                    try:
                        p.OnGmComboDropdownOpen(self)
                    except Exception:
                        pass
                self.isListOpened = True
                self.listBox.Show()
                self.__ArrangeListBox()
                try:
                    self.listBox.SetTop()
                except Exception:
                    pass


# --- Ayarlar ---
MAX_ARAMA_SONUC = 50
ATTR_SATIR = 7
TAS_SOCKET_SAYISI = 3
ATTR_ROW_STEP = 26

# Sunucu APPLY tipi (byte) = ilk sütun; isimler sabit TR (uitooltip yerine)
GM_APPLY_OPTIONS = (
    (0, u"- Efsun yok -"),
    (1, u"Maximum HP"),
    (2, u"Maximum MP"),
    (3, u"Ya\u015fam Enerjisi"),
    (4, u"G\xfc\xe7"),
    (5, u"Dayan\u0131kl\u0131l\u0131k"),
    (6, u"\xc7eviklik"),
    (7, u"Sald\u0131r\u0131 H\u0131z\u0131"),
    (8, u"Hareket H\u0131z\u0131"),
    (9, u"B\xfcy\xfc H\u0131z\u0131"),
    (10, u"Hp \xdcretimi"),
    (11, u"MP \xdcretimi"),
    (12, u"Zehirlenme De\u011fi\u015fimi"),
    (13, u"Sersemletme \u015eans\u0131"),
    (14, u"Yava\u015fl\u0131k De\u011fi\u015fimi"),
    (15, u"Kritik Vuru\u015f \u015eans\u0131"),
    (16, u"Delici Vuru\u015f \u015eans\u0131"),
    (17, u"Yar\u0131 \u0130nsana Kar\u015f\u0131 G\xfc\xe7l\xfc"),
    (18, u"Hayvanlara Kar\u015f\u0131 G\xfc\xe7l\xfc"),
    (19, u"Orklara Kar\u015f\u0131 G\xfc\xe7l\xfc"),
    (20, u"Misiklere Kar\u015f\u0131 G\xfc\xe7l\xfc"),
    (21, u"\xd6l\xfcms\xfczlere Kar\u015f\u0131 G\xfc\xe7l\xfc"),
    (22, u"\u015eytanlara Kar\u015f\u0131 G\xfc\xe7l\xfc"),
    (23, u"%? Hasar Hp Taraf\u0131ndan Emilecek"),
    (24, u"%? Hasar Mp Taraf\u0131ndan Emilecek"),
    (25, u"D\xfc\u015fmandan Sp \xe7alma \u015eans\u0131"),
    (26, u"%? Vururken Sp Alma \u015eans\u0131"),
    (27, u"Beden Kar\u015f\u0131s\u0131nda Atak Bloklanmas\u0131"),
    (28, u"Oklardan Korunma \u015eans\u0131"),
    (29, u"K\u0131l\u0131\xe7 Savunmas\u0131"),
    (30, u"\xc7ift El Savunma"),
    (31, u"Han\xe7er Savunmas\u0131"),
    (32, u"\xc7an Savunmas\u0131"),
    (33, u"Yelpaze Savunmas\u0131"),
    (34, u"Oka Kar\u015f\u0131 Dayan\u0131kl\u0131l\u0131k"),
    (35, u"Ate\u015fe Kar\u015f\u0131 Dayan\u0131kl\u0131l\u0131k"),
    (36, u"\u015eim\u015fek Kar\u015f\u0131 Dayan\u0131kl\u0131l\u0131k"),
    (37, u"B\xfcy\xfcye Kar\u015f\u0131 Dayan\u0131kl\u0131l\u0131k"),
    (38, u"R\xfczgara Kar\u015f\u0131 Dayan\u0131kl\u0131l\u0131k"),
    (39, u"V\xfccut Darbelerini Yans\u0131tma \u015eans\u0131"),
    (40, u"Lanet Yans\u0131tmas\u0131"),
    (41, u"Giftwiderstand"),
    (42, u"Sp Y\xfcklemesi %? De\u011fi\u015fti"),
    (43, u"%? Exp Bonus \u015eans\u0131"),
    (44, u"% Kat Yang D\xfc\u015fme \u015eans\u0131"),
    (45, u"% Kat E\u015fya d\xfc\u015fme \u015eans\u0131"),
    (46, u"\u0130ksir %? Etki G\xf6sterdi"),
    (47, u"Hp Y\xfcklemesi %? De\u011fi\u015fti"),
    (48, u"Sersemlik Ba\u011f\u0131\u015f\u0131kl\u0131k"),
    (49, u"Yava\u015flatma Ba\u011f\u0131\u015f\u0131kl\u0131k"),
    (50, u"Yere D\xfc\u015fme Ba\u011f\u0131\u015f\u0131kl\u0131k"),
    (51, u"UNKNOW_TYPE[51]"),
    (52, u"Yay Menzili +? Metre"),
    (53, u"Sald\u0131r\u0131 De\u011feri +"),
    (54, u"Savunma +"),
    (55, u"B\xfcy\xfcl\xfc Sald\u0131r\u0131 De\u011feri +"),
    (56, u"B\xfcy\xfcl\xfc Savunma De\u011feri +"),
    (57, u"UNKNOW_TYPE[57]"),
    (58, u"Max. Dayan\u0131kl\u0131l\u0131k"),
    (59, u"Sava\u015f\xe7\u0131lara Kar\u015f\u0131 G\xfc\xe7l\xfc"),
    (60, u"Ninjalara Kar\u015f\u0131 G\xfc\xe7l\xfc"),
    (61, u"Suralara Kar\u015f\u0131 G\xfc\xe7l\xfc"),
    (62, u"\u015eamanlara Kar\u015f\u0131 G\xfc\xe7l\xfc"),
    (63, u"Yarat\u0131klara Kar\u015f\u0131 G\xfc\xe7l\xfc"),
    (64, u"Sald\u0131r\u0131 De\u011feri +?%"),
    (65, u"Savunma +?%"),
    (66, u"EXP +?%"),
    (67, u"Elde Edilen Nesne Kat Say\u0131s\u0131"),
    (68, u"Elde Edilen Yang Kat Say\u0131s\u0131"),
    (69, u"UNKNOW_TYPE[69]"),
    (70, u"UNKNOW_TYPE[70]"),
    (71, u"Beceri Hasar\u0131"),
    (72, u"Ortalama Zarar"),
    (73, u"Tekrarlanan Beceri Hasar\u0131na Kar\u015f\u0131 Koyma"),
    (74, u"Ortalama Zarara Direni\u015f"),
    (75, u"UNKNOW_TYPE[75]"),
    (76, u"\u0130cafe Exp Bonus +?%"),
    (77, u"E\u015fya Ele Ge\xe7irme Art\u0131\u015f\u0131 ?/2"),
    (78, u"Sava\u015f\xe7\u0131 Sald\u0131r\u0131lar\u0131na Kar\u015f\u0131 Savunma \u015eans\u0131"),
    (79, u"Ninja Sald\u0131r\u0131lar\u0131na Kar\u015f\u0131 Savunma \u015eans\u0131"),
    (80, u"Sura Sald\u0131r\u0131lar\u0131na Kar\u015f\u0131 Savunma \u015eans\u0131"),
    (81, u"\u015eaman Sald\u0131r\u0131lar\u0131na Kar\u015f\u0131 Savunma \u015eans\u0131"),
)

_itemdesc_cache = None


def _load_itemdesc():
    global _itemdesc_cache
    if _itemdesc_cache is not None:
        return _itemdesc_cache
    _itemdesc_cache = {}
    path = app.GetLocalePath() + "/itemdesc.txt"
    try:
        f = open(path, "r")
    except IOError:
        return _itemdesc_cache
    for line in f:
        line = line.strip()
        if not line or line.startswith("#"):
            continue
        parts = line.split("\t")
        if len(parts) < 2:
            continue
        try:
            vid = int(parts[0].strip())
            name = parts[1].strip()
            if name:
                _itemdesc_cache[vid] = name
        except ValueError:
            continue
    f.close()
    return _itemdesc_cache


def _build_apply_list():
    return list(GM_APPLY_OPTIONS)


def _build_metin_list(desc_dict):
    out = [(0, "- Tas yok -")]
    for vnum, name in sorted(desc_dict.iteritems(), key=lambda x: x[1].lower()):
        if item.IsMetin(vnum):
            out.append((vnum, "%s  (%d)" % (name, vnum)))
    return out


def _search_items(desc_dict, needle, limit):
    if not needle:
        return []
    n = needle.lower()
    res = []
    for vnum, name in desc_dict.iteritems():
        if n in name.lower():
            res.append((vnum, name))
    res.sort(key=lambda x: x[1].lower())
    return res[:limit]


class GmItemPanel(ui.ScriptWindow):

    def __init__(self):
        ui.ScriptWindow.__init__(self)
        self.board = None
        self.searchEdit = None
        self.resultList = None
        self.selectedLabel = None
        self.countEdit = None
        self.spawnBtn = None
        self.cancelBtn = None
        self.btnSearch = None
        self.previewImg = None
        self.selectedVnum = 0
        self._attr_apply = [0] * ATTR_SATIR
        self._stone_vnum = [0] * TAS_SOCKET_SAYISI
        self._attr_combos = []
        self._attr_val_edits = []
        self._attr_pct_edits = []
        self._stone_combos = []
        self._apply_items = []
        self._metin_items = []
        self.resultScroll = None
        self._dyn = []
        self._attr_row_blocks = []
        self._stone_row_blocks = []
        self._stone_title_line = None
        self._gm_footer_btns = []
        self._gm_dd_hidden = []

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

    def _dyn_add(self, w):
        self._dyn.append(w)

    def _gm_dd_restore(self):
        for w in getattr(self, "_gm_dd_hidden", []):
            try:
                w.Show()
            except Exception:
                pass
        self._gm_dd_hidden = []

    def OnGmComboDropdownClose(self, opener=None):
        self._gm_dd_restore()

    def OnGmComboDropdownOpen(self, opener):
        for cb in self._attr_combos + self._stone_combos:
            if cb is not opener and getattr(cb, "isListOpened", False):
                try:
                    cb.CloseListBox()
                except Exception:
                    pass
        self._gm_dd_restore()
        self._gm_dd_hidden = []
        k = getattr(opener, "_gm_z_kind", None)
        idx = getattr(opener, "_gm_z_idx", 0)
        to_hide = []
        if k == "attr":
            for j in xrange(idx + 1, ATTR_SATIR):
                to_hide.extend(self._attr_row_blocks[j])
            if self._stone_title_line:
                to_hide.append(self._stone_title_line)
            for blk in self._stone_row_blocks:
                to_hide.extend(blk)
            to_hide.extend(self._gm_footer_btns)
        elif k == "stone":
            for j in xrange(idx + 1, TAS_SOCKET_SAYISI):
                to_hide.extend(self._stone_row_blocks[j])
            to_hide.extend(self._gm_footer_btns)
        for w in to_hide:
            if w is None:
                continue
            try:
                w.Hide()
                self._gm_dd_hidden.append(w)
            except Exception:
                pass

    def LoadWindow(self):
        try:
            py = ui.PythonScriptLoader()
            py.LoadScriptFile(self, "uiscript/gmpanel_item.py")
        except:
            import exception
            exception.Abort("GmItemPanel.LoadWindow")

        try:
            self.board = self.GetChild("Board")
            self.searchEdit = self.GetChild("SearchEdit")
            self.resultList = self.GetChild("ResultList")
            self.selectedLabel = self.GetChild("SelectedLabel")
            self.countEdit = self.GetChild("CountValue")
            self.spawnBtn = self.GetChild("SpawnButton")
            self.cancelBtn = self.GetChild("CancelButton")
            self.btnSearch = self.GetChild("SearchButton")
            self.btnSearch.SetEvent(ui.__mem_func__(self.OnSearch))
            self.resultScroll = self.GetChild("ResultScrollBar")
        except:
            import exception
            exception.Abort("GmItemPanel.Bind")

        self.resultScroll.SetScrollBarSize(100)
        self.resultScroll.SetScrollEvent(ui.__mem_func__(self._on_result_scroll))
        if app.ENABLE_MOUSEWHEEL_EVENT:
            self.resultList.SetMouseWheelScrollEvent(ui.__mem_func__(self._on_result_list_wheel))

        self.board.SetCloseEvent(ui.__mem_func__(self.Close))
        self.spawnBtn.SetEvent(ui.__mem_func__(self.OnSpawn))
        self.cancelBtn.SetEvent(ui.__mem_func__(self.Close))
        self.searchEdit.SetReturnEvent(ui.__mem_func__(self.OnSearch))
        self.searchEdit.SetEscapeEvent(ui.__mem_func__(self.Close))
        self.countEdit.SetEscapeEvent(ui.__mem_func__(self.Close))
        self.resultList.SetEvent(ui.__mem_func__(self.OnPickResult))

        desc = _load_itemdesc()
        self._apply_items = _build_apply_list()
        self._metin_items = _build_metin_list(desc)
        self.previewImg = ui.ImageBox()
        self.previewImg.SetParent(self.board)
        self.previewImg.SetPosition(300, 168)
        try:
            self.previewImg.AddFlag("not_pick")
        except Exception:
            pass
        self.previewImg.Hide()

        t = ui.TextLine()
        t.SetParent(self.board)
        t.SetPosition(12, 216)
        t.SetText("Efsunlar:")
        t.Show()
        self._dyn_add(t)

        base_y = 232
        self._attr_row_blocks = []
        for i in xrange(ATTR_SATIR):
            row_y = base_y + i * ATTR_ROW_STEP
            lb = ui.TextLine()
            lb.SetParent(self.board)
            lb.SetPosition(12, row_y + 3)
            lb.SetText("%d." % (i + 1))
            lb.Show()
            self._dyn_add(lb)

            cb = GmComboBox()
            cb.SetParent(self.board)
            cb.SetPosition(32, row_y)
            cb.SetSize(214, 18)
            cb.SetGmDropdownShield(self, "attr", i)
            self._fill_gm_combo(cb, self._apply_items)
            cb.SetEvent(lambda aid, r=i: self._on_attr_apply(r, aid))
            cb.Enable()
            cb.Show()
            self._attr_combos.append(cb)

            sb = ui.SlotBar()
            sb.SetParent(self.board)
            sb.SetPosition(256, row_y)
            sb.SetSize(48, 18)
            sb.Show()
            self._dyn_add(sb)
            ev = ui.EditLine()
            ev.SetParent(sb)
            ev.SetPosition(3, 3)
            ev.SetSize(42, 16)
            ev.SetMax(5)
            ev.SetNumberMode()
            ev.Show()
            self._attr_val_edits.append(ev)
            self._dyn_add(ev)

            sb2 = ui.SlotBar()
            sb2.SetParent(self.board)
            sb2.SetPosition(310, row_y)
            sb2.SetSize(44, 18)
            sb2.Show()
            self._dyn_add(sb2)
            pv = ui.EditLine()
            pv.SetParent(sb2)
            pv.SetPosition(3, 3)
            pv.SetSize(38, 16)
            pv.SetMax(4)
            pv.SetNumberMode()
            pv.SetText("100")
            pv.Show()
            self._attr_pct_edits.append(pv)
            self._dyn_add(pv)
            self._attr_row_blocks.append([lb, cb, sb, sb2])

        ts = ui.TextLine()
        ts.SetParent(self.board)
        ts.SetPosition(12, base_y + ATTR_SATIR * ATTR_ROW_STEP + 14)
        ts.SetText("Taslar (max %d socket):" % TAS_SOCKET_SAYISI)
        ts.Show()
        self._dyn_add(ts)
        self._stone_title_line = ts

        stone_y = base_y + ATTR_SATIR * ATTR_ROW_STEP + 34
        self._stone_row_blocks = []
        for s in xrange(TAS_SOCKET_SAYISI):
            sy = stone_y + s * ATTR_ROW_STEP
            lb = ui.TextLine()
            lb.SetParent(self.board)
            lb.SetPosition(12, sy + 3)
            lb.SetText("Tas %d:" % (s + 1))
            lb.Show()
            self._dyn_add(lb)

            cb = GmComboBox()
            cb.SetParent(self.board)
            cb.SetPosition(52, sy)
            cb.SetSize(368, 18)
            cb.SetGmDropdownShield(self, "stone", s)
            self._fill_gm_combo(cb, self._metin_items)
            cb.SetEvent(lambda vid, idx=s: self._on_stone_pick(idx, vid))
            cb.Enable()
            cb.Show()
            self._stone_combos.append(cb)
            self._stone_row_blocks.append([lb, cb])

        self._gm_footer_btns = [self.spawnBtn, self.cancelBtn]

        self._sync_result_scroll()

    def _fill_gm_combo(self, combo, pairs):
        combo.ClearItem()
        for k, t in pairs:
            combo.InsertItem(k, _wnd_text(t))
        if pairs:
            combo.SetCurrentItem(_wnd_text(_short_label(pairs[0][1])))

    def _on_attr_apply(self, row, apply_id):
        self._attr_apply[row] = apply_id

    def _on_stone_pick(self, slot_idx, vnum):
        self._stone_vnum[slot_idx] = vnum

    def _result_scroll_max(self):
        n = self.resultList.GetItemCount()
        v = max(1, self.resultList.GetViewItemCount())
        return max(0, n - v)

    def _on_result_scroll(self):
        mx = self._result_scroll_max()
        if mx <= 0:
            self.resultList.SetBasePos(0)
            return
        pos = self.resultScroll.GetPos()
        bp = int(round(pos * mx))
        if bp > mx:
            bp = mx
        self.resultList.SetBasePos(bp)

    def _on_result_list_wheel(self, mode):
        mx = self._result_scroll_max()
        if mx <= 0:
            return
        bp = getattr(self.resultList, "basePos", 0)
        if mode == "UP":
            bp = max(0, bp - 1)
        else:
            bp = min(mx, bp + 1)
        self.resultList.SetBasePos(bp)
        self.resultScroll.SetPos(float(bp) / float(mx))

    def _sync_result_scroll(self):
        n = self.resultList.GetItemCount()
        if n == 0:
            self.resultScroll.Hide()
            self.resultScroll.SetPos(0.0)
            self.resultList.SetBasePos(0)
            return
        mx = self._result_scroll_max()
        if mx <= 0:
            self.resultScroll.Hide()
            self.resultScroll.SetPos(0.0)
            self.resultList.SetBasePos(0)
            return
        self.resultScroll.Show()
        v = max(1, self.resultList.GetViewItemCount())
        self.resultScroll.SetMiddleBarSize(min(1.0, float(v) / float(n)))
        bp = getattr(self.resultList, "basePos", 0)
        if bp > mx:
            bp = mx
            self.resultList.SetBasePos(bp)
        self.resultScroll.SetPos(float(bp) / float(mx))

    def OnSearch(self):
        desc = _load_itemdesc()
        if not desc:
            chat.AppendChat(chat.CHAT_TYPE_INFO, "[GM] itemdesc.txt yuklenemedi: %s" % (app.GetLocalePath() + "/itemdesc.txt"))
            return
        q = self.searchEdit.GetText().strip()
        self.resultList.ClearItem()
        self.resultList.SetBasePos(0)
        self.resultScroll.SetPos(0.0)
        found = _search_items(desc, q, MAX_ARAMA_SONUC)
        for vnum, name in found:
            self.resultList.InsertItem(vnum, "%d  |  %s" % (vnum, name))
        self._sync_result_scroll()
        if not found:
            chat.AppendChat(chat.CHAT_TYPE_INFO, "[GM] Sonuc yok.")

    def OnPickResult(self, vnum, text):
        self.selectedVnum = vnum
        self.selectedLabel.SetText("Secilen: %s" % text[:60])
        self._refresh_preview()

    def _refresh_preview(self):
        if self.selectedVnum <= 0:
            self.previewImg.Hide()
            return
        item.SelectItem(self.selectedVnum)
        fn = item.GetIconImageFileName()
        if not fn or fn == "Noname":
            self.previewImg.Hide()
            return
        try:
            self.previewImg.LoadImage(fn)
            self.previewImg.Show()
        except RuntimeError:
            self.previewImg.Hide()

    def Destroy(self):
        if self.board:
            self.board.SetCloseEvent(None)
        if self.spawnBtn:
            self.spawnBtn.SetEvent(None)
        if self.cancelBtn:
            self.cancelBtn.SetEvent(None)
        if self.btnSearch:
            self.btnSearch.SetEvent(None)
        if self.searchEdit:
            self.searchEdit.SetReturnEvent(ui.Window.NoneMethod)
            self.searchEdit.SetEscapeEvent(ui.Window.NoneMethod)
        if self.countEdit:
            self.countEdit.SetEscapeEvent(ui.Window.NoneMethod)
        if self.resultList:
            self.resultList.SetEvent(None)
            if app.ENABLE_MOUSEWHEEL_EVENT:
                self.resultList.SetMouseWheelScrollEvent(None)
        if self.resultScroll:
            self.resultScroll.SetScrollEvent(None)
        for cb in self._attr_combos:
            try:
                cb.CloseListBox()
            except Exception:
                pass
            try:
                cb.SetEvent(None)
                cb.Destroy()
            except Exception:
                pass
        for cb in self._stone_combos:
            try:
                cb.CloseListBox()
            except Exception:
                pass
            try:
                cb.SetEvent(None)
                cb.Destroy()
            except Exception:
                pass
        self._attr_combos = []
        self._stone_combos = []
        for w in self._dyn:
            try:
                w.Destroy()
            except Exception:
                pass
        self._dyn = []
        if self.previewImg:
            try:
                self.previewImg.Destroy()
            except Exception:
                pass
        self.previewImg = None
        self.ClearDictionary()
        self.board = None
        self.searchEdit = None
        self.resultList = None
        self.selectedLabel = None
        self.countEdit = None
        self.spawnBtn = None
        self.cancelBtn = None
        self.btnSearch = None

    def Open(self):
        if not chr.IsGameMaster(player.GetMainCharacterIndex()):
            return
        self.SetCenterPosition()
        self.SetTop()
        self.Show()
        self.searchEdit.SetFocus()

    def Close(self):
        self._gm_dd_restore()
        for cb in self._attr_combos + self._stone_combos:
            try:
                cb.CloseListBox()
            except Exception:
                pass
        self.Hide()
        return True

    def Toggle(self):
        if not chr.IsGameMaster(player.GetMainCharacterIndex()):
            return
        if self.IsShow():
            self.Close()
        else:
            self.Open()

    def OnSpawn(self):
        if not chr.IsGameMaster(player.GetMainCharacterIndex()):
            return
        if self.selectedVnum <= 0:
            chat.AppendChat(chat.CHAT_TYPE_INFO, "[GM] Once listeden item secin.")
            return
        c = self.countEdit.GetText().strip()
        if not c:
            c = "1"
        self._refresh_preview()
        cmd = "/item7 %d %s" % (self.selectedVnum, c)
        for i in xrange(ATTR_SATIR):
            t = self._attr_apply[i]
            try:
                val = int(self._attr_val_edits[i].GetText() or 0)
            except ValueError:
                val = 0
            try:
                pct = int(self._attr_pct_edits[i].GetText() or 100)
            except ValueError:
                pct = 100
            if pct <= 0:
                pct = 100
            final = (val * pct) / 100
            cmd += " %d %d" % (t, final)
        for s in xrange(TAS_SOCKET_SAYISI):
            cmd += " %d" % (self._stone_vnum[s])
        net.SendChatPacket(cmd)

    def OnPressEscapeKey(self):
        for cb in self._attr_combos + self._stone_combos:
            try:
                if cb.isListOpened:
                    cb.CloseListBox()
                    return True
            except Exception:
                pass
        return self.Close()



5) İstemci — uiscript/gmpanel_item.py

Ne yapıyoruz: Pencere iskeleti (GmItemPanel): başlık, arama, liste, scrollbar, adet, Ekle / İptal. Efsun/taş satırları LoadWindow içinde Python ile eklenir.

Yol:
Kod:
pack/root/uiscript/gmpanel_item.py

Kod:
import uiScriptLocale

W = 440
H = 650

window = {
    "name" : "GmItemPanel",
    "x" : 0,
    "y" : 0,
    "style" : ("movable", "float",),
    "width" : W,
    "height" : H,
    "children" :
    (
        {
            "name" : "Board",
            "type" : "board_with_titlebar",
            "x" : 0,
            "y" : 0,
            "width" : W,
            "height" : H,
            "title" : "VezirSOFT - GM Edit Paneli",
            "children" :
            (
                {
                    "name" : "SearchLabel",
                    "type" : "text",
                    "x" : 12,
                    "y" : 30,
                    "text" : "Item adi ara:",
                },
                {
                    "name" : "SearchSlot",
                    "type" : "slotbar",
                    "x" : 12,
                    "y" : 46,
                    "width" : 220,
                    "height" : 18,
                    "children" :
                    (
                        {
                            "name" : "SearchEdit",
                            "type" : "editline",
                            "x" : 3,
                            "y" : 3,
                            "width" : 214,
                            "height" : 18,
                            "input_limit" : 40,
                        },
                    ),
                },
                {
                    "name" : "SearchButton",
                    "type" : "button",
                    "x" : 242,
                    "y" : 44,
                    "width" : 70,
                    "height" : 21,
                    "text" : "Ara",
                    "default_image" : "d:/ymir work/ui/public/middle_button_01.sub",
                    "over_image" : "d:/ymir work/ui/public/middle_button_02.sub",
                    "down_image" : "d:/ymir work/ui/public/middle_button_03.sub",
                },
                {
                    "name" : "ResultList",
                    "type" : "listbox",
                    "x" : 12,
                    "y" : 72,
                    "width" : 372,
                    "height" : 100,
                },
                {
                    "name" : "ResultScrollBar",
                    "type" : "scrollbar",
                    "x" : 388,
                    "y" : 72,
                    "size" : 100,
                },
                {
                    "name" : "SelectedLabel",
                    "type" : "text",
                    "x" : 12,
                    "y" : 178,
                    "text" : "Secilen: (liste tikla)",
                },
                {
                    "name" : "CountLabel",
                    "type" : "text",
                    "x" : 12,
                    "y" : 196,
                    "text" : "Adet",
                },
                {
                    "name" : "CountSlot",
                    "type" : "slotbar",
                    "x" : 52,
                    "y" : 194,
                    "width" : 50,
                    "height" : 18,
                    "children" :
                    (
                        {
                            "name" : "CountValue",
                            "type" : "editline",
                            "x" : 3,
                            "y" : 3,
                            "width" : 44,
                            "height" : 18,
                            "input_limit" : 4,
                            "only_number" : 1,
                            "text" : "1",
                        },
                    ),
                },
                {
                    "name" : "SpawnButton",
                    "type" : "button",
                    "x" : -70,
                    "y" : 612,
                    "width" : 61,
                    "height" : 21,
                    "horizontal_align" : "center",
                    "text" : "Ekle",
                    "default_image" : "d:/ymir work/ui/public/middle_button_01.sub",
                    "over_image" : "d:/ymir work/ui/public/middle_button_02.sub",
                    "down_image" : "d:/ymir work/ui/public/middle_button_03.sub",
                },
                {
                    "name" : "CancelButton",
                    "type" : "button",
                    "x" : 70,
                    "y" : 612,
                    "width" : 61,
                    "height" : 21,
                    "horizontal_align" : "center",
                    "text" : uiScriptLocale.CANCEL,
                    "default_image" : "d:/ymir work/ui/public/middle_button_01.sub",
                    "over_image" : "d:/ymir work/ui/public/middle_button_02.sub",
                    "down_image" : "d:/ymir work/ui/public/middle_button_03.sub",
                },
            ),
        },
    ),
}



6) İstemci — interfacemodule.py

B3-1 — Import
Ara:
Diğer
Kod:
import
satırları.
Kod:
import uigmitempanel
yoksa ekle.

B3-2 — Oluşturma (Interface.__init__)
Ara:
Kod:
self.dlgPointReset.Hide()

Hemen altına:
Kod:
        self.dlgItemEdit = uigmitempanel.GmItemPanel()
        self.dlgItemEdit.LoadWindow()
        self.dlgItemEdit.Hide()

B3-3 — Destroy
Ara:
Kod:
self.dlgPointReset.Destroy()
Altına:
Kod:
        if self.dlgItemEdit:
            self.dlgItemEdit.Destroy()

B3-4 — del
Ara:
Kod:
del self.dlgPointReset
Altına:
Kod:
del self.dlgItemEdit

B3-5 — Toggle
Ara:
Kod:
def OpenPointResetDialog(self):
civarı / Calling Functions bölümü.
Ekle:
Kod:
    def ToggleItemEditPanel(self):
        if self.dlgItemEdit:
            self.dlgItemEdit.Toggle()

B3-6 — Toplu Hide
Çok pencerenin
Kod:
.Hide()
olduğu yere:
Kod:
        if self.dlgItemEdit:
            self.dlgItemEdit.Hide()



7) İstemci — game.py

Ara:
Kod:
onPressKeyDict[app.DIK_F4]

Örnek altına ekle:
Kod:
        onPressKeyDict[app.DIK_F10]    = lambda : self.interface.ToggleItemEditPanel()
F10 doluysa F11 vb. kullan; önemli olan ToggleItemEditPanel çağrısı.



8) Sohbet formatı (uyum)

Panel Ekle deyince örnek yapı:
  • Kod:
    /item7 <vnum> <adet>
  • 7 kez:
    Kod:
    <apply_tipi> <final_deger>
    — final = değer × yüzde / 100
  • Kod:
    <socket0> <socket1> <socket2>
Sunucu one_argument ile sırayla okur; apply sayısı ITEM_ATTRIBUTE_MAX_NUM, socket ITEM_SOCKET_MAX_NUM.



9) Özet tablo
Dosyaİş
cmd.cppACMD(do_item_gm7); + cmd_info "item7"
cmd_gm.cppdo_item bitişi + ACMD(do_item_gm7)
uigmitempanel.pyÜstteki spoiler tam metin
gmpanel_item.pyÜstteki uiscript tam metin
interfacemodule.pyImport, init, Destroy, del, Toggle, Hide
game.pyTuş → ToggleItemEditPanel


 
Tesekkurler.
 
Teşekkürler
 
Yapay zeka çoğu daha özgün yapabilirsek daha iyi olur. Sadece gorsel video arat ekle arat ekle örnek.

Eline saglik
 
PAYLAŞIM İÇİN TEŞEKKÜRLER,ELİNE SAĞLIK.
 

Şu an konuyu görüntüleyenler (Toplam : 1, Üye: 0, Misafir: 1)

Geri
Üst