Скриптование - Страница 222 - Скрипты / конфиги / движок - AMK Team
Перейти к контенту

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

Тема для обсуждения скриптов всего и всех в серии игр 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
Ссылка на комментарий
https://www.amk-team.ru/forum/topic/6185-skriptovanie/

_Призрак_, хм, стандартных функций нету, я не нашел, может кто получше знает? Но пришла идея. Пост получился в стиле догадок, так что попрошу не смеяться\плакать. Прим.: лв - левел вертекс.

Как можно вообще получить лв?

1. Через граф игры, но там нигде не используется позиция. В общем, не то, хотя кто его знает.

2. Методы game_object.

2.1. accessible_nearest(const vector&, vector&)

Первый вектор это наша позиция, второй - направление(?). Предположительно, возвращает ближайший вертекс к позиции в направлении второго вектора, куда может пойти непись, к которому был применен этот метод. У меня вызывал вылет без лога, может у тебя, _Призрак_, получиться. Пример использования в xr_kamp, при этом, как условие, используется и метод accessible(number), аргумент - ид лв. Общий смысл наверное этот, но почему у меня не работает, не знаю. Это было первое, что мне пришло в голову.

 

2.2. level_vertex_id()

Более чем знакомый метод. Поясню смысл, по заданной позиции мы спавним предмет, который не требует лв (антирад например). Дальше я хотел узнать сразу лв через свойство серверного объекта m_level_vertex_id, но ни черта не вышло - вернуло nil, почему? Класс не тот? Использовал другую секцию, соответственно другой класс, где это свойство точно должно быть, и опять nil. Решил довести до конца, т.е. до клиентского объекта.

if se_obj then
    local cl_obj = level.object_by_id(se_obj.id)
    if cl_obj then
        local text = string.format("diff time %s; c_lv: %s; s_lv %s; s_gv %s",
        time - begin,c_obj:level_vertex_id(),tostring(se_obj.m_level_vertex_id),tostring(se_obj.m_game_vertex_id))
        dprint(text)
        alife():release(se_obj,true)
        se_obj = nil
    end
else
    se_obj = alife():create("antirad",vector():set(42.7,6.1,-23.67),0,2791)
    begin = time_global()
end

Все это дело конечно же в апдейте, вне функций объявлены se_obj и begin. В лог посыпалась такая инфа

! Cannot find saved game ~~~ diff time 239; c_lv: 17459; s_lv nil; s_gv nil
! Cannot find saved game ~~~ diff time 249; c_lv: 17459; s_lv nil; s_gv nil
! Cannot find saved game ~~~ diff time 296; c_lv: 17459; s_lv nil; s_gv nil
! Cannot find saved game ~~~ diff time 252; c_lv: 17459; s_lv nil; s_gv nil
! Cannot find saved game ~~~ diff time 258; c_lv: 17459; s_lv nil; s_gv nil
! Cannot find saved game ~~~ diff time 280; c_lv: 17459; s_lv nil; s_gv nil
! Cannot find saved game ~~~ diff time 286; c_lv: 17459; s_lv nil; s_gv nil
! Cannot find saved game ~~~ diff time 250; c_lv: 17459; s_lv nil; s_gv nil
! Cannot find saved game ~~~ diff time 224; c_lv: 17459; s_lv nil; s_gv nil
! Cannot find saved game ~~~ diff time 258; c_lv: 17459; s_lv nil; s_gv nil
! Cannot find saved game ~~~ diff time 271; c_lv: 17459; s_lv nil; s_gv nil
! Cannot find saved game ~~~ diff time 269; c_lv: 17459; s_lv nil; s_gv nil
! Cannot find saved game ~~~ diff time 269; c_lv: 17459; s_lv nil; s_gv nil
! Cannot find saved game ~~~ diff time 264; c_lv: 17459; s_lv nil; s_gv nil
! Cannot find saved game ~~~ diff time 287; c_lv: 17459; s_lv nil; s_gv nil

 

Лв тот, это с моей локации, но способ убивает своей дорогой в Москву через Китай, при этом нужно знать хотябы один гейм вертекс с локации. В общем кривое и сумасшедшее решение.

 

2.3. set_actor_position(vector&)

И тут мне пришла еще одна дурацкая идея, разновидность 2.2. Можно переместить ГГ в заданную позицию, на следущем апдейте снять его лв и вернуть обратно. Минусы значительнее: все это только в пределах активной локации, невозможность обработать сразу несколько точек. Точнее можно и несколько точек, но если их будет слишком много, то играющий успеет увидеть мерцание экрана сразу после загрузки игры (если вообще планируется снимать лв в самом начале, иначе тоже ф топку).

if begin == true then
    old_pos = db.actor:position()
    db.actor:set_actor_position(vector():set(42.7,6.1,-23.67))
    begin = false
elseif begin == false then
    dprint(db.actor:level_vertex_id())
    db.actor:set_actor_position(old_pos )
    begin = nil
end

Снова в апдейте, а begin и old_pos так же объявлены как глобальные для модуля. Единственный плюс, меньше нагрузки и скорость побольше, за один апдейт все свершиться. Но о лучше\хуже вообще не стОит говорить, все как видно и так плачевно :)

 

3. level.vertex_in_direction(number, vector&, number)

И вот вроде бы эврика, но черта с два. Тесты показали несостоятельность этой задумки, точнее только на половину. Итак, эта функция возвращает лв в направлении единичного вектора (2 аргумент) от другого лв (ид - 1 аргумент) на расстоянии (число - 3 аргумент). Например level.vertex_in_direction(0,vector():set(0,0,1),5) - по хорошему это дело вернет лв от нулевого лв на расстоянии 5 метров строго на север, НО если на пути не будет ноды (аи сетка пошла вокруг камня, а направление проходит как раз через камень), то возвратится граничный лв. Решил немножко порисовать. 6b8f865cf50a15758c3fb370f6fe68c1bce20d126316361.jpg

Я думаю все наглядно, в итоге мы получим не зеленый лв, а синий. Но могу сказать, что способ вполне рабочий на целой аи сетке.

function get_vl_by_pos(pos_lv)
    local n = 16661
    pos_lv = vector():set(42.7,6.1,-23.67)
    local pos_n = level.vertex_position(n)
    local dir = vector():sub(pos_lv,pos_n)
    local radius = dir:magnitude()
    dir:normalize()
    local lv = level.vertex_in_direction(n,dir,radius)
    dprint(lv)
end

Сначала я взял n = 0 но не вышло изза описаной выше проблемы, взял который не так далеко, все заработало. Тут я переопределил входной аргумент, это исходная позиция.

 

 

В итоге тоже присоединяюсь к вопросу, покажите мне, извращенцу, как можно получить лв по позиции? И задам еще более обширный вопрос, как получить все лв, которые находятся в какой либо зоне, в рестрикторе например?

ТЧ 1.0004. SAP и Trans mod

github

Zander_driver, А возможно ли заблокировать стандартное значения конфига, допустим опять же inv_weight, будет считываться не с конфига а со скрипта ?

Я бы конечно бы последовал твоему методу,но мне нужно изменять значения через скрипт не только для предметов, но и для характеристик актора.

Возможно есть какое ни будь решение с характеристиками ?

boryan67, собственно все есть в процитированном тобою же.

Если в логике для конкретного рестриктора указать типа:

[logic]
active = sr_idle@in

[sr_idle@in]
on_actor_inside = nil %=my_func(my_param)%

- то в my_func(actor,obj,p) ты можешь делать все что хочешь именно с этим рестриктором (obj). Т.е. он "сам себе" вызвал функцию и в ней его же можно удалить иль еще чего душа пожелает. Условие "on_actor_inside" подбираешь под свои задачи.

 

boryan67: Другими словами, возможно ли установить, что данный конкретный рестриктор уже отработал и может быть удален?

А вот об этом ты должен позаботиться. Скрипт сам не может знать, отработал об'ект свою задачу иль нет. Дав, например, какой нибудь инфопоршень при выпонении задачи - ты по наличию этого инфопоршня и подскажешь скрипту ... Для одноразовых, как в примере выше, это не требуется.

 

_Призрак_, не получится в игре ТЧ получить айдишники вертексов по позиции ... без доработки движка или без трудоемкой иттерации. Для ЧН/ЗП есть: level.vertex_id(vPos).

Во-первых, идентификаторы левел-вертексов (да и game-) не распложены как-то упорядоченно, т.е. не получиться составить табличку соответствий координат и идентификаторов.

Во-вторых, при перекомпиляции карт все подобное соответстве изменяется, а это значит, что и в модах с разными картами все это различно.

 

Desertir, твой вопрос о нахождении всех лв в некоей зоне тем более врядли выполним.

 

Могу только предложить некоторые наработки по этой теме из Симбиона:

function Get_LevelId(idGv)
  if idGv and game_graph():valid_vertex_id(idGv) then
    local oVertex = game_graph():vertex(idGv)
    if oVertex then
      return oVertex:level_id() --/> idLevel | idMap
    end
  end
  printf("Get_LevelId:idGv=[%s]<~NOT_valid:<%s>", idGv, "Warning!")
  return nil --/>
end

function fGet_LevelId(Obj,idGv)
  if not idGv and Obj then
    idGv = Obj.m_game_vertex_id
    if not idGv then
      idGv = Obj.game_vertex_id and Obj:game_vertex_id()
    end
  end
  if idGv then
    return this.Get_LevelId(idGv) --/> idLevel | idMap
  end
  printf("fGet_LevelId:Obj=[%s/%s]:<%s>", type(Obj), type(Obj) == 'userdata' and Obj:name(), "Warning!")
  return nil --/>
end

function Get_LevelName(idGv)
  local idLevel = this.Get_LevelId(idGv)
  if idLevel then
    return sim:level_name(idLevel) --/> sLevelName
  end
  return nil --/>
end

function fGet_LevelName_Object(Obj)
  local idLevel = this.fGet_LevelId(Obj)
  if idLevel then
    return sim:level_name(idLevel) --/> sLevelName
  end
  return nil --/>
end

function Get_LevelIdByName(sLevelName)
  if not tLevelIdByName[sLevelName] then
    local idLevel,sLevel = 0,""
    --/ 'глобальное' сканирование всех game_vertex'ов
    local id,idLevelSav,sLevelSav = 0,0,""
    local gmg = game_graph()
    while gmg:valid_vertex_id(id) do
      idLevel = gmg:vertex(id):level_id() --/ ID уровня по game_vertex'у
      if idLevel ~= idLevelSav then --/ сменился ID-уровня?
        sLevel = sim:level_name(idLevel) --/ имя уровня по его ID
        if sLevel ~= sLevelSav then --/ сменилось имя уровня?
          sLevelSav = idLevel
          sLevelSav = sLevel
          tLevelIdByName[sLevel] = idLevel --/ запоминаем
        end
      end
      id = id +1
    end
  end
  return tLevelIdByName[sLevelName] --/> idLevel
end

function Get_IdsByLevelName(sLevelName)
  if not tIdsByLevelName[sLevelName] then
    local idMap = this.Get_LevelIdByName(sLevelName)
    if idMap then
      local idGv = 0
      local gmg = game_graph()
      while gmg:valid_vertex_id(idGv) do
        if gmg:vertex(idGv):level_id() == idMap then
          local idLv = gmg:vertex(idGv):level_vertex_id()
          tIdsByLevelName[sLevelName] = {idMap,idGv,idLv}
          return idMap, idGv, idLv --/>
        end
        idGv = idGv +1
      end
    end
    tIdsByLevelName[sLevelName] = {idMap,nil,nil}
  end
  return tIdsByLevelName[sLevelName][1],tIdsByLevelName[sLevelName][2],tIdsByLevelName[sLevelName][3] --/>
end

--/ вычисление Min & Max game- и level- вертексов для всех локаций
function Choice_MinMax_Vertexes()
  local gmg = game_graph()
  if not gmg then return end --/> еще рано?
  local id,idMap,idPreMap = 0,nil,-1
  while id < 65536 do
    if gmg:valid_vertex_id(id) then
      idMap = gmg:vertex(id):level_id() --/ ID локации
      if idMap ~= idPreMap then --/ не сканировалась?
        tMaxVertexIds[idMap] = {}
        tMaxVertexIds[idMap][1] = id --/ min idGv
        if tMaxVertexIds[idPreMap] then --/ предыдущая просканированная локация
          tMaxVertexIds[idPreMap][2] = id-1 --/ max idGv
        end
        idPreMap = idMap
      end
    else
      tMaxVertexIds[idPreMap][2] = id-1 --/ last max idGv
      break
    end
    id = id +1
  end
  for idx,v in pairs(tMaxVertexIds) do
    v[3] = this.Get_Max_IdLevelVertex(idx,v[1],v[2]) --/ добавляем max idLv
  end
end

function Get_MinMax_IdVertexes(idMap)
  if not idMap then idMap = sim:level_id() end --/ берем текущий уровень
  if not tMaxVertexIds[idMap] then
    local gmg = game_graph()
    local id,idGvMin,idGvMax = 0,nil,nil
    while id < 65536 do
      if gmg:valid_vertex_id(id) and gmg:vertex(id):level_id() == idMap then --/ ID искомой локации?
        if not idGvMin then
          idGvMin = id --/ 1-й индекс искомой локации
        end
        idGvMax = id --/ текущий (он же последний) искомой локации
      elseif idGvMin then --id = 65536
        break
      end
      id = id +1
    end
    local idLvMax = this.Get_Max_IdLevelVertex(idMap,idGvMin,idGvMax)
    tMaxVertexIds[idMap] = {idGvMin,idGvMax,idLvMax}
  end
  return tMaxVertexIds[idMap][1], tMaxVertexIds[idMap][2], tMaxVertexIds[idMap][3] --/> idGvMin и idGvMax и idLvMax
end

function Get_Max_IdLevelVertex(idMap,idGvMin,idGvMax)
  local idLvMax = idMap and tMaxVertexIds[idMap] and tMaxVertexIds[idMap][3]
  if idLvMax then
    return idLvMax --/>
  elseif not (idGvMin and idGvMax) then
    if not idMap then
      idMap = this.Get_LevelId(idGvMin or idGvMax or sim:level_id())  --/ ... или сканируем текущий уровень
    end
    idGvMin,idGvMax,idLvMax = this.Get_MinMax_IdVertexes(idMap)
  end
  if not idLvMax and idGvMin and idGvMax then
    local gmg = game_graph()
    local id,idLv = 0,nil
    for id=idGvMin, idGvMax do
      idLv = gmg:vertex(id):level_vertex_id()
      if not idLvMax or idLvMax < idLv  then
        idLvMax = idLv
      end
    end
    if idMap then tMaxVertexIds[idMap][3] = idLvMax end
  end
  return idLvMax --/>
end

--/ -----------------------------------------------------------------
--/ минимизация погрешности ранее вычисленного 'idLvMax' для текущего уровня:
--/ -----------------------------------------------------------------
function Correct_Max_IdLevelVertex()
  local idLvMax = idMapNow and idMapNow > 0 and tMaxVertexIds[idMapNow] and tMaxVertexIds[idMapNow][3] --/< idLvMaxNow
  if not idLvMax then return end --/> еще рано ...
  local idLv,id,vPos,vPosPrev = 0,1,vector(),vector()
  --/ последовательная итерация увеличения максимального индекса левел-вертекса до НЕ валидного:
  for id=1, 32768 do --/16, 512, 1024, 8192, 16384, 32768, 65535<~X
    idLv = idLvMax + id
    vPos = level.vertex_position(idLv)
    if type(vPos) ~= 'userdata' or type(vPos.getP) ~= 'function' --/ вектор?
       or type(vPos.x) ~= 'number' or type(vPos.y) ~= 'number' or type(vPos.z) ~= 'number' --/ имеются осевые координаты?
       or (vPos.x == 0 and vPos.y == 0 and vPos.z == 0) --/ валидна хотя бы одна из осевых координат?
       or (vPos.x == vPosPrev.x and vPos.y == vPosPrev.y and vPos.z == vPosPrev.z) --/ координаты идентичны предыдущим?
      then --/ не валиден
      idLv = idLv -1 --/ откат к предыдущему валидному значению
      break --/ прерываем итерацию
    else
      vPosPrev = vPos --/ запоминаем вектор координат валидного вертекса
    end
  end
  --/ сравниваем новый и прежний:
  if idLv > idLvMax then --/ 'новый' индекс вертекса больше прежнего?
    idLvMaxNow, tMaxVertexIds[idMapNow][3] = idLv, idLv --/ обновляем новым значением!
    return idLvMaxNow --/>
  end
end
--/ -----------------------------------------------------------------
--/ определение ближайшего левел вертекса к заданной координате (position) с погрешностью ...
--/ -----------------------------------------------------------------
function Get_Never_idLv_by_Pos(vPos,iErr,Obj)
  if not iErr then iErr = 0.5 end --/ если не задана погрешность по дистанции (0 => макс.точность)
  if not vPos and Obj then --/ если не задана позиция ...
    if type(Obj.position) == 'function' then
      vPos = Obj:position()
    else
      vPos = Obj.position
    end
  end
  local idLv,iDistMin,iDist
  for id=0,idLvMaxNow do
    iDist = level.vertex_position(id):distance_to_sqr(vPos)
    if not iDistMin or iDist < iDistMin then
      idLv = id
      iDistMin = iDist
      if iDistMin < iErr then break end --/ прерываем цикл
    end
  end
  return idLv,iDistMin --/>
end

- самая последняя - попытка все же получить ид по позиции ... но врядли это востребовано ... если только в единичных случаях.

 

Добавлено через 6 мин.:

GreadFiasco, тебе стОит понять, что при запуске игры движек считывает все штатные конфиги в свою "память" и ими оперирует. Т.о. параметры, для которых не предусмотрены методы для изменения их значений - не доступны ни для измененеий ни для блокировки.

И параметров актора это касается в первую очередь ... дабы читерить потруднее было бы :crazy:

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Как сделать в скриптовом диалоге рандомный выбор следующей фразы?(одну из двух)...пробовал и с прекондишном, и с пустой фразой...что-то все не то что нужно.

 

Вот когда сформулируешь, что же "нужно", и что/как делал и вышло - "не нужно", тогда и возможен дальнейший разговор/подсказки, а не погадалки. --/Artos

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

Artos, Не думаю что имея конфиги актора и прочего, кому то будет трудно считерить.

Но всё же было желание сделать определённую фичу. Допустим при старте игры выдалось бы окно, с выбором так сказать, стиля игры... Тоесть выбирая стиль снайпер, вручалась допустим сву и настраивались характеристики оружия так, что бы всё оружие приближенное к снайперу имело меньшую отдачу, и меньшее шатание в руках. Ну и параметры актора, на меньший переносимый вес и посильнее дыхалка.

Знаю что можно сделать разные конфиги и добавить их в геймдату. Но это только перед игрой, а хотелось бы сделать изменение непосредственно при начале или перед стартом при выборе уровня сложности, заменив уровни на стиль.

Делал я откровенно говоря бред, поэтому и вышло то что "не нужно".

 

А что надо...

 

- Текст 1 =>

- Текст 2 =>

- Текст 3 либо Текст 4

 

Еще часто баги вылетают такие, что как бы НПС говорит фразу ГГ, или после моей фразы опять такая же(по содержанию) только НПС ее говорит. Как с этим бороться?

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

local vis = tostring(stalk.visual)

if string.find(vis,"stalker_bandit_1") then

как-то так, более знающие поправят.

Еще часто баги вылетают такие, что как бы НПС говорит фразу ГГ, или после моей фразы опять такая же(по содержанию) только НПС ее говорит. Как с этим бороться?

Скорее всего, ид фраз неправильно задаешь. Не тот тип данных при своевольных трактовках луа приводит к глюкам в данном случае.

По нужной тебе затее - в первой фразе через экшен вызови math.random(1,100)

Сохрани результат. А на нужные тебе рандомные фразы повесь прекондишены вида

function randomselect_1_2() return (phrase_select_random < 51) end
function randomselect_2_2() return (phrase_select_random > 50) end

 

Driv3r

Магазинное питание при разрядке оружия производит переконвертацию магазинов. т.к. фактически при разрядке из оружия выпадает столько магазинов, сколько было в нем патронов. Скрипт магазинного питания удаляет лишние, переводя количество в состояние магазина, записывая число патронов иным образом. А скрипт ограничения рюкзака вмешивается в этот процесс, пытаясь произвести действия с объектами, которые были удалены магазинным питанием, отсюда вылет.

Решение - не бодаться с магазинным питанием, пусть конвертирует, а ограничение рюкзака переделай - вместо немедленных действий надо сначала записать ид объекта, а на следующем апдейте, проверить его существование. Если объект все еще не удален, тогда уже можно делать свои действия.

Мод, где не бывает одинаковых путей - Судьба Зоны. (Лучшее, что у меня получилось на X-Ray) На базе модифицированного движка OGSR Engine.

Бывший мододел на X-Ray / Начинающий игродел на Unreal Engine. Программист.

AMD Ryzen 9 7950X (16 ядер, 32 потока, 5.75 ГГц); RTX 3080; 128 ГБ DDR5; Arctic Liquid Freezer II-420; 3 ТБ SSD PCIe 4.0; 4ТБ HDD.

Zander_driver,

 

Не тот тип данных при своевольных трактовках луа приводит к глюкам в данном случае.

 

Не понял вот эту фразу...вот мой диалог в котором косяки:

 

function news_dlg(dlg)
     phr0 = dlg:AddPhrase(intro_phrase[math.random(1, table.getn(intro_phrase))], "0", "", -10000):GetPhraseScript()
    phr0:AddHasInfo("tutorial_end")
     phr1 = dlg:AddPhrase("Текст 2", "1_2", "0", -10000):GetPhraseScript()
    phr1:AddAction("escape_dialog.costs")
    phr1:AddPrecondition("escape_dialog.randomselect_1_2")
    phr2 = dlg:AddPhrase(no_item_phrase[math.random(1, table.getn(no_item_phrase))], "2_2", "0", -10000):GetPhraseScript()
     phr2:AddPrecondition("escape_dialog.randomselect_2_2")
    -- phr2:AddAction("dialogs.break_dialog")
end

 

Добавлено через 30 мин.:

Что-то никак не поборю эти баги, рандом работает как нужно, спасибо.

 

Вот я даже засунул диалог и тутора(там априори не может быть неправильно), вот такое словил:

 

3176410m.jpg

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

Прошу помочь с вопросом. Допустим. Есть секция предмета в device.ltx.

[active_ruck]
GroupControlSection    = spawn_group
discovery_dependency    = 
$spawn                          = "devices\active_ruck"
class                = O_INVBOX
cform                = skeleton
visual = dynamics\devices\dev_rukzak\dev_rukzak.ogf
script_binding      = bind_secret_box.init

Далее биндер предмета

function init(Obj)
    local new_binder = InvBinder(Obj)
    Obj:bind_object(new_binder)
end

class "InvBinder" (object_binder)
function InvBinder:__init(Obj) super(Obj)
   self.rr_id=Obj:id()
end

function InvBinder:reload(section)
    object_binder.reload(self, section)
end

function InvBinder:reinit()
    object_binder.reinit(self)
    self.object:set_callback(callback.use_object, self.use_callback, self)
end

function InvBinder:update(delta)
    --local actor_pos = db.actor:position()
    --local obj_pos = self.object:position()
    --local dist = actor_pos:distance_to(obj_pos)
    object_binder.update(self, delta)
end

function InvBinder:net_spawn(data)
    return object_binder.net_spawn(self, data)
    if self.rr_id==nil then
        local se_obj=alife():object(self.rr_id)
        if se_obj~=nil then
            level.map_add_object_spot_ser(se_obj.id, "treasure_spot", game.translate_string("mod_treasure"))
            news_manager.send_tip(db.actor, "Получен уникальный тайник", nil, nil, 5000)
        end
        self.rr_id=nil
    end
end

function InvBinder:net_destroy()
    object_binder.net_destroy(self)
    self.object:set_callback(callback.use_object, nil)
end

function InvBinder:net_save_relevant()
    return true
end

function InvBinder:save(packet)
    object_binder.save(self, packet)
end

function InvBinder:load(reader)
    object_binder.load(self, reader)
end

function InvBinder:use_callback(Obj, Who)
  if Obj and Who:id() == db.actor:id() then
    if self.rr_id~=nil and level.map_has_object_spot(self.rr_id, "treasure_spot")~= 0 then
       level.map_remove_object_spot(self.rr_id, "treasure_spot")
    end
  end         
end

Из схемы видно, что являеться целью данного мучения. Я не скриптер, и только учусь. Прошу подсказать, правильно ли я сделал? И в случае спавна разных предметов этой секции произойдёт ли установка метки на другой обьект? Спавн такой схемой

CreateTreasureBox("active_ruck",vector():set(20.52420,-3.29770,-54.53437),298504,112,"avs_secret_1")
--спавн инвенторного ящика
function CreateTreasureBox(section,position,level_vertex_id,game_vertex_id,custom_name)
    local obj = alife():create(section, position, level_vertex_id, game_vertex_id)
    if obj then
        local t = amk.get_invbox_data(obj)
        t.custom = "[logic]\ncfg = scripts\\mod_secret\\"..custom_name..".ltx"
        amk.set_invbox_data(t, obj)
    end
end

В кустом дате обьекта секция [spawn] и перечесление предметов.

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

GreadFiasco, все же темы по фантазиям в ином месте, а тут - о том что имеем и конкретно по скриптам. ;-)

 

proger_Dencheek, в ТЧ/ЧН проверку визуала можно сделать только или прочитав соответствующий параметр из нет-пакета непися или парсинком его профиля в xml'ке ...

 

Struck, рандомность выбора фраз в диалогах возможна только при самом первом создании драфта (дерева) диалога. В последующем - что получил - то и будет показывать в диалоге, и так до перезагрузки.

 

Добавлено через 6 мин.:

panzyuza, метки подобным образом ставятся на идентификатор об'екта и поэтому "произойти установки метки на другой обьект" накак не может. Т.е. на какой id ставишь - не том и будет метка.

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Artos, если я правильно понял, нужно оставить данную секцию как базовую, и просто спавнить рюкзаки с другими секциями. Значит, их секции и будут использованы как id. Изменено пользователем panzyuza

panzyuza, у тебя какая-то каша в голове ....

1. Что значит в твоем понимании и в контексте твоего вопроса "базовая секция"?

2. Секции НЕ имеют и не подучают идентификаторов (id), вот заспавнив по какой-либо секции об'ект - он и получает игровой иденификатор, который можно использовать ...

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Как сделать, чтоб после определенного действия улучшались характеристики определенного оружия(хочу сделать подобие книги тактики ведения боя, из Sigerous)

Не понял вот эту фразу...вот мой диалог в котором косяки:

Ну что тут не понять? игра хочет видеть число, а ты ей строку подсовываешь.

 phr0 = dlg:AddPhrase(intro_phrase[math.random(1, table.getn(intro_phrase))], "0", "", -10000):GetPhraseScript()

"0" измени на 0. "" - на -1.

 phr1 = dlg:AddPhrase("Текст 2", "1_2", "0", -10000):GetPhraseScript()

"1_2" - замени на 2. "0" - на 0.

И так далее, не строки, а числа. Как я понял из сторонних источников, строковые ид фраз применяются начиная с 5-го патча. А на 4-м и ранее - только числа.

Artos !

Struck, рандомность выбора фраз в диалогах возможна только при самом первом создании драфта (дерева) диалога. В последующем - что получил - то и будет показывать в диалоге, и так до перезагрузки.

Ну вы бы читали хоть вышенаписанное. Я же уже привел пример как рандомный выбор реализовать :)

 

Вот, если угодно, его величество рандом во всей красе

local phrase_select_random
function upd_random()
phrase_select_random = math.random(1,100)
end
function randomselect_1_10() return (phrase_select_random < 11) end
function randomselect_2_10() return (phrase_select_random > 10 and phrase_select_random < 21) end
function randomselect_3_10() return (phrase_select_random > 20 and phrase_select_random < 31) end
function randomselect_4_10() return (phrase_select_random > 30 and phrase_select_random < 41) end
function randomselect_5_10() return (phrase_select_random > 40 and phrase_select_random < 51) end
function randomselect_6_10() return (phrase_select_random > 50 and phrase_select_random < 61) end
function randomselect_7_10() return (phrase_select_random > 60 and phrase_select_random < 71) end
function randomselect_8_10() return (phrase_select_random > 70 and phrase_select_random < 81) end
function randomselect_9_10() return (phrase_select_random > 80 and phrase_select_random < 91) end
function randomselect_10_10() return (phrase_select_random > 90) end

 

первую функцию - вызываем через экшен в стартовой фразе диалога. остальные используем в качестве прекондишенов для рандомных фраз.

число функций и подбор чисел соответственно - должны совпадать с числом вариантов рандомной фразы.

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

Мод, где не бывает одинаковых путей - Судьба Зоны. (Лучшее, что у меня получилось на X-Ray) На базе модифицированного движка OGSR Engine.

Бывший мододел на X-Ray / Начинающий игродел на Unreal Engine. Программист.

AMD Ryzen 9 7950X (16 ядер, 32 потока, 5.75 ГГц); RTX 3080; 128 ГБ DDR5; Arctic Liquid Freezer II-420; 3 ТБ SSD PCIe 4.0; 4ТБ HDD.

У меня вопрос касающийся зомбиков.

--    if self.object:character_community() == "zombied" then
        local manager = self.object:motivation_action_manager()
        manager:remove_evaluator    (stalker_ids.property_anomaly)
        manager:add_evaluator        (stalker_ids.property_anomaly, property_evaluator_const(false))
--    end

Здесь сказан, что для зомби аномалий нет.

А если я сделаю так:

    if self.object:character_community() == "zombied" then
        local manager = self.object:motivation_action_manager()
        manager:remove_evaluator    (stalker_ids.property_anomaly)
        manager:add_evaluator        (stalker_ids.property_anomaly, property_evaluator_const(true))
    end

зомби теперь будут умирать, при попадании в аномалию?

 

Добавлено через 15 мин.:

И ещё помогите создать функцию на проверку из какого оружия убили НПС или монстра, и если это граната, wpn_rg-6

wpn_rpg7, то эффект был как от аномалии грави (точно не помню, принцип её действии как трамплин в ЗП). Труп должен исчезнуть, а на его мести заспавниться рюкзак с оружием, патронами и прочими вещами, что было у нпс. Если уничтожен монстр то просто исчезает, конечно же остаётся кровь.

 

Извиняюсь если не понятно высказал свои мысли...

32481252.f.500.500.jpg

proger_Dencheek, проверять свершилось ли твое действие, и подменять ствол на более лучший.

 

Zander_driver, спасибо, все вышло как надо, просто я делал по тутору...и не удосужился посмотреть примеры в файлах игры, все как всегда просто оказалось, появился вылет правда "No available phrase to say, dialog[escape_trader_test_2]", но видно диалог не так составил.

 

Strelok_124, вешай в death_callback'и неписей и монстров проверку на активное оружие в руках, если это гранатометы, то считывай инвентарь НПС записывай в табличку спавни рюкзак при взятии которого эта табличка спавнится актору(на мотив сетевой игры), а труп удаляй и проигрывай партикл...был какойто забугорный мод где это сделали. А кровь вроде и так останется...но я не уверен.

Artos, провел эксперимент по самоудалению рестриктора.

Логика:

[logic]
active = sr_idle@one

[sr_idle@one]
on_actor_inside = | nil %=debug.del_restr%

Функция:

function del_restr(actor, obj, p)
    if obj then
        alife():release(obj)
    end
end

Функция получает правильный объект. Отрабатывает, объект не удаляется, биндер виснет (часы останавливаются).

В чем моя ошибка?

boryan67, удалять надо серверный объект, а не что под руку попало.

    if obj then
        local sobj = alife():object(obj:id())
        if sobj then
            alife():release(sobj,true)
        end
    end

 

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

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

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

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

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

Войти

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

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

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