Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

GAMEINATOR forums _ Мастерская: создание модов для S.T.A.L.K.E.R. _ Скрипты

Автор: vintprog 05.07.2009, 16:03

Какие возможности у скрипта LUA?

Можно например реализовать:
Гравитационое оружия,
Литания на самолетах,
Огнемет,
прикрепление приклада и.т.д?

Автор: Shadow. 05.07.2009, 16:10

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

Автор: Stalbar 05.07.2009, 16:13

Цитата(vintprog @ 05.07.2009, 20:03) *
Какие возможности у скрипта LUA?

Можно например реализовать:
Гравитационое оружия,
Литания на самолетах,
Огнемет,
прикрепление приклада и.т.д?

Вы это хотите "чисто на скриптах" изобразить??

Цитата(Shadow. @ 05.07.2009, 20:10) *
Хотелось бы научиться данному языку хоть немного.Подскажите кто-нибудь нормальный учебник по этому делу.

учебник там --> http://www.lua.ru/doc/

Автор: vintprog 05.07.2009, 16:20

Нет я просто интересуюся можно ли создать такое.

Скриптингом только недавно начал заниматса в STALKER,а так я программирую на Delphi немного знаю C++,
еще хачю найти учебники по модингу,
и по создания нового HUD -оружия

Автор: Neo][ 05.07.2009, 17:00

Цитата(vintprog @ 05.07.2009, 19:20) *
еще хачю найти учебники по модингу,
и по создания нового HUD -оружия

vintprog, в помощь http://stalkerin.gameru.net/wiki

Автор: vintprog 05.07.2009, 17:10

Neo][
Спасибо больщое,
а что правдо выйдет SDK для одиночной игры?

Автор: Lance 05.07.2009, 17:19

Цитата(vintprog @ 05.07.2009, 21:10) *
Neo][
Спасибо больщое,
а что правдо выйдет SDK для одиночной игры?

хочется ответить словами из песни:
"... наверно, в следующей жизни, когда я стану кошкой..."

Автор: vintprog 05.07.2009, 17:23

Ну что можно реализовать те возможности, что я описал выше в скрипти Stalker?

Автор: Unstoppoble 05.07.2009, 17:42

Цитата(vintprog @ 05.07.2009, 18:23) *
Ну что можно реализовать те возможности, что я описал выше в скрипти Stalker?


Цитата
Гравитационое оружия,
Литания на самолетах,


Речь об этом ? smile.gif Если да, то ответ - нет.

Автор: Merc Shram 05.07.2009, 17:47

http://www.lua.ru/doc/

Научись сначала писать правильно
Можно например реализовать:
Гравитационое оружия, -> Гравитационное оружие
Литания на самолетах, -> Летание на самолетах

Автор: vintprog 05.07.2009, 18:00

А вобще можно?

Автор: Орион 05.07.2009, 18:01

Цитата(Unstoppoble @ 05.07.2009, 17:42) *
ответ - нет.

Автор: vintprog 05.07.2009, 18:14

А перемещать npc на координаты, и ставить партиклы на координаты это хоть можно в скриптенги?

Автор: Stalbar 05.07.2009, 18:28

Цитата(vintprog @ 05.07.2009, 22:14) *
А перемещать npc на координаты, и ставить партиклы на координаты это хоть можно в скриптенги?

В "скриптенги" точно нельзя. Ибо нет такого, не то что понятия, - слова такого нет. Тебе дали кучу ссылок на информацию - читай, изучай, пробуй. Будут адекватные вопросы - будут адекватные ответы.

Автор: CHOPK 05.07.2009, 18:29

Цитата(vintprog @ 05.07.2009, 16:03) *
Огнемет,

АМК уже давно сделали огнёмёт rolleyes.gif

Цитата(Stalbar @ 05.07.2009, 16:13) *
учебник там --> http://www.lua.ru/doc/

о,спс,давно искал)

Автор: UX.Loki 05.07.2009, 19:08

vintprog, поставь мозилу файрфокс , он умеет подчеркивать не правильные грамматически слова и выдавать верные решения .

Автор: BAC9-FLCL 05.07.2009, 19:41

Видимо, заметить тему было сложно.
http://www.gameru.net/forum/index.php?showtopic=14792

Автор: vintprog 12.07.2009, 11:37

Все облазел не могу найти учебники по скриптпингу s.t.a.l.k.e.r,
будь он не ладный этот LUA пока внем разберещся борода вырастет,лутчи был бы Pascal или c++,
срочно нужно сделать моды новых миссий новых возможностей,
пожалуйста помогите мне найти учебники или статьи по скриптпингу.

Автор: Shadow. 12.07.2009, 11:53

Как-бы с такой грамматикой ты далеко не пойдёшь...
А лучше скажу - выкинь эту мысль из головы,с нуля вот так,взять и начать писать скрипты тебе будет сложно.Хотя почему....даже невозможно
www.lua.ru

Автор: DmitrjT 12.07.2009, 11:58

http://wiki.masu-inform.ru:8888/index.php/Lua
http://club.shelek.ru/viewart.php?id=77
Если применительно к Сталкеру то примеры есть в билде 1935 и на АМК и OGSE форумах.

Автор: vintprog 12.07.2009, 12:05

В сталкере невидел var,
мне нужно знать функцыии для
создания NPC, как заставить их ийти на заданые координаты,
как выдать им пушки, как заставить их стрелять в кого либо...
***** в Delphi и C++ программить и то лутче.

кто знает эти функцыии?


1. маты запрещены правилами форума
2. безграмотные сообщения тоже

Автор: DmitrjT 12.07.2009, 12:12

Вот тебе простой пример
Создание NPC "привязанного к точке" автор Меченый(Стрелок) (amk-team)

Снайпер

*1
Для начала создадим профиль!
Откроем фаил character_****.xml
и создаем там новый профиль
Пример:
<specific_character id="название_секции" team_default = "1">
<name>GENERATE_NAME_stalker</name>
<icon>иконка</icon>
<map_icon x="1" y="0"></map_icon>
<bio>Опытный сталкер. Детальная информация отсутствует.</bio>

<class>класс</class>
<community>группировка</community> <terrain_sect>stalker_terrain</terrain_sect>
<snd_config>characters_voice\human_01\папка с названием группировки\</snd_config>

<rank>цифры от 0 до 900</rank>
<reputation>цифры от 0 до 1000</reputation>

<visual>путь до модели"визуала"</visual>
<supplies>
[spawn] \n
оружие \n
патроны к этому оружию = 5 \n
</supplies>
#include "gameplay\character_criticals_4.xml"
#include "gameplay\character_dialogs.xml"
</specific_character>

*2
Теперь нужно прописать класс нашего НПС в npc_profile.xml
Пример:
<character id="название_секции из character_****.xml">
<class>класс прописанный вами ранее</class>
<specific_character>название_секции из character_****.xml</specific_character>
</character>

*3
Теперь зарегистрируем Нашего НПС в spawn_section.ltx
Пример:
[секция спавна(название пишите сами)]:stalker
$spawn = "respawn\секция спавна"
character_profile = название_секции из character_****.xml
spec_rank = regular ;это ранг непеся оставляйте как есть ,особой роли не играет
community = группировка которую вы приписали этому (название_секции из character_****.xml)
custom_data = scripts\sniper_addon\sniper_addon_***_logic.ltx;*** - если группировка НПС нейтральна к вам или дружелюбна ,то friend , в противном случае enemy

*4
Потом открываем xr_conditions.script
и добавляем вот такую функцию
function is_sniper_enemy(enemy, object)
return enemy:id() ~= db.actor:id()
end
PS:Если нет такого фаила ,то возьмите из оригинальной Игры!

*5
Теперь осталось Заспавнить Нашего НПСа
PS:Тем кто делает это впервые ,прочитайте дальше smile.gif,а если сталкивались ,всё равно читайте smile.gif

*5.1
Для Начала нам нужно снять координаты того места Где появится наш Снайпер.
Для этого открываем ui_main_menu.script
находим вот примерно такое
if dik == DIK_keys.DIK_Q then
self:OnMessageQuitWin()
end
и делаем так :
if dik == DIK_keys.DIK_Q then
self:OnMessageQuitWin()
elseif dik==DIK_keys.DIK_W then
self:position_info()
end
И в конец фаила.В Самый Конец!!!
function main_menu:position_info()
local a = db.actor:position()
local vid = db.actor:level_vertex_id()
local gvid = db.actor:game_vertex_id()
local text = "GPS:\\nX= "..a.x.."\\nY= "..a.y.."\\nZ= "..a.z.."\\nlevel_vertex= "..vid.."\\ngame_vertex_id= "..gvid
news_manager.send_tip(db.actor, text, nil, nil, 30000)
end
Сохраняем!!!
*5.2
Заходим в игру ,добегаем до места где бы хотели чтобы сидел снайпер,выходим в Меню и в меню жмём на W , потом возвращаемся в игру
И Делаем скриншот (F12)
*5.3
Далее создаём скрипт спавна
(создаётся с помощью блокнота или Notepad++)
Например sniper_add.script
В нём будем писать функции!
function start_add_spawn()--\\*Это "список".Сюда будем вписывать вызов всех функции спавна
--\\*Сюда вписываем название ваших функций
--пример:
spawn_sniper_one()
end

function название_латиницей()--\\spawn_sniper_one()
local x= смотрим скриншот и переписываем сюда x
local y= смотрим скриншот и переписываем сюда y
local z= смотрим скриншот и переписываем сюда z
local level_vertex= смотрим скриншот и переписываем сюда level_vertex
local game_vertex_id= смотрим скриншот и переписываем сюда game_vertex_id
alife():create("тут название вашей из spawn_section.ltx",vector():set(x,y,z),level_vertex,game_vertex_id)
end

function save_variable(variable_name, value)
xr_logic.pstor_store(db.actor, variable_name, value)
end
function load_variable(variable_name, value_if_not_found)
return xr_logic.pstor_retrieve(db.actor, variable_name, value_if_not_found)
end

*5.4
Когда вписали всех наших Снайперов и все функции спавна и внесли их в "список",то добавляем вызов нашей функции в bind_stalker.script

в функцию actor_binder:update(delta)
перед последнем end'ом этой функции
добавляем
if sniper_add.load_variable("spawn_sniper",false)==false then
sniper_add.start_add_spawn()
sniper_add.save_variable("spawn_sniper",true)
end

Сохраняем!

*6
Теперь работаем с логикой.
в папке configs/scripts создаём папку с sniper_addon , открываем её
*6.1
Создаём два фаила
sniper_addon_friend_logic.ltx и sniper_addon_enemy_logic.ltx
*6.2
открываем sniper_addon_friend_logic.ltx
и вписываем туда:
;SNIPER ADDON
;Меченый(Стрелок)
[logic]
active = remark@search

[remark@fire]
combat_ignore_cond = {!is_sniper_enemy}
radius = 0
anim = hide
on_info = {=health_le(0.5)} remark@search
wounded = wounded@work
sniper = true

[remark@search]
combat_ignore_cond = true
combat_ignore_keep_when_attacked = false
anim = hide
target = actor
on_info = {=see_enemy} remark@fire
wounded = wounded@work
[smart_terrains]
none = true
[wounded@work]
hp_state = 0|wounded_heavy@help_heavy
hp_state_see = 0|wounded_heavy@help_heavy
hp_victim = 0|nil
hp_fight = 0|false
hp_cover = 0|false

Сохраняем этот фаил и открываем второй
и вставляем туда
;SNIPER ADDON
;Меченый(Стрелок)
[logic]
active = remark@search

[remark@fire]
combat_ignore_cond = {!is_enemy_actor}
radius = 0
anim = hide
on_info = {=health_le(0.5)} remark@search
wounded = wounded@work
sniper = true
[smart_terrains]
none = true
[remark@search]
combat_ignore_cond = true
combat_ignore_keep_when_attacked = false
anim = hide
target = actor
on_info = {=see_actor} remark@fire
wounded = wounded@work

[wounded@work]
hp_state = 0|wounded_heavy@help_heavy
hp_state_see = 0|wounded_heavy@help_heavy
hp_victim = 0|nil
hp_fight = 0|false
hp_cover = 0|false

Автор: vintprog 12.07.2009, 12:18

DmitrjT
Не плохо,интересно есть справочник всех функцый в сталкере,
есл есть тогда можно садитса делать моды на сталкер.

Автор: DmitrjT 12.07.2009, 12:21

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

Автор: vintprog 12.07.2009, 12:24

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

Автор: DmitrjT 12.07.2009, 13:06

Пожалуйста >>http://stalker-mod.ucoz.ru/load/0-0-0-19-20

Автор: Орион 13.07.2009, 11:34


FAQ

Lua

http://club.shelek.ru/viewart.php?id=77
http://www.lua.ru/doc/
Lua в X-Ray

Список всех функций, переменных, классов и т.п. что используются в Сталкере находится по адресу:
Код
gamedata/scripts/lua_help.script

Для получения файла надо распаковать игру. Можно скачать, в принципе smile.gif Тут =>>http://narod.ru/disk/10866278000/lua_help.script.html<<=
Уроки

http://www.gameru.net/forum/index.php?s=&showtopic=26547&view=findpost&p=799232 скриптами ЛУА. Автор: меченый(стрелок)
http://stalkerin.gameru.net/wiki/index.php?title=%D0%9A%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D1%8F:%D0%A1%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D1%8B

http://lua.org, http://luajit.org, http://luabind.sourceforge.net/docs.html, https://www.lua.org/cgi-bin/demo

https://yadi.sk/d/4EUvTWhzdnAve

Автор: DmitrjT 13.07.2009, 14:26

Для тех кого интересует скриптинг в Сталкере выкладываю статью тов. KamikaZze (ogse team) к сожалению полностью доделать ее нет времени полный текст материалов можно найти http://forum.ogse.ru/viewtopic.php?f=6&t=476&start=15
http://stalker-mod.ucoz.ru/_ld/0/20_2r6.rtf

Автор: jboo7 18.07.2009, 20:19

Можно ли как-то взорвать бочку не причиняя ей вред?) То есть не стрелять, не взрывать её, вообще с ней ничего не делать. Просто заспавнить через скрипт и потом так же через скрипт взорвать. Типа дистанционная бомбаsmile.gif

Автор: Орион 18.07.2009, 20:34

Это как? О_о

Автор: jboo7 18.07.2009, 20:53

Что "как?"?
Заспавнил бочку где-то рядом с собой, и нажал на заветную кнопку в главном меню, возвратился в игру и ты уже труп, потому что бочка взорвалась от нажатия на ту заветную кнопку. Как это можно было бы реализовать?

Автор: Орион 18.07.2009, 21:04

Кнопкой не знаю, если честно.. спейс рестриктором можно. Все помним сцены с туннелями в Рыжем Лесу, куда убегал Стрелок?) Можно по аналогии попробовать.

Автор: jboo7 18.07.2009, 21:26

Можно немного поподробнее?)

Автор: PATRON 18.07.2009, 23:43

Может попробовать нанести обьекту hit при помощи скрипта? Отследить его id, и дать хитом?

Автор: jboo7 18.07.2009, 23:51

А как тогда отследить его id после создания через alife():create?

Автор: Stalbar 19.07.2009, 08:53

Цитата(jboo7 @ 19.07.2009, 03:51) *
А как тогда отследить его id после создания через alife():create?

Ну етить... Вот ведь вопросы smile.gif В мануалах всё расписано как, и не только это, кстати... Читайте мануалы, и будет вам счастье. laugh.gif
Код
-- Создаём объект
local obj_name -- имя объекта
local pos, lvid, gvid -- позиция, левел-вертекс, гейм-вертекс
spawn_obj = alife():create(obj_name, pos, lvid, gvid) -- спавним объект
local obj_id = spawn_obj.id -- комментарии нужны? Если да, то это и есть "его id после создания"

Потом, когда нужно, наносим объекту хит, в данном случае взрывом
Код
-- получаем игровой объект по его номеру и взрываем
local boom_obj = level.object_by_id(obj_id)
local boom = hit()
boom.direction = vector():set(0,0,0) -- направление хита
boom.impulse = 10 -- импульс
boom.draftsman = boom_obj
boom.power = 10 -- сила хита
boom.type = hit.explosion -- тип хита, в данном случае, взрыв
if boom_obj then -- проверка, а собственно есть то, что нужно взорвать?
   boom_obj:hit(boom) -- большой бада-бум
end

Не сложно ведь?

Автор: PATRON 19.07.2009, 11:40

Stalbar, ну спасибо, давно искал это!

Автор: jboo7 19.07.2009, 13:50

Спасибо, Stalbar, проверю счасsmile.gif

Автор: jboo7 19.07.2009, 16:57

Попробовал то, что посоветовал Stalbar с канистрой из АМК. Ничего с канистрой не произошло, проверил вот эту строчку local boom_obj = level.object_by_id(obj_id) просто обратившись к объекту boom_obj:name(). Выкинуло, подозреваю, что level.object_by_id попросту ничего не вернуло и в boom_obj ничего нет.

Автор: Stalbar 19.07.2009, 23:34

Цитата(jboo7 @ 19.07.2009, 20:57) *
Попробовал то, что посоветовал Stalbar с канистрой из АМК. Ничего с канистрой не произошло, проверил вот эту строчку local boom_obj = level.object_by_id(obj_id) просто обратившись к объекту boom_obj:name(). Выкинуло, подозреваю, что level.object_by_id попросту ничего не вернуло и в boom_obj ничего нет.

Распиши подробно, что делаешь, как обращаешься, откуда и т.п. Пишешь, что выкинуло - лог имеется? Попробуй получить имя, как boom_obj:section_name()

Автор: jboo7 20.07.2009, 01:53

Код у меня такой:

local object_s = alife():create("amk_kanistra",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id())
local object_id = object_s.id
local object_n = level.object_by_id(object_id)

--local st = object_n:name() --узнаем имя, для проверки)
--get_console():execute("object_n..name>>"..st)

local boom = hit()
boom.direction = vector():set(0,1,0)
boom.impulse = 1000000
boom.draftsman = object_n
boom.power = 1000
boom.type = hit.explosion

if object_n then
object_n:hit(boom)
else --чтобы не было вылетов, выведем просто в консоль, что объекта нет
get_console():execute("object_n..is..nill>>")
end


Если убрать там комменты, игра вылетит с таким логом:

Expression : fatal error
Function : CScriptEngine::lua_error
File : E:\stalker\patch_1_0004\xr_3da\xrGame\script_engine.cpp
Line : 73
Description : <no expression>
Arguments : LUA error: ...s\s.t.a.l.k.e.r\gamedata\scripts\ui_main_menu.script:452: attempt to index local 'object_n' (a nil value)

Отсюда следует, что object_n = nil ...

Вместо вылетов поставил условие, чтобы не надоедало)

Автор: HikeR 20.07.2009, 02:12

Цитата(jboo7 @ 20.07.2009, 02:53) *
localobject_s = alife():create("amk_kanistra",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id())

то есть канистру в инвентарь спавните. а разве level.object_by_id() что-нибудь возвращает для объектов в инвентаре, и присутсвует ли вообще эта канистра в игре как объект, который можно взорвать?
попробуйте просто перед собой заспавнить в паре метров.
Код
local pos = db.actor:position()
local dir = db.actor:direction()
pos = pos:add(dir:mul(5))
-- создаем предмет в 5 метрах прямо перед нами
alife():create(чего_надо, pos, 1, db.actor:game_vertex_id())

Автор: jboo7 20.07.2009, 02:46

По сути у тебя тоже самое, что и у меня. Чтобы заспавнить в инвентарь нужно писать так

alife():create("amk_kanistra",
db.actor:position(),
db.actor:level_vertex_id(),
db.actor:game_vertex_id(),
db.actor:id())

тогда канистра попадет в инвентарь.

А так она спавнится под ногами у ГГ

Автор: Stalbar 20.07.2009, 08:28

Цитата(jboo7 @ 20.07.2009, 05:53) *
--local st = object_n:name() --узнаем имя, для проверки)
--get_console():execute("object_n..name>>"..st)

Измени и дополни вывод инфы

local st = object_n:section_name() --узнаем имя, для проверки)
get_console():execute("object_n..name>>"..tostring(st))
get_console():execute("object_id>>"..tostring(object_id))


и посмотри, что выдаст

Цитата(jboo7 @ 20.07.2009, 05:53) *
else --чтобы не было вылетов, выведем просто в консоль, что объекта нет
get_console():execute("object_n..is..nill>>")

А вот это отрабатывает в консоль? Если object_n nil то в логе будет такая запись..

Автор: andrey_chel_2905 20.07.2009, 08:42

как написать скрипт следования nps за игроком

Автор: Орион 20.07.2009, 11:07

andrey_chel_2905,
Изучайте тутор: http://sdk.stalker-game.com/ru/index.php?title=%D0%9B%D0%BE%D0%B3%D0%B8%D0%BA%D0%B0_NPC

Автор: jboo7 20.07.2009, 12:01

Цитата(Stalbar @ 20.07.2009, 08:28) *
Цитата(jboo7 @ 20.07.2009, 05:53) *
--local st = object_n:name() --узнаем имя, для проверки)
--get_console():execute("object_n..name>>"..st)

Измени и дополни вывод инфы

local st = object_n:section_name() --узнаем имя, для проверки)
get_console():execute("object_n..name>>"..tostring(st))
get_console():execute("object_id>>"..tostring(object_id))


и посмотри, что выдаст


Я попробую, но в принципе в этом нет смысла, потому что в логе написано, что object_n == nil. Для этого я и добавил там в условие else, чтобы узнать есть ли этот объект вообще.

В общем оставил только незакомментеной строчку get_console():execute("object_id>>"..tostring(object_id)). id у неё есть какое-то...

Цитата(Stalbar @ 20.07.2009, 08:28) *
Цитата(jboo7 @ 20.07.2009, 05:53) *
else --чтобы не было вылетов, выведем просто в консоль, что объекта нет
get_console():execute("object_n..is..nill>>")

А вот это отрабатывает в консоль? Если object_n nil то в логе будет такая запись..


Просто консоль попытается это воспринять как команда, но такой команды нет, поэтому, если зайти в консоль и если object_n == nil, то в консол красным будет выведена надпись "object_n..is..nill>>"


При запуске того кода в консол выводится "object_n..is..nill>>".

Автор: Stalbar 20.07.2009, 12:56

Цитата(jboo7 @ 20.07.2009, 05:53) *
if object_n then
object_n:hit(boom)
else --чтобы не было вылетов, выведем просто в консоль, что объекта нет
get_console():execute("object_n..is..nill>>")
end

Тогда не парься и давай хит прямо по object_s

if object_s then
object_s:hit(boom)
else --чтобы не было вылетов, выведем просто в консоль, что объекта нет
get_console():execute("object_s..is..nill>>")
end

Автор: jboo7 20.07.2009, 13:21

Цитата(Stalbar @ 20.07.2009, 12:56) *
Цитата(jboo7 @ 20.07.2009, 05:53) *
if object_n then
object_n:hit(boom)
else --чтобы не было вылетов, выведем просто в консоль, что объекта нет
get_console():execute("object_n..is..nill>>")
end

Тогда не парься и давай хит прямо по object_s

if object_s then
object_s:hit(boom)
else --чтобы не было вылетов, выведем просто в консоль, что объекта нет
get_console():execute("object_s..is..nill>>")
end


После этого игра вылетает с таким логомsmile.gifsmile.gifsmile.gifsmile.gifsmile.gifsmile.gifsmile.gifsmile.gifsmile.gifsmile.gif

Expression : fatal error
Function : CScriptEngine::lua_error
File : E:\stalker\patch_1_0004\xr_3da\xrGame\script_engine.cpp
Line : 73
Description : <no expression>
Arguments : LUA error: ...s\s.t.a.l.k.e.r\gamedata\scripts\ui_main_menu.script:464: attempt to call method 'hit' (a nil value)

То есть у object_s нема метода hit(). И че делать?)

Автор: jboo7 21.07.2009, 18:24

Кто-то знает какого класса объект, возвращаемый alife():create()?

Автор: HikeR 21.07.2009, 18:34

ссылку на game_object, надо полагать.

Автор: jboo7 21.07.2009, 18:44

Тогда у него был метод hit(), но его у него нет. Еще вариантыsmile.gif

Автор: Stalbar 21.07.2009, 20:38

jboo7, самому докопаться до истины - "не наш метод"?? Ну ок, сделаю тебе полный "тутор по взрыву канистры". В картинках. С кодом.

Так как амк_канистры не нашёл, сделал пример на "Ниве", надеюсь, это-то сможешь поменять?? В файле ui_main_menu.script объявляем переменную в самом начале:

local niva_id = 0

далее добавляем свои вызовы в function main_menu:OnKeyboard(dik, keyboard_action) - вешаем на F1 и F2

Код
        if dik == DIK_keys.DIK_F1 then
            if level.present() and (db.actor ~= nil) and db.actor:alive() then
                local console = get_console()
                console:execute("main_menu off")
                spawn_niva()
            end
        end
        if dik == DIK_keys.DIK_F2 then
            if level.present() and (db.actor ~= nil) and db.actor:alive() then
                local console = get_console()
                console:execute("main_menu off")
                boom_niva()
            end
        end


в конце скрипта, собственно, "наше всё"

Код
function spawn_niva()
local lvid, gvid = db.actor:level_vertex_id(),db.actor:game_vertex_id()
local pos = db.actor:position()
local dir = db.actor:direction()
    pos = pos:add(dir:mul(5))
local spawn_item = alife():create("vehicle_niva",pos,lvid, gvid)
local niva_name = spawn_item:section_name()
    niva_id = spawn_item.id
    amk.logf("Марка и номер двигателя: "..tostring(niva_name).." "..tostring(spawn_item.id))
end

function boom_niva()
local obj_niva = level.object_by_id(niva_id)
    if obj_niva then
    local niva_pos = obj_niva:position()
    local niva_dist = niva_pos:distance_to(db.actor:position())
        amk.logf("Номер авто в ГАИ: "..tostring(niva_id))
        amk.logf("Позиция авто: "..tostring(niva_pos.x).." "..tostring(niva_pos.y).." "..tostring(niva_pos.z))
        amk.logf("Расстояние до актора: "..tostring(niva_dist))        
    local boom = hit()
        boom.direction = vector():set(0,1,0)
        boom.impulse = 1
        boom.draftsman = obj_niva
        boom.power = 10
        boom.type = hit.explosion
        obj_niva:hit(boom)
    else
        amk.logf("Авто в ГАИ не зарегестировано!! Угнали??")
    end
end


Запускаем, проверяем, скриним

http://img.gameru.net/?v=05729.jpg

Тыц на Esc и F1, опа, сработало!

http://img.gameru.net/?v=a2a89.jpg

И в логе появилось ! Unknown command: :Марка и номер двигателя: vehicle_niva 41217

Отходим, шоб не долбануло...

http://img.gameru.net/?v=b8c4c.jpg

Тыц на Esc и F2, Бумс!

http://img.gameru.net/?v=7732c.jpg

Ну и на финал, лог

! Unknown command: :Номер авто в ГАИ: 41217
! Unknown command: :Позиция авто: -119.96485137939 -8.2003936767578 -141.2625579834
! Unknown command: :Расстояние до актора: 12.44276714325


Вывод в лог используется амк-шный, ибо удобен... если у тебя нет файла amk.script ( в чём я сомневаюсь), то вот используемые функции

Код
function logf( fmt, ... )
    logf_console = get_console()
    logf = logf_main
    logf_main( fmt, ... )
end

function logf_main( fmt, ... )
    local c = select( "#", ... )
    if c <= 0 then -- nothing to format
        logf_console:execute( ":" .. string.gsub( fmt, " ", "\160" ) )
    else
        logf_console:execute( ":" .. string.gsub( string.format( fmt, ... ), " ", "\160" ) )
    end
end


Вопросы??

Автор: jboo7 21.07.2009, 21:33

Без сомнений всё подробно описал, респект)
Но вопрос только один: почему level.object_by_id амк_канистру не находит?..

Автор: Stalbar 21.07.2009, 21:56

Цитата(jboo7 @ 22.07.2009, 01:33) *
Без сомнений всё подробно описал, респект)
Но вопрос только один: почему level.object_by_id амк_канистру не находит?..

А откуда уверенность, что не находит? Судя по вашему коду, там проверки на это нет... Я видел только попытки получить name неверным методом (--local st = object_n:name() --узнаем имя, для проверки)), а проверку того, что же всё-таки содержится в object_n я не видел. Собственно, весь пример выше и нужен был только для "показа" переменных.

Автор: jboo7 21.07.2009, 22:03

CODE
if object_n then
object_n:hit(boom)
else
get_console():execute("object_n..is..nill>>")
end


А это разве не проверка в моем коде на существование объекта?

Автор: Stalbar 21.07.2009, 22:26

jboo7, тогда пожалуйста, по порядку smile.gif Весь код, что приведён в первом сообщении на этой странице - он откуда? Как вызывается? Этот код из одной функции, или из нескольких?

Автор: jboo7 21.07.2009, 22:38

Две функции, думаю не стоит рассказывать как я их вызываю)

CODE

function main_menu:spawn(n)
local object_s = alife():create("amk_kanistra",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id())
local object_id = object_s.id
object_n = level.object_by_id(object_id)
end

function main_menu:explode()

local boom = hit()
boom.direction = vector():set(1,0,0)
boom.impulse = 1000000
boom.draftsman = object_n
boom.power = 1000
boom.type = hit.explosion

if object_n then
object_n:hit(boom)
else
get_console():execute("object_n..is..nil>")
end
end


Тут все понятно, но в object_n пусто...

Автор: Kolmogor 21.07.2009, 22:48

Цитата(jboo7 @ 21.07.2009, 23:38) *
Две функции, думаю не стоит рассказывать как я их вызываю)

function main_menu:spawn(n)
local object_s = alife():create("amk_kanistra", ...)
local object_id = object_s.id
object_n = level.object_by_id(object_id)
end

Тут все понятно, но в object_n пусто...

В этой функции вы пытаетесь получить клиентский объект сразу после создания. Его еще нет в игре, так как в онлайн он еще не перешел. Поэтому там и пусто. Лучше запомнить object_id и по нему получить клиентский объект в explode()
То есть как-то так

CODE

local object_id

function main_menu:spawn(n)
local object_s = alife():create("amk_kanistra",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id())
object_id = object_s.id
end

function main_menu:explode()
local boom = hit()
boom.direction = vector():set(1,0,0)
boom.impulse = 1000000
boom.draftsman = object_n
boom.power = 1000
boom.type = hit.explosion

local object_n = level.object_by_id(object_id)
if object_n then
object_n:hit(boom)
else
get_console():execute("object_n..is..nil>")
end
end


Автор: jboo7 21.07.2009, 23:10

Kolmogor, спасибо большое) Это действительно помогло) Не думал, что все так просто, одну строку перенести в другое местоsmile.gif

Автор: HikeR 21.07.2009, 23:33

Цитата(Kolmogor @ 21.07.2009, 23:48) *
Вэтой функции вы пытаетесь получить клиентский объект сразу после создания. Его еще нет в игре, так как в онлайн он еще не перешел.

кстати, может кто скажет, почему цикл while с ожиданием наступления момента появления объекта в онлайне сразу после создания обычно вызывает краш?
и есть ли какой-то аналог ф-ии wait(столько-то-секунд), которую можно использовать?

просто была такая же заморочка.
iterate_inventory(... -- перебираю инвентарь
alife():release(... -- убираю некоторый объект
iterate_inventory(... -- опять перебираю, а объект все еще есть.

если добавить проверку вида
while true do
if not is_object_online(obj_id) then break end
end

то вываливаюсь, а по идее цикл должен был крутится пока этот obj_id не перестанет отзываться.

Автор: Stalbar 22.07.2009, 09:09

HikeR, насчёт аналога - не подскажу, но может попробовать такую конструкцию?
В начале скрипта поставить что-то типа

local flag = true

Затем, после того как "alife():release(... -- убираю некоторый объект", в цикле ставить проверку, наподобие

while flag == true do
if "убитый_объект" ~= nil then flag = true else flag = false end
end

Автор: Kolmogor 22.07.2009, 09:26

Цитата(HikeR @ 22.07.2009, 00:33) *
просто была такая же заморочка.
iterate_inventory(... -- перебираю инвентарь
alife():release(... -- убираю некоторый объект
iterate_inventory(... -- опять перебираю, а объект все еще есть.

Думаю дело в этом:
alife():release(...) убивает серверный объект
iterate_inventory(...) итерирует по клиентским
А синхронизация серверных и клиентских произойдет не раньше следующего actor_binder:update.

Автор: PATRON 22.07.2009, 10:43

А можно как-то, зная название обьекта, и не спавня его(так как он в игре уже есть как онлайн), ударить по нему хитом?
Вот например удаление долговца:

Код
function udar_nishtak()
    for a=10,65635,1 do
    local obj=alife():object(a)
        if obj and string.find(obj:name(),"dolg_regular") then
        alife():release(obj,true)
        end
    end
end

А вот кто-нибудь может переделать этот код, чтобы получилось что-то вроде:
Код
function udar_nishtak()
    for a=10,65635,1 do
    local obj=alife():object(a)
        if obj and string.find(obj:name(),"dolg_regular") then
        Какой код нужно поставить сюда, для хита?
        end
    end
end

Автор: vintprog 22.07.2009, 11:22

А кто знает как удалить все миссии действия в скриптах.
И начать делать миссии и всякое с нуля? rolleyes.gif

Автор: Kolmogor 22.07.2009, 12:00

Цитата(PATRON @ 22.07.2009, 11:43) *
А можно как-то, зная название обьекта, и не спавня его(так как он в игре уже есть как онлайн), ударить по нему хитом?

выше был пример взрыва бочки. Её взрывали нанося хит.
Разницы между бочкой и долговцем в этом случае никакой

Автор: Stalbar 22.07.2009, 14:32

Цитата(Kolmogor @ 22.07.2009, 16:00) *
Цитата(PATRON @ 22.07.2009, 11:43) *
А можно как-то, зная название обьекта, и не спавня его(так как он в игре уже есть как онлайн), ударить по нему хитом?

выше был пример взрыва бочки. Её взрывали нанося хит.
Разницы между бочкой и долговцем в этом случае никакой

Можно дополнить? smile.gif В примере выше использовался тип повреждения hit.explosion... Надо-ли говорить, что тип не один? Есть несколько типов - можете найти примеры использования в оригинальных скриптах и наносить объекту хит, наиболее подходящий для ситуации.

Автор: HikeR 22.07.2009, 15:02

Цитата(Stalbar @ 22.07.2009, 10:09) *
но может попробовать такую конструкцию?

она по сути повторяет тот же while true...
Цитата(Kolmogor @ 22.07.2009, 10:26) *
А синхронизация серверных и клиентских произойдет не раньше следующего actor_binder:update.

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

Автор: Kolmogor 22.07.2009, 21:31

Цитата(Stalbar @ 22.07.2009, 15:32) *
Можно дополнить? smile.gif В примере выше использовался тип повреждения hit.explosion... Надо-ли говорить, что тип не один? Есть несколько типов - можете найти примеры использования в оригинальных скриптах и наносить объекту хит, наиболее подходящий для ситуации.

есть еще
hit.burn
hit.chemical_burn
hit.fire_wound
hit.radiation
hit.shock
hit.strike
hit.telepatic
hit.wound
Использовать так же как и hit.explosion. Эти значения взял из файла lua_help.script. Там же можно найти и много другой полезной информации. Ну а какой наиболее подходящий Вам виднее

Цитата(HikeR @ 22.07.2009, 16:02) *
ахха, то есть минимальный момент времени, который нужно подождать - 1FPS. вопрос в том, как именно нужно ждать wink.gif
просто есть подозрение, что любой цикл приостанавливает выполнение скрипта, и при определенной задержке, то есть при отсутсвии возврата, игра крешится, специально либо из-за рассинхронизации.
а вешать на апдейт разовую ф-ию как-то не хочется.

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

Ну и кстати с циклом по идее вылета не должно быть. просто по идее биндер должен зависнуть и все smile.gif (то есть перестать срабатывать функции биндера). В АМК например, это зависание отлавливается и игра специально крешится. А можно лог вылета, если сохранился

Автор: HikeR 23.07.2009, 00:11

Цитата(Kolmogor @ 22.07.2009, 22:31) *
Можноеще правда set_fastcall попытаться приспособить

смотрел на это дело, но издалека, надо попробовать.
Цитата(Kolmogor @ 22.07.2009, 22:31) *
А можно лог вылета, если сохранился

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

Автор: Stalbar 23.07.2009, 10:10

Вопрос - кто-нибудь знает, как прочитать последнюю строку консоли в запущенной игре?

Автор: jboo7 23.07.2009, 11:46

В lua_help.script есть класс CConsole.

CODE
C++ class CConsole {
function execute_script(string);
function get_string(string);
function execute(string);
function get_bool(CConsole*, string);
function get_float(CConsole*, string);
function get_integer(CConsole*, string);
function get_token(string);
function show();
function hide();
};


Может get_string() что-то даст, по названию как ни какsmile.gif

Автор: Stalbar 23.07.2009, 11:51

Да, это я видел, даже пробовал вытащить именно через get_console:get_string(), что-то пока не получается. Поэтому и спросил, может кто подтолкнёт.. smile.gif

Автор: jboo7 23.07.2009, 12:49

get_string определенно не то, что нужно, потому что она возвращает значение в строке любой консольной команды, переданой в качестве параметра...

local str = get_console():get_string("rs_stats")

в итоге в str будет "on" или "off"

и разницы между get_string и get_token не нашел...
dry.gif

Автор: kutuzvden 23.07.2009, 13:02

Здрасте. Мб не совсем в тему, но все таки. Подскажите плиз, где находится в сталкере скрипт, отвечающий за голод, а то я в скриптах не бум бум-хочу сделать аналогичный скрипт по примеру голода. И еще: где и что нужно написать, чтоб игра обращалась к этому скрипту?

Автор: jboo7 23.07.2009, 13:40

Stalbar, может попробуешь сохранять лог-игры, когда нужно во время её работы, и просто читать от туда последнюю строку?smile.gif

Автор: Stalbar 23.07.2009, 13:54

jboo7, флушить лог можно, но как добиться, чтобы это происходило именно в момент появления там нужной мне строки???? smile.gif Хотя, если по этому условию можно флушить лог, то тогда мне и лог совсем не нужен smile.gif Мне нужно отловить именно появление определённой строки в логе, вернее в консоли.

Автор: Kolmogor 23.07.2009, 17:18

Цитата(Stalbar @ 23.07.2009, 14:54) *
Мне нужно отловить именно появление определённой строки в логе, вернее в консоли.

А какая задача вообще стоит? Зачем пытаешься строку в консоли отловить? Может необязательно строку в консоли отлавливать, может по-другому можно?

Автор: Stalbar 23.07.2009, 17:47

Цитата(Kolmogor @ 23.07.2009, 21:18) *
А какая задача вообще стоит? Зачем пытаешься строку в консоли отловить? Может необязательно строку в консоли отлавливать, может по-другому можно?

При активации артефакта под названием "мина" рождается аномалия "минное поле" smile.gif Движок на это непотребство реагирует выдачей в консоль 2 строк такого вида:
artefact [af_mine31076] spawned a zone [zone_mine_field] at [92.799683]
- !!!processing_enabled ->destroy_queue.push_back af_mine31076[31076] frame [18310]

Вот хочу попытаться отловить не факт перемещения игроком в активный слот айтема (он его может покрутить в руках и назад в рюкзак сунуть), а именно момент активации мины, после которого движок выдаёт в консоль вышеприведённые строки. Также очень хочется отловить момент "сработки" минного поля, как вот это реализовать - я пока в глубоких раздумьях... Если по варианту активации мины есть решение, но очень "некрасивое", я бы сказал, хотелось бы более элегантного, то по вопросу срабатывания минного поля мыслей пока никаких нет. Совсем. sad.gif

Автор: Kolmogor 23.07.2009, 23:24

Цитата(Stalbar @ 23.07.2009, 18:47) *
Вот хочу попытаться отловить не факт перемещения игроком в активный слот айтема (он его может покрутить в руках и назад в рюкзак сунуть), а именно момент активации мины, после которого движок выдаёт в консоль вышеприведённые строки.

При активации мины артефакт пропадает? Тогда это отлавливается как и использование предмета: в on_item_drop запоминаем ид, и в апдейт проверяем наличие объекта с таким ид - если объекта нет - значит заюзали

Автор: Stalbar 23.07.2009, 23:46

Цитата(Kolmogor @ 24.07.2009, 03:24) *
При активации мины артефакт пропадает? Тогда это отлавливается как и использование предмета: в on_item_drop запоминаем ид, и в апдейт проверяем наличие объекта с таким ид - если объекта нет - значит заюзали

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

Автор: kutuzvden 24.07.2009, 00:07

Ау... Ответьте.

Автор: DmitrjT 24.07.2009, 00:53

Цитата(kutuzvden @ 24.07.2009, 01:07) *
Ау... Ответьте.

В ЛС

Автор: IG-2007 24.07.2009, 09:36

Цитата(Stalbar @ 24.07.2009, 00:46) *
А вот момент срабатывания уже самой аномалии на сегодняшний момент вижу только как проверку по нанесению хита какому-либо объекту в известной позиции (радиус аномалии). Пока больше никаких вариантов по этой проблеме у меня нет.

Можно определять не срабатывание аномалии, а вхождение в область её действия. В ЧН так отслеживалось наступание ГГ на мины.

Автор: Stalbar 24.07.2009, 10:13

Цитата(IG-2007 @ 24.07.2009, 13:36) *
Можно определять не срабатывание аномалии, а вхождение в область её действия. В ЧН так отслеживалось наступание ГГ на мины.

Ну да, значит "рою" в правильном направлении smile.gif Спасибо!

Автор: IG-2007 24.07.2009, 11:55

Цитата(Stalbar @ 24.07.2009, 11:13) *
Ну да, значит "рою" в правильном направлении smile.gif Спасибо!

Да, не за что smile.gif
Можно ещё в моде ZEN-а посмотреть, там было минирование. Он долго мучался с повторным срабатыванием мин, но потом, вроде бы, победил. Так что, там должно быть реализовано отслеживание срабатывания и не только для ГГ.

Автор: Stalbar 24.07.2009, 14:56

Цитата(IG-2007 @ 24.07.2009, 15:55) *
Можно ещё в моде ZEN-а посмотреть, там было минирование. Он долго мучался с повторным срабатыванием мин, но потом, вроде бы, победил. Так что, там должно быть реализовано отслеживание срабатывания и не только для ГГ.

Там просто заносились все новые минные поля в табличку и спустя энное кол-во часов убирались. Все. И сработавшие и не сработавшие.

Автор: vintprog 31.07.2009, 07:10

Ребята может кто подсказать несколько функцый:
1) как спавнить npc с хендлом и по этому хендлу менять его пармметры?
2) как дать npc-у оружие и.т.д.
3) как заставить npc стрелять без перерывов например с ak
4) как заставить npc идти на опредиленые координаты
5) как уничтожить npc

Автор: HikeR 31.07.2009, 11:36

vintprog, начните с вики для начала.

Автор: bill_gates 10.08.2009, 13:52

Люди, помогите! Как можно реализовать таймер через скрипт? Чтобы таймер запускался в игровом времени через функцию (например, вызываемую диалогом) и по истечении времени, на которое он был поставлен он должен выполнять определенную функцию. Например, чтобы после диалога с npc через 10 минут игрового времени актору выдавался инфопоршень. Как запускать функции из диалога и т.д. я знаю, но вот как сделать таймер не пойму. В amk и ogsm модах есть функция g_start_timer. Пробовал через нее - ничего не выходит(((

Автор: Stalbar 10.08.2009, 19:30

Цитата(bill_gates @ 10.08.2009, 17:52) *
В amk и ogsm модах есть функция g_start_timer. Пробовал через нее - ничего не выходит(((

Т.е. пробовал "выдёргивать" только эту функцию, или в самих модах пробовал запускать свой таймер? Не получается - игра крэшится с ошибкой, или просто ничего не происходит? Конкретизируй проблему smile.gif

Автор: bill_gates 10.08.2009, 20:59

Все! Я разобрался наконец. Просто я забывал добавить имя таймера в функцию __do_timer_action. Теперь все работает.

Автор: Nekt 10.08.2009, 21:42

kutuzvden на сколько помнится даже опроса на сколько голоден нету, как у здоровья.
Так-что ...
Хотя если кто знает, функцию опроса можете просветить человека.

Автор: Lance 20.08.2009, 09:49

На днях тут пришла идея с ЛЦУ для оружия.
И вот что заинтересовало:
Чисто теоретически, можно ли написать такой скрипт, чтобы при переключении на оружие с ЛЦУ, прицел менялся на динамический прицел-точку как в режиме без оружия?

Автор: Орион 20.08.2009, 11:49

Lance, Можно, но очень много мороки с проверками фова, враг/невраг и состояние оружия)Скрипт будет очень громоздким и мб просадку фпс даст хорошую. Но в теории - реально smile.gif

Автор: Lance 20.08.2009, 21:15

да враг/невраг ненадо совсем, т.к. тупо красная точка, цвет не меняет...
Хм. ну если идея кому понравилась, я моделькой лцу снабжу за написаный скрипт) т.к. пока самому луа учить времени нет.

Автор: jboo7 09.09.2009, 23:46

Можно как-то организовать респаун долговцев на кордоне?

Автор: jocker_27 06.10.2009, 13:56

Комрады, а можно (чисто теоретически) привязать alife к мультиплееру?

Автор: Орион 06.10.2009, 14:23

jocker_27, Нет, невозможно.

Автор: 123456 30.11.2009, 22:48

Люди, нужна помощь!
Как в ТЧ в ДМ называются и вызываются функции fraglist и playerlist ??

Автор: 123456 02.12.2009, 00:08

Никто незнает unsure.gif

Автор: Shadow. 02.12.2009, 00:14

Цитата(jocker_27 @ 06.10.2009, 13:56) *
Комрады, а можно (чисто теоретически) привязать alife к мультиплееру?

Цитата
jocker_27, Нет, невозможно.

Орион,соответственно,сделать в мультиплеере спавн предметов в инвентарь по нажатию кнопки в меню тоже никак?

Автор: Орион 02.12.2009, 00:35

Shadow., Даже не пробовал... попробуй) Проблема в том, что не все далеко переменные глобальные инициализируются в мп-режиме. Следовательно, не все методы будут работать. Спавн через alife():create() вряд ли будет работать по понятным причинам smile.gif

Автор: 123456 02.12.2009, 01:17

z_cry.gif

Автор: Shadow. 02.12.2009, 15:03

Цитата(Орион @ 02.12.2009, 00:35) *
Shadow., Даже не пробовал... попробуй) Проблема в том, что не все далеко переменные глобальные инициализируются в мп-режиме. Следовательно, не все методы будут работать. Спавн через alife():create() вряд ли будет работать по понятным причинам smile.gif

Верно,не работает. smile.gif
Скрипт спавна в принципе делал давно,как раз через alife():create(), в сингле работает исправно,а вот в мультиплеере вылет с уж не помню каким логом.
А сделать как-то иначе возможно?

Автор: Орион 02.12.2009, 15:14

Shadow., Угу. Дизассемблер и учебник по языку асмы в руки. Поделишься результатами smile.gif

Автор: Scarabay 05.12.2009, 17:14

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

Автор: =SaleR= 05.12.2009, 18:06

Scarabay, вот статья со сталкер-портала:

Тыц
Первое обновление. Теперь можно выбирать, какой формы будет рестриктор, Шар или Куб.
Для Куба устанавливаются размеры по x,y,z.

Второе обновление. Теперь, в качестве кастом даты, можно указывать ltx файлы, из папки config. Путь указывается таким образом:

local ltx = "scripts\имя_файла.ltx"

Итак. Создаём файл _new_create.script, если такового ещё нет, и добавляем в него нашу функцию:

function create_restr(storid, pos_restr, lvid_restr, gvid_restr, custom_restr, radius_restr, ax_x, ax_y, ax_z)
local obj = alife():create("space_restrictor", pos_restr, lvid_restr, gvid_restr)

local packet = net_packet()
obj:STATE_Write(packet)
----------------------- load ------------------------------
local game_vertex_id = packet:r_u16()
local cse_alife_object__unk1_f32 = packet:r_float()
local cse_alife_object__unk2_u32 = packet:r_u32()
local level_vertex_id = packet:r_u32()
local object_flags = packet:r_u32()
local custom_data = packet:r_stringZ()
local story_id = packet:r_u32()
local spawn_story_id = packet:r_u32()
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 axis_x = packet:r_vec3()
local axis_y = packet:r_vec3()
local axis_z = packet:r_vec3()
local offset = packet:r_vec3()
end
end

local restrictor_type = packet:r_u8()
-------------------------- save -----------------------------
packet:w_begin(game_vertex_id)
packet:w_float(cse_alife_object__unk1_f32)
packet:w_u32(cse_alife_object__unk2_u32)
packet:w_u32(level_vertex_id)
packet:w_u32( bit_not(193) )

if custom_restr ~= nil then
if string.find (custom_restr, '.ltx') ~= nil then
custom_restr = '[logic]\n cfg = '..custom_restr..'\n'
end
packet:w_stringZ(custom_restr)
else
packet:w_stringZ(custom_data)
end

if storid ~= nil then
packet:w_u32(storid)
else
packet:w_u32(story_id)
end

packet:w_u32(spawn_story_id)

packet:w_u8(1)
if radius_restr ~= nil then
packet:w_u8(0)
packet:w_vec3(vector():set(0, 0, 0))
packet:w_float(radius_restr)
elseif radius_restr == nil and ax_x == nil then
packet:w_u8(0)
packet:w_vec3(vector():set(0, 0, 0))
packet:w_float(2.5)
else
packet:w_u8(1)
packet:w_vec3(vector():set(ax_x, 0, 0))
packet:w_vec3(vector():set(0, ax_y, 0))
packet:w_vec3(vector():set(0, 0, ax_z))
packet:w_vec3(vector():set(0, 0, 0))
end

packet:w_u8(restrictor_type)
-----------------------------------------------------
packet:r_seek(0)
obj:STATE_Read(packet, packet:w_tell())
end

Вызов спавна будет производиться из других функций, других файлов, таким образом:

для формы Шар:
_new_create.create_restr(sid, pos, lv, gv, ltx, radius)

для Формы Куб:
_new_create.create_restr(sid, pos, lv, gv, ltx, nil, x, y, z)

Где:
sid --стори айди рестриктора (или nil, если не используется)
pos --позиция спавна рестриктора vector():set(x,y,z)
lv --левел вертекс позиции спавна
gv --гейм вертекс позиции спавна
ltx --кастом дата рестриктора
radius --радиус зоны рестриктора (в метрах) (или nil, если используется форма куба)
x,y,z --размеры куба, по x,y,z соответственно.

Теперь разберём такие настройки как, ltx и sid.

---------------------------------
ltx

Кастом дата рестриктора. Тобишь, логика по которой будет работать данный рестриктор.
Чтобы указать логику из статитеского файла ltx, находящегося в папке config, нужно прописать так:

local ltx = "scripts\\имя_файла.ltx"

или

local ltx = "misc\\имя_файла.ltx"

или

local ltx = "имя_файла.ltx"

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

Если нас статический ltx не устраивает. То можно прописать логику динамически.
Тобишь, в той же функции, от куда и будет вызываться спавн рестриктора.
Итак, пред вызовом спавна создаём локальную переменную ltx, и в значении данной переменной прописываем всю логику нашего рестриктора.
Например, установим эффект активации слота "ножь", при входе ГГ в рестриктор:

local ltx = "[logic]\n"..
"active = sr_idle@in\n"..

"[sr_idle@in]\n"..
"on_actor_inside = %=activate_knife% sr_idle@out\n"..

"[sr_idle@out]\n"..
"on_actor_outside = sr_idle@in\n"


Разберём особенности динамического ltx:

\n -прописать в новой строке, динамического файла ltx.
.. -привязать следующую строку к общей схеме динамического ltx.
Каждая строка, обязательно заключается в кавычки, кроме двоеточия.
В последней строке, двоеточие запрещается ставить категорически.

Если логика рестриктора, не предусмотрена, то вместо неё ставить nil.

-------------------------------------------------------
sid

Стори айди рестриктора. Используется при отслеживании попадания неписей под рестриктор. Если не используется, то ставить значение nil.

-------------------------------------------------------

Есть возможность использовать значения по умолчанию:

_new_create.create_restr(sid, pos, lv, gv, ltx)

или

_new_create.create_restr(sid, pos, lv, gv)
если custom_data не предусматривается.

По умолчанию рестриктор имеет форму Шара, с радиусом 2.5 метра.

Всё. Пробуйте. У меня работает отлично.

Автор: macron 16.12.2009, 20:36

Цитата(Shadow. @ 02.12.2009, 15:03) *
Скрипт спавна в принципе делал давно,как раз через alife():create(), в сингле работает исправно,а вот в мультиплеере вылет с уж не помню каким логом.
А сделать как-то иначе возможно?

Shadow., скрипты в мультиплеере - штука не простая. Вещи типа "alife():create()" там не должны работать в принципе. У меня точно срабатывали совсем примитивные скрипты на выполнение консольной команды (причем только на невыделенном сервере). Сам скрипт запускался через level.ltx конкретного уровня, туда добавлял:

[level_scripts]
script=ыыыы

где ыыыы - этоо файл gamedata\scripts\ыыыы.script. Вроде еще можно грузить через gamedata\config\script.ltx - там есть отдельные секции для каждого mp-режима.

ЗЫ: возник ряд вопросов по скриптам:
1. Можно ли скриптом разрешить трупу/с трупа жрать аптечку или еду? Чтобы на 6 патче не вылетало.

2. В 7 mp-патче значительно ускорен курсор в менюшках - очень резво реагирует на движение мышки, удобней вобщем. В его xrgame.dll добавлена такая фишка: CUICursor::UpdateCursorPosition. В 4 и 6 патче такого нет. Можно ли скриптом добавить "акселерацию" мышки в менюшках?

3. Нужен скрипт для переключения оружия из одного слота без захода в инвентарь: то есть, допустим, у нас в руках автомат и в рюкзаке автомат. Нажимаем на 3, и оружие меняется.

Автор: Shadow. 16.12.2009, 21:01

Цитата
Сам скрипт запускался через level.ltx конкретного уровня, туда добавлял:

[level_scripts]
script=ыыыы

Я всё делал через скрипт главного меню,мне так проще,на основе вызова Spawnmenu,что по кнопке S(закомменчено в финалке).Фактически,только добавить нужные функции и всё,ну на крайняк тупо вызов функции из другого скрипта,чтобы поопрятнее выглядело.

Автор: whoami 20.12.2009, 12:14

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

вылеты
exp​ression : fatal error
Function : CScriptEngine::lua_error
File : E:\stalker\patch_1_0004\xr_3da\xrGame\script_engine.cpp
Line : 73
Description : <no exp​ression>
Arguments : LUA error: ...lker_soc\datas\gamedata\scripts\smart_terrain.script:1137: attempt to call method 'smart_terrain_id' (a nil value)

if нпс залезет в аномалию\его прибъёт другой монстр


exp​ression : fatal error
Function : CScriptEngine::lua_error
File : E:\stalker\patch_1_0004\xr_3da\xrGame\script_engine.cpp
Line : 73
Description : <no exp​ression>
Arguments : LUA error: ...alker_soc\datas\gamedata\scripts\xr_statistic.script:105: attempt to concatenate local 'community' (a nil value)

if гг убъёт нпс


Автор: Darien 25.12.2009, 19:08

Цитата(whoami @ 20.12.2009, 12:14) *
...продолжаю работу одного человека по воссоздания крысы, как полноценно играбельного монстра, с модельками и анимацией всё в порядке, но:

вылеты
exp​ression : fatal error
Function : CScriptEngine::lua_error
File : E:\stalker\patch_1_0004\xr_3da\xrGame\script_engine.cpp
Line : 73
Description : <no exp​ression>
Arguments : LUA error: ...lker_soc\datas\gamedata\scripts\smart_terrain.script:1137: attempt to call method 'smart_terrain_id' (a nil value)

if нпс залезет в аномалию\его прибъёт другой монстр


exp​ression : fatal error
Function : CScriptEngine::lua_error
File : E:\stalker\patch_1_0004\xr_3da\xrGame\script_engine.cpp
Line : 73
Description : <no exp​ression>
Arguments : LUA error: ...alker_soc\datas\gamedata\scripts\xr_statistic.script:105: attempt to concatenate local 'community' (a nil value)

if гг убъёт нпс


Я в этом не очень разбрираюсь, но ответить попробую:
1)Либо ты используешь метод класса, который не поддерживает этот метод, либо сам метод не существует.
2)Возможно, ты не правильно используешь concat. Помимо чисел и строк что-нибудь пытаешься соединить? Сейчас буду проверять из-за чего выскакивает.

Кидай сюда обе ф-ии, разберёмся.

Автор: whoami 03.01.2010, 11:53

спасибо за ответ...

Цитата
1)Либо ты используешь метод класса, который не поддерживает этот метод, либо сам метод не существует.

вообщето да, секция конфига крысы базирована на конфиге тушкана ([m_rat_e]:m_tushkano_e), но класс крысячий laugh.gif

Цитата
2)Возможно, ты не правильно используешь concat.

эээм... скрипты вообщето я не трогал smile.gif

Автор: dnepar 03.01.2010, 11:55

люди тут вопрос у меня возник

Автор: eNdimion 14.01.2010, 21:58

Код
[i]У объекта сталкера можно вызвать скриптовые функции
flags32 get_actor_relation_flags()
set_actor_relation_flags(flags32)

Значение для флагов в namespace game_object:

relation_attack
relation_fight_help_monster
relation_fight_help_human
relation_kill

Т.е. предполагается работь следующим образом:
Смотрим, когда есть такая возможность и актер рядом, что флажки не пустые.
В соответствии с поднятым флагом выполняем какое-то действие (устанавливаем диалог, играем звук/анимацию), а потом сбрасываем флаг.[/i]

честно сказать не очень шарю в скриптинге... это работает?

Автор: -=Kurt=- 10.02.2010, 23:27

Цитата(macron @ 16.12.2009, 21:36) *
ЗЫ: возник ряд вопросов по скриптам:
1. Можно ли скриптом разрешить трупу/с трупа жрать аптечку или еду? Чтобы на 6 патче не вылетало.
Я в любом случае не отвечу, н омне просто интересно, что значит эта фраза wink_old.gif .
Цитата
3. Нужен скрипт для переключения оружия из одного слота без захода в инвентарь: то есть, допустим, у нас в руках автомат и в рюкзаке автомат. Нажимаем на 3, и оружие меняется.
+1 - тоже интересует этот вопрос. Макрон, ты случаем не над мп-модом трудишься? wink_old.gif
Напоследок, вопрос ко всем: можноли в мп скриптом лечить актора при наличии у него в инвентаре аптечки?
Я давным-давно пробовал переделать сингловый скрипт, но ничего не вышло....

Автор: bill_gates 10.04.2010, 21:23

Люди, а что такое нетпакет? И зачем он нужен?

Автор: rekongstor 16.04.2010, 14:59

Как спавнить через Net Packet?

Автор: Scarabay 24.07.2010, 22:19

Всем привет. Может кто поделится функцией определения визуала нпс? Или хотя бы расскажите как считать необходимые данные из нет-пакета? Заранее спасибо.

Автор: djslavikoz 29.09.2010, 07:25

Подскажите пожалуста функцию спавна вертольота через скрипт. Желательно подробно что и куда нада писать

Автор: сталкероид 29.09.2010, 23:07

Цитата(bill_gates @ 10.04.2010, 21:23) *
Люди, а что такое нетпакет? И зачем он нужен?

Буквально "сетевой пакет". Небольшая область памяти (8 кбайт), в которую записывается текущее состояние какого-либо объекта (актора, непися и т.д.), т.е. количество лута в инвентаре, список хабара в нычках, выполненные квесты, статистика и пр. Работать с ним можно, только когда объект находится в оффлайне.
Подробнее от нет_пакете и не только http://www.amk-team.ru/forum/index.php?showtopic=7450&view=findpost&p=258470
djslavikoz, какой именно вертолет? Если просто валяющийся на земле, то прописать его в алспавне по аналогии с другими трупиками вертолетов, а если прилетающий по какому-то событию, то тогда все гораздо сложнее - надо прописать рестриктор и написать вертолету логику (можно глянуть например http://stalkerin.gameru.net/wiki/index.php/%D0%9D%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0_%D0%BB%D0%BE%D0%B3%D0%B8%D0%BA%D0%B8._%D0%A7%D0%B0%D1%81%D1%82%D1%8C_4#3.12._.D0.9B.D0.BE.D0.B3.D0.B8.D0.BA.D0.B0_.D0.B2.D0.B5.D1.80.D1.82.D0.BE.D0.BB.D1.91.D1.82.D0.B0).

Автор: djslavikoz 30.09.2010, 07:23

Сталкероид
В основном я научился спавнить через all.spawn . Ну примерно вот так.

[10001]
; cse_abstract properties
section_name = helicopter
name = esc_heli_55555
position = 57.8794326782227,-0.705963671207428,114.27214050293
direction = 0,-1.47526597976685,0

; cse_alife_object properties
game_vertex_id = 94
distance = 0
level_vertex_id = 345092
object_flags = 0xfffffffa
custom_data = <<END
[logic]
cfg = scripts\vertol.ltx

END

; cse_visual properties
visual_name = physics\vehicles\mi24\veh_mi24_u_01

; cse_motion properties
motion_name = helicopter\aaa.anm

; cse_ph_skeleton properties
skeleton_name = idle

; cse_alife_helicopter properties
cse_alife_helicopter__unk1_sz = idle
engine_sound = alexmx\helicopter
Вопрос так в чём моя проблема????? Проблема в том что я создал новую локацию(военную базу) и когда делаю таким способом как на ескейпе то получаю лог вот такого плана.
FATAL ERROR

[error]Expression : motion_ID.valid()
[error]Function : CKinematicsAnimated::ID_Cycle
[error]File : E:\stalker\patch_1_0004\xr_3da\SkeletonAnimated.cpp
[error]Line : 136
[error]Description : ! MODEL: can't find cycle:
[error]Arguments :


А с логикой и другим проблем нет я в курсе как ето делается.

Автор: Erwin Rommel 30.09.2010, 18:39

Может ты анимацию модели установил не ту?

Автор: сталкероид 30.09.2010, 19:02

djslavikoz, проблема в логике вертолета. Что ты прописал в файле vertol.ltx?

Для примера вертолёт на блокпосте
[logic]
active = heli_move@idle

[heli_move@idle]
path_move = heli_blockpost_idle_move
engine_sound = false
on_info = {+твой_инфопоршень} heli_move@fly
combat_safe_altitude = -50

[heli_move@fly]
path_move = heli_blockpost_fly
engine_sound = true
combat_enemy = actor
combat_use_rocket = true
combat_use_mgun = true
rocket_delay = 3000
combat_safe_altitude = -70
on_timer = 120000 | heli_move@retreat

[heli_move@retreat]
path_move = heli_blockpost_idle_move
engine_sound = true
combat_use_rocket = false
combat_use_mgun = false
combat_safe_altitude = -50
on_timer = 120000 | heli_move@stop

[heli_move@stop]
path_move = heli_blockpost_idle_move
engine_sound = false

Вообще, ругается на то, что не может найти цикл анимации (есть такой файлик .skl).
Попробуй вообще убрать эту строку в алспавне motion_name = helicopter\aaa.anm . К чему это относится: cse_alife_helicopter__unk1_sz = idle?

Автор: djslavikoz 05.10.2010, 10:19

Господа скриптологи помогите пожалоста. Лог по вашей теме. Ето спавн вертольота.
Как написал мне на амк форуме один товарищ.... Цытирую

Надо дописать функцию в xr_effects.script, какую я не знаю, сам не делал.




! Unknown command: ERROR:object
* Log file has been saved successfully!

FATAL ERROR

[error]Expression : fatal error
[error]Function : CScriptEngine::lua_error
[error]File : E:\stalker\patch_1_0004\xr_3da\xrGame\script_engine.cpp
[error]Line : 73
[error]Description : <no expression>
[error]Arguments : LUA error: ....r. - shadow of chernobyl\gamedata\scripts\_g.script:20: bad argument #2 to 'format' (string expected, got no value)

Автор: Lekzd 05.10.2010, 10:46

djslavikoz, вот нет, чтобы сравнить файлы без изменений и с изменениями (программа для этого специальная есть)
не уповай на экстрасенсов - их тут нет

Автор: nike88 05.10.2010, 12:13

djslavikoz допиши что-то типа

Код
function уровень_heli_mapspot(actor, npc, p)
    if p[1] and not level_tasks.is_map_spot_present( p[1], "anomaly_zone_location" ) then
        level_tasks.add_location( p[1], "anomaly_zone_location", "vertolyot!" )
    end
end

Автор: RedPython 24.10.2010, 17:34

Как можно получить имя текущей погодной секции? Нужно что-то типа level.get_weather_name()

Автор: Erwin Rommel 25.10.2010, 08:53

Поставь ватчдог от АМК и смотри в консоли погодные секции. Проследи работу игры

Автор: Kolmogor 25.10.2010, 10:56

Цитата(RedPython @ 24.10.2010, 18:34) *
Как можно получить имя текущей погодной секции? Нужно что-то типа level.get_weather_name()

level.get_weather()

Автор: djslavikoz 27.02.2011, 10:58

Ребята вот пример спавна через скрипт:

local zombie_types = {"zombie_weak", "zombie_normal", "zombie_strong", "zombie_immortal", "zombie_ghost"}
function spawn_zombies( position, total )
local zombie_index
local new_pos, x_offset, z_offset
for zombie_index=1, total do
x_offset = math.random(5)
z_offset = math.random(5)
new_pos = position
new_pos.x = new_pos.x + x_offset
new_pos.z = new_pos.z + z_offset
alife():create(zombie_types[math.random(5)],new_pos,326087,91)
end
end
function zombie_story_1(actor, npc)
local spawn_point = vector():set(43.21, 2.14, 47.16)
spawn_zombies(spawn_point, 10)
end


Скажите пожалуйста ,а можно в этом скрипте прописать логику ?????

Автор: BelKa Production 21.07.2011, 16:46

djslavikoz, У меня вместо слов - черные линии. z_crazy.gif
Я не большой спец. по скриптам. Может я и ошибаюсь, но в скрипте логику приписать нельзя

Автор: Modera 21.07.2011, 16:49

угу её надо писать в конфе т.е. надо создать новый тип зомбей с костюм датой

Автор: K.D. 21.07.2011, 19:55

логику вписать можно. Но надо перезаписывать нет-пакет. Скрипт по объему вырастет сурово)

Автор: alg0r1tm 11.10.2011, 14:32

Помогите плиз разобратся в сне от АМК smile.gif
Цель такова: нужно сделать сон как в билдах через инвентарь smile.gif
Простите за банальность

Зы, не пинайте только) я в скриптах null smile.gif

Автор: Policai 23.02.2012, 07:34

Народ!!!!
Нужна помощь гуру!


Анимация - дверь сдвигающаяся всторону, 1 кость, сдвиг вправо на 1.5 метра, 3 секунды пауза и сдвиг обратно на место.(Самодельный обьект, ставлю через спавн, в сдк анимация работает)
Попытался запустить анимацию по анологии лабы х-8 из припяти.
В кустом дата прописана ссылка на логику, с текстом:


Дверь
[collide]
ignore_static

[animated_object]

Пульт взят оттуда же , с родной логикой, я просто изменил на своё название анимации, спейса и смарта:


Пульт
[logic]
active = ph_button@no_card

[ph_button@no_card]
anim = idle
tooltip = tip_no_access_card
on_info = {=actor_has_item(zat_a23_labx8_key)} ph_button@has_card

[ph_button@has_card]
anim = idle
tooltip = tip_need_access_card
on_press = ph_button@unlocked
on_info = {!actor_has_item(zat_a23_labx8_key)} ph_button@no_card

[ph_button@unlocked]
anim = idle
tooltip = st_lx8_button_press_true
on_game_timer = 20 | {-lx8_door_open} %+lx8_door_open =anim_obj_forward(lim_door_laba_hide)%
on_game_timer2 = 10 | {-lx8_green_on} %+lx8_green_on =turn_off(lx8_light_switch_1_red_id) =turn_on(lx8_light_switch_1_green_id)%
on_info = {=actor_in_zone(lim_sr_actor_in_lab) -lim_actor_in_lab} %+lim_actor_in_lab =create_squad(lx8_polter_squad:lim_smart_terrain)%

Всё проходит до запуска анимации, то есть без карты требует карту доступа, с картой появляется сообщение доступ разрешён, потом завис на 3-4 секунды, (в этот момент должна отработать анимация), и вылет с жалобой:

Лог
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 : ....r. - Зов Припяти\gamedata\scripts\xr_effects.script:1317: attempt to index field '?' (a nil value)
stack trace:

Понимаю что это всё туфта, просто я в скриптах ноль, и пытаюсь разобраться методом тыка.

xr_effects родной нетронутый. Подскажите куда ткнуться.

Автор: Ким 23.02.2012, 08:40

Policai,
xr_effects, строчки с 1314 по 1320:
function anim_obj_forward(actor, npc, p)
for k,v in pairs(p) do
if v ~= nil then
db.anim_obj_by_name[v]:anim_forward() - 1317 строка
end
end
end
твоя логика
[ph_button@unlocked]
anim = idle
tooltip = st_lx8_button_press_true
on_game_timer = 20 | {-lx8_door_open} %+lx8_door_open =anim_obj_forward(lim_door_laba_hide)% - ссылается на 1317 строку
on_game_timer2 = 10 | {-lx8_green_on} %+lx8_green_on =turn_off(lx8_light_switch_1_red_id) =turn_on(lx8_light_switch_1_green_id)%
on_info = {=actor_in_zone(lim_sr_actor_in_lab) -lim_actor_in_lab} %+lim_actor_in_lab =create_squad(lx8_polter_squad:lim_smart_terrain)%

Что-то не так с названием анимки, либо она не подходит.

Кстати, ты на ТЧ это делаешь?)
Если на ТЧ, то надо допилить этот самый эффектс, три функции, как минимум, добавить.

Автор: Policai 23.02.2012, 09:07

Цитата
Что-то не так с названием анимки, либо она не подходит.

Кстати, ты на ТЧ это делаешь?)
Если на ТЧ, то надо допилить этот самый эффектс, три функции, как минимум, добавить.


Ким
В этом то и проблема, анимка другая, на родной двери от этого скрипта 9 костей и работает на поворот, но она работает анимацией, и прописана анимацией, моя анимация - одна кость и работает на сдвиг, я просто не знаком со скриптами и попытался методом тыка подсунуть.
Платформа ЗП.
Гугл не помогает, а я не знаю как это делается. Мне нужно просто запустить выбранную анимацию по команде. Такая же проблема у меня и с мостом в рыжем лесу, не хочет он опускаться когда мне надо, попытался проследить скрипты с которыми он работает в оригинале ЧН, заблудился, там их штук 20 задействовано.
Вопрос такой: Как простейшим методом запустить выбранную анимацию по некой команде.

Автор: Ким 23.02.2012, 10:47

Policai, вот так и вызывается.
Пример простой логики для теста:
[logic]
active = ph_button@test

[ph_button@test]
anim = idle
tooltip = tip_need_access_card
on_press = ph_button@test1

[ph_button@test1]
anim = idle
tooltip = tip_need_access_card
on_press = ph_button@unlocked
on_info = {+door_open} %=anim_obj_forward(анимация_открытия)%

можно сделать привязку к кнопке (допустим нум7), котоаря будет выдавать нужный инфопоршень и логика двери даст команду на открытие.



Слушай, вот что, а логику ты привязываешь жэ к кнопке, а не к двери biggrin.gif
логика кнопки
[logic]
active = ph_button@test

[ph_button@test]
anim = idle
tooltip = tip_need_access_card
on_press = %+door_open%

логика двери

[logic]
active = ph_door@test

[ph_door@test]
anim = idle
on_info = {+door_open} %=anim_obj_forward(анимация_открытия)%

Насчёт двери не знаю как привязать анимку, вечером ещё гляну

По идее к двери не привязана анимка, она просто переходит в состояние "открыто" (во всяком случае анимка не указывается в логике, где-то в скриптах может быть)
там просто переход к другой логике, где дверь: "locked = false"

Чисто теоритечески логика для двери:
[logic]
active = ph_door@test

[ph_door@test]
anim = idle
on_info = {+door_open} %=anim_obj_forward(анимация_открытия)%
должна работать, по идее функция указана в xr_effects, а значит должна вызываться для любых объектов (такого типа). Попробуй привзять стандартную анимаку через эту логику, если заработает, значит и твоя анимка будет работать

Автор: Policai 23.02.2012, 10:49

Тут вроде понял, возник сразу вопрос, логика двери??? У меня простая анимация, вернее в максе вшил 3 одна просто открытие open, вторая закрытие close, и третья полный цикл: открытие, задержка в открытом состоянии 3 секунды и закрытие idle. Вшил также две контрольные точки, закрытая дверь и открытая дверь.
Теперь можно по подробнее по логике двери? что это? анимация вшитая или писать логику для неё надо?

Цитата
просто я в скриптах ноль, и пытаюсь разобраться методом тыка

Автор: Ким 23.02.2012, 10:55

Вообще в xr_effects указано три типа функций - anim_obj_forward, anim_obj_backforward и anim_obj_forward (reset, точного названия не помню). Соотвественно все три можно вызывать из логики.

"Тут вроде понял, возник сразу вопрос, логика двери??? У меня простая анимация, вернее в максе вшил 3 одна просто открытие open, вторая закрытие close, и третья полный цикл: открытие, задержка в открытом состоянии 3 секунды и закрытие idle. Вшил также две контрольные точки, закрытая дверь и открытая дверь.
Теперь можно по подробнее по логике двери? что это? анимация вшитая или писать логику для неё надо?"
я них.. ничего не понял biggrin.gif
Да, в спавне укажу путь к кастомдате двери, по этому пути создай лтх файл логики (с соответствующим названием), туда напиши логику, что я тебе написал) Ну, знаешь ли, без логики анимация как бы не работает biggrin.gif А вот то, что ты написал в первом посте - это привязка к кнопке, естественно кнопка не может открыться, это же кнопка, а не дверь)


Policai, там ничего сложного, поверь) Просто большинство скриптов написано.. эм.. как бы сказать.. некомпетентными людьми)

Вот смотри, логика для двери, используется у нас в "Обливион Лосте" (в бета тесте отсутствует):
[logic]
active = ph_door@locked

[ph_door@locked]
locked = true
on_info = {+quest_gr_art_1_start} ph_door@close - игрок получает первое задание и дверь открывается, ну прям как в ТЧ laugh.gif
tip_open = tip_door_locked
snd_open_start = trader_door_locked
not_for_npc = true


[ph_door@close]
locked = false
closed = true
tip_open = tip_door_open
on_use = ph_door@open
not_for_npc = true

[ph_door@open]
locked = false
closed = false
on_use = ph_door@close
tip_close = tip_door_close
not_for_npc = true

Автор: Policai 23.02.2012, 11:10

Цитата
первом посте - это привязка к кнопке, естественно кнопка не может открыться, это же кнопка, а не дверь)


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

biggrin.gif наверно по разному общаемся... да и трудно обьяснить тупому мне.... я работаю не с аллспавном а в сдк.

Я сделал так: ставлю физик\ доор, присваиваю визуал моей двери, прописываю там анимацию полную idle, (Мне надо чтоб дверь открылась и закрылась сама )в кустом дате указываю путь к файлу лтх с названием как у этой двери. В этом лтх прописываю:

[collide]
ignore_static

[animated_object]


ставлю пульт сбоку и прописываю в кустом дата путь к лтх с названием как и у пульта, в лтх прописываю:


[logic]
active = ph_button@no_card

[ph_button@no_card]
anim = idle
tooltip = tip_no_access_card
on_info = {=actor_has_item(zat_a23_labx8_key)} ph_button@has_card

[ph_button@has_card]
anim = idle
tooltip = tip_need_access_card
on_press = ph_button@unlocked
on_info = {!actor_has_item(zat_a23_labx8_key)} ph_button@no_card

[ph_button@unlocked]
anim = idle
tooltip = st_lx8_button_press_true
on_game_timer = 20 | {-lx8_door_open} %+lx8_door_open =anim_obj_forward(lim_door_laba_hide)%
on_game_timer2 = 10 | {-lx8_green_on} %+lx8_green_on =turn_off(lx8_light_switch_1_red_id) =turn_on(lx8_light_switch_1_green_id)%
on_info = {=actor_in_zone(lim_sr_actor_in_lab) -lim_actor_in_lab} %+lim_actor_in_lab =create_squad(lx8_polter_squad:lim_smart_terrain)%


Именно так сделано в ЗП вход в лабу х-8. Жирным выделено то что я поменял на своё, всё остальное так как было в оригинале. Карточку заспавнил рядышком и проверяю в игре.
Подхожу к пульту, появляется надпись нужна карта доступа, отхожу , беру карту, подхожу с картой, появляется надпись Открыть, нажимаю ввод появляется надпись Доступ разрешён потом 3-4 секунды и вылет с жалобой на строку 1317.
Я понимаю что эта анимация просто не прописана поэтому вылет. Я также понимаю что скорее всего логика на ту родную анимацию уже есть в файлах игры где то, вопрос где?

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


Автор: Ким 23.02.2012, 12:51

Policai, погоди, но зачем создавать анимку, если такая уже есть? Возьми аналог (те же двери лифта) и установи их на дверь (в тч - это проход со свалки к бару).

Автор: Policai 23.02.2012, 13:08

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

Автор: Ким 23.02.2012, 13:12

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

Автор: Policai 23.02.2012, 13:27

В ЗП нету отьезжающих дверей...... повырезали всё, есть лифтовые двери но там нет анимации как таковой, там 2 положения, открытые и закрытые, типо актор не видит сам процесс открывания, думаю это сделать проще.... а мне надо именно чтоб был этот сам процесс открытия двери... в этом весь смак... с ТЧ и ЧН в ЗП не работают скрипты, с мостом в рыжем лесу такая же проблема....

Автор: Dart_Sergius 23.02.2012, 21:22

Цитата(Ким @ 23.02.2012, 13:12) *
Policai, тогда их надо прописывать в скриптах, но там будет куча возни.

Кстати интересный вопрос где их прописывать. Тоже интересовала эта проблема, решения пока не нашёл.

Автор: Ким 24.02.2012, 08:08

Dart_Sergius, скорее всего в ph_door, там смещение каждого объекта надо будет указать и т.д. Либо с нуля написать скрипт логики.

Автор: Policai 26.02.2012, 17:08

Ким
Всё разобрался..... сделал, всё гораздо проще чем кажется.....
Единственный минус что на любую анимацию я использую логику двери...... какие могут быть последствия?
А так работает всё как надо, и не нужно писать скрипт логики с нуля.

Сейчас у меня практически на одинаковой логике работает анимация стены сдвигающейся в сторону, управление с пульта, и подьёмный мост с рыжего леса, управление с рубильника, и самодельная дверь, тоже с пульта...

Автор: Ким 26.02.2012, 17:29

Policai, ну ка напиши в чем проблема была, а то кому-нибудь понадобится)
Последствия? Да вроде не должны быть, единственное в игре не красиво будет.

Автор: Tron 28.02.2012, 16:12

скажу сразу,что в lua,я почти профан(синтаксиса не знаю) и сейчас его прикручиваю к движку
Возможен ли precache?-т.е инклуд скрипта,но его выполнение будет происходить только после вызова именно этого скрипта.. Читал про "http://www.gamedev.ru/code/forum/?id=119712",но у автора почти такая же байда как и у меня


если я первый скрипт вызваю как(С++)

Код
RunLuaScript("..\\EngineMedia\\Scripts\\startup.lua");



то я бы второй хотел бы вызвать так:
Код
RunLuaScript("keyboard-esc.lua");

А не как сейчас:
Код
RunLuaScript("..\\EngineMedia\\Scripts\\keyboard-esc.lua");


Вводить собственный precache всех ресурсов не хотелось бы-нужны именно скрипты

Автор: [=sinedsc=] 09.05.2012, 10:18

Параметр в кастом дате смарт террейна

Код
stay = min[, max]                  ;время, на которое сталкер останется, умолчание=навсегда

как задаются параметры
min и мах?
пытался задавать так
Код
stay = 9, 11

пишет что инвалидный параметр.
Подскажите как задать этот параметр

Автор: Tron 02.06.2014, 02:12

Забыл отписать-разобрался в своей проблеме.
Линковал статически луабинд,ко многим длл.кам из проекта,и передавал туда lua_state.
Вообще странно было,что статические функции работали

Автор: Alwen 11.06.2014, 17:41

Вопрос по работе диалогов. В чем может быть ошибка?

dialogs_escape.script
function money_check_1()
return db.actor:money() >= 10
end

function fuel_to_actor_1(oSpeaker1, oSpeaker2)
dialogs.give_items("explosive_mobiltank", 1)
dialogs.relocate_money(oNPC, 10, "out")
end


function money_check_2()
return db.actor:money() >= 20
end


function fuel_to_actor_2(oSpeaker1, oSpeaker2)
dialogs.give_items("explosive_mobiltank", 2)
dialogs.relocate_money(oNPC, 20, "out")
end


function money_check_4()
return db.actor:money() >= 40
end


function fuel_to_actor_4(oSpeaker1, oSpeaker2)
dialogs.give_items("explosive_mobiltank", 4)
dialogs.relocate_money(oNPC, 40, "out")
end


function no_money_for_fuel()
return db.actor:money() >= 0
end


dialogs_escape
<dialog id="esc_need_fuel">
<phrase_list>
<phrase id="0">
<text>Нужен бензин.</text>
<next>2</next>
</phrase>
<phrase id="2">
<text>Хорошо. Сколько канистр?</text>
<next>3</next>
<next>4</next>
<next>5</next>
<next>6</next>
</phrase>

<phrase id="3">
<text>Одной хватит.</text>
<next>31</next>
<next>7</next>
</phrase>
<phrase id="31">
<precondition>dialog_escape.money_check_1</precondition>
<action>dialog_escape.fuel_to_actor_1</action>
<text>Ни гвоздя, ни жезла тебе, Меченый.</text>
</phrase>

<phrase id="4">
<text>Две.</text>
<next>41</next>
<next>7</next>
</phrase>

<phrase id="41">
<precondition>dialog_escape.money_check_2</precondition>
<action>dialog_escape.fuel_to_actor_2</action>
<text>Ни гвоздя, ни жезла тебе, Меченый.</text>
</phrase>

<phrase id="5">
<text>Сразу четыре.</text>
<next>51</next>
<next>7</next>

</phrase>

<phrase id="51">
<precondition>dialog_escape.money_check_4</precondition>
<action>dialog_escape.fuel_to_actor_4</action>
<text>Ни гвоздя, ни жезла тебе, Меченый.</text>
</phrase>


<phrase id="6">
<text>Я передумал...</text>
<action>dialogs.break_dialog</action>
</phrase>

<phrase id="7">
<precondition>dialog_escape.no_money_for_fuel</precondition>
<text>Походу, пока тебе с твоими деньгами только пешеходом быть.</text>
</phrase>

</phrase_list>

</dialog>

При кликах на пункты с выбором(3, 4, 5) иногда выкидывает фразу из диалога "не хватает денег", как будто врет функция money_check_X. При повторном клике все идет как надо и это сообщение выскакивает когда положено.

За основу взял диалог с покупкой авто у Бармена из LA, и там не понятно назначение функции в конце:
Цитата
function not_has_car_money()
return not has_car_money()
end
-- has_car_money - денег >= цене самого дешевого автомобиля
, которая является предусловием для пункта диалога "у тебя нет денег" в dialogs.xml

Что эта функция выполняет, если и так по умолчанию при недостатке денег диалог на "нет денег" и ссылается?

Автор: K.D. 11.06.2014, 18:11

Цитата(Alwen @ 11.06.2014, 18:41) *
function no_money_for_fuel()
return db.actor:money() >= 0
end

Уверен? biggrin.gif

Автор: Alwen 11.06.2014, 18:46

Цитата(K.D. @ 11.06.2014, 19:11) *
Цитата(Alwen @ 11.06.2014, 18:41) *
function no_money_for_fuel()
return db.actor:money() >= 0
end

Уверен? biggrin.gif

Нет. Но если делать как у торговли авто ЛА, с предусловием актор_мани() <= мин_цена_айтема, то при выборе самого дорого товара и недостатке денег на него стабильно получаю вылет No available phrase to say, dialog[esc_need_fuel]

Автор: K.D. 11.06.2014, 19:09

Цитата(Alwen @ 11.06.2014, 19:46) *
Нет. Но если делать как у торговли авто ЛА

Причем тут ЛА? Очевидно же, что функция возвращает true всегда, когда у актора есть деньги. Т.о. прекондишн твоей фразы про нехватку денег всегда пропускает эту фразу. Делай конкретно в этом месте < 10.
Upd: лучше сделать так, наверное. Сделай для каждой фразы свою фразу отказа и там отдельную функцию no_money с разными количествами проверямых денег.

Автор: Alwen 11.06.2014, 20:01

Второй вариант сделал, но мучает этот вылет "No available phrase to say, dialog[esc_need_fuel]", если нажимать вариант на 40 при 30 денег в инентаре.

dialog_escape.script

function money_check_1()
return db.actor:money() >= 10
end

function fuel_to_actor_1(oSpeaker1, oSpeaker2)
dialogs.give_items("explosive_mobiltank", 1)
dialogs.relocate_money(oNPC, 10, "out")
end


function money_check_2()
return db.actor:money() >= 20
end


function fuel_to_actor_2(oSpeaker1, oSpeaker2)
dialogs.give_items("explosive_mobiltank", 2)
dialogs.relocate_money(oNPC, 20, "out")
end


function money_check_4()
return db.actor:money() >= 40
end


function fuel_to_actor_4(oSpeaker1, oSpeaker2)
dialogs.give_items("explosive_mobiltank", 4)
dialogs.relocate_money(oNPC, 40, "out")
end

--function no_money_check()
-- return db.actor:money() < 0
--end


function no_money_for_fuel()
return not money_check_1
end

function no_money_for_fuel_two()
return not money_check_2
end

function no_money_for_fuel_four()
return not money_check_4
end



dialogs_escape.xml
<dialog id="esc_need_fuel">
<phrase_list>
<phrase id="0">
<text>Нужен бензин.</text>
<next>2</next>
</phrase>
<phrase id="2">
<text>Хорошо. Сколько канистр?</text>
<next>3</next>
<next>4</next>
<next>5</next>
<next>6</next>
</phrase>

<phrase id="3">
<text>Одной хватит.</text>
<next>31</next>
<next>7</next>
</phrase>
<phrase id="31">
<precondition>dialog_escape.money_check_1</precondition>
<action>dialog_escape.fuel_to_actor_1</action>
<text>Ни гвоздя, ни жезла тебе, Меченый.</text>
</phrase>

<phrase id="4">
<text>Две.</text>
<next>41</next>
<next>72</next>
</phrase>

<phrase id="41">
<precondition>dialog_escape.money_check_2</precondition>
<action>dialog_escape.fuel_to_actor_2</action>
<text>Ни гвоздя, ни жезла тебе, Меченый.</text>
</phrase>

<phrase id="5">
<text>Сразу четыре.</text>
<next>51</next>
<next>71</next>

</phrase>

<phrase id="51">
<precondition>dialog_escape.money_check_4</precondition>
<action>dialog_escape.fuel_to_actor_4</action>
<text>Ни гвоздя, ни жезла тебе, Меченый.</text>
</phrase>


<phrase id="6">
<text>Я передумал...</text>
<action>dialogs.break_dialog</action>
</phrase>

<phrase id="7">
<precondition>dialog_escape.no_money_for_fuel</precondition>

<text>Походу, пока тебе с твоими деньгами только пешеходом быть.</text>
</phrase>

<phrase id="71">
<precondition>dialog_escape.no_money_for_fuel_four</precondition>

<text>Тебе на столько не хватит.</text>
</phrase>

<phrase id="72">
<precondition>dialog_escape.no_money_for_fuel_two</precondition>

<text>Тебе на столько не хватит.</text>
</phrase>

</phrase_list>

</dialog>

Автор: hi_flyer 11.06.2014, 20:07

Alwen,

Перенеси весь текст (<text></text>) в любой файл из config\text\rus.

Автор: abramcumner 11.06.2014, 20:52

Цитата(Alwen @ 11.06.2014, 21:01) *
Код
function no_money_for_fuel()
      return not money_check_1
end

А в ЛА-то скобочки были:
Код
function not_has_car_money()
return not has_car_money()
end


Может проще добавить эти канистры в продажу по десяточке? smile.gif

Автор: Alwen 11.06.2014, 21:50

Про скобочки забыл smile.gif Теперь все заработало. Спасибо всем отписавшимся.

Автор: hi_flyer 07.07.2014, 19:36

Ни у кого случайно не остался xs_sandbox от xStream ? Скиньте у кого есть плиз.

Автор: Pavel_Blend 16.12.2014, 19:46

Хочу изучить луа. Скачал интерпретатор, пишу код. Но когда запускаю скрипт двойным щелчком мыши, он выполняется и окно сразу закрывается. Как заставить консольное окно не закрываться? Чтобы можно было посмотреть на результат работы.

Автор: Modera 16.12.2014, 19:58

Pavel_Blend, pause

Автор: Pavel_Blend 16.12.2014, 22:06

Modera, это в батнике писать ведь? А стандартными средствами луа это никак не сделать? Чтобы в самом коде это было прописано. Я ведь скрипты не через батники хотел запускать, а двойным щелчком.

Автор: HikeR 16.12.2014, 22:47

выкиньте мышь и осваивайте консоль. cmd -> lua.exe script.lua -> результат работы.


Автор: Forser 11.09.2015, 19:49

Цитата(hi_flyer @ 07.07.2014, 19:31) *
Ни у кого случайно не остался xs_sandbox от xStream ? Скиньте у кого есть плиз.

https://yadi.sk/d/GV1pRum8ibXrK

Автор: evg 30.11.2016, 03:39

как создать новый ammo_class для оружия

Автор: aka_sektor 26.04.2017, 13:58

А вот такой вопрос: возможно ли вынести текст о версии мода из скрипта ui_main_menu.script, в какой-нибудь конфиг?
в скрипте он прописан как:

Код
_ver:TextControl():SetText  ("ver. " .. mm:GetGSVer().." + Кастомный текст")

Просто в чем суть, при обновлении мода, нужно менять скрипт, а если этот мод ещё куда-то адаптирован, то нужно будет повторно скрипт менять. Не проще ли в одном конфиг файле версию менять и все?

Автор: RayTwitty 26.04.2017, 20:28

Цитата(aka_sektor @ 26.04.2017, 14:01) *
Не проще ли в одном конфиг файле версию менять и все?

АМК в 2008 году это сделали.

Автор: Forser 26.04.2017, 23:14

Цитата(RayTwitty @ 26.04.2017, 20:31) *
Цитата(aka_sektor @ 26.04.2017, 14:01) *
Не проще ли в одном конфиг файле версию менять и все?

АМК в 2008 году это сделали.

Ты сейчас про xml?

Автор: aka_sektor 27.04.2017, 00:14

Цитата(RayTwitty @ 26.04.2017, 20:31) *
АМК в 2008 году это сделали.

Угу, похоже на то:
ТЧ финалка

Код
function main_menu:InitControls()
    self:Init(0,0,1024,768)              
    local xml = CScriptXmlInit()
    xml:ParseFile("ui_mm_main.xml")
    
    xml:InitStatic("back_movie", self)
    xml:InitStatic("background", self)
    xml:InitStatic("fire_movie", self)
    self.shniaga = xml:InitMMShniaga("shniaga_wnd",self);
    
    self.message_box = CUIMessageBoxEx()
    self:Register(self.message_box, "msg_box")    
    
    local _ver = xml:InitStatic        ("static_version",self)
    local mm                        = _G.main_menu.get_main_menu()
    _ver:SetText                    ("ver. " .. mm:GetGSVer())
    
end
AMK 1.4.1 patch 2

Код
function main_menu:InitControls()
    self:Init(0,0,1024,768)              
    local xml = CScriptXmlInit()
    xml:ParseFile("ui_mm_main.xml")
    
    xml:InitStatic("back_movie", self)
    xml:InitStatic("background", self)
   -- xml:InitStatic("fire_movie", self)
    self.shniaga = xml:InitMMShniaga("shniaga_wnd",self);
    
    self.message_box = CUIMessageBoxEx()
    self:Register(self.message_box, "msg_box")    
    
    local _ver = xml:InitStatic        ("static_version",self)
    local mm                        = _G.main_menu.get_main_menu()
    --_ver:SetText                    ("ver. " .. mm:GetGSVer())
    local amk_title         = amk_ver.amk_title
    local amk_version        = amk_ver.amk_version
    local amk_revision    = amk_ver.amk_revision
    local debug_mode = ""
    _ver:SetText("Версия игры - " .. mm:GetGSVer() .. "  " .. amk_title .. " " .. amk_version .. " " .. amk_revision)
end

У них просто читается функция из скрипта amk_ver. Это даже лучше и проще.
Спасибо.

Автор: aka_sektor 11.06.2017, 21:41

Кто шарит в логике, подскажите, как тут дописать правильно, чтобы в сообщении указывалось имя NPC, а не писалось "Сообщение".

Код
[sr_idle@20]
on_game_timer = 10000 | sr_idle@30 %+sad_artefuck_ready =send_tip(sad_artefact_upgr_ready:sad_atr_trader) -sad_atr_trader_go_kitchen%

send_tip - понятно, что это функция в xr_effects.script

Есть даже такой комментарий:
Код
--[[
send_tip(news_id:sender:sender_id)
        1. news_id
        2. sender*
        3. sender_id*
        * - not necessary
--]]

news_id - это текст сообщения, т.е. string id. В моей логике имя sad_artefact_upgr_ready
sender - это иконка в секции tips_icons news_manager.script. В моей логике имя sad_atr_trader
sender_id - а это заголовок сообщения, story_id NPC.

story_id моего персонажа прописан в файле по пути: gamedata\configs\creatures\spawn_sections_sad.ltx

И выглядит так:
Код
[sad_atr_trader]:stalker
$spawn                     = "respawn\sad_atr_trader"
character_profile     = sad_atr_trader
story_id = sad_atr_trader

Т.е. в логике я указал как:
Код
[sr_idle@20]
on_game_timer = 10000 | sr_idle@30 %+sad_artefuck_ready =send_tip(sad_artefact_upgr_ready:sad_atr_trader:sad_atr_trader) -sad_atr_trader_go_kitchen%

Дело в том, что хоть story_id и указан, заголовок все также остается как "Сообщение".

Автор: aka_sektor 11.06.2017, 23:02

UPD:
Я все-таки думаю, что story_id читается, но не отображается. Потому что, если указать другое имя, не являющееся story_id - игра вылетит.
Думаю, дело в функции send_tip в news_manager.script. Там не прописано отображение имени.
Возможно, что-то со времен прошлых игр удалили из скриптов, т.к. я действительно не помню чтобы в ЗП игрок получал сообщения с подписанным именем NPC.

Автор: AndreySol 24.06.2017, 09:03

Цитата(aka_sektor @ 11.06.2017, 22:45) *
...чтобы в сообщении указывалось имя NPC, а не писалось "Сообщение".

Цитата
Думаю, дело в функции send_tip в news_manager.script. Там не прописано отображение имени.

Зачем гадать ? Открыть скрипт и посмотреть код !
Код
    local news_text = "%c[255,160,160,160[b]]"..game.translate_string("st_tip").."[/b]\\n".."%c[default]"..game.translate_string(news_id)
    actor:give_game_news(news_text, "ui\\ui_iconsTotal", Frect():set(x,y,83,47), timeout*1000, showtime)

st_tip(в gamedata\config\text\rus\ui_st_pda.xml):
<string id="st_tip">
<text>Сообщение</text>
</string>
Если очень хочется - доработать ф-цию, в ее начале по StoryID получаем объект, соответственно получить от объекта его игровое имя и подставить вместо game.translate_string("st_tip").

Автор: aka_sektor 24.06.2017, 10:55

AndreySol, сорян, тут не отписался, уже давно разобрался. Подсказали правильную функцию: http://ap-pro.ru/forum/114-90122-1046243-16-1497252988

Автор: Forser 24.06.2017, 22:48

Цитата(aka_sektor @ 24.06.2017, 10:59) *
http://ap-pro.ru/forum/114-90122-1046243-16-1497252988

Мне кажется или тут "end" не хвататет?


P.S. Уж не злитесь, очень давно скрипты не писал.


Автор: RayTwitty 24.06.2017, 23:18

Код
if ... then
end
elseif ... then
end
не тоже самое, что
Код
if (...) {
}
else if (...) {
}

Логику закрывающих ключевых слов проверьте. Выход из выражения не в том месте.

Автор: Anarchy 12.07.2017, 17:19

Подскажите. Всеми известный скрипт xrs_armor.script будет работать на платформе зп, если заменить все переменные, или всё же требуется изменение скрипта?

Автор: NanoBot-AMK 21.07.2017, 20:06

Сейчас работаю над новым гравиприводом, обнаружил такой баг, когда НПС выхватывает оружия у врага, и притягивает его с себе, то срабатывает команда self.target:transfer_item(self.target, self.parent), и захваченное оружие отправляется к НПС в инвентарь, в логе выскакивает:
~ ERROR: can't detach independant object. entity[wpn_bm160159:159], parent[wpn_bm160159:159], section[wpn_bm16]
И меняется у НПС clsid с script_stalker=33 на 83.
Мод AI additions версия 2.0 fix3
Может именно в нём дело.
Кстати, да, у меня НПС могут использовать гравипривод, выхватывая оружие у врагов, и ещё в планах научить доставать разные вещи из аномалий.

Автор: NanoBot-AMK 08.08.2017, 23:44

У кого есть дока по методам для управления сталкеров типа set_item и другим методам? Что у меня плохо получается непысей программировать.

Автор: Gaz24 21.09.2017, 23:24

Всем привет. Мне нужно удалить вещи из инвентаря НПС при старте игры (например удалить ПДА), причем отдельным скриптом. Проблема заключается в подключении. Пробовал через bind_stalker и xr_motivator подключать, не получается. Хотя в Ai Addtitions спавн вещей через скрипт работает (в сехеме rx_knife функция spawn_knife(npc)).

Автор: aka_sektor 21.09.2017, 23:37

Цитата(Gaz24 @ 21.09.2017, 23:24) *
удалить вещи из инвентаря НПС при старте игры

А изначально его инвентарь отредактировать что мешает?

Автор: Gaz24 22.09.2017, 06:29

Цитата(aka_sektor @ 22.09.2017, 00:37) *
Цитата(Gaz24 @ 21.09.2017, 23:24) *
удалить вещи из инвентаря НПС при старте игры

А изначально его инвентарь отредактировать что мешает?


Проблема в том, что ПДА для сталкеров не прописывается ни в конфигах, ни в скриптах. Так что мне надо его удалить через скрипт.

Автор: aka_sektor 22.09.2017, 11:24

Цитата(Gaz24 @ 22.09.2017, 06:29) *
ПДА для сталкеров

А каким образом он вообще попадает NPC в инвентарь? Какой-то мод? В оригинале не выпадали им КПК.
Глянул бы как там устроено в моде то, может банальный death_manager.

Автор: RayTwitty 22.09.2017, 13:42

Цитата(Gaz24 @ 22.09.2017, 06:29) *
что ПДА для сталкеров не прописывается ни в конфигах, ни в скриптах

config\gameplay\character_*.xml файлы персонажей смотрел? ПДА там должен прописываться.

device_pda, вроде так называется.

Автор: Gaz24 22.09.2017, 17:40

Цитата(RayTwitty @ 22.09.2017, 14:42) *
config\gameplay\character_*.xml файлы персонажей смотрел? ПДА там должен прописываться.

device_pda, вроде так называется.


Искал Notepad'ом++. Выдало только 1 результат, да и то в энциклопедии. Я уверен что спавн ПДА очень хитро завязан профили персонажей.

https://images.gameru.net/image/f5206c1e59.png.html

Автор: aka_sektor 22.09.2017, 17:45

Цитата(Gaz24 @ 22.09.2017, 17:40) *
энциклопедии

Это просто статья в "энциклопедии". В оригинале, описание предметов выпилили из КПК в ТЧ. Восстановлено в "Истории Прибоя".

Ты хоть заскринь, что имеешь ввиду. Ты так и не ответил, что там у тебя? Мод или что?

В ТЧ есть секция device_pda в gamedata\config\misc\items.ltx

Автор: Gaz24 22.09.2017, 18:10

Цитата(aka_sektor @ 22.09.2017, 18:45) *
Ты хоть заскринь, что имеешь ввиду. Ты так и не ответил, что там у тебя? Мод или что?


Прошу прощения. Я пока в чистом ТЧ делаю эту фичу, но потом добавлю ее свой мод. Хочу удалить из инвентаря неписей пда. Я заметил, что если удалить пда у живых неписей, то в контактах они не будут отображаться. Причем сделать так, что у них в место пда был предмет "выключенный пда или т.п." на классе антирадина или гитары. И хотел бы сделать в отдельном скрипте через подключение в bind_stalker и xr_motivator.

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

Секцию пда в items.ltx смотрел. Ничего интересного в ней не нашел. Разве что проверить класс в ресурсах или исходниках.

Автор: aka_sektor 22.09.2017, 18:12

Цитата(Gaz24 @ 22.09.2017, 18:10) *
Я пока в чистом ТЧ делаю эту фичу

laugh.gif
Прикалываешься? Сам добавил, а потом спрашиваешь как удалить.
Все я сваливаю...

Автор: Gaz24 22.09.2017, 18:15

Цитата(aka_sektor @ 22.09.2017, 19:12) *
Сам добавил, а потом спрашиваешь как удалить.

В том то и дело, что я ничего не добавлял. Потому и спрашиваю где у сталкеров пда спавнится, если нет никаких секций спавна ни в конфигах, ни в скриптах.

Автор: RedPython 22.09.2017, 19:03

Боюсь, что пда — это часть сущности сталкиров в системе алайф scratch_one-s_head.gif нехай программисты скажут точно

Автор: hi_flyer 22.09.2017, 19:21

Если не ошибаюсь, ПДА ровно как и болт спавнит движок в НПС. Без сторонних .ltx или .xml

Автор: RayTwitty 22.09.2017, 19:26

Цитата(Gaz24 @ 22.09.2017, 18:10) *
Я заметил, что если удалить пда у живых неписей, то в контактах они не будут отображаться

Ясен пень, ПЫС на этапе тру разработки сделало все по уму - отображаются не НПС на карте, а именно ПДА)

Кстати, а ведь в оригинале ПДА скрыты при обыске, ибо находятся в слоте. Так зачем удалять их?

Автор: SkyLoader 22.09.2017, 19:32

Если в игре ломаются скрипты(биндеры), то после смерти неписей можно увидеть у них в инвентаре пда, гармошки, гитары, которые из за поломки скриптов не удаляются. Причем пда имеет название, завязанное на имени непися, например, "Пда Васян Маслинный". Очевидно предположить, что это делается в движке, так как пда и непись связываются.
Удалить пда у живого непися скорее всего можно, но это может повлечь за собой последствия. Лучше не стоит этого делать.

Автор: Gaz24 22.09.2017, 19:38

Цитата(RayTwitty @ 22.09.2017, 20:26) *
Кстати, а ведь в оригинале ПДА скрыты при обыске, ибо находятся в слоте. Так зачем удалять их?


Они не скрыты. После смерти удаляются detath_manager'ом. А удалить ПДА я хочу чтобы вместо него добавить в инвнтарь неписю предмет "выключенный пда" или вообще не ничего не добавлять, чтобы придать некого реализма.

Автор: AndreySol 23.09.2017, 08:01

Цитата(Gaz24 @ 22.09.2017, 20:38) *
... чтобы вместо него добавить в инвнтарь неписю предмет "выключенный пда" или вообще не ничего не добавлять, чтобы придать некого реализма.

В чем реализм - сталкер, которому прилетело насмерть в голову, все-же успел выключить ПДА... "из последних сил"?

Автор: Gaz24 23.09.2017, 12:33

Цитата(AndreySol @ 23.09.2017, 09:01) *
В чем реализм - сталкер, которому прилетело насмерть в голову, все-же успел выключить ПДА... "из последних сил"?


Реализм заключается в том, что ПДА удаляется и спавнится вместо него "выключенный" еще у живых нпс . Например чтобы не палится в контактах других у сталкеров, или вообще ПДА сломан у него, ну и т.д.

Автор: aka_sektor 05.12.2017, 20:04

Словил тут вылет, когда помер в ЗП:

Код
xr_conditions.script:2196: attempt to index field 'actor' (a nil value)

Точнее при загрузке последнего сохранения.

В кондишнс у меня добавлен код:
Код
function sad_predateli_pda()
if (db.actor:object("sad_mudak_pda") ~= nil) and not (db.actor:has_info("sad_predateli_info")) then
db.actor:give_info_portion("sad_predateli_info")
end
end


2196 это вторая строка, которая if
В чем тут дело?

Изначальная функция взята отсюда: http://www.amk-team.ru/forum/topic/8806-cop-kvesty/?page=2&tab=comments#comment-349951

Автор: RayTwitty 05.12.2017, 20:15

Цитата(aka_sektor @ 05.12.2017, 20:04) *
при загрузке

Ты хочешь получить клиентский объект актора до того как он появился. Это надо делать на net_spawn или ставить колбек на выход в онлайн (тема избитая).

Автор: aka_sektor 05.12.2017, 20:48

Цитата(RayTwitty @ 05.12.2017, 20:15) *
ставить колбек

Да, там ниже это и предложили: http://www.amk-team.ru/forum/topic/8806-cop-kvesty/?do=findComment&comment=350365

Вот только с колбеком on_item_take есть косяк, описанный в этом посте: http://www.amk-team.ru/forum/topic/6185-skriptovanie/?do=findComment&comment=1122162

Цитата(RayTwitty @ 05.12.2017, 20:15) *
надо делать на net_spawn

Можешь показать?

Вообще, предложили дописать проверку актера на nil, вот так:
Код
function sad_predateli_pda()
if db.actor ~= nil and db.actor:object("sad_mudak_pda") ~= nil and not db.actor:has_info("sad_predateli_info") then
db.actor:give_info_portion("sad_predateli_info")
end
end


UPD:
Проверил - больше не вылетает.

Автор: RayTwitty 27.05.2018, 17:00

Запамятовал, ключом таблицы в Lua может быть только строка или целое число?))

upd:

Цитата
Тип table (таблица) реализует ассоциативные массивы, это значит, что массив может быть проиндексирован не только числами, но и любым Lua значением, кроме nil и NaN. (Not a Number специальное значение для представления неопределенных и непредставимых числовых результатов, таких как 0/0.) Таблицы могут быть гетерогенными (разнородными); т.е. могут содержать значения всех типов (кроме nil). Любой ключ со значением nil не считается частью таблицы. И наоборот, любой ключ, не являющийся частью таблицы, имеет ассоциированное значение nil.

Действительно работает))
Код
local t1 = { [1] = "one" }

local t2 = { [t1] = "two" }

print(t2[t1]) --> "two"

Хотя на практике я не встречал, чтобы в качестве ключей использовалось что-то отличное от числа или строки.

Автор: TIGER_VLAD 27.05.2018, 17:59

Цитата(RayTwitty @ 27.05.2018, 17:00) *
Запамятовал, ключом таблицы в Lua может быть только строка или целое число?))

upd:
Цитата
Тип table (таблица) реализует ассоциативные массивы, это значит, что массив может быть проиндексирован не только числами, но и любым Lua значением, кроме nil и NaN. (Not a Number специальное значение для представления неопределенных и непредставимых числовых результатов, таких как 0/0.) Таблицы могут быть гетерогенными (разнородными); т.е. могут содержать значения всех типов (кроме nil). Любой ключ со значением nil не считается частью таблицы. И наоборот, любой ключ, не являющийся частью таблицы, имеет ассоциированное значение nil.

Действительно работает))
Код
local t1 = { [1] = "one" }

local t2 = { [t1] = "two" }

print(t2[t1]) --> "two"

Хотя на практике я не встречал, чтобы в качестве ключей использовалось что-то отличное от числа или строки.


А еще для строковых ключей квадратные скобки можно не указывать:
local my_t = {green="зеленый", yellow="желтый", red="красный"}

Автор: kiperenok 09.06.2018, 19:56

Объясните пожалуйста синтаксис второй строчки кода, что делает двоеточие ? Вообще интересует синтаксис двоеточия в Lua.

local visualMonitor = require( "com.ponywolf.visualMonitor" ) -- к локальной переменной visualMonitor подключить файл visualMonitor
local visMon = visualMonitor:new()

Автор: RayTwitty 09.06.2018, 20:14

Цитата(kiperenok @ 09.06.2018, 19:56) *
Объясните пожалуйста синтаксис второй строчки кода, что делает двоеточие ?

Обращение к полю. Погугли операторы и метатаблицы Lua.

Вот неплохое руководство по Lua: https://yadi.sk/d/4EUvTWhzdnAve

Автор: kiperenok 09.06.2018, 20:22

Цитата(RayTwitty @ 09.06.2018, 20:14) *
Цитата(kiperenok @ 09.06.2018, 19:56) *
Объясните пожалуйста синтаксис второй строчки кода, что делает двоеточие ?

Обращение к полю. Погугли операторы и метатаблицы Lua.

Вот неплохое руководство по Lua: https://yadi.sk/d/4EUvTWhzdnAve

А так это просто книга Роберта Иерусалимски - просто интерактиваная. Спасибо что скинул ссылку. Че то бегло пробежался по метатаблицам и такого не увидел sad.gif

Автор: abramcumner 09.06.2018, 20:27

Цитата(kiperenok @ 09.06.2018, 20:22) *
Че то бегло пробежался по метатаблицам и такого не увидел sad.gif

А в операторах нет оператора двоеточие и в метатаблицах нет smile.gif
Двоеточие это синтаксический сахар для сокращения записи.
Запись
local visMon = visualMonitor:new()
эквивалентна
local visMon = visualMonitor.new(visualMonitor)

То есть объект перед двоеточием передается первым параметром в функцию.
А при объявлении функции через двоеточие в функцию добавляется первый аргумент self.

https://www.lua.org/manual/5.3/manual.html#3.4.11
Цитата
The colon syntax is used for defining methods, that is, functions that have an implicit extra parameter self. Thus, the statement
function t.a.b.c:f (params) body end
is syntactic sugar for
t.a.b.c.f = function (self, params) body end

Автор: kiperenok 19.06.2018, 14:07

abramcumner помоги со следующим: rolleyes.gif

function instance:touch(event)
self.xScale, self.yScale = 0.95, 0.95
end


Как я это понял - self это первый скрытый параметр у функции, тогда получается у функции touch первым аргументом идет instance, а вторым event.
Тогда self.xScale равносильно instance.xScale ?

Автор: Neo][ 19.06.2018, 14:33

kiperenok, по вопросу - в зависимости от того, как вызываешь touch и да, и нет smile.gif
Если вызываешь, как instance:touch(ev) или instance.touch(instance, ev) то да, если же как instance.touch(other_table, ev) то нет.

Я думаю эта https://www.lua.org/pil/16.html отвечает на все вопросы )

Автор: kiperenok 19.06.2018, 15:36

Цитата(Neo][ @ 19.06.2018, 14:33) *
Я думаю эта https://www.lua.org/pil/16.html отвечает на все вопросы )

Не в моем случае laugh.gif Там все на английском.

Автор: abramcumner 19.06.2018, 16:12

Цитата(kiperenok @ 19.06.2018, 14:07) *
Как я это понял - self это первый скрытый параметр у функции, тогда получается у функции touch первым аргументом идет instance, а вторым event.
Тогда self.xScale равносильно instance.xScale ?

Да, все правильно. Но это странный подход - разбирать код таким образом smile.gif
Тебе абревиатура ООП о чем-нибудь говорит? Объекты там, классы.

Цитата
Не в моем случае laugh.gif Там все на английском.

RayTwitty давал ссылку на эту же книгу на русском smile.gif

Автор: kiperenok 19.06.2018, 19:23

Цитата(abramcumner @ 19.06.2018, 16:12) *
RayTwitty давал ссылку на эту же книгу на русском smile.gif

Нашел в книге на русском эту главу, прочитал - вот теперь все понятно. Всем кто помог БОЛЬШОЕ спасибо ! wink.gif

Автор: buffy 12.12.2018, 16:19

Последняя luabind на текущий момент 0.7.1(2014 год) судя соурсфоржу и гиту. Проект в каком либо виде поддерживается на данный момент?

Автор: Marafonec 27.09.2019, 18:39

Парни, может кто подсказать в чем кроется проблема?
Вот такой код

Код
for cf, sec in string.gmatch(str, "%s*([%\%.-_%w]+)%s*%|%s*([-_%w]+)%s*") do
валит игру с логом:
Код
SCRIPT SYNTAX ERROR:
c:\ogsr\gamedata\scripts\_utils.script:225: invalid escape sequence near '"%s*([%'

Использую недавно вышедший движок OGSR x64. На оригинальном движке ТЧ этот код работает безо вских проблем.

Автор: Люпус Эст 28.09.2019, 01:37

Небось старый луа просто тихо удалял бекслеш, а новый уже не переваривает кривые ескейп-последовательности и хочет, чтобы ты экранировал \. Попробуй добавить ещё один бекслеш перед существующим. Хз как в огср, но в обычном луа5.3 оно вывелось без ошибок: https://rextester.com/live/XSSP38105


А что вообще должна делать эта регулярка?

Автор: abramcumner 28.09.2019, 11:06

Цитата(Люпус Эст @ 28.09.2019, 01:37) *
А что вообще должна делать эта регулярка?

Ищет пары слов, разделенные вертикальной чертой.

Автор: Marafonec 28.09.2019, 13:07

Цитата(Люпус Эст @ 28.09.2019, 01:37) *
Попробуй добавить ещё один бекслеш перед существующим.
Спасибо, помогло.

Цитата(Люпус Эст @ 28.09.2019, 01:37) *
Хз как в огср, но в обычном луа5.3 оно вывелось без ошибок
Судя по логу: "--LUA version: [LuaJIT 2.1.0-beta3]"

Цитата(Люпус Эст @ 28.09.2019, 01:37) *
А что вообще должна делать эта регулярка?
+++
--/summary/>> функция парсинга параметров файла "overrides_by_schemes.ltx"
function getTableValuesParam(str)
local all_els = {}
--'парсим скриптовые таблицы
for ft in string.gmatch(str, '%"%s*([-_%.%w]+)%s*%"') do
local base_tbl, file_name
local tbl_name = ft
for f, t in string.gmatch(ft, "([-_%w]+)%.([-_%w]+)") do
file_name = f
tbl_name = t
end
if file_name and tbl_name then
base_tbl = _G[file_name] and _G[file_name][tbl_name]
else
base_tbl = _G[ft]
end
if type(base_tbl) == "table" then
for k in pairs(base_tbl) do
table.insert(all_els, k)
end
end
end
--'парсим конфиговые списки параметров
for cf, sec in string.gmatch(str, "%s*([%\\%.-_%w]+)%s*%|%s*([-_%w]+)%s*") do
--'"%s*([%'
local ini = ini_file(cf)
if ini and ini:section_exist(sec) then
do
local ind = 0
repeat
local valid, id, value = ini:r_line(sec, ind, "", "")
if valid then
table.insert(all_els, id.." >> "..value)
end
ind = ind + 1
until (not valid)
end
end
end
--'парсим дополнительные параметры
for pm, list in string.gmatch(str, "%s*([%+%-])%s*%{%s*([-_%s%,%w]+)%s*%}") do
for el in string.gmatch(list, "%s*([^%,%s][-_%w]+)%s*") do
if pm == "+" then
table.insert(all_els, el)
end
if pm == "-" then
local ind = 0
for i, v in ipairs(all_els) do
if v == el then
ind = i
break
end
end
if ind > 0 and all_els[ind] then
table.remove(all_els, ind)
end
end
end
end
return all_els
end


Автор: Pavel_Blend 14.11.2019, 17:11

Я сегодня ещё раз начал вникать в луа. Частично прочитал несколько небольших учебников. Появились вопросы:

1) что это за слово class? Понятно, что создаёт класс, но в Notepad++ это ключевое слово даже не подсвечивается цветом. Такое ощущение, что эта вещь есть только в сталкеровских скриптах. Это слово class ведь не стандартная для языка часть?

2) как в луа работает система модулей и пакетов? В книжках пишут, что нужно использовать require. Но в сталкерских скриптах нету ни одного require. Я заметил, что модули используются без импорта. Например, если в папке gamedata\scripts есть файл my_module.script, то чтобы использовать функции из этого модуля, нужно сразу (без импорта) к ним обращаться: my_module.my_funct()
В питоне с модулями всё по-другому. Их всегда нужно импортировать так: import my_module, а потом использовать так: my_module.my_funct(). Но в луа я не совсем понимаю, как обращаться к коду из вне. Всё как волшебство какое-то. Пишем my_module.my_funct() и он сам импортируется что ли?

3) откуда растут ноги у скриптов сталкера? Какой скрипт вызывается самым первым? Что является началом работы скриптов?

4) как скриптом вывести в игровую консоль сообщение? printf вроде не работает.

Автор: abramcumner 14.11.2019, 17:33

Цитата(Pavel_Blend @ 14.11.2019, 17:07) *
1) что это за слово class? Понятно, что создаёт класс, но в Notepad++ это ключевое слово даже не подсвечивается цветом. Такое ощущение, что эта вещь есть только в сталкеровских скриптах. Это слово class ведь не стандартная для языка часть?

Это магия луа+луабинд.
Луа: при вызове функции с одним строковым(таблицей) параметром можно опускать скобки. Записи class("se_stalker") и class "se_stalker" эквивалентны.
Луабинд: добавляет функцию class и прочую обвязку. См. luabind open.cpp

Цитата
2) как в луа работает система модулей и пакетов? В книжках пишут, что нужно использовать require. Но в сталкерских скриптах нету ни одного require. Я заметил, что модули используются без импорта. Например, если в папке gamedata\scripts есть файл my_module.script, то чтобы использовать функции из этого модуля, нужно сразу (без импорта) к ним обращаться: my_module.my_funct()
В питоне с модулями всё по-другому. Их всегда нужно импортировать так: import my_module, а потом использовать так: my_module.my_funct(). Но в луа я не совсем понимаю, как обращаться к коду из вне. Всё как волшебство какое-то. Пишем my_module.my_funct() и он сам импортируется что ли?

Это магия движка. Если не находится таблица my_module, пытается подгрузить из одноименного файла .script.

Цитата
3) откуда растут ноги у скриптов сталкера? Какой скрипт вызывается самым первым? Что является началом работы скриптов?

Формально наверное _G.script. Но скрипты, привязанные к серверным и клиентским объектам, диалогам и прочему, вызываются "сами по себе".

Цитата
4) как скриптом вывести в игровую консоль сообщение? printf вроде не работает.

Если собрать движок без дефайна MASTER_GOLD работает и printf и log. Если на оригинальном движке, то только через console():execute("load ~~~"..escape(msg)). Типа загружаешь несуществующий сейв, движок ругается на его отсутствие и выводит твою строку smile.gif В принципе во всех модах есть уже готовая функция log/dbglog.

Автор: Modera 14.11.2019, 17:40

Цитата(abramcumner @ 14.11.2019, 17:29) *
Это магия луа+луабинд.
Луа: при вызове функции с одним строковым(таблицей) параметром можно опускать скобки. Записи class("se_stalker") и class "se_stalker" эквивалентны.
Луабинд: добавляет функцию class и прочую обвязку. См. luabind open.cpp

Ещё стоит упомянуть что это функция возвращает функцию в которую передаётся базовый класс в скобках.
Это уже граничит с чёрной магией, но луабинд целиком на ней построен, так что не страшно.

Автор: atanda 14.11.2019, 18:09

Цитата(Pavel_Blend @ 14.11.2019, 17:07) *
3) откуда растут ноги у скриптов сталкера? Какой скрипт вызывается самым первым? Что является началом работы скриптов?

Я тоже задавался этим вопросом, но после анализа(возможно, плохого) исходников пришёл к выводу, что фактически ничего не является началом работы. Каждый скрипт уникален и не предполагает наличие соседей. При загрузки скрипта, чтобы не конфликтовали глобальные переменные, для содержимого(функций, глоб. переменных) создаётся отдельное пространство имён. Далее скрипт исполняется, при обращении к несуществующей на момент исполнения таблице, например, my_script, действия продолжаются рекурсивно.

Автор: RayTwitty 14.11.2019, 20:09

Цитата(Pavel_Blend @ 14.11.2019, 17:07) *
2) как в луа работает система модулей и пакетов?

В сталкерском луа вообще нет как таковых модулей и пакетов. Обращаемся сразу, никаких импортов, инклудов, запросов и т.д. С этим намного проще, чем в чистых языках.

Автор: Pavel_Blend 14.11.2019, 20:41

Меня ещё удивил то факт, что можно обращаться к некоторым функциям, не указывая модуля, в котором они хранятся. Например, функция printf хранится в файле _g.script, а вызывать из других скриптов её можно так: printf(), а не так _g.printf(). Ещё видел другую функцию (не printf), которая так же использовалась.

Автор: RayTwitty 14.11.2019, 21:54

Цитата(Pavel_Blend @ 14.11.2019, 20:37) *
Меня ещё удивил то факт, что можно обращаться к некоторым функциям, не указывая модуля, в котором они хранятся.

Это касается содержимого только _g скрипта. g - global

Автор: Pavel_Blend 16.11.2019, 21:58

Продолжаю изучать луа. Кое что изучил, но всё равно не могу писать скрипты для сталкера. Какой способ изучения лучше всего выбрать, чтобы начать программировать для сталкера? Я пока думаю так:

1) читаю учебник "Программирование на языке Lua. Третье издание. (рус)" (ссылка в шапке данной темы), чтобы изучить чистый луа (без сталкеровских классов/функций) (или есть более полная/лучшая книга на русском?)

2) изучить стандартную библиотеку луа (на удивление она оказалась крошечной, по сравнению со стандартной библиотекой python)

3) как-то изучить сталкеровские функции/классы по lua_help.script

Наверное, самое трудное - это 3 пункт. Так как информация в lua_help.script не многословная и в сети нету полной документации.

Пока я остановился на первом пункте. И получилось сделать свой первый скрипт:
https://github.com/PavelBlend/stalker-lua-scripts/blob/master/dm_reader.lua

Он считывает бинарные данные из dm файлов, помещает их в таблицу и печатает в консоль.

Ещё пытался изучать скрипты от модов, но ничего не понял. Изучал nlc7 и удивился скриптам, а именно sak_dialog.script и sak.script. Эти скрипты имеют несколько тысяч строк кода. Один в 9 тысяч, другой в 11 тысяч. Как разработчики умудряются с такими скриптами работать? Я бы разделил бы их на куски по 100-500 строк. Наверняка диалоги можно было бы разбить по локациям.

Автор: abramcumner 17.11.2019, 11:47

Цитата(Pavel_Blend @ 16.11.2019, 21:54) *
Ещё пытался изучать скрипты от модов, но ничего не понял.

А зачем моды, лучше с оригинала начать тогда.
На АМК есть тема с разбором lua_help: https://www.amk-team.ru/forum/topic/7450-spravochnik-po-funkciyam-i-klassam/
В ней если не все описано, то очень многое.

Цитата
Изучал nlc7 и удивился скриптам, а именно sak_dialog.script и sak.script. Эти скрипты имеют несколько тысяч строк кода. Один в 9 тысяч, другой в 11 тысяч. Как разработчики умудряются с такими скриптами работать? Я бы разделил бы их на куски по 100-500 строк. Наверняка диалоги можно было бы разбить по локациям.

Диалоги и так разбиты по локациям(config/gameplay/dialogs_*.xml), в скриптах вспомогательная обвязка. Из-за того, что в оригинале из диалога в скриптовую функцию нельзя передать аргументы, приходится плодить кучу функций, которые вызывают одну и ту же функцию, но с разными аргументами. А если делать какой-нибудь бартер/выбор награды/починку на диалогах, то количество скриптовых функций разрастается в геометрической прогрессии. Смысла разбивать диалоговые функции по разным файлам нет, и пишутся и читаются они наоборот: сначала диалог, потом функция. Точно также и функции для логики.


Автор: atanda 17.11.2019, 14:10

Цитата(Pavel_Blend @ 16.11.2019, 21:54) *
Изучал nlc7 и удивился скриптам, а именно sak_dialog.script и sak.script

Вполне возможно, что alpet'ом была написана на дельфях утилита для создания диалогов и в ней можно было бы писать экшены, а потом утилита сама записывала функции в файлик.

Автор: RayTwitty 17.11.2019, 15:26

Pavel_Blend, может стоит сначала изучить файловую структуру игры? Не просто где конфиги и где скрипты, а более детально - диалоги, предметы, существа, UI, тексты и т.д. А по модам изучать смысла мало - как правило там лютый ахтунг, который только добавит вопросов.

Автор: Gaz24 18.11.2019, 14:49

Добрый день. Вопрос по поводу скриптов и аи-схем. Как определить, что НПС в определенный момент времени ведет огонь через менеджер состояний или другой метод?

Автор: Pavel_Blend 18.11.2019, 23:50

Такой вопрос возник:

движок сталкера добавляет функции в луа, которые равноправны функциям из базовой библиотеки? То есть например, есть функции pairs, getmetatable, next, которые находятся в базовой библиотеке. И чтобы их вызвать, достаточно написать getmetatable(). Но есть функции, которые предоставляются другими библиотеками, доступ к которым осуществляется не просто find, а string.find или math.abs. То есть нужно писать имя библиотеки и ставить точку, после которой идёт имя функции. Так вот, движок сталкера добавляет функции в базовую библиотеку, и чтобы использовать эти функции, не нужно писать имя библиотеки и точку. Например, есть такие функции, как vector(). Я ведь всё правильно понял? Ну, что движок xray добавляет новые функции именно в базовую библиотеку.

И ещё вопрос: есть ли у кого xml файл для Notepad++, который добавляет подсветку синтаксиса lua вместе со всеми сталкеровскими функциями? И чтобы сталкеровские функции были отличны по цвету от стандартных. Просто у меня не получается добавить новые ключевые слова в файл langs.xml. Notepad их просто игнорирует. Поэтому мне нужен отдельный xml файл с User Defined Language с описанием всего синтаксиса луа + сталкеровские функции.

Автор: atanda 18.11.2019, 23:58

Цитата(Pavel_Blend @ 18.11.2019, 23:46) *
Ну, что движок xray добавляет новые функции именно в базовую библиотеку.

Смысл верен, только всё немного не так: "регистрация" происходит не в "базовой библиотеке", а в глобальном пространстве имён "_G", т.е. вызывая string.find, ты фактически делаешь _G["string"].find. Луа проходится по таблице и ищет соответствующее пространство имён, в данном случае "string".

Автор: Pavel_Blend 19.11.2019, 00:02

atanda, понятно. А для notepad++ ни кто не добавлял сталкеровские функции? Для новичков было бы удобнее. Так как большая часть кода в сталкере - это вызов функций, добавленных из движка.

Автор: atanda 19.11.2019, 00:16

Примерно так:
https://images.gameru.net/image/e5d347bf789ede3.png.html
или создавать свои файлы синтаксиса.

Автор: abramcumner 19.11.2019, 00:16

Pavel_Blend, https://ap-pro.ru/forum/105-10388-1

Автор: Pavel_Blend 19.11.2019, 00:25

abramcumner, по твоей ссылке есть только автозавершение и проверка синтаксиса. Мне нужна подсветка синтаксиса сталкеровских функций. Только нужно, чтобы цвет отличался от стандартных функций.

Автор: RayTwitty 19.11.2019, 00:55

Цитата(Pavel_Blend @ 19.11.2019, 00:21) *
Мне нужна подсветка синтаксиса сталкеровских функций. Только нужно, чтобы цвет отличался от стандартных функций.

Такого вроде не существует. Единственное что я например делал, так это ассоциацию файлов .script с lua-синтаксисом (в оригинальном луа расширение .lua).

Цитата(Pavel_Blend @ 18.11.2019, 23:46) *
Так вот, движок сталкера добавляет функции в базовую библиотеку, и чтобы использовать эти функции, не нужно писать имя библиотеки и точку. Например, есть такие функции, как vector().

Ну так самописный вектор они в глобальную загнали, поэтому нет никаких "библиотек". В луа/сталке тут более уместно пространства имен.

Цитата(atanda @ 18.11.2019, 23:54) *
Луа проходится по таблице и ищет соответствующее пространство имён, в данном случае "string".

А еще, при однозначном определении типа, можно прям как в питоне вызывать напрямую))
Код
local t = "lol"
t:find("kek")

Автор: atanda 19.11.2019, 08:28

Цитата(RayTwitty @ 19.11.2019, 00:51) *
можно прям как в питоне вызывать напрямую

Это больше похоже на синтаксический сахар. rolleyes.gif

Автор: Pavel_Blend 19.11.2019, 14:01

Цитата(RayTwitty @ 19.11.2019, 00:51) *
Цитата(Pavel_Blend @ 19.11.2019, 00:21) *
Мне нужна подсветка синтаксиса сталкеровских функций. Только нужно, чтобы цвет отличался от стандартных функций.

Такого вроде не существует. Единственное что я например делал, так это ассоциацию файлов .script с lua-синтаксисом (в оригинальном луа расширение .lua).

а в каком текстовом редакторе есть возможность добавить новые ключевые слова в lua, чтобы они были произвольного цвета, отличного от цвета стандартных функций? И как получить список всех функций, которые добавил движок в луа сталкера? Я пробовал пройтись по значениям из _G таблицы, но в ней, помимо си++ функций есть обычные скрипты, стандартные луа функции и прочее. Единственный способ - это извлекать имена из lua_help.script?

Автор: Pavel_Blend 19.11.2019, 21:29

Получилось заставить Notepad++ читать более 4 наборов ключевых слов. Добавил ключевые слова из сталкеровского движка. Теперь они подсвечиваются розовым цветом. Но я не всё добавил. И так же добавилось кое-что лишнее. Например, функция printf. Она определена в файле _G.script и по идее не должна подсвечиваться розовым цветом. Как я узнал список ключевых слов: запустил игру и вызвал скрипт, который выводил в файл все ключи таблицы _G. Там много чего лишнего. А не добавились методы классов. На скриншоте видно, что слово object_binder подсвечено цветом, а net_spawn - нет. Нужно сделать подсветку метода net_spawn и всех других методов сталкеровских классов. Но вот как узнать список всех классов методов?
https://images.gameru.net/image/b270d4aa76fd1ca.jpg.html

Автор: Shoкer 19.11.2019, 23:06

Pavel_Blend, открой скрипт lua_help.script из оригинальной игры. Там будет всё то, что экспортируется из движка. Всё остальное создаётся напрямую в скриптах.
Ещё много полезного есть здесь - https://www.amk-team.ru/forum/topic/7450-spravochnik-po-funkciyam-i-klassam/ , хотя писалось достаточно давно, ещё до исходников движка.

Автор: NanoBot-AMK 21.11.2019, 19:34

Кстати, функции типа object_binder.update(self, delta) можно спокойно исключить, это просто пустышки, которые ничего не делают, кроме времени(2-3 мксек). Исключения только для метода net_spawn, там это нужно.

Автор: Gaz24 23.11.2019, 07:43

Хотел добавить свою аи-схему, которая запускается во время боя. Все подключил, добавил эвалуатор, работает. А вот экшен не работает от слова совсем. В чем могла быть ошибка?

Код
Код
local base = xr_evaluators_id.combat_new_base
local eval_on_combat = base + 0

base = xr_actions_id.combat_new_base
local act_on_combat = base + 0
----------------------------------------------------------------------------------------------------------------------
-- модификация xr_combat
----------------------------------------------------------------------------------------------------------------------
class "evaluator_mod_combat" (property_evaluator)

function evaluator_mod_combat:__init(name,storage) super (nil, name)
    self.st = storage
end

function evaluator_mod_combat:evaluate()
    local cond = self.object:motivation_action_manager():current_action_id() == stalker_ids.action_combat_planner
    --news_manager.send_tip(db.actor, self.object:character_name())
    return cond
end

----------------------------------------------------------------------------------------------------------------------
class "action_mod_combat" (action_base)

function action_mod_combat:__init(name,storage) super (nil, name)
    self.st = storage
end

function action_mod_combat:initialize()
    action_base.initialize(self)
    news_manager.send_tip(db.actor, 1)
end

function action_mod_combat:execute()
    action_base.execute(self)
end

function action_mod_combat:finalize()
    action_base.finalize(self)
end

----------------------------------------------------------------------------------------------------------------------
-- binder
----------------------------------------------------------------------------------------------------------------------
function add_to_binder(npc, ini, scheme, section, storage)
    local manager = npc:motivation_action_manager()

    manager:add_evaluator( eval_on_combat, this.evaluator_mod_combat("eval_mod_combat",storage) )

    local action = this.action_mod_combat("act_mod_combat",storage)
    --action:add_precondition(world_property(stalker_ids.property_alive, true))
    manager:add_action(act_on_combat, action)
end

Автор: abramcumner 23.11.2019, 10:55

Цитата(Gaz24 @ 23.11.2019, 07:39) *
Хотел добавить свою аи-схему, которая запускается во время боя. Все подключил, добавил эвалуатор, работает. А вот экшен не работает от слова совсем. В чем могла быть ошибка?

Он и не должен работать, ты же экшен никак в GOAP не встроил:
1. твоему экшену надо добавить прекондишен и эффект. Например, что он вызывается, когда world_property(eval_on_combat) = true и обещает перевести world_property(eval_on_combat) в false.
2. добавить существующему экшену прекондишен world_property(eval_on_combat) = false, например к stalker_ids.action_combat_planner

Тогда НПЦ попытается в очередной раз попытается решить загадку зоны; увидит, что ему мешает world_property(eval_on_combat) = true(пункт 2); для устранения такой неприятности у него есть твой экшен(пункт 1) и НПЦ запустит твой экшен.

Посмотри на аи-схемы из оригинала или из модов. Там есть оба пункта.

Автор: Gaz24 23.11.2019, 11:54

abramcumner, я со своим эвалуатором использовал изначально, поэтому другой запустил. Сделал так, как ты посоветовал. Все равно экшен не срабатывает. Я может плохо написал из-за своего непонимания.

Код
Код
local action = manager:action(stalker_ids.action_combat_planner)
action:add_precondition(world_property(world_property(eval_on_combat), true))
local action = this.action_mod_combat("act_mod_combat",storage)
action:add_effect(world_property(world_property(eval_on_combat), false))
manager:add_action(act_on_combat, action)

Автор: abramcumner 23.11.2019, 13:16

Gaz24, не так. К сожалению не могу найти статью по аи-схемам в сталкере.

Смотри цель любого сталкера - решить загадку зоны, это world_property(puzzleSolved)=true, такой эффект есть у экшена xr_actions_id.alife. Но у него есть прекондишены: жив, нет врагов и тд. Планировщик НПЦ смотрит, как решить загадку зоны, она решается экшеном stalker_ids.action_alife. У него есть прекондишены, планировщик их проверяет. Если все выполнены, то нпц решает загадку зоны, игра заканчивается(в том самом билде). Если не выполнены, то планировщик ищет экшен, который выполнит прекондишен. У него опять проверяет прекондишены, ищет новый экшен,... В итоге доходит до экшена, который может сейчас выполнить и который ведет к решению загадки зоны.

Например логика и гулаги подрубаются так: к экшену xr_actions_id.alife добавляется прекондишен типа "need_remark"=false, а action_remark умеет переводить need_remark в false. Сначала отыграй анимку, а потом можешь решать загадку зоны.

Теперь по-твоему коду. Ты combat_planner`у добавил прекондишен eval_on_combat=true. Планировщик будет искать экшен, который переводит eval_on_combat в true. Но такого нет - act_mod_combat переводит eval_on_combat в false. Надо в эффекте поменять false на true. После этого твой экшен должен начать бесконечно вызываться. Ну и для срабатывания твоего экшена нужен враг, без него боевка и не будет запускаться.

И так не надо писать "world_property(world_property(eval_on_combat), true)", просто "world_property(eval_on_combat, true)".

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

Автор: Gaz24 23.11.2019, 14:04

abramcumner, заработало, спасибо. Правда с прекондишенами надо поиграться. А так, осознал.

Если ты говорил про эту http://stalkerin.gameru.net/wiki/index.php?title=SoC._Логика_NPC, то я на нее очень сильно опирался, но из-за своего косяка вообще не понимал.

Автор: RayTwitty 08.01.2020, 22:34

В дополнение к https://www.amk-team.ru/forum/topic/7450-spravochnik-po-funkciyam-i-klassam/?do=findComment&comment=302379

uint64<class_id> r_clsid(string<section>, string<line>) - возвращает id класса по имени класса (т.е. вызов ini:r_clsid(obj:section(), "class") полностью эквивалентен вызову obj:clsid()).
string<result> r_string_wq(string<section>, string<line>) - тоже самое что и стандартный r_string, только этот метод убирает ещё и кавычки.

Пример
Код
[mysection]
param = "myvalue"

------------------

print(ini:r_string("mysection", "param"))
print(ini:r_string_wq("mysection", "param"))

Результаты
Код
"myvalue"
myvalue
vector<result> r_vector(string<section>, string<line>) - разбивает строку вида "param = number,number,number" и возвращает сформированный из этих компонентов вектор.
int32<result> r_s32(string<section>, string<line>) - возвращает 4-байтовое целое число в диапазоне [-2.147.483.648, 2.147.483.647].
uint32<result> r_u32(string<section>, string<line>) - возвращает 4-байтовое беззнаковое целое число в диапазоне [0, 4.294.967.295].
int<item_id> r_token(string<section>, string<line>, token_list*) - довольно интересный метод, который работает следующим образом:
Открыть
Допустим, у нас имеется токен (лист с именами и их идентификаторами):
Код
local my_token = token_list()
my_token:add("value1", 0)
my_token:add("value2", 1)
my_token:add("value3", 2)

И имеется конфиг со строкой:
Код
[mysection]
param = value2

Нам нужно выяснить, какому идентификатору соответствует это значение (и соответствует ли вообще). Читаем:
Код
local item_id = ini:r_token("mysection", "param", my_token)
log(item_id)

Результат
Код
1

(что соответствует value2 = 1).
Если значение в конфиге не соответствует никакому значению из токена, то вернет ноль.

И ещё, сразу сюда же - метод ini_file* create_ini_file(string<file_text>)
Собственно создает конфиг-файл. После чего, с ним можно работать как и с обычным конфигом:
Код
local ini = create_ini_file("[mysection]\nmyparam = value")


З.Ы. Это перенос моего старого поста с другого форума. Пусть будет и здесь.

Автор: Diesel 02.07.2020, 20:22

Вопрос по скрипту ОГСМ ogsm_rt_manager.script. В игре, с локациями ЧН, вылета не было. Вылет идёт по спавну в алспавн мертвого сталкера на новой локации.

--Регистрация целей для тасков типа kill_stalker
function CRandomTask:register_target(obj)
if IsStalker(obj) then
for k,v in pairs(self.task_id_by_type["kill_stalker"]) do -- !!! ТУТ ВЫЛЕТ !!!
if obj.alive ~= nil and obj:alive() == true and
obj:profile_name() == self.task_info[v].target
then
if self.task_info[v].target_objects == nil then
self.task_info[v].target_objects = {}
end
table.insert(self.task_info[v].target_objects, obj.id)
end
end
end
end

Если выпиливаю полностью тело функции, то срабатывает нормально. А вообще это что за тема задумана такая?


Может перечисление локаций ЧН сделать, типа такого?
if level.name() == "agroprom_underground" then

Или куда то надо новую локацию прописать или трупы? Тупизна меня обуяла.

А там еще ака Bak намутил rx_wmgr.script - что на сивой кобыле не проехать.

Короче, для нового уровня - ОГСМ - это Ж...

Автор: Diesel 09.08.2020, 02:18

Кто желает разобраться в хитросплетениях диалога. Вылет идёт когда раненому даю аптечку в ЧН (мод SGM).
Вылетает рандомно. В интернетах разумного ответа нет.

FATAL ERROR

[error]Expression : !phrase_dialog->m_PhraseVector.empty()
[error]Function : CPhraseDialog::SayPhrase
[error]File : .\PhraseDialog.cpp
[error]Line : 146
[error]Description : No available phrase to say, dialog[dm_hello_dialog]


stack trace:

0023:0077B1D3 xrCore.dll, xrDebug::backend(), x:\source_scs602\components\engine\xrcore\xrdebugnew.cpp, 278
0023:0077B381 xrCore.dll, xrDebug::fail(), x:\source_scs602\components\engine\xrcore\xrdebugnew.cpp, 366
0023:046E1113 xrGame.dll, CPhraseDialog::SayPhrase(), x:\source_scs602\components\engine\xrgame\phrasedialog.cpp, 146
0023:046E432A xrGame.dll, CPhraseDialogManager::SayPhrase(), x:\source_scs602\components\engine\xrgame\phrasedialogmanager.cpp, 77
0023:0490187A xrGame.dll, CUITalkWnd::SayPhrase(), x:\source_scs602\components\engine\xrgame\ui\uitalkwnd.cpp, 304
0023:04901D3F xrGame.dll, CUITalkWnd::UpdateQuestions(), x:\source_scs602\components\engine\xrgame\ui\uitalkwnd.cpp, 139
0023:04901EDA xrGame.dll, CUITalkWnd::Update(), x:\source_scs602\components\engine\xrgame\ui\uitalkwnd.cpp, 218
0023:04902317 xrGame.dll, CUITalkWnd::InitTalkDialog(), x:\source_scs602\components\engine\xrgame\ui\uitalkwnd.cpp, 83
0023:04902408 xrGame.dll, CUITalkWnd::Show(), x:\source_scs602\components\engine\xrgame\ui\uitalkwnd.cpp, 240
0023:048E81ED xrGame.dll, CDialogHolder::StartMenu(), x:\source_scs602\components\engine\xrgame\uidialogholder.cpp, 77
0023:048E82E8 xrGame.dll, CDialogHolder::StartStopMenu(), x:\source_scs602\components\engine\xrgame\uidialogholder.cpp, 224
0023:04960A28 xrGame.dll, CUIGameSP::StartTalk(), x:\source_scs602\components\engine\xrgame\uigamesp.cpp, 157
0023:046A956F xrGame.dll, CActor::RunTalkDialog(), x:\source_scs602\components\engine\xrgame\actor_communication.cpp, 210
0023:046A97B8 xrGame.dll, CActor::TryToTalk(), x:\source_scs602\components\engine\xrgame\actor_communication.cpp, 194
0023:046BCFA3 xrGame.dll, CActor::ActorUse(), x:\source_scs602\components\engine\xrgame\actorinput.cpp, 402
0023:046BD47C xrGame.dll, CActor::IR_OnKeyboardPress(), x:\source_scs602\components\engine\xrgame\actorinput.cpp, 144
0023:0468189B xrGame.dll, CLevel::IR_OnKeyboardPress(), x:\source_scs602\components\engine\xrgame\level_input.cpp, 416
0023:00411A02 xrEngine.exe, CInput::KeyUpdate(), x:\source_scs602\components\engine\xrengine\xr_input.cpp, 201

Движковый вылет

bool CPhraseDialog::SayPhrase (DIALOG_SHARED_PTR& phrase_dialog, const shared_str& phrase_id)
{
THROW(phrase_dialog->IsInited());

phrase_dialog->m_SaidPhraseID = phrase_id;

bool first_is_speaking = phrase_dialog->FirstIsSpeaking();
phrase_dialog->m_bFirstIsSpeaking = !phrase_dialog->m_bFirstIsSpeaking;

const CGameObject* pSpeakerGO1 = smart_cast<const CGameObject*>(phrase_dialog->FirstSpeaker()); VERIFY(pSpeakerGO1);
const CGameObject* pSpeakerGO2 = smart_cast<const CGameObject*>(phrase_dialog->SecondSpeaker()); VERIFY(pSpeakerGO2);
if(!first_is_speaking) std::swap(pSpeakerGO1, pSpeakerGO2);

CPhraseGraph::CVertex* phrase_vertex = phrase_dialog->data()->m_PhraseGraph.vertex(phrase_dialog->m_SaidPhraseID);
THROW(phrase_vertex);

CPhrase* last_phrase = phrase_vertex->data();

//вызвать скриптовую присоединенную функцию
//активируется после сказанной фразы
//первый параметр - тот кто говорит фразу, второй - тот кто слушает
last_phrase->GetScriptHelper()->Action(pSpeakerGO1, pSpeakerGO2, *phrase_dialog->m_DialogId, phrase_id.c_str());

//больше нет фраз, чтоб говорить
phrase_dialog->m_PhraseVector.clear();
if(phrase_vertex->edges().empty())
{
phrase_dialog->m_bFinished = true;
}
else
{
//обновить список фраз, которые сейчас сможет говорить собеседник
for(xr_vector<CPhraseGraph::CEdge>::const_iterator it = phrase_vertex->edges().begin();
it != phrase_vertex->edges().end();
it++)
{
const CPhraseGraph::CEdge& edge = *it;
CPhraseGraph::CVertex* next_phrase_vertex = phrase_dialog->data()->m_PhraseGraph.vertex(edge.vertex_id());
THROW (next_phrase_vertex);
shared_str next_phrase_id = next_phrase_vertex->vertex_id();
if(next_phrase_vertex->data()->GetScriptHelper()->Precondition(pSpeakerGO2, pSpeakerGO1, *phrase_dialog->m_DialogId, phrase_id.c_str(), next_phrase_id.c_str()))
{
phrase_dialog->m_PhraseVector.push_back(next_phrase_vertex->data());
#ifdef DEBUG
if(psAI_Flags.test(aiDialogs))
{
LPCSTR phrase_text = next_phrase_vertex->data()->GetText();
shared_str id = next_phrase_vertex->data()->GetID();
Msg("----added phrase text [%s] phrase_id=[%s] id=[%s] to dialog [%s]", phrase_text, phrase_id, id, phrase_dialog->m_DialogId.c_str());
}
#endif
}

}

R_ASSERT2 (
!phrase_dialog->m_PhraseVector.empty(),
make_string(
"No available phrase to say, dialog[%s]",
*phrase_dialog->m_DialogId
)

);

//упорядочить списко по убыванию благосклонности
std::sort(phrase_dialog->m_PhraseVector.begin(),
phrase_dialog->m_PhraseVector.end(), PhraseGoodwillPred);
}



//сообщить CDialogManager, что сказана фраза
//и ожидается ответ
if(first_is_speaking)
phrase_dialog->SecondSpeaker()->ReceivePhrase(phrase_dialog);
else
phrase_dialog->FirstSpeaker()->ReceivePhrase(phrase_dialog);


return phrase_dialog?!phrase_dialog->m_bFinished:true;
}


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

Автор: Pavel_Blend 07.09.2020, 16:02

Недавно возобновил изучение луа. Вот вроде бы проще питона, но как-то труднее его изучить. Может из-за того, что желание изучать меньше. В общем пытаюсь хоть что-то сделать в скриптах. Максимум удалось вывести сообщение в консоль. При изучении нужно знать две вещи: сам луа и собственно функции движка (в блендере это называется API, наверное в X-Ray это тоже API в виде lua функций).
С первым вроде бы понятно, информацию найти можно, а вот со вторым труднее. Читал на АМК посты по функциям и ничего не понятно.

В общем вопросы (эти вопросы по ТЧ скриптам):

как вообще можно встроить свои собственные скрипты в сталкер? Я пока знаю, что можно в диалогах прописать вызов скрипта и функции. А какие ещё способы есть?

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

Автор: RayTwitty 07.09.2020, 21:20

Цитата(Pavel_Blend @ 07.09.2020, 16:02) *
При изучении нужно знать две вещи: сам луа и собственно функции движка (в блендере это называется API, наверное в X-Ray это тоже API в виде lua функций).

Луа в сталкере это по сути интерфейс, осуществляющий доступ к внутридвижковым объектам. Этакая надстройка на логикой внутри движка.

Цитата(Pavel_Blend @ 07.09.2020, 16:02) *
как вообще можно встроить свои собственные скрипты в сталкер? Я пока знаю, что можно в диалогах прописать вызов скрипта и функции. А какие ещё способы есть?

Можно просто вызвать любую функцию в скрипте, тогда он инициализируется. Поскольку, почти все начинают работать с конкретными объектами и чаще всего с актором, свои скрипты инициализируют из bind_stalker.script.

Цитата(Pavel_Blend @ 07.09.2020, 16:02) *
И как сделать редактор погоды в игре?

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

Автор: Pavel_Blend 08.09.2020, 17:44

Цитата(RayTwitty @ 07.09.2020, 21:20) *
Можно просто вызвать любую функцию в скрипте, тогда он инициализируется. Поскольку, почти все начинают работать с конкретными объектами и чаще всего с актором, свои скрипты инициализируют из bind_stalker.script.

а вообще, какой принцип работы скриптов в сталкере? Вот в blender game engine есть такое понятие, как такт, который длится 1/60 секунд. Во время этого такта выполняются действия. А в сталкере как всё работает? Например, как работает bind_stalker? В этом скрипте каждый кадр выполняется определённая функция? Или данный скрипт выполняется один раз за весь сеанс игры? И вообще где выполняется основная работа скриптовой системы? Вот к примеру скрипт из диалога выполнится только один раз. А какие скрипты непрерывно работают в игре и обрабатывают события?

Автор: Diesel 08.09.2020, 21:35

Pavel_Blend, движок заранее заготовленные внедряет свои щупальца в скрипты. И ждёт их изменений, согласно обновлений в движке.
В движке создаются скрипты, как основа, для луа. Каждая функция луа, заранее прописана в движок. Если и не прописана, то предок этой функции всё равно в движке есть.

В поиск визуалки забей .def и увидишь сколько их там.

Автор: RayTwitty 08.09.2020, 23:06

Цитата(Pavel_Blend @ 08.09.2020, 17:44) *
В этом скрипте каждый кадр выполняется определённая функция?

Нет, в движке есть глобальный шедулер (апдейтер), из которого уже апдейтятся все онлайновые объекты (он в свою очередь вроде бы как раз из рендера должен вызываться, но я уже не помню). Покадрового апдейта в скриптах нет, у актора вроде бы интервал каждые 20-40 мс, он динамичен, для этого есть переменная delta в аргументе. У других объектов интервал в целях оптимизации может быть больше.

Цитата(Pavel_Blend @ 08.09.2020, 17:44) *
Или данный скрипт выполняется один раз за весь сеанс игры?

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

Плюс те же функции в биндерах, вызываются при определенных события. Например net_spawn при появлении актора на уровне, update - периодический апдейт (см. выше) и т.д.

Цитата(Pavel_Blend @ 08.09.2020, 17:44) *
А какие скрипты непрерывно работают в игре и обрабатывают события?

Ну кроме апдейта объектов и некоторых апдейтов в UI-интерфейсах таких нет.

Автор: Pavel_Blend 10.09.2020, 12:23

А с помощью скриптов возможно сделать такую вещь:

добавить отметки в пда на все динамические объекты. На сталкеров, на мутантов, тайники, физические объекты, лампочки, бочки, аномалии, еду, патроны, оружие. В общем на всё. И сделать так, чтобы при убийстве сталкера, в пда была метка его трупа. Только метка меняла цвет на серый. Была метка бандита, к примеру, красной, а при убийстве стала серой. И чтобы можно было скрывать метки по типу: аномалии, тайники, трупы, физ. объекты и т. д.

И как можно полностью отключить респавн? Чтобы новые мутанты и сталкеры не появлялись?

Автор: Yara 10.09.2020, 21:31

Цитата(Pavel_Blend @ 10.09.2020, 15:23) *
И как можно полностью отключить респавн? Чтобы новые мутанты и сталкеры не появлялись?

Попробуй в se_respawn.script заремить строку self:spawn(), а для отметок всего использую такое:
...

CODE

По клавише в главном меню: ui_main_menu.script,
-----------------------------
function main_menu:OnKeyboard(dik, keyboard_action) --virtual function
...
if keyboard_action == ui_events.WINDOW_KEY_PRESSED then
...
if dik == DIK_keys.DIK_NUMPAD0 then
if (level.present() and db.actor ~= nil and db.actor:alive()) then
this.mark_all_objects()
end
end



В самый конец файла добавить:

function mark_all_objects()
for i=1,65535,1 do
local obj = alife():object(i)
if (obj and obj.parent_id and obj.parent_id == 65535) then
local obj_name = obj:name()

-- from _g.script

if (IsStalker(obj)) then
level.map_add_object_spot(obj.id, "obj_location", tostring(obj_name))
end
if (IsMonster(obj)) then
--if (IsMonster(obj) and obj:alive()) then -- только живых
level.map_add_object_spot(obj.id, "obj_location", tostring(obj_name))
end

if (
isWeapon(obj) or -- оружие

-- from lua_help.script

get_clsid(obj)==clsid.wpn_ammo or -- патроны
get_clsid(obj)==clsid.wpn_ammo_og7b or -- выстрелы рг/пг
get_clsid(obj)==clsid.wpn_ammo_vog25 or
get_clsid(obj)==clsid.wpn_ammo_m209 or

get_clsid(obj)==clsid.obj_explosive or -- взрывные бочки и прочее

get_clsid(obj)==clsid.obj_food or -- еда и медицина
get_clsid(obj)==clsid.obj_antirad or
get_clsid(obj)==clsid.obj_bandage or
get_clsid(obj)==clsid.obj_bottle or
get_clsid(obj)==clsid.obj_medkit or

get_clsid(obj)==clsid.equ_stalker_s or -- костюмы

get_clsid(obj)==clsid.artefact_s or -- арты
get_clsid(obj)==clsid.artefact or

get_clsid(obj)==clsid.inventory_box or -- тайники
get_clsid(obj)==clsid.obj_phskeleton or -- физ.объекты
get_clsid(obj)==clsid.obj_phys_destroyable or
get_clsid(obj)==clsid.obj_physic or
get_clsid(obj)==clsid.obj_breakable or
get_clsid(obj)==clsid.script_phys or
get_clsid(obj)==clsid.obj_climable or -- лестницы
get_clsid(obj)==clsid.projector or -- прожектор
get_clsid(obj)==clsid.hanging_lamp or -- лампочки

get_clsid(obj)==clsid.ameba_zone or -- аномалии
get_clsid(obj)==clsid.torrid_zone or
get_clsid(obj)==clsid.zone or
get_clsid(obj)==clsid.zone_acid_fog or
get_clsid(obj)==clsid.zone_bfuzz_s or
get_clsid(obj)==clsid.zone_dead or
get_clsid(obj)==clsid.zone_galant_s or
get_clsid(obj)==clsid.zone_galantine or
get_clsid(obj)==clsid.zone_mbald_s or
get_clsid(obj)==clsid.zone_mincer_s or
get_clsid(obj)==clsid.zone_mosquito_bald or
get_clsid(obj)==clsid.zone_radioactive or
get_clsid(obj)==clsid.zone_rusty_hair or
get_clsid(obj)==clsid.nogravity_zone or

get_clsid(obj)==clsid.level_changer or -- переходы
get_clsid(obj)==clsid.respawn or -- респавнеры
get_clsid(obj)==clsid.smart_terrain or -- смарты
get_clsid(obj)==clsid.script_restr or -- рестрикторы
get_clsid(obj)==clsid.script_zone or
get_clsid(obj)==clsid.car_s or -- машины
get_clsid(obj)==clsid.script_heli or -- вертолёты
get_clsid(obj)==clsid.helicopter
)
then
level.map_add_object_spot(obj.id, "obj_location", tostring(obj_name))
end

end
end
end



Добавить в map_spots.xml,
-----------------------------
<!-- debug icon -->
<obj_location>
<level_map spot="obj_location_spot"/>
<mini_map spot="obj_location_spot"/>
</obj_location>
<obj_location_spot x="0" y="0" width="4" height="4" alignment="c" stretch="1">
<texture r="0" g="255" b="255">ui_minimap_point</texture>
</obj_location_spot>


Автор: RayTwitty 12.09.2020, 23:30

Цитата(Pavel_Blend @ 10.09.2020, 12:23) *
А с помощью скриптов возможно сделать такую вещь:

добавить отметки в пда на все динамические объекты. На сталкеров, на мутантов, тайники, физические объекты, лампочки, бочки, аномалии, еду, патроны, оружие. В общем на всё.

Можно. Перебираешь все айдишники (1..65536, 0 - актор, его пропускаем) объектов в игре через alife():object(id), или если нужно только онлайновых то level.object_by_id(id). Добавляем метку через level.map_add_object_spot.

Цитата(Pavel_Blend @ 10.09.2020, 12:23) *
И сделать так, чтобы при убийстве сталкера, в пда была метка его трупа. Только метка меняла цвет на серый. Была метка бандита, к примеру, красной, а при убийстве стала серой.

Так это штатный механизм ПДА. Надо только тег level_spot/mini_spot в xml конфиге проверить/сделать.

Цитата(Pavel_Blend @ 10.09.2020, 12:23) *
И чтобы можно было скрывать метки по типу: аномалии, тайники, трупы, физ. объекты и т. д.

Для этого нужно написать UI, в котором добавлять/удалять метки по типу объекта. Скрывать нельзя, только если экспортировать из движка получение CUIStatic метки.

Цитата(RayTwitty @ 07.09.2020, 21:20) *
В ТЧ без правок движка никак. Исходя из первой моей цитаты, тебе потребуется написать экспорт движковых функций в Lua, после чего написать на основе оконной системы сталкера весь интерфейс. Задача весьма нетривиальная и не на пару часов.

Вот кстати чувак сделал консольные команды, к которым можно привязаться в интерфейсе biggrin.gif
https://www.gameru.net/forum/index.php?s=&showtopic=23443&view=findpost&p=1680713
Правда команд мало, и вообще это нужно было бы сделать через экспорт методов, но уж как есть.

Автор: Pavel_Blend 13.09.2020, 13:01

RayTwitty, попробовал редактор погоды. Трудновато редактировать. Хотелось бы иметь ползунки, чтобы плавно менять цвета. Ну или чтобы были горячие клавиши. Например, стрелки (вниз-вверх - листать параметры, влево-вправо - менять значения параметров). И ещё трудно угадать цвет солнца. Всё таки без игрового редактора удобнее тем, что можно загрузить в фотошоп текстуру неба и пипеткой скопировать цвет солнца. А потом пропорционально его увеличить или уменьшить.

А что ещё интересного можно сделать с помощью скриптов, кроме проставления меток?

И вопрос: я проставил метки на всех сталкеров и удалил респавн. Зачистил локации от врагов, но не от всех. Остались монолитовцы, к примеру. Они видны на карте, но их там нет. И монстры. Монолитовцы в припяти возле гаражей у костра. Они не спавнятся. Не выполнено определённое условие для их спавна. В userdata у них прописано это:

CODE
[smart_terrains]
none = true

[logic]
active = kamp1
combat_ignore = combat_ignore

;on_signal = arrived | camper2 %+pri_wave1_side_start%

[kamp1]
center_point = pri_sideway_left_kamp

[combat_ignore]


Как заспавнить с помощью скриптов объекты, которые уже есть, но не заспавнены (как монолитовцы).

https://images.gameru.net/image/a2a1f2326979e8c.jpg.html

Автор: AndreySol 30.09.2020, 17:06

Цитата
А что ещё интересного можно сделать с помощью скриптов, кроме проставления меток?

Ну так весь сюжет в общем-то скриптами строится. Вся логика объектов в конечном счете разворачивается в скрипты(xr_logic.script и все схемы поведения), все гулаги и их работы(xr_gulag.script). Спавн объектов, всякие UI-окна с различным функционалом.

Автор: RayTwitty 11.12.2020, 02:18

Наткнулся на интересный прикол с вещественным типом в Lua. Есть два листинга:

1) Здесь к одному числу прибавляется другое и в результате получается 0.75. После чего я выполняю сравнение с константой 0.75, которое разумеется проходит (YES).

Код
local value = 0.25

value = value + 0.5

print(value) --> 0.75

if value <= 0.75 then
    print("YES")
else
    print("NO")
end

2) По сути тоже самое, только довожу число до 0.75 за несколько шагов. Весь цимес заключается в том, что сравнение с константой 0.75 не проходит (NO)!
Код
local value = 0.25

for i = 1, 10 do
    value = value + 0.05
end

print(value) --> 0.75

if value <= 0.75 then
    print("YES")
else
    print("NO")
end

Если в Си у меня бы вопросов не возникло, то тут получается довольно неожиданно (всегда думал, что Lua пытается автоматом привести точность, что видно в первом листинге). В игре из-за этого не проходит сравнение по достижению числа верхней границы (меняю прозрачность и она не может дойти до 100%). Я так понимаю, это особенности внутренних расчетов Lua и на каком-то этапе там все-таки записывается в конец числа некий мусор? Получается, сравнивать надо с эпсилоном (+0.001 например) или вручную обрезать число до сотых?

P.S. опытным путем выяснил, что сравнение перестает работать уже на втором шаге:

Код
local value = 0.7
value = value + 0.05
print(value) --> 0.75
if value <= 0.75 then print("YES") else print("NO") end --> YES


Код
local value = 0.65
value = value + 0.05
value = value + 0.05
print(value) --> 0.75
if value <= 0.75 then print("YES") else print("NO") end --> NO


P.S2. соорудил такую дичь z_lol1.gif
Код
tonumber(tostring(value)) <= 0.75

работает отлично в обоих случаях.

P.S3. оказывается в Питоне есть целый класс для таких нужд:
https://www.bestprog.net/ru/2019/10/18/python-numbers-with-fixed-precision-class-decimal-ru/#q03
поэтому функция
Код
function normalize_decimal(n)
    return tonumber(tostring(n))
end

уже не так сильно похожа на дичь... Возможно в питонском классе внутри происходит тоже самое.

Автор: 1001v 11.12.2020, 03:02

RayTwitty, https://0.30000000000000004.com/

Автор: RayTwitty 11.12.2020, 05:33

Цитата(RayTwitty @ 11.12.2020, 02:18) *
работает отлично в обоих случаях.

А вот в стулкере в отличии от консольной Луа почему-то не сработало.

Поэтому пришлось расчехлить функцию округления с заданной точностью и вручную указывать количество знаков:
Код
function math.round(n, exactness)
    return tonumber(string.format("%."..(exactness or 0).."f", n))
end

local value = 0.65
value = value + 0.05
value = value + 0.05
print(value) --> 0.75
if math.round(value, 2) <= 0.75 then print("YES") else print("NO") end --> YES

pardon.gif

Автор: abramcumner 11.12.2020, 13:14

Цитата(RayTwitty @ 11.12.2020, 05:33) *
А вот в стулкере в отличии от консольной Луа почему-то не сработало.

Потому что это дичь и не должно работать. Попробуй свою функцию не на 0.75, а 0.8, например.
Почитай ссылку, которую дали.

Цитата
math.round(value, 2) <= 0.75

Можно нормально же записать в виде value < 0.75 + eps, где eps ты выбрал 0.01.

Зачем тебе вообще проверять на равенство?

Цитата
Возможно в питонском классе внутри происходит тоже самое.

Питоновский класс реализует арифметику на числах с фиксированной точкой. Основан на https://github.com/python/cpython/tree/e42b705188271da108de42b55d9344642170aa2b/Modules/_decimal. Можно затащить в луа и будет, как в питоне smile.gif

Автор: RayTwitty 11.12.2020, 23:18

Цитата(abramcumner @ 11.12.2020, 13:14) *
Можно нормально же записать в виде value < 0.75 + eps, где eps ты выбрал 0.01.

В реальном коде условие сложнее, есть еще нижняя граница, где нужно уже отнимать eps. В целом, fsimilar из движка ровно это и делает, только нужно изменить функцию на предмет сравнения <= или >=.

Цитата
value < 0.75

У меня шаг 0.05, с таким условием застопорится на 0.7. Можно в константе указать заранее больше, но эта константа может меняться в дальнейшем и не хотелось бы подразумевать в ней некоторые условия и подводные камни.

Цитата(abramcumner @ 11.12.2020, 13:14) *
Потому что это дичь и не должно работать.

Да, я об этом сразу и написал) Просто меня навело на мысль, что стандартный print выводит число с правильной точностью и возможно дело в банальном переводе в строку. Исходники не смотрел, быстрее было в консоли проверить на практике. Выходит, что нет и там скорее всего какой-нибудь format как у меня в round-функции.

Цитата(abramcumner @ 11.12.2020, 13:14) *
Почитай ссылку, которую дали.

Я на основе этой ссылки и других, которые сам нашел, последний пост и написал. Ранее я уже писал про eps, это первое что я и сделал - прибавил и отнял 0.00001.
Вопрос был даже не в этом скорее, а почему в Луа только со второй операции начинает портиться точность.

Автор: abramcumner 12.12.2020, 02:12

Цитата(RayTwitty @ 11.12.2020, 23:18) *
Ранее я уже писал про eps, это первое что я и сделал - прибавил и отнял 0.00001.
Вопрос был даже не в этом скорее, а почему в Луа только со второй операции начинает портиться точность.

Ни число 0.7, ни число 0.05 не могут быть представлены в формате ieee754. Вместо них берутся ближайшие значения. Условно 0.70000000001 и 0.04999999999. Так получается, что в сумме они дают 0.75. А если к 0.650000000001 прибавить два раза по 0.04999999999, то 0.75 не получится.
Точность вычислений никуда не девается, она ровно такая же точная

Цитата
У меня шаг 0.05, с таким условием застопорится на 0.7.

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

Автор: RayTwitty 12.12.2020, 03:42

Цитата(abramcumner @ 12.12.2020, 02:12) *
Если работает через преобразование в строку, то и с эпсилоном в условиях должен работать.

А не прокатит с эпсилоном в моем случае. Но по другой причине: при изменении прозрачности, у меня вот эта погрешность с каждым шагом увеличивается и если погонять туда-сюда получается лютое смещение - не тысячные, а уже десятые. Я правда не совсем уверен, что это вина чисто Луа, возможно арифметика в сталкерском методе. У меня новый метод для оконных классов, который меняет прозрачность - по сути тот же стандартный SetColor, только устанавливает альфу 0..1 (умножается на 255). При получении соответственно делится. Сама прозрачность устанавливается v:SetOpacity(v:GetOpacity() + step), видимо здесь накапливается погрешность.
Всё это удалось решить с помощью math.round на каждом шаге (заодно, оно же решило вопрос при сравнении с границами).

Если делать совсем по красоте, то надо тащить питоновский класс))

Автор: abramcumner 12.12.2020, 15:27

Цитата(RayTwitty @ 12.12.2020, 03:42) *
Сама прозрачность устанавливается v:SetOpacity(v:GetOpacity() + step), видимо здесь накапливается погрешность.

Ну пусть здесь "копится погрешность", но по-прежнему непонятно в чем проблема. Похоже ты делаешь какое-то анимирование(типа проявляешь окно). Пусть у тебя на каком-то шаге(хотя по расчетам должно было сработать) не сработало условие value >= 0.75, потому что value = 0.7499999, ну так сработает на следующем. Будет 0.799999999. Это так принципиально?

Или можно делать по шагам. Посчитал, что прозрачность нужно изменить за 5 итераций, ну и сделал 5 итераций. В конце можно установить прозрачность на то значение, которое требуется.

Автор: RayTwitty 12.12.2020, 16:41

Цитата(abramcumner @ 12.12.2020, 15:27) *
Ну пусть здесь "копится погрешность", но по-прежнему непонятно в чем проблема.

Было две разных проблемы:
1) Сравнение с пределом (константой 0.75). Лечится эпсилоном к константе или math.round к value.
2) Проблема с прозрачностью, выше пост. Скорее всего внутридвижковая проблема сталкера, лечится math.round на каждом шаге.

Цитата(abramcumner @ 12.12.2020, 15:27) *
Или можно делать по шагам.

По шагам, по сути, я тоже делал но там именно накапливается погрешность. К примеру первые 10 раз получается от 0.25 до 0.74, потом вернулись на 10 назад, получили не 0.25, а уже 0.24 и т.д. Так нижний предел я легко сместил до 0.1 вообще biggrin.gif Видимо где-то, что-то округляется, в Луа или в движке при делении/умножении хз. math.round корректировка на каждом шаге помогла.

А могут быть потери при переводе float -> u32? У меня прозрачность float от 0 до 1, а альфа текстуры задается целым числом от 0 до 255:
alpha = u32(opacity*255.f)
соответственно геттер обратно преобразует u32 -> float.
opacity = float(alpha)/255.f

Автор: abramcumner 14.12.2020, 22:58

Цитата(RayTwitty @ 12.12.2020, 16:41) *
А могут быть потери при переводе float -> u32? У меня прозрачность float от 0 до 1, а альфа текстуры задается целым числом от 0 до 255:
alpha = u32(opacity*255.f)
соответственно геттер обратно преобразует u32 -> float.
opacity = float(alpha)/255.f

Да, конечно. К тому же здесь ты переводишь не в u32, а в u8 по сути.

Автор: RayTwitty 14.12.2020, 23:29

abramcumner, исправить никак нельзя? Или только переписывать весь код цвета на один формат?

Автор: abramcumner 14.12.2020, 23:33

Вот так в цикле не писать "v:SetOpacity(v:GetOpacity() + step)" и все. В начале сделать
local opacity = v:GetOpacity()
и работать уже с переменной opacity.

Автор: RayTwitty 14.12.2020, 23:55

abramcumner, идею понял, только в моем случае все несколько сложнее - окон (статиков) куда больше чем один, у базового окна куча дочерних, для которых я пропорционально тоже меняю прозрачность. В этом случае, придется в таблице хранить текущую прозрачность для каждого из них. В целом, пока выглядит более хлопотнее чем:

Код
local normalize_opacity = function(opacity)
    return math.round(opacity, 2)
end

for k, v in pairs(windows_collection) do
    v:SetOpacity(normalize_opacity(v:GetOpacity() + step))
end

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

Автор: abramcumner 15.12.2020, 12:23

Цитата(RayTwitty @ 14.12.2020, 23:55) *
Но если с типами в движке ничего замутить нельзя (и без переписывания целиком управления цветом), тогда ладно.

Можно перевести SetOpacity/GetOpacity на работу с диапазоном 0-255, а не 0..1. Тогда вообще все должно круто работать.

Автор: RayTwitty 10.01.2021, 02:00

Есть функция clamp, которая держит число в рамках диапазона. Стандартная функция и много где используется, в движке сталкера, в вебе (особенно в css) и т.д.

Код
function clamp(n, min, max)
    return n < min and min or n > max and max or n
end


Есть еще такая функция - по сути тоже самое, что и предыдущее, только если n больше максимального, то возвращается минимальное и наоборот. Для простоты обозвал ее iclamp (inverted clamp). У меня часто используется в разных списках, прокрутках значений, переключении полей TABом и т.д.
Код
function iclamp(n, min, max)
    return min + (n - min) % (max - min + 1)
end

Вопрос - может быть у последней функции есть какое-то общепринятое название? Не сильно важно конечно, но мб кто-то в курсе. Пока оставлю как есть.

Автор: abramcumner 10.01.2021, 03:18

https://en.wikipedia.org/wiki/Modulo_operation#Modulo_with_offset biggrin.gif

Цитата
The modulo with offset a modd n is implemented in Mathematica as[16] Mod[a, n, d].

Думаю и для луа сойдет math.fmod с тремя аргументами.

Автор: RayTwitty 11.01.2021, 01:15

abramcumner, а там разве не со смещением? https://en.wikipedia.org/wiki/Wrapping_(graphics)? В моем случае, при превышении max всегда будет на выходе min, то есть по смыслу (применения) функция как раз ближе к clamp-у.

Вот кстати wrap, переписанный с википедии под луа, с включением мин/макса:

Код
function wrap(x, min, max)
    x = x - math.floor((x - min) / (max - min + 1)) * (max - min + 1)
    --[[if x < 0 then
        x = x + max - min
    end]]
    return x
end

PS условие с проверкой на ноль можно выпилить по идее.

Автор: abramcumner 11.01.2021, 02:14

RayTwitty, со смещением. В твоем iclamp по идее тоже превышение прибавляется к min.
На мой взгляд все три функции делают одно и то же. Название wrap лучше и привычнее.

Автор: RayTwitty 11.01.2021, 02:42

Цитата(abramcumner @ 11.01.2021, 02:14) *
В твоем iclamp по идее тоже превышение прибавляется к min.

Нет, при превышении max результат будет равен min, при принижении(? biggrin.gif ) min результат будет равен max. wrap тоже самое, только учитывает смещение.

В общем я понял, что в принципе, можно называть как угодно biggrin.gif Видимо мой случай часто делают просто условиями по месту и не парятся с отдельными функциями.

Автор: RayTwitty 12.01.2021, 22:54

Следующий код проигрывает звук в голове актора:

Код
sound_object("zvuk"):play_no_feedback(db.actor, sound_object.s2d, 0, vector():set(0,0,0), 1.0)

меня глючит или если указать вектор vector():set(0,0,1)
Код
sound_object("zvuk"):play_no_feedback(db.actor, sound_object.s2d, 0, vector():set(0,0,1), 1.0)

то звук будет играть как бы чуть на расстоянии?
Может у кого есть хорошие наушники чтобы проверить? Я на колонках разницы вообще не слышу.

На всякий случай: https://xray-engine.org/index.php?title=Класс_sound_object

Автор: abramcumner 13.01.2021, 00:05

Цитата(RayTwitty @ 12.01.2021, 22:54) *
Код
sound_object("zvuk"):play_no_feedback(db.actor, sound_object.s2d, 0, vector():set(0,0,1), 1.0)

то звук будет играть как бы чуть на расстоянии?

sound_object.s2d должен игнорировать настройки расстояния и просто играть, как будто ты звук в медиаплеере слушаешь.

Автор: RayTwitty 14.01.2021, 00:54

Что-то я не выкупаю. Есть строка

Код
"hud_fov 0.55"

Нужно из нее вытащить символы до пробела, то есть в данном случае hud_fov.
Пишу:
Код
print ( string.match("hud_fov 0.55", "^([A-Za-z0-9_]+)%s") )

всё работает. Пишу:
Код
print ( string.match("hud_fov 0.55", "^(%w+)%s") )

не работает. Опытным путем выяснил, что дело в символе нижнего подчеркивания.

Но ведь %w как раз должен соответствовать классу [A-Za-z0-9_] ?

https://duckduckgo.com/?q=regexp+cheat+sheet&t=ffab&iax=cheatsheet&ia=cheatsheet

Автор: atanda 14.01.2021, 10:45

Ну, на сколько я знаю луа использует не регекспы, а паттерны, которые выглядят похожими, но соответствуют различным входным данным. http://lua-users.org/wiki/PatternsTutorial

Цитата(RayTwitty @ 14.01.2021, 00:54) *
Но ведь %w как раз должен соответствовать классу [A-Za-z0-9_] ?

нет. https://www.lua.org/manual/5.3/manual.html#6.4.1

Твой код следует написать так
Код
string.match("hud_fov 0.55", "^([%w_]+)")


Может быть можно сделать проще - не знаю, я не силён в паттернах, да и на луа давно не кодил.

Автор: RayTwitty 15.01.2021, 01:27

Цитата(atanda @ 14.01.2021, 10:45) *
Ну, на сколько я знаю луа использует не регекспы, а паттерны, которые выглядят похожими, но соответствуют различным входным данным

Да, в луа %w не содержит нижнее подчеркивание.
Цитата
For example, [%w_] (or [_%w]) represents all alphanumeric characters plus the underscore.

Подразумевается, мы сами как бы группу(класс) расширяем. По работе в основном сталкиваюсь с js и питоном, там по стандарту андескор в \w есть. Спасибо за наводку.

Автор: Пчел 3д 24.01.2021, 14:01

Добрый день, подскажите пожалуйста, как прописать скрипт на дверь в сталкер зов припяти, чтоб дверь открывалась нажатием клавиши "F" (использовать). Скрипт двери я прописал, но дверь открывается только в одну сторону и только тогда, когда актер в нее упирается. А хотелось бы как в игре, чтоб выскочило сообщение (открыть дверь - нажмите F)

Автор: Билдомассон 24.01.2021, 15:29

Цитата(Пчел 3д @ 24.01.2021, 14:01) *
Добрый день, подскажите пожалуйста, как прописать скрипт на дверь в сталкер зов припяти, чтоб дверь открывалась нажатием клавиши "F" (использовать). Скрипт двери я прописал, но дверь открывается только в одну сторону и только тогда, когда актер в нее упирается. А хотелось бы как в игре, чтоб выскочило сообщение (открыть дверь - нажмите F)

скопируй логику какой-нибудь из labx8.level, он по-моему идет вместе с сдк 0.7.
ну или вот взял логику от рандомной двери:
CODE
[collide]
ignore_static

[logic]
active = ph_door@close

[ph_door@close]
locked = false
closed = true
snd_open_start = trader_door_open_start
snd_close_start = trader_door_close_start
snd_close_stop = trader_door_close_stop
on_use = ph_door@open

[ph_door@open]
locked = false
closed = false
snd_open_start = trader_door_open_start
snd_close_start = trader_door_close_start
snd_close_stop = trader_door_close_stop
on_use = ph_door@close

Автор: Пчел 3д 28.01.2021, 12:35

Цитата(Билдомассон @ 24.01.2021, 15:29) *
Цитата(Пчел 3д @ 24.01.2021, 14:01) *
Добрый день, подскажите пожалуйста, как прописать скрипт на дверь в сталкер зов припяти, чтоб дверь открывалась нажатием клавиши "F" (использовать). Скрипт двери я прописал, но дверь открывается только в одну сторону и только тогда, когда актер в нее упирается. А хотелось бы как в игре, чтоб выскочило сообщение (открыть дверь - нажмите F)

скопируй логику какой-нибудь из labx8.level, он по-моему идет вместе с сдк 0.7.
ну или вот взял логику от рандомной двери:
CODE
[collide]
ignore_static

[logic]
active = ph_door@close

[ph_door@close]
locked = false
closed = true
snd_open_start = trader_door_open_start
snd_close_start = trader_door_close_start
snd_close_stop = trader_door_close_stop
on_use = ph_door@open

[ph_door@open]
locked = false
closed = false
snd_open_start = trader_door_open_start
snd_close_start = trader_door_close_start
snd_close_stop = trader_door_close_stop
on_use = ph_door@close



Спасибо, все получилось.

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)