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

Помощь тем кто хочет знать больше о игре и модах

Если у вас появились вопросы по модостроению в игре S.T.A.L.K.E.R. Задавайте их в этой теме - умные головы,
модосторители и просто разбирающиеся в программировании люди вам ответят.


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

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

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

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

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

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

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

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

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

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

[/cut]


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


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


Посты, для которых есть свои категории, из этой темы будут удаляться или перемещаться в соответсвующую тему. Персональных извещений в ЛС о переносе\удалении поста не будет, ищите сами. Учитывайте, что в системах Ucoz тема не обновляется в статистике при переносе поста.
Посты, написанные здесь-же после переноса, будут расцениваться как кросспостинг, со всеми вытекающими


[cut noguest=Первый юбилей нашей темы]

Здравствуйте господа модостроители, и все так или иначе причастные к этому.
Нашей теме исполнился 1 год.
От души поздравляю Всех Вас дорогие друзья, творческих успехов.
Хочу так же выразить отдельную благодарность denis2000 и ХОВАН.

tracker 23.06.11



[/cut]
 
alex_xp_77Дата: Чт, 12.06.2014, 16:37 | Сообщение # 436
Научный сотрудник.
Ученые сталкеры
Сообщений: 242
Награды: 6
Репутация: [ 41 ]

Добрый день всей планете Сергиус!! Извиняюсь за не полный вопрос, вчера вымотался, на работе и с музыкой в игре, вот файлы которые я менял
1) редактирование конфига ui_mm_main тут : http://SSMaker.ru/85adffac/
2) папка sounds с ogg треками тут http://SSMaker.ru/960c12b3/

Больше ничего не правил!!
И еще, кто разбирается, как сделать микс исполнителей, помогите , точнее подскажите как этого добиться??
Был бы очень признателен!!




Сообщение отредактировал alex_xp_77 - Чт, 12.06.2014, 18:12
 
denis2000Дата: Чт, 12.06.2014, 21:37 | Сообщение # 437
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

Цитата alex_xp_77 ()
Больше ничего не правил!!

Этого вполне достаточно. Смотри в конфиге указал играть файл music\wasteland2 или файл music\wasteland3:
Код
<menu_music>music\wasteland2</menu_music>
   <menu_music>music\wasteland3</menu_music>

Теперь собственно в папке должны быть ЧЕТЫРЕ файла:
Код
music\wasteland2_l
music\wasteland2_r
music\wasteland3_l
music\wasteland3_r

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


"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..."
(Чугунный всадник)
 
alex_xp_77Дата: Чт, 12.06.2014, 22:22 | Сообщение # 438
Научный сотрудник.
Ученые сталкеры
Сообщений: 242
Награды: 6
Репутация: [ 41 ]

Денис не подскажете как же мне сделать микс, то есть 3, и более композиций??Как напримере солянки??Хотя думаю сам погяжу как там, так и будет у меня )) Весьма благодарен!!
Что то у меня никак не получается внедрить вообще никакую музыку один лишь лог :
[cut][error]Expression : wave&&wave->length()
[error]Function : CSoundRender_Source::LoadWave
[error]File : E:\stalker\patch_1_0004\xrSound\SoundRender_Source_loader.cpp
[error]Line : 65
[error]Description : Can't open wave file:
[error]Arguments : d:\сталкер тени чернобыля для теста\s.t.a.l.k.e.r. - shadow of chernobyl\gamedata\sounds\music\wasteland_3_l.ogg[/cut]

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

Просто вчера выбирались файлы music\wasteland2. А в случае выбора music\wasteland3 вылет из-за отсутствия файла. denis2000




Сообщение отредактировал alex_xp_77 - Чт, 12.06.2014, 23:21
 
a4927860Дата: Пт, 13.06.2014, 13:21 | Сообщение # 439
Новичок
Пользователи
Сообщений: 81
Награды: 0
Репутация: [ 22 ]

denis2000, Спасибо большое за подробные ответы.

Сделал итем запускающий скрипт

Нужно:
1) найти нпс на которого наведен курсор (прицел) если он не дальше h
2) найти всех нпс в радиусе r от нпс к которому идет первоначальное действие
Собственно вопрос - как их указывать в скриптах (и первого и последующих)?

У вас в аномальном костюме стоит проверка на монстре в файле bind_monster однако на сколько я понимаю это идет запуск скрипта, у меня же скрипт запускает сам игрок по заранее не известному объекту (опять таки в уроках я этого не нашел - хотя может просто проморгал)

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

update
кажется нашел кусок отвечающий за поиск объекта, но чтото уж больно он адский 46 строк на поиск и проверку предмета, может таки можно по легче как то сделать?
Код

function ggun_binder:capture(cone,dist)
  if not cone then cone = 0.999 end -- на деле - cos угла захвата на дистанции dist
  if not dist then dist = 13 end -- дистанция захвата
  local back = 2 --  смещение конуса захвата за спину актора.
  dist = dist + back
  local capt_id = nil
  local capt_obj = nil
  local dist_min = 1.2*dist
  local cone_max = 0.8*cone
  for id,v in pairs (ggunable) do
   local cobj = level.object_by_id(id)
   if cobj and cobj:get_physics_shell() then
    local rvec = cobj:center():sub(device().cam_pos:mad(device().cam_dir, -2.0))
    local r = rvec:magnitude()
    if r < 1.1*dist and r > back + 1 then -- в радиусе захвата, но перед актором
     local proj = rvec:dotproduct(device().cam_dir)
     local cos_a = proj/r
     if cos_a > cone then -- попадает в конус прицеливания
      if cos_a >= cone_max and r < dist_min then  
      -- если предмет хотя бы не дальше от оси прицеливания, чем предыдущий выбранный,  
      -- но ближе по расстоянию, то выбираем его
       dist_min = r
       cone_max = cos_a
       capt_id = id
       capt_obj = cobj
      end
     end
    end
   else
    ggunable[id] = nil
   end
  end
  if capt_id and capt_obj then -- если выбрали подходящий объект для захвата
   self.target = capt_obj -- запомнили
   self.target_id = capt_id -- запомнили id
   self.capture_nomove_counter = 3
   capt_obj:set_const_force(vector():set(0,1,0), capt_obj:mass()*19.62, 65535*65535)
  else
   if not self.sound_nohold:playing() then
    if not self.block_nohold then
     self.sound_nohold:play_at_pos(db.actor, self.gun_end_pos)
     self.block_nohold = true
    end
   end
  end
end


Сообщение отредактировал a4927860 - Пт, 13.06.2014, 16:43
 
denis2000Дата: Пт, 13.06.2014, 19:46 | Сообщение # 440
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

a4927860, Я делал Локатор объектов с отображением меток на «забрале», там НПС находящиеся на небольшой дистанции в поле зрения помечаются метками на экране. В принципе если метка ложиться в определенное пространство экрана, то можно считать что НПС в секторе прицела.
Затем итерируясь по таблице НПС можно выбрать тех которые находятся от прицельного на расстоянии не более заданного.

Цитата a4927860 ()
можно по легче как то сделать?

Автору скрипта виднее. Хотите упростить - пожалуйста, упрощайте.


"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..."
(Чугунный всадник)
 
a4927860Дата: Пт, 13.06.2014, 19:58 | Сообщение # 441
Новичок
Пользователи
Сообщений: 81
Награды: 0
Репутация: [ 22 ]

denis2000,
Имелось ввиду - нет ли простого универсального решения согласно которому вычисляется таргет?
например - совпадение с перекрестием прицела?

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

Цитата a4927860 ()
например - совпадение с перекрестием прицела?

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


"Он ловко выхватил из-под себя табуретку и очень метко и сильно бросил ее в докладчика..."
(Чугунный всадник)
 
a4927860Дата: Пт, 13.06.2014, 21:16 | Сообщение # 443
Новичок
Пользователи
Сообщений: 81
Награды: 0
Репутация: [ 22 ]

Цитата denis2000 ()
придется интенсивно работать скриптам


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

Спасибо за советы, надеюсь не сильно отвлек =)

Добавлено (13.06.2014, 21:16)
---------------------------------------------
решил разбить задачу (которая оказалась значительно сложнее чем думалось)
допустим на секунду что я нашел объект который мне нужен - как определить что этот объект - нпс?

 
denis2000Дата: Пт, 13.06.2014, 21:22 | Сообщение # 444
Полевой исследователь
Ученые сталкеры
Сообщений: 2399
Награды: 35
Репутация: [ 1918 ]

Цитата a4927860 ()
как определить что этот объект - нпс?

Глобальная функция IsStalker должна вернуть true.
Код
if IsStalker(object) then ... end


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

a4927860, Скрипт, который передает объект в необходимую модмейкеру функцию, давно написан. Используется при стрельбе из БТР. Там сделано так, куда поворачивается камера ГГ ( прицел статичен, поворачивается именно камера и создаётся иллюзия наведения прицела), туда же и поворачивается пушка БТР.
Скрипт универсальный и может использоваться, как для НПС ( Сталкеры и монстры ), так и для других объектов ( БТРы, вертушки). Главное, чтобы объект биндился.
Покажу на примере Сталкера.

[cut noguest]

В файле xr_motivator.script в методе UPDATE пишите.

Код
if self.object:alive()  then
      if actor_target(self.object) then
         self.target = self.object:id()
      end
end


В самый конец файла добавляете две функции

Код
function actor_target(object)
      if db.actor and object then
       local dangerang = 1/object:position():distance_to(device().cam_pos)
       local ang = horz_angle(device().cam_dir, object:position():sub(device().cam_pos))
       local tgt = ang > -dangerang and ang < dangerang
       if tgt then return true else return false end
      end
      return false
end

function horz_angle(vec1,vec2)
       local x = vec2.x*vec1.x+vec2.z*vec1.z
       local y = -vec2.z*vec1.x+vec2.x*vec1.z
       return math.atan2(y,x)
end


Теперь ID объекта, на который наведено перекрестие, хранится в переменной self.target
Можете передать её в вашу функцию или разобраться с ней нам месте.
[/cut]


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


Сообщение отредактировал makdm - Пт, 13.06.2014, 21:53
 
a4927860Дата: Сб, 14.06.2014, 00:52 | Сообщение # 446
Новичок
Пользователи
Сообщений: 81
Награды: 0
Репутация: [ 22 ]

makdm, Спасибо!
п.с. еще раз посмотрел уроки на тему возвращения к жизни бтр - там такого нет

Речь видимо идет о моде Время Альянса ver. 2.0. denis2000

Ох как же грустно мало знать, а отпуск не бесконечный увы...
[cut]
Код

if self.object:alive()  then -- Добавление апдейта для таргета ABILITY
     if actor_target(self.object) then    
      self.target = self.object:id()    
     end    
    end


я поместил в
function motivator_binder:update(delta)

два оставшихся куска - в самый конец файла

в своем я соответственно делаю
Код

    if item_name=="hero_ability_1" then    
     give_object_to_actor("hero_ability_1")
     function kill()
      local oNpc = level.object_by_id(self.target)
       if oNpc and  IsStalker(self.target) and db.actor:id()~= self.target then
        oNpc:kill(oNpc)
       end
     end    
     function dell_kluk_final()
      local se_obj = alife():object("self.target")
       if se_obj then
        alife():release(se_obj, true)
       end
     end
    end    


предмет что характерно выдается - больше ни чего не происходит. хотя хоть один из них но должен вроде сработать...[/cut]
 
makdmДата: Сб, 14.06.2014, 09:43 | Сообщение # 447
Рожденный в СССР
Разработчики
Сообщений: 1294
Награды: 29
Репутация: [ 1909 ]

Цитата a4927860 ()
в своем я соответственно делаю


a4927860, немного не так. Откуда ваша функция знает, что такое self.target ? Для неё значение self.target = nil
Нужно передавать ID в вашу функцию.

if self.object:alive() then -- Добавление апдейта для таргета ABILITY
if actor_target(self.object) then
ИМЯ_ВАШЕГО_ФАЙЛА.ИМЯ_ВАШЕЙ_ФУНКЦИИ( self.object:id() )
end
end

И вот это:

if oNpc and IsStalker(self.target) and db.actor:id()~= self.target then

Раз аргумент передан из биндера, то как oNpc может быть nil? Вы передаёте это из биндера Сталкера, то зачем ещё раз проверять, что это Сталкер? Зачем сравнивать его ID с ID актора? Абсолютно ненужные проверки.


Терпение......
И все получится!
 
a4927860Дата: Сб, 14.06.2014, 17:16 | Сообщение # 448
Новичок
Пользователи
Сообщений: 81
Награды: 0
Репутация: [ 22 ]

Цитата makdm ()
ИМЯ_ВАШЕГО_ФАЙЛА.ИМЯ_ВАШЕЙ_ФУНКЦИИ( self.object:id() )


[cut]
Я по всей видимости чегото основопологающего не понимаю...
[cut]
так?
Код

        if self.object:alive()  then -- Добавление апдейта для таргета ABILITY
         if actor_target(self.object) then        
          Hero_ability.on_use_hero_ability(self.target) = self.object:id()        
         end        
        end


или же я добавляю в свой скрипт local target=xr_motivator.motivator_binder(self.target)?
не работает в любом случае
[/cut]

Добавлено (14.06.2014, 14:19)
---------------------------------------------
мне кажется что я ошибаюсь в каких то мелочах которые просто не вижу исходя из учебников и уроков. Господа если у вас есть возможность связаться со мной и немного времени на объяснение - я буду очень признателен.

Добавлено (14.06.2014, 16:00)
---------------------------------------------
кажется понял...

[cut]
Код

        if self.object:alive()  then -- Добавление апдейта для таргета ABILITY
         if actor_target(self.object) then        
          self.target = self.object:id()
          Hero_ability.on_use(self.target)        
         end        
        end

[/cut]

вот только теперь у меня ругается моя функция на: attempt to index local 'sect' (a number value)
на сколько я понимаю это происходит из за того что изначально функция предназначенна для обработки действий предмета и в ней используются соответствующие параметры.

Добавлено (14.06.2014, 16:39)
---------------------------------------------
я в ступоре.
после того как я вроде обошел предыдущую ошибку выводом функции kill в корень своей функции с последующим обращением к ней из мотиватора она начала ругаться на то что self.target = nil
я добавил условие проверки self.target ~= nil но после этого ругаться стало вообще на мотиватор - xr_motivator.script:354: attempt to index global 'Hero_ability' (a nil value) - из серии куда вы посылаете..
[/cut]

Добавлено (14.06.2014, 17:16)
---------------------------------------------
Вернулся к схеме с одной функцией...

У меня в результвте:
Из мотиватора передается self.target
А из bind_stalker передается (obj)
таким образом они похоже конфликтуют...

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

Как разрулить это?

[cut noguest=собственно мой скрипт ]
Код
function on_use(sect)    
--Переменные    
local actor=db.actor
local item_name=sect:section() -вот тут ругается если давать инф от мотиватора
local actor_pos=db.actor:position()    
local active_slot=db.actor:active_slot()    
local active_item=db.actor:active_item()    
local pistol_in_slot=db.actor:item_in_slot(2)    
local rifle_in_slot=db.actor:item_in_slot(3)    
local outfit_in_slot=db.actor:item_in_slot(7)    
local helm_in_slot=db.actor:item_in_slot(12)    

     if item_name=="hero_ability_1" then    
      give_object_to_actor("hero_ability_1")
--     local oNpc = level.object_by_id(self.target) -- Сейчас отрубил чтобы не вылетало почем зря но здесь должена быть собственно функция выполняющаяся над объектом, для примера взял убийство - его точно не промаргаешь
--     if oNpc then
--      oNpc:kill(oNpc)
--     end
     end    

end

[/cut]


Сообщение отредактировал a4927860 - Сб, 14.06.2014, 19:05
 
alex_xp_77Дата: Сб, 14.06.2014, 18:47 | Сообщение # 449
Научный сотрудник.
Ученые сталкеры
Сообщений: 242
Награды: 6
Репутация: [ 41 ]

Дорого вечера уважаемой публике!! У меня вопрос, много раз задавал, в последний раз все понял, сделал по схеме Дениса2000, но она что то не работает, странно, должна играть музыка но вылетает, что не так делаю, вот скрины настроек!!
Папка music http://SSMaker.ru/dbbccf7f/
папка ui---ui_mm_main http://SSMaker.ru/ed9279dd/
Лог[cut noguest=Читать далее]
! Missing ogg-comment, file: d:\сталкер тени чернобыля для теста\s.t.a.l.k.e.r. - shadow of chernobyl\gamedata\sounds\characters_voice\scenario\video\intro_gsc_wp_r.ogg

FATAL ERROR

[error]Expression : wave&&wave->length()
[error]Function : CSoundRender_Source::LoadWave
[error]File : E:\stalker\patch_1_0004\xrSound\SoundRender_Source_loader.cpp
[error]Line : 65
[error]Description : Can't open wave file:
[error]Arguments : d:\сталкер тени чернобыля для теста\s.t.a.l.k.e.r. - shadow of chernobyl\gamedata\sounds\music\wasteland4_l.ogg][/cut]

Помогите понять что я делаю не так??? Весьма благодарен за любую помощь!!

Файлы музыка именуете неправильно. Прочтите в логе какого файла ждет движек и посмотрите как поименовали вы. denis2000

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

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




Сообщение отредактировал alex_xp_77 - Сб, 14.06.2014, 20:35
 
makdmДата: Сб, 14.06.2014, 20:55 | Сообщение # 450
Рожденный в СССР
Разработчики
Сообщений: 1294
Награды: 29
Репутация: [ 1909 ]

Цитата a4927860 ()
я в ступоре.

a4927860, вам немного почитать основы модинга и ступор пройдёт.
Делаете так, например ГГ наводит перекрестие на НПС и принимает аптечку - НПС помирает.
[cut noguest]
В мотиваторе в методе update пишите

Код
if self.object:alive()  then
       if actor_target( self.object ) then            
          hero_ability.target_on = self.object:id()
       else
            if   hero_ability.target_on ~= nil then
                if hero_ability.target_on == self.object:id()  then
                    hero_ability.target_on = nil
               end
            end
       end            
     end


Теперь сама функция on_use в файле hero_ability.script

Код


target_on = nil

function on_use( sect )        
local item_name=sect:section()     
         if item_name=="medkit" and target_on ~= nil then        
            give_object_to_actor("hero_ability_1")     
            local oNpc = level.object_by_id(target_on)     
           if oNpc then     
              oNpc:kill(oNpc)     
           end     
        end        

end
[/cut]


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


Сообщение отредактировал makdm - Сб, 14.06.2014, 21:07
 
Поиск: