Войти на сайт Регистрация Лента форума Пользователи Правила сайта Поиск по форуму
Модератор форума: denis2000, FantomICW  
Модостроение. Редактирование и создание скриптов
denis2000Дата: Пн, 10.10.2011, 21:17 | Сообщение # 1
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

Редактирование и создание скриптов

Редактирование и создание скриптов на языке LUA

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


Много интересного материала здесь (wiki), Lua_help.script, Help из SDK 0.7

Сборник модостроения ЗП v10.10.11 (автор: XOBAH): *.CHM, *.HTML
[cut noguest=Если у вас не открывается файл CHM]Если у вас не открывается файл:
1. Запустите [Пуск]=>[Выполнить] (либо хот-кей [WIN]+[R])
2. Введите команду (без кавычек) "regsvr32 %windir%\system32\hhctrl.ocx"
3. Если вылезло окно об успешном завершении вы все сделали правильно и можете перезагружать компьютер (а может и не надо)
Также: файлы МОГУТ не открываться если в пути к файлу есть: символы кириллицы, "_", "#"
Также: есть не стандартные программы-просмоторщики CHM файлов. Например: FBReader[/cut]

[cut=Где найти лог игры после вылета]Что такое LOG ошибки, и как мне его найти?
Это система отладки происходивших вылетов, которая подается игрой в форме текста, хотя не всегда.
Для того чтоб найти LOG необходимо зайти вот сюда:

В Win хр лог находится:

C:\Documents and Settings\All Users\Документы\S.T.A.L.K.E.R. - Зов Припяти\logs

Затем открываете первый файл в формате TXT, и в нем отбираете с низу 25 строчек. После кидаете эти 25 строчек в сообщение на форум.

В Win7 лог находится C:\Users\Public\Documents\S.T.A.L.K.E.R. - Зов Припяти\logs

Путь к папке с логом можно найти открыв файл fsgame.ltx который находится в корневой директории ЗП, за это отвечает строка:
...
$app_data_root$ = true | false| $fs_root$| users\
(тут мы указываем что папка пользователя, будет хранится рядом с Fsgame.ltx)
...
$logs$ = true| false| $app_data_root$| logs\
(а тут мы указываем что в папке пользователя, в подпапке Logs будут храниться наши логи)
...
[/cut][cut=Получение более подробной информации о вылете (ХОВАН)]
Открываем файл _g.script и ищем такую функцию: function abort(fmt, ...)
Там есть заккомментированная строчка "--error_log(reason)", ее и надо расскомментировать, должно получиться вот так:
Code
function abort(fmt, ...)
                             local reason = string.format(fmt, ...)
                             error_log(reason)
end

Вот для примера два одинаковых вылета, первый с функцией по умолчанию, второй - с поправленной функцией

Первый:
Code
Expression    : !m_error_code
Function      : raii_guard::~raii_guard
File          : D:\prog_repository\sources\trunk\xrServerEntities\script_storage.cpp
Line          : 748
Description   : ....a.l.k.e.r. - Зов Припяти\gamedata\scripts\_g.script:478: bad argument #2 to 'format' (string expected, got nil)

Второй:
Code
Expression    : 0
Function      : ErrorLog
File          : D:\prog_repository\sources\trunk\xrServerEntities\script_engine_script.cpp
Line          : 49
Description   : 'Attempt to read a non-existant string field 'path_walk' in section 'walker@mechanic'

[/cut]


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


Если произошел вылет - выкладываем лог! Вопрос ставим четко, не забываем указывать версию игры, установленные моды их версии, установленные фиксы модов и подробно ваши правки.
Помните чем подробнее вопрос, тем точнее ответ.


"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..."
(Чугунный всадник)
 
makdmДата: Ср, 14.06.2017, 20:40 | Сообщение # 886
Рожденный в СССР
Разработчики
Сообщений: 1294
Награды: 29
Репутация: [ 1909 ]

Цитата sergej5500 ()
local sobj = alife():object( self.object:id() )

alife():create("remote_mine_field",sobj:position(),sobj:level_vertex_id(),sobj:game_vertex_id())


Получаем серверный класс объекта.
И спавним, применяя методы для клиентского класса объекта.

Круто!!!

sergej5500, вот так нужно :

alife():create("remote_mine_field",self.object:position(),self.object:level_vertex_id(),self.object:game_vertex_id())

Или если работаете с cерверным объектом, то

alife():create("remote_mine_field",sobj.position,sobj.m_level_vertex_id,sobj.m_game_vertex_id)


Терпение......
И все получится!


Сообщение отредактировал makdm - Ср, 14.06.2017, 21:09
 
sergej5500Дата: Пн, 27.11.2017, 22:36 | Сообщение # 887
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
Награды: 29
Репутация: [ 1355 ]

Добрый вечер.

Обратил внимание на следующую вещь. Зов Припяти.

1. Игрок приближается к Скадовску. База пока в оффлайне.


2. Скадовск попал в онлайн. Проявились метки важных персов (торговцы, медики и т.д.), спального места и личного ящика.


3. Игрок ушёл от судна. Метки спального места и личного ящика пропали. Метки персов остались.


С моей точки зрения это не очень верно. Метки персов то же нужно убирать. Как нужно подправить скрипт, чтобы метки удалялись?

[cut=stalker_generis]----------------------------------------------------------------------------------------------------------------------
-- STALKER NPC INFO
----------------------------------------------------------------------------------------------------------------------

function set_npc_info(npc, ini, scheme, section)
--printf("INFO SECTION [%s]", utils.to_str(section))

local in_info = get_infos_from_data(npc, utils.cfg_get_string(ini, section, "in", npc, false, ""))
local out_info = get_infos_from_data(npc, utils.cfg_get_string(ini, section, "out", npc, false, ""))

for k,v in pairs(in_info) do
npc:give_info_portion(v)
end
for k,v in pairs(out_info) do
npc:disable_info_portion(v)
end
end
function get_infos_from_data(npc, s)
-- printf("get_infos_from_data [%s]", utils.to_str(s))
local t = {}
if s then
for name in string.gfind( s, "(%|*[^%|]+%|*)%p*" ) do
-- printf("[%s]", utils.to_str(name))
local condlist = xr_logic.parse_condlist(npc, "in", name, name)
if condlist then
table.insert(t, xr_logic.pick_section_from_condlist(db.actor, npc, condlist))
end
end
end
return t
end

----------------------------------------------------------------------------------------------------------------------
-- STALKER IGNORE MONSTER THRESHOLD
----------------------------------------------------------------------------------------------------------------------
-- Вызывается на переключении на новую секцию. Производит вычитывание настроек из текущей секции.
function reset_threshold(npc, scheme, st, section)
local threshold_section
if scheme == nil or scheme == "nil" then
threshold_section = utils.cfg_get_string(st.ini, st.section_logic, "threshold", npc, false, "")
else
threshold_section = utils.cfg_get_string(st.ini, section, "threshold", npc, false, "")
end

--'printf("THRESHOLD SECTION [%s]", utils.to_str(threshold_section))
if threshold_section then
local max_ignore_distance = utils.cfg_get_number(st.ini, threshold_section, "max_ignore_distance", npc, false)
if max_ignore_distance then
npc:max_ignore_monster_distance(max_ignore_distance)
else
npc:restore_max_ignore_monster_distance()
end
local ignore_monster = utils.cfg_get_number(st.ini, threshold_section, "ignore_monster", npc, false)
if ignore_monster then
npc:ignore_monster_threshold(ignore_monster)
else
npc:restore_ignore_monster_threshold()
end
end
end

----------------------------------------------------------------------------------------------------------------------
-- STALKER MAP SHOW
----------------------------------------------------------------------------------------------------------------------
-- Вызывается на переключении на новую секцию. Производит вычитывание настроек из текущей секции.
function reset_show_spot(npc, scheme, st, section)
local spot_section
if scheme == nil or scheme == "nil" then
spot_section = utils.cfg_get_string(st.ini, st.section_logic, "show_spot", npc, false, "")
else
spot_section = utils.cfg_get_string(st.ini, section, "show_spot", npc, false, "")
end
local map_spot = utils.cfg_get_string(st.ini, st.section_logic, "level_spot", npc, false, "")
if map_spot == nil then
map_spot = utils.cfg_get_string(st.ini, section, "level_spot", npc, false, "")
end
if map_spot ~= nil then
map_spot = xr_logic.parse_condlist(npc, section, "level_spot", map_spot)
map_spot = xr_logic.pick_section_from_condlist(db.actor, npc, map_spot)
end
--' printf("STALKER SPOT SECTION [%s]", utils.to_str(spot_section))

if spot_section == nil then
spot_section = "true"
end

local spot = "false"
-- if character_community(npc) ~= "zombied" then
local spot_condlist = xr_logic.parse_condlist(npc, section, "show_spot", spot_section)
spot = xr_logic.pick_section_from_condlist(db.actor, npc, spot_condlist)
-- end

local sim = alife()
if not sim then
return
end

local obj = sim:object(npc:id())
if obj and obj.online then
local npc_id = npc:id()
if spot == "false" then
-- прячем
obj:visible_for_map(false)
else
-- ставим
obj:visible_for_map(true)
end
if map_spot ~= nil then
local map_location = ""
local hint = ""
if map_spot == "trader" then
map_location = "ui_pda2_trader_location"
hint = "st_ui_pda_legend_trader"
elseif map_spot == "mechanic" then
map_location = "ui_pda2_mechanic_location"
hint = "st_ui_pda_legend_mechanic"
elseif map_spot == "guider" then
map_location = "ui_pda2_scout_location"
hint = "st_ui_pda_legend_scout"
elseif map_spot == "quest_npc" then
map_location = "ui_pda2_quest_npc_location"
hint = "st_ui_pda_legend_vip"
elseif map_spot == "medic" then
map_location = "ui_pda2_medic_location"
hint = "st_ui_pda_legend_medic"
elseif map_spot == "bankir" then
map_location = "ui_pda2_bankir_location"
hint = "st_ui_pda_legend_bankir"
elseif map_spot == "breeder" then
map_location = "ui_pda2_breeder_location"
hint = "st_ui_pda_legend_breeder"
end
if level.map_has_object_spot(npc_id, map_location) ~= 0 then
level.map_remove_object_spot(npc_id, map_location)
end
if db.actor and npc and npc:general_goodwill(db.actor) > -1000 then
level.map_add_object_spot(npc_id, map_location, hint)
end
else
if level.map_has_object_spot(npc_id, "ui_pda2_trader_location") ~= 0 then
level.map_remove_object_spot(npc_id, "ui_pda2_trader_location")
elseif level.map_has_object_spot(npc_id, "ui_pda2_mechanic_location") ~= 0 then
level.map_remove_object_spot(npc_id, "ui_pda2_mechanic_location")
elseif level.map_has_object_spot(npc_id, "ui_pda2_scout_location") ~= 0 then
level.map_remove_object_spot(npc_id, "ui_pda2_scout_location")
elseif level.map_has_object_spot(npc_id, "ui_pda2_quest_npc_location") ~= 0 then
level.map_remove_object_spot(npc_id, "ui_pda2_quest_npc_location")
elseif level.map_has_object_spot(npc_id, "ui_pda2_medic_location") ~= 0 then
level.map_remove_object_spot(npc_id, "ui_pda2_medic_location")
elseif level.map_has_object_spot(npc_id, "ui_pda2_bankir_location") ~= 0 then
level.map_remove_object_spot(npc_id, "ui_pda2_bankir_location")
elseif level.map_has_object_spot(npc_id, "ui_pda2_breeder_location") ~= 0 then
level.map_remove_object_spot(npc_id, "ui_pda2_breeder_location")
end
end
end
end

function remove_level_spot(npc, st)
local map_spot = utils.cfg_get_string(st.ini, st.section_logic, "level_spot", npc, false, "")
if map_spot == nil then
map_spot = utils.cfg_get_string(st.ini, st.active_section, "level_spot", npc, false, "")
end
if map_spot ~= nil then
map_spot = xr_logic.parse_condlist(npc, st.active_section, "level_spot", map_spot)
map_spot = xr_logic.pick_section_from_condlist(db.actor, npc, map_spot)
end
local sim = alife()
if not sim then
return
end

local obj = sim:object(npc:id())
if obj then
local npc_id = npc:id()
if map_spot ~= "" and map_spot ~= nil then
local map_location = ""
if map_spot == "trader" then
map_location = "ui_pda2_trader_location"
elseif map_spot == "mechanic" then
map_location = "ui_pda2_mechanic_location"
elseif map_spot == "guider" then
map_location = "ui_pda2_scout_location"
elseif map_spot == "quest_npc" then
map_location = "ui_pda2_quest_npc_location"
elseif map_spot == "medic" then
map_location = "ui_pda2_medic_location"
elseif map_spot == "bankir" then
map_location = "ui_pda2_bankir_location"
elseif map_spot == "breeder" then
map_location = "ui_pda2_breeder_location"
end
if level.map_has_object_spot(npc_id, map_location) ~= 0 then
level.map_remove_object_spot(npc_id, map_location)
end
end
end
end

--'--------------------------------------------------------------------------------------------------------------------
--' INVULNERABILITY
--'--------------------------------------------------------------------------------------------------------------------
function is_need_invulnerability(npc)
local npc_st = db.storage[npc:id()]
local invulnerability = utils.cfg_get_string(npc_st.ini, npc_st.active_section, "invulnerable", npc, false, "", nil)

if invulnerability == nil then
return false
end

invulnerability = xr_logic.parse_condlist(npc, "invulnerability", "invulnerability", invulnerability)

return xr_logic.pick_section_from_condlist(db.actor, npc, invulnerability) == "true"
end

--' Вызывается на переключении на новую секцию. Производит вычитывание настроек из текущей секции.
function reset_invulnerability(npc, ini, section)
local invulnerability = is_need_invulnerability(npc)

printf("RESET INVULNERABILITY. npc[%s] = [%s]", npc:name(), tostring(invulnerability))
if npc:invulnerable() ~= invulnerability then
npc:invulnerable(invulnerability)
end
end
function disable_invulnerability(npc)
printf("DISABLE INVULNERABILITY. npc[%s] = [false]", npc:name())
npc:invulnerable(false)
end

function update_invulnerability(npc)
local invulnerability = is_need_invulnerability(npc)

if npc:invulnerable() ~= invulnerability then
printf("UPDATE INVULNERABILITY. npc[%s] = [%s]", npc:name(), tostring(invulnerability))
npc:invulnerable(invulnerability)
end
end

--'--------------------------------------------------------------------------------------------------------------------
--' TEAM SQUAD GROUP
--'--------------------------------------------------------------------------------------------------------------------
--' Вызывается на переключении на новую секцию. Производит вычитывание настроек из текущей секции.
function reset_group(npc, ini, section)
local group = utils.cfg_get_number(ini, section, "group", npc, false, -1)

if group ~= -1 then
npc:change_team(npc:team(), npc:squad(), group)
end
end

function take_items_enabled(npc, scheme, st, section)
local take_items = nil
if(st.ini:line_exist(section, "take_items")) then
take_items = utils.cfg_get_bool(st.ini, section, "take_items", npc, false, true)
else
take_items = utils.cfg_get_bool(st.ini, st.section_logic, "take_items", npc, false, true)
end
npc:take_items_enabled(take_items)
end

function can_select_weapon(npc, scheme, st, section)
local str = utils.cfg_get_string(st.ini, section, "can_select_weapon", npc, false, "", "")
if(str=="") then
str = utils.cfg_get_string(st.ini, st.section_logic, "can_select_weapon", npc, false, "", "true")
end

local cond = xr_logic.parse_condlist(npc, section, "can_select_weapon", str)
local can = xr_logic.pick_section_from_condlist(db.actor, npc, cond)
npc:can_select_weapon(can=="true")
end
[/cut]
 
denis2000Дата: Вт, 28.11.2017, 09:42 | Сообщение # 888
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

sergej5500, Пробуйте в скрипт xr_motivator.script в функцию motivator_binder:update(delta) в самый конец добавить:
Код
local st = db.storage[self.object:id()]
    local npc = self.object
    if npc:position():distance_to_sqr(db.actor:position())>22500 then
  stalker_generic.remove_level_spot(npc, st)
    end


"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..."
(Чугунный всадник)
 
sergej5500Дата: Вт, 28.11.2017, 11:21 | Сообщение # 889
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
Награды: 29
Репутация: [ 1355 ]

denis2000,

За помощь спасибо. Вечером опробую. Возник еще один вопрос.

Стандартная функция для спавна сквадов.

[cut=create_squad]function create_squad(actor, obj, p)
if obj ~= nil then
printf("pl:creating_squad from obj [%s] in section [%s]", tostring(obj:name()), tostring(db.storage[obj:id()].active_section))
end
local squad_id = p[1]
if squad_id == nil then
abort("Wrong squad identificator [NIL] in create_squad function")
end
local smart_name = p[2]
if smart_name == nil then
abort("Wrong smart name [NIL] in create_squad function")
end

local ltx = sim_board.squad_ltx

if not ltx:section_exist(squad_id) then
abort("Wrong squad identificator [%s]. Squad descr doesnt exist.", tostring(squad_id))
end

local board = sim_board.get_sim_board()
local smart = board.smarts_by_names[smart_name]
if smart == nil then
abort("Wrong smart_name [%s] for [%s] faction in create_squad function", tostring(smart_name), tostring(player_name))
end

local squad = board:create_squad(smart, squad_id)

board:enter_smart(squad, smart.id)

for k in squad:squad_members() do
board:setup_squad_and_group(k.object)
end

squad:update()
end[/cut]

Возникла идея поставить на сквад метку. В стандартной функции это не предусмотрено. Метка должна ставиться в момент спавна сквада. Что то вроде функции типа.

create_skvad("squad","smart","spot")

Как то так.

create_skvad("squad","smart","spot")
xr_effects.create_squad(actor,nil,{"squad","smart"})
функция установки спота
end

Как должна выглядеть функция установки спота?
 
denis2000Дата: Вт, 28.11.2017, 12:21 | Сообщение # 890
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

sergej5500, В конец функции xr_effects.create_squad добавляете:
Код
local squad_spot = p[3]
    local squad_hint = p[4]
    if squad_spot ~= nil then
  if squad_hint == nil then squad_decr = "" end
  if squad:commander_id() ~= nil then
   level.map_add_object_spot(squad:commander_id(), squad_spot, squad_hint)
  end
    end

Вызов: xr_effects.create_squad(actor,nil,{"squad","smart","spot","hint"})


"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..."
(Чугунный всадник)
 
sergej5500Дата: Вт, 28.11.2017, 20:26 | Сообщение # 891
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
Награды: 29
Репутация: [ 1355 ]

denis2000,

Спасибо за помощь. Удаление меток с важных персов работает отлично.

С метками на сквадах возникли трудности.

1. При гибели командира метка не переносится с него на следующего командира.

2. После гибели всего сквада метка продолжает висеть на трупе.
 
denis2000Дата: Ср, 29.11.2017, 13:36 | Сообщение # 892
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

Цитата sergej5500 ()
1. При гибели командира метка не переносится с него на следующего командира.
2. После гибели всего сквада метка продолжает висеть на трупе.

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


"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..."
(Чугунный всадник)
 
sergej5500Дата: Ср, 29.11.2017, 21:56 | Сообщение # 893
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
Награды: 29
Репутация: [ 1355 ]

Добрый вечер.

Тестирую функцию спавна множества аномалий с рандомной позицией.

[cut=Функции]
function test_anomaly_spawn()
local anomaly = {"mod_zone_mine_electric_weak","mod_zone_mine_electric_average"}
for i = 1, 150 do
local section = anomaly[ math.random( #anomaly ) ]
create_anomaly_2(section,5,math.random(1,1800000),db.actor:game_vertex_id())
end
end

-- 'Спавн аномалии.
function create_anomaly_2(zone_name,zone_radius,lv,gv)
local sobj=alife():create(zone_name,level.vertex_position(lv),lv,gv)
local packet = net_packet()
packet:w_begin(0)
sobj:STATE_Write(packet)
packet:r_seek(2)
local game_vertex_id = packet:r_u16()
local distance = packet:r_float()
local direct_control = packet:r_s32()
local level_vertex_id = packet:r_s32()
local object_flags = packet:r_s32()
local custom_data = packet:r_stringZ()
local story_id = packet:r_s32()
local spawn_story_id = packet:r_s32()
local shape_count = packet:r_u8()
for i = 1,shape_count do
local shape_type = packet:r_u8()
if shape_type == 0 then
local center = packet:r_vec3()
local radius = packet:r_float()
else
local box = packet:r_matrix()
end
end
local restrictor_type = packet:r_u8()
local max_power = packet:r_float()
local owner_id = packet:r_s32()
local enabled_time = packet:r_u32()
local disabled_time = packet:r_u32()
local start_time_shift = packet:r_u32()
local offline_interactive_radius = packet:r_float()
local artefact_spawn_count = packet:r_u16()
local artefact_position_offset = packet:r_s32()
local new_center = vector():set(0,0,0)
owner_id = bit_not(0)
restrictor_type = 3
max_power = 0
offline_interactive_radius = 30
artefact_spawn_count = 32
packet:w_begin(0)
packet:w_u16(game_vertex_id)
packet:w_float(distance)
packet:w_s32(direct_control)
packet:w_s32(level_vertex_id)
packet:w_s32(object_flags)
packet:w_stringZ(custom_data)
packet:w_s32(story_id)
packet:w_s32(spawn_story_id)
packet:w_u8(1)
packet:w_u8(0)
packet:w_vec3(new_center)
packet:w_float(zone_radius)
packet:w_u8(restrictor_type)
packet:w_float(max_power)
packet:w_s32(owner_id)
packet:w_u32(enabled_time)
packet:w_u32(disabled_time)
packet:w_u32(start_time_shift)
packet:w_float(offline_interactive_radius)
packet:w_u16(artefact_spawn_count)
packet:w_s32(artefact_position_offset)
packet:r_seek(2)
sobj:STATE_Read(packet,packet:w_tell())
return sobj
end[/cut]

По горячей клавише в разных точках рандомно спавнятся 150 аномалий. Клавишу нажимаю один раз в несколько секунд.

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

[cut=Лог]FATAL ERROR

[error]Expression : !m_error_code
[error]Function : raii_guard::~raii_guard
[error]File : D:\prog_repository\sources\trunk\xrServerEntities\script_storage.cpp
[error]Line : 748
[error]Description : ...publishing\Зов Припяти\gamedata\scripts\utils.script:588: attempt to index local 't' (a number value)


stack trace:[/cut]

Глючная функция

-- запись CTime в пакет. если t=nil, то запишет один нулевой байт
function w_CTime( p, t )
--set_save_marker(p, "save", false, "CTIME")
if t == nil then
p:w_u8(-1)
--set_save_marker(p, "save", true, "CTIME")
return
end

if (CTime == nil) or (t ~= CTime_0) then
local Y, M, D, h, m, s, ms = 0, 0, 0, 0, 0, 0, 0
Y, M, D, h, m, s, ms = t:get( Y, M, D, h, m, s, ms ) -- 588 строка

p:w_u8 ( Y - 2000 )
p:w_u8 ( M )
p:w_u8 ( D )
p:w_u8 ( h )
p:w_u8 ( m )
p:w_u8 ( s )
p:w_u16( ms )
else
p:w_u8 ( 0 )
end
--set_save_marker(p, "save", true, "CTIME")
end

Как можно избавиться от вылета?
 
denis2000Дата: Чт, 30.11.2017, 16:46 | Сообщение # 894
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

sergej5500, Проблема не в этой функции, а в той что вызывает ее, передавая вместо даты/времени число. Искать надо начинать именно там.
Возможно причина в том, что при спавне аномалий происходит очень часто и много чтений и записей нетпакетов объектов.


"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..."
(Чугунный всадник)
 
makdmДата: Чт, 30.11.2017, 22:57 | Сообщение # 895
Рожденный в СССР
Разработчики
Сообщений: 1294
Награды: 29
Репутация: [ 1909 ]

sergej5500, неправильно прочитан и записан нет-пакет. Отсюда вылет, связанный со временем.
Вот так нужно делать:

[cut noguest=Функция]function create_anomaly( zone_name, zone_radius, position, lv, gv )

----------------------------Создаём объект - аномалию----------------------------

local sobj = alife():create( zone_name, position, lv, gv )

local packet = net_packet()
packet:w_begin( 0 )

-------------------------------------Читаем нет-пакет --------------------------
sobj:STATE_Write( packet )
packet:r_seek( 2 )

local game_vertex_id = packet:r_u16()
local distance = packet:r_float()
local direct_control = packet:r_s32()
local level_vertex_id = packet:r_s32()
local object_flags = packet:r_s32()
local custom_data = packet:r_stringZ()
local story_id = packet:r_s32()
local spawn_story_id = packet:r_s32()
local shape_count = packet:r_u8()
for i = 1,shape_count do
local shape_type = packet:r_u8()
if shape_type == 0 then
local center = packet:r_vec3()
local radius = packet:r_float()
else
local box = packet:r_matrix()
end
end
local restrictor_type = packet:r_u8()
local max_power = packet:r_float()
local owner_id = packet:r_s32()
local enabled_time = packet:r_u32()
local disabled_time = packet:r_u32()
local start_time_shift = packet:r_u32()
local offline_interactive_radius = packet:r_float()
local artefact_spawn_count = packet:r_u16()
local artefact_position_offset = packet:r_s32()
local last_spawn_time = packet:r_u8()

------------------------------------------Меняем данные пакета

local new_center = vector():set( 0, 0, 0 )
owner_id = bit_not( 0 )
restrictor_type = 3
max_power = 0
offline_interactive_radius = 30
artefact_spawn_count = 32
last_spawn_time = 0

------------------------------------------------Пишем в пакет

packet:w_begin( 0 )
packet:w_u16( game_vertex_id )
packet:w_float( distance )
packet:w_s32( direct_control )
packet:w_s32( level_vertex_id )
packet:w_s32( object_flags )
packet:w_stringZ( custom_data )
packet:w_s32( story_id )
packet:w_s32( spawn_story_id )
packet:w_u8( 1 )
packet:w_u8( 0 )
packet:w_vec3( new_center )
packet:w_float( zone_radius )
packet:w_u8( restrictor_type )
packet:w_float( max_power )
packet:w_s32( owner_id )
packet:w_u32( enabled_time )
packet:w_u32( disabled_time )
packet:w_u32( start_time_shift )
packet:w_float( offline_interactive_radius )
packet:w_u16( artefact_spawn_count )
packet:w_s32( artefact_position_offset )
packet:w_u8( last_spawn_time )

packet:r_seek( 2 )
sobj:STATE_Read( packet, packet:w_tell() )
return sobj
end
[/cut]


Терпение......
И все получится!


Сообщение отредактировал makdm - Чт, 30.11.2017, 22:58
 
sergej5500Дата: Пн, 04.12.2017, 00:04 | Сообщение # 896
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
Награды: 29
Репутация: [ 1355 ]

Добрый вечер.

Взял из СГМ функцию спавна костюмов в трупы. Адаптировал её на чистый ЗП.

local outfit_container_list={
{"stalker_neutral_1","stalker_outfit",0.90},
{"stalker_neutral_2","stalker_outfit",0.95},
{"stalker_neutral_3","scientific_outfit",0.92},
{"stalker_neutral_4","exo_outfit",0.91}
}

function container_stalker_death(victim,killer)
local victim_sect=victim:section()
local victim_visual=victim:get_visual_name()
for k,v in pairs(outfit_container_list) do
if find_in_string(victim_visual,v[1]) and math.random(100)<=v[3]*100 then
local sobj=alife():create(v[2],vector(),0,0,victim:id())
end
end
end

Функция вызывается из коллбэка на смерть сталкера. В принципе всё работает. Костюмы появляются в трупах. Встал вопрос. Как сделать костюм изношенным?

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

Если ли другой способ? Можно ли задать износ костюма в момент спавна?
 
denis2000Дата: Пн, 04.12.2017, 08:30 | Сообщение # 897
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

Цитата sergej5500 ()
Можно ли задать износ костюма в момент спавна?

Возможно что - нет, все может в итоге свестись к тому, что нужно каким либо методом после спавна устанавливать костюму его новое состояние (функцией с постоянным апдейтом - плохо или зарегистрированным для этого колбеком - лучше).
Цитата sergej5500 ()
Если ли другой способ?

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


"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..."
(Чугунный всадник)
 
makdmДата: Чт, 07.12.2017, 20:11 | Сообщение # 898
Рожденный в СССР
Разработчики
Сообщений: 1294
Награды: 29
Репутация: [ 1909 ]

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

Однозначно лучше ставить колбек.
sergej5500, после строки

local sobj=alife():create(v[2],vector(),0,0,victim:id())

Ставим колбек на проспавн костюма и переход его в онлайн.
Пишем так:

[cut noguest]

level.add_call(
function ()
if sobj.online then
return true
end
end,
function ()
local condition = ( math.random(40) + 40 )/100
level.object_by_id( sobj.id ):set_condition( condition )
end
)
break

[/cut]


Терпение......
И все получится!


Сообщение отредактировал makdm - Чт, 07.12.2017, 20:20
 
sergej5500Дата: Вт, 02.01.2018, 22:04 | Сообщение # 899
Полевой Исследователь
Ученые сталкеры
Сообщений: 3793
Награды: 29
Репутация: [ 1355 ]

Добрый вечер.

В СГМ есть чит-режим "бесконечные патроны". Я на досуге изучал, как он работает.

[cut=Основная функция чит-режима] if check_actor_item_in_slot(2,"self",true) or check_actor_item_in_slot(3,"self",true) then
local ammo_types=sgm_functions.ReadAmmoClass(db.actor:active_item():section())
respawn_item_if_comparison("ammo_9x18_fmj",ammo_types,4)
respawn_item_if_comparison("ammo_9x19_fmj",ammo_types,4)
respawn_item_if_comparison("ammo_11.43x23_fmj",ammo_types,4)
respawn_item_if_comparison("ammo_12x70_buck",ammo_types,4)
respawn_item_if_comparison("ammo_5.45x39_fmj",ammo_types,4)
respawn_item_if_comparison("ammo_9x39_pab9",ammo_types,4)
respawn_item_if_comparison("ammo_5.56x45_ss190",ammo_types,4)
respawn_item_if_comparison("ammo_7.62x54_7h1",ammo_types,2)
respawn_item_if_comparison("ammo_og-7b",ammo_types,2)
respawn_item_if_comparison("ammo_gauss",ammo_types,2)
respawn_item_if_comparison("ammo_pkm_100",ammo_types,2)
respawn_item_if_comparison("ammo_dumdum",ammo_types,2)
end[/cut]

[cut=Вспомогательные функции]
-- 'Типы патронов, поддерживаемые оружием.
function ReadAmmoClass(section)
local ltx = system_ini()
if ltx:line_exist(section,"ammo_class") then
return ltx:r_string(section,"ammo_class")
else
return nil
end
end

-- 'Проверка на наличие предмета в слоте и при необходимости, на соответствие к compare_section.
function check_actor_item_in_slot(need_slot,compare_section,need_active)
local currert_slot=db.actor:item_in_slot(need_slot)
local active_item=db.actor:active_item()
if currert_slot~=nil and currert_slot:section()~=nil then
if compare_section~=nil and compare_section=="self" then
compare_section=currert_slot:section()
end
if compare_section~=nil and currert_slot:section()==compare_section then
if need_active~=true then
return true
else
if active_item and active_item:section()==compare_section then
return true
end
end
elseif compare_section==nil then
return true
end
end
return false
end

-- 'Респаун предмета при соблюдении специального условия.
function respawn_item_if_comparison(need_value_and_item,comparison_value,item_count)
local check_item=need_value_and_item
if find_in_string(comparison_value,check_item) then
check_actor_item_to_add(check_item,item_count)
end
end

-- 'Проверка на отсутствие предмета, и спаун предмета.
function check_actor_item_to_add(target_item,count)
if not db.actor:object(target_item) then
give_object_to_npc(target_item,db.actor,count)
end
end

-- 'Создание предмета в рюкзаке НПС.
function give_object_to_npc(section,npc,count)
if count==nil then count=1 end
for i=1, count do
alife():create(section,npc:position(),npc:level_vertex_id(),npc:game_vertex_id(),npc:id())
end
end

-- 'Присутствие в названии строки.
function find_in_string(where,what)
if where~=nil and what~=nil and string.find(where,what) then
return true
elseif where==nil or what==nil then
return nil
end
return false
end[/cut]

Функция не работает для РПГ. Хотя боеприпас от РПГ там прописан. В чем может быть причина?
 
denis2000Дата: Ср, 03.01.2018, 12:33 | Сообщение # 900
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

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

Как и предполагалось не срабатывает условие find_in_string. Чтобы работало нужно поставит костыли например так:
Код
respawn_item_if_comparison("ammo_7.62x54_7h1",ammo_types,2)
respawn_item_if_comparison("ammo_og",ammo_types,2)
respawn_item_if_comparison("ammo_gauss",ammo_types,2)

Код
function respawn_item_if_comparison(need_value_and_item,comparison_value,item_count)
   local check_item=need_value_and_item
    if find_in_string(comparison_value,check_item) then
  if check_item=="ammo_og" then check_item="ammo_og-7b" end
      check_actor_item_to_add(check_item,item_count)
   end
end


"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..."
(Чугунный всадник)
 
Поиск: