Перейти к контенту

Рекомендуемые сообщения

Тема для обсуждения скриптов всего и всех в серии игр STALKER.


Задавая вопрос (!):
1. Внимательно изучите суть вопроса. Вопрос должен соответствовать выбранной Вами темы. Это поможет сохранить порядок и читабельность темы, а также облегчит поиск и понимание сего;
2. Изучите то, что уже есть в теме (пролистайте "руками", воспользуйтесь поиском на форуме);
3. Изучите информацию которая может вам помочь:

 
 

Stalkerin. Там есть много хороших статей касательно данной темы.
Уроки по модостроению. Есть рабочие примеры готовых скриптов различного назначения.

 

Справочное руководство по языку Lua 5.1
https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual/ru
Справочник по функциям и классам. Собрано много информации по функциям и классам, не всем, но по основные сведения предоставлены.

4. Дабы не превращать обсуждение в "кашу" разной информативной направленности, задавайте несколько вопросов по порядку (в разных постах) после того, как получите ответ на предыдущий вопрос;
5. "Спасибо" и тому подобное - будьте так любезны в ПМ. Если не любите писать в ПМ, в конце вопроса напишите фразу: "Заранее спасибо!" - или что-то в этом духе;
6. ПОЖАЛУЙСТА! Указывайте, для какой игры Вам необходима информация (ТЧ, ЧН, ЗП), если стоит мод - укажите название мода;
7. Если Вы что-то сделали и результат не такой, какой Вами задумывался, то, пожалуйста, приводите коды которые Вы изменяли/писали целиком! Это поможет другим правильно ответить на Ваш вопрос, а также оградит Вас от лишней писанины.
8. Оформляйте сообщение. Пользуйтесь тегами для того, чтобы отделить код от текста. Пишите грамотно - ПОЛЬЗУЙТЕСЬ ЗНАКАМИ ПРЕПИНАНИЯ.
9. И помните: «Правильно заданный вопрос – половина ответа».

 

Какие вопросы следует задавать, а какие нет...

 

Задавайте вопросы, которые касаются непосредственно скриптов и их работы, т.е. Вы что-то делаете, а у Вас что-то не получается, при этом у Вас на руках должен быть хотя бы какой-то код, свидетельствующий о Вашей причастности к вопросу.

 

Вопросы которые будут удалятся, следовательно их задавать не нужно:
-- Где находится та или иная функция?
Для ответа используем поиск по словам среди файлов оригинальной игры или мода, если объект поиска относится к нему, при помощью программы, которая Вам наиболее симпатизирует;
-- Как сделать что-то/то-то?
С подобными вопросами, либо в "ковырялки", где Вам вероятнее всего так же не ответят, либо выдвигаем мысли, подкреплённые теорией, практикой (идеальный вариант) и здравым рассудком;
-- Вопросы со смыслом: "сделайте", "совместите" и подобными глаголами повелительного наклонения.
-- К тому же удалению будут подвергаться вопросы, в которых масштабно не используются теги, для отделения кода и цитат от основного текста, а также не вписан в спойлер код размером превышающие семь строк.
Ответ на возможно возникший вопрос: В какую тему можно обратиться по поводу логики и спавна объектов?
В тему "ковырялок" соответствующей версии игры, для которой Вы задаёте вопрос.

И последнее: очень рекомендовано к прочтению Правила форума
 


  • Спасибо 1
  • Полезно 2
Ссылка на комментарий

@naxac, вопрос как к специалисту. Безлоговый вылет при загрузке любого сохранения, но при этом при перезаходе в игру этот же любой сейв грузится нормально. Я понимаю, что телепатов нет, но хотелось бы знать к чему такие симптомы. Я так понимаю, в сейв пишется что-то непотребное, которое потом грузится нормально... Куда хоть копать в первую очередь? Net_spawn функции, bind-скрипты? Если бы вылет был стабильным, а так-то оно грузится... со второго раза.

Изменено пользователем Капрал Хикс
Ссылка на комментарий

@naxac Сменил класс для двух сброшенных артефактов: вылет "нет объекта ГГ" при проверке дистанции в измененном [se_artefact.script]. Как такое может быть, если ГГ грузится первым?

Изменено пользователем Norman Eisenherz

Мини-моды: ТЧ ЧН ЗП

Шпаргалка

Ссылка на комментарий

@Norman Eisenherz , ты используешь переменную клиентского актера db.actor. В момент появления серверного объекта артефакта клиентского объекта актера ещё нет. Используй либо серверный объект актера alife():actor(), либо проверку на наличие db.actor.

@Капрал Хикс , может быть, на net_destroy какое-нибудь непотребство происходит? В какой-нибудь схеме сбой, или в каком-нибудь биндере?... Ещё, вроде, что-то такое было, если не убрать перед дестроем статик с экрана, добавленный через AddDialogToRender.

Изменено пользователем naxac
  • Полезно 3

Аддон для ОП-2.09.2: Яндекс/Google/GitHub

naxac.gif

Ссылка на комментарий

Что-то туплю видимо, давно lua не ковырял :biggrin:

 

Есть локальная функция в модуле:

local function myfunc()
    print("myfunc !!!")
end

Нужно вызвать ее по имени. Но, имя генерируется в другом месте. Первая мысль была сделать просто ["myfunc"](), но не сработало, как и this["myfunc"]()

Так, как сделать? Через loadstring что ли? loadstring(script_name()..".myfunc()")() выглядит как дичь же :biggrin: (но работает, правда не с локальными функциями, что логично)

Ссылка на комментарий

Такой вопрос...

Метод self.start_btn:SetText("") для ui_main_menu.script поддерживает кириллицу вот тут ""? Пробую сослаться на стринговый файл текста с кириллицей - отображает id строки. Пробую вставить в "" кириллицу - отображает кракозябры.

Это для текста "нажмите любую клавишу для перехода к игре", для ТЧ, пауза при загрузке игры как в ЗП.

Ссылка на комментарий

@Капрал Хикс , если self.start_btn - это статик, а не кнопка, то у него есть метод SetTextST("string_id"), которому game.translate_string не нужно, он автоматически транслирует строку.

  • Нравится 2

Аддон для ОП-2.09.2: Яндекс/Google/GitHub

naxac.gif

Ссылка на комментарий
14 часов назад, Norman Eisenherz сказал:

при прямом вводе – переводить скрипт в кодировку ANSI или Windows-1251.

Помог этот вариант, мододелам на заметку.

Изменено пользователем Капрал Хикс
Ссылка на комментарий
16 hours ago, naxac said:

если self.start_btn - это статик, а не кнопка, то у него есть метод

Так у дочерних классов методов только больше. Где-то попадалось исключение по наследованию родительских методов, но точно не в CUIStatic.

  • Полезно 2

Мини-моды: ТЧ ЧН ЗП

Шпаргалка

Ссылка на комментарий

Стоит фишка на использование горячих клавиш Enter и Delete для загрузки/удаления сохранений в соотв. меню. Так вот если курсор не стоит на строке сохранения, при нажатии клавиши подтверждения удаления сохранки вылет:

[error]Expression    : fatal error
[error]Function      : CScriptEngine::lua_error
[error]File          : E:\stalker\sources\trunk\xr_3da\xrGame\script_engine.cpp
[error]Line          : 73
[error]Description   : <no expression>
[error]Arguments     : LUA error: ... of chernobyl\gamedata\scripts\ui_load_dialog.script:234: attempt to index local 'item' (a nil value)

Как бы доработать скрипт?

Скрытый текст

-- File:        UI_LOAD_DIALOG.SCRIPT
-- Description: Load Dialog for STALKER
-- Created:     28.10.2004
-- Copyright:   2004 GSC Game World
-- Author:      Serhiy Vynnychenko (narrator@gsc-game.kiev.ua)
-- Version:     0.5

class "load_item" (CUIListItemEx)

function load_item:__init() super()
    self.file_name        = "filename"
    self:SetWndRect        (0,0,430,22)

    local ca = 255
    local cr = 216
    local cg = 186
    local cb = 140

    self.fn                = CUIStatic    ()
    self.fn:SetAutoDelete    (true)
    self:AttachChild        (self.fn)
    self.fn:SetWndRect        (0,0,230,22)
    self.fn:SetText            ("filename")
    self.fn:SetFont            (GetFontLetterica18Russian())
    self.fn:SetTextColor    (ca,cr,cg,cb)

    self.fage            = CUIStatic    ()
    self.fage:SetAutoDelete    (true)
    self:AttachChild        (self.fage)
    local shirik = (device().height/device().width > 1.5)
    local fageX = shirik and 250 or 325
    self.fage:SetWndRect    (fageX,0,150,22)
    self.fage:SetText        ("fileage")
    self.fage:SetFont        (GetFontLetterica16Russian())
    self.fage:SetTextColor    (ca,cr,cg,cb)
end

class "load_dialog" (CUIScriptWnd)

function load_dialog:__init() super()
   self:InitControls()
   self:InitCallBacks()
   self:FillList()
end

function load_dialog:__finalize()

end

function load_dialog:FillList()
    local f = getFS()
    local flist = f:file_list_open_ex("$game_saves$",bit_or(FS.FS_ListFiles,FS.FS_RootOnly),"*.sav")
    local f_cnt = flist:Size()

    flist:Sort(FS.FS_sort_by_modif_down)

    for    it=0, f_cnt-1     do
        local file    = flist:GetAt(it)
        local file_name = string.sub(file:NameFull(), 0, (string.len(file:NameFull()) - 4))
        local date_time = "[" .. file:ModifDigitOnly() .. "]"
        --menu_item = .. 
        self:AddItemToList(file_name, date_time)
    end
end

function load_dialog:InitControls()
    self:Init(0,0,1024,768)

    local xml             = CScriptXmlInit()
    local ctrl
    xml:ParseFile("ui_mm_load_dlg.xml")

    xml:InitStatic("back_video", self)

    xml:InitStatic("background",            self)
    --xml:InitStatic("newspaper_video",        self)

    self.form = xml:InitStatic("form",        self)

    xml:InitStatic("form:caption",            self.form)

    ctrl = xml:InitStatic("form:picture",        self.form)
    ctrl:SetWindowName("static_pict")

    xml:InitStatic("form:file_info",        self.form)

    self.file_caption     = xml:InitStatic("form:file_caption",    self.form)
    self.file_data        = xml:InitStatic("form:file_data",    self.form)

    xml:InitFrame("form:list_frame",        self.form)

    ctrl = xml:InitList("form:list",         self.form)
    ctrl:ShowSelectedItem(true)
    self:Register(ctrl, "list_window")

    ctrl = xml:Init3tButton("form:btn_load",    self.form)
    self:Register(ctrl, "button_load")

    ctrl = xml:Init3tButton("form:btn_delete",    self.form)
    self:Register(ctrl, "button_del")

    ctrl = xml:Init3tButton("form:btn_cancel",    self.form)
    self:Register(ctrl, "button_back")

    self.message_box = CUIMessageBoxEx()
    self:Register(self.message_box,"message_box")
end

function load_dialog:InitCallBacks()
    self:AddCallback("button_load",        ui_events.BUTTON_CLICKED,             self.OnButton_load_clicked,    self)
    self:AddCallback("button_back",        ui_events.BUTTON_CLICKED,             self.OnButton_back_clicked,    self)
    self:AddCallback("button_del",        ui_events.BUTTON_CLICKED,             self.OnButton_del_clicked,    self)
    self:AddCallback("message_box",        ui_events.MESSAGE_BOX_YES_CLICKED,    self.OnMsgYes,            self)
    self:AddCallback("message_box",        ui_events.MESSAGE_BOX_OK_CLICKED,     self.OnMsgYes,            self)

    self:AddCallback("list_window", ui_events.LIST_ITEM_CLICKED,         self.OnListItemClicked,        self)
    self:AddCallback("list_window", ui_events.WINDOW_LBUTTON_DB_CLICK,    self.OnListItemDbClicked,    self)
end

function file_exist(fname)
    local f = getFS()
    local flist = f:file_list_open_ex("$game_saves$",bit_or(FS.FS_ListFiles,FS.FS_RootOnly) , fname)
    local f_cnt = flist:Size()

    if f_cnt > 0 then
        return true
    else
        return false
    end
end

function delete_save_game(filename)
    local save_file        = filename .. ".sav"
    local dds_file        = filename .. ".dds"

    local f = getFS()

    f:file_delete("$game_saves$",save_file)

    if file_exist(dds_file) then
        f:file_delete("$game_saves$", dds_file)
    end
end

function AddTimeDigit(str, dig)
    if (dig > 9) then
        str = str .. dig
    else
        str = str .. "0" .. dig
    end

    return str

end

function file_data(fname)
    local f = getFS()
    local flist = f:file_list_open_ex("$game_saves$",bit_or(FS.FS_ListFiles,FS.FS_RootOnly) , fname .. ".sav")
    local f_cnt = flist:Size()

    if f_cnt > 0 then
        local file        = flist:GetAt(0)
        local sg = CSavedGameWrapper(fname)

        local y,m,d,h,min,sec,ms = 0,0,0,0,0,0,0
        y,m,d,h,min,sec,ms = sg:game_time():get(y,m,d,h,min,sec,ms)

        local date_time = ""

        date_time = AddTimeDigit(date_time, h)
        date_time = date_time .. ":"
        date_time = AddTimeDigit(date_time, min)
        date_time = date_time .. " "
        date_time = AddTimeDigit(date_time, m)
        date_time = date_time .. "/"
        date_time = AddTimeDigit(date_time, d)
        date_time = date_time .. "/"

        date_time = date_time .. y

        --string.format("[%d:%d:%d %d]",m,d,h,min,y)
        local health = string.format("\\n%s %d%s", game.translate_string("ui_inv_health"),sg:actor_health()*100,"%")

        return game.translate_string("st_level") .. ": " .. game.translate_string(sg:level_name()) .. "\\n" .. game.translate_string("ui_inv_time")..": " .. date_time .. health
    else
        return "no file data"
    end
end

function load_dialog:OnListItemClicked()
    local list_box        = self:GetListWnd("list_window")

    if list_box:GetSize()==0 then return end

    local picture        = self:GetStatic("static_pict")
    local itm_index        = list_box:GetSelectedItem()
    local item        = list_box:GetItem(itm_index)

    if item == nil then
        self.file_caption:SetText    ("")
        self.file_data:SetText        ("")
        picture:InitTexture        ("ui\\ui_noise")
        return
    end

    local item_text            = item.fn:GetText()
    self.file_caption:SetText    (item_text)
    self.file_data:SetText        (file_data(item_text))

    if file_exist(item_text .. ".sav") ~= true then
        list_box:RemoveItem(itm_index)
        return
    end

    if file_exist(item_text .. ".dds") then
        picture:InitTexture(item_text)
    else
        picture:InitTexture("ui\\ui_noise")
    end
end

function load_dialog:OnListItemDbClicked()
    self:OnButton_load_clicked()
end

function load_dialog:OnMsgYes()
    local list = self:GetListWnd("list_window")
    local index = list:GetSelectedItem()

    if index == 4294967295 then return end

    if self.msgbox_id == 1 then
        local item  = list:GetItem(index)
        local fname = item.fn:GetText()

        delete_save_game    (fname)

        list:RemoveItem        (index)

        self:OnListItemClicked()
    elseif self.msgbox_id == 2 then
        self:load_game_internal()
    end

    self.msgbox_id = 0
end

function load_dialog:load_game_internal()
    local console = get_console()
    local list = self:GetListWnd("list_window")

    if list:GetSize()==0 then return end

    local index = list:GetSelectedItem()

    if index == 4294967295 then return end

    local item  = list:GetItem(index)
    local fname = item.fn:GetText()

    if (alife() == nil) then
        console:execute    ("disconnect")
        console:execute    ("start server(" .. fname .. "/single/alife/load) client(localhost)")
    else
        console:execute    ("load " .. fname)
    end
end

function load_dialog:OnButton_load_clicked()
    local console = get_console()
    local list = self:GetListWnd("list_window")

    if list:GetSize()==0 then return end

    local index = list:GetSelectedItem()

    if index == 4294967295 then return end

    local item        = list:GetItem(index)
    local fname        = item.fn:GetText()

    if (alife() == nil) then

        if valid_saved_game(fname) then
            self:load_game_internal()
        else
            self.msgbox_id            = 0
            self.message_box:Init        ("message_box_invalid_saved_game")
            self:GetHolder():start_stop_menu(self.message_box, true)
        end

        return
    end

    if valid_saved_game(fname) then
        self.msgbox_id = 2
        self.message_box:Init("message_box_confirm_load_save")
        self:GetHolder():start_stop_menu(self.message_box, true)
    else
        self.msgbox_id            = 0
        self.message_box:Init        ("message_box_invalid_saved_game")
        self:GetHolder():start_stop_menu(self.message_box, true)
    end
end

function load_dialog:OnButton_back_clicked()
    self:GetHolder():start_stop_menu    (self.owner, true) --new(show main window)
    self:GetHolder():start_stop_menu    (self,true)
    self.owner:Show                (true)
end

function load_dialog:OnButton_del_clicked()
    local list = self:GetListWnd("list_window")

    if list:GetSize()==0 then return end
    local index = list:GetSelectedItem()

    if index == 4294967295 then return end

    self.msgbox_id = 1
    self.message_box:Init("message_box_delete_file_name")
    self:GetHolder():start_stop_menu(self.message_box, true)
end

function load_dialog:OnKeyboard(dik, keyboard_action)  --virtual function
--[[
   ui_base_dialog.base_dialog.OnKeyboard(self,dik,keyboard_action)

   DIK_RETURN = 28
   WINDOW_KEY_PRESSED = 6

    if dik == DIK_RETURN and keyboard_action == WINDOW_KEY_PRESSED then
        self:GetHolder():start_stop_menu    (self.owner, true) --new
        self:GetHolder():start_stop_menu    (self,true)
        self.owner:Show                (true)
    end

    return true
--]]
    CUIScriptWnd.OnKeyboard(self,dik,keyboard_action)
    local bind = dik_to_bind(dik)

    if keyboard_action == ui_events.WINDOW_KEY_PRESSED then
        if dik == DIK_keys.DIK_RETURN or dik == DIK_keys.DIK_SPACE then --* Enter/Space
            self:OnButton_load_clicked()
        elseif dik == DIK_keys.DIK_DELETE or dik == DIK_keys.DIK_DECIMAL then --* Delete/.(Numpad)
            self:OnButton_del_clicked()
        elseif dik == DIK_keys.DIK_ESCAPE or dik == DIK_keys.DIK_HOME then --* Esc/ Home /DIK_BACK - Back Space
            self:OnButton_back_clicked()
        end
    end

    return true
end

function load_dialog:AddItemToList(file_name, date_time)
    local _itm            = load_item()
    _itm.fn:SetText            (file_name)
    _itm.fage:SetText        (date_time)

    local list_box            = self:GetListWnd("list_window")
    list_box:AddItem        (_itm)
end
 

 

Ссылка на комментарий

@Капрал Хикс попробуй все строчки вида

if index == 4294967295 then return end

заменить на

if index == 4294967295 or index == -1 then return end

Возможно скрипт написан под обновленный lua.

  • Нравится 1
Ссылка на комментарий

@Капрал Хикс тогда надо дебажить, выводить в лог индекс который выдает GetSelectedItem, смотреть, почему с ним не работает GetItem (получение элемента списка по его номеру) и т.д.

 

Да и вообще, в целом не ясно "если курсор не стоит на строке сохранения" - курсор это что? Фокус мыши не наведен на элемента списка? Или элемент списка не выделен?

Просто в каком-то ориг скрипте был момент (наверно save dialog), что вместо GetSelectedItem использовался GetFocusedItem, и там как раз тоже был косяк с тем, что при подвязке хоткеев мышь могла не быть над элементом списка в момент действия. Но тут такого я не вижу.

Ссылка на комментарий

@RayTwitty , да проблема в том, что клавиша Delete в таком случае нажимается и при подтверждении удаления вылет. Тут бы запретить вызов клавиши Delete при невыделенной строке как-то.

Ссылка на комментарий
30 минут назад, Капрал Хикс сказал:

Тут бы запретить вызов клавиши Delete при невыделенной строке как-то.

Тогда вылет по идее должен быть при нажатии визуальной кнопки Удалить, функция та же самая вызывается.

Ссылка на комментарий

Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

Создать аккаунт

Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!

Зарегистрировать новый аккаунт

Войти

Есть аккаунт? Войти.

Войти
  • Недавно просматривали   0 пользователей

    • Ни один зарегистрированный пользователь не просматривает эту страницу.
×
×
  • Создать...