1. hmtoggle_plus1Создаем невидимый костюм

Режим не очень серьёзный. Глаза - глазами, а на слух неписи как собаки, прям! На зверьё прозрачный режим ГГ не действует. Это - пример. Браз что-то сделал, надеюсь лучше, чем у меня.

Создаём пустой файл в \scripts\trans_outfit.script и создаём две функции:

 

function transparent_gg() --назовём её для памяти - "хулиганы зрения лишают!"

local fov1, range1, id, obj_around, alife_obj, dist_act_npc

if db.actor == nil then

return nil

end

--если ГГ голый

if db.actor:item_in_slot(7) == nil then

fov1 = 150

range1 = 80

--если на ГГ одет костюм новичка

elseif db.actor:item_in_slot(7):section() == "novice_outfit" then

fov1 = 1

range1 = 1

--если на ГГ одет другой броник

else

fov1 = 150

range1 = 80

end

--задача предыдущего куска проанализировать, что надето на ГГ и установить

--соответствующие угол обзора и дальность зрения

--

--дальше перебор ВСЕХ объектов в игре по его id

for id = 1, 65534 do

obj_around = level.object_by_id(id) -- создаём онлайн объект

if obj_around ~= nil and IsStalker(obj_around) then --если есть такой и это сталкер

--создаём серверный объект, соответствующий онлайновому

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

--ну, наверное, мало рыл

alife_obj = alife():object(id)

if alife_obj then

--определяем дистанцию между ГГ и неписем

dist_act_npc = db.actor:position():distance_to(alife_obj.position)

end

if dist_act_npc <= 120 then --отличаясь огромным человеколюбием я решил не бросать

--в беде ослеплённых сталкеров и восстанавливать им зрение в кольце 120-150 метров.

--ну жалко их, болезных

if obj_around then - проверка обязательна иначе может быть

--вылет при убийстве вражины

obj_around:set_fov(fov1) --портим неписю угол зрения

obj_around:set_range(range1) --портим неписю дальность зрения

end

else

if obj_around then --если непись в кольце 120-150м восстанавливаем зрение

obj_around:set_fov(150)

obj_around:set_range(80)

end

end

end

end

end

 

--а это стартёр нашей функции "хулиганы зрения лишают!"

--тупой до бесконечности, когда я подоткнулся к таймерам Николая - диалоги начали мелькать.

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

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

--на 50 раз обнуляем глобалку и запускаем "хулиганы зрения лишают!"

 

function timer_trans()

timer_transparent = timer_transparent + 1

if timer_transparent >= 50 then

timer_transparent = 0

transparent_gg()

end

end

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

Далее открываем файл \scripts\_g.script и внем прописываем свою глобалку:

dev_debug = false

sim_debug = false

mus_vol = 0

amb_vol = 0

timer_transparent = 0 --вот она, родная!

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

Ну и последний штрих: подключить моторчик, чтобы пятидесятки считались, и "хулиганы

зрения лишают!" запускалась один раз на 50 апдейтов биндера.

Открываем \scripts\bind_stalker.script

ищем функцию апдейта function actor_binder:update(delta)

и так скромненько пристраиваем ей в хвостик свой доморощенный таймер

pda.fill_sleep_zones()

trans_outfit.timer_trans() -- функция из другого файла вызывается с префиксом имяфайла.

-- загрузка мода(постоянное обновление)

if mod_update() then

sgm_loader.sigerous_mod_main()

end

end

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

Всё в игре находим/обдираем/покупаем костюм новичка и пробуем инвизибл вар!

 

2. hmtoggle_plus1Частота выбросов

открываем файл: scripts\surge_manager.ltx

 

и меням параметры:

 

local START_MIN_SURGE_TIME -------- минимальное время до первого выброса

local START_MAX_SURGE_TIME ------ максимальное время до первого выброса

local MIN_SURGE_TIME -------------------- минимальное время между выбросами

local MAX_SURGE_TIME ------------------ максимальное время между выбросами

 

Формат: ЧЧ*ММ*СС игрового времени

 

3. hmtoggle_plus1Выводим координаты на худ

В файл: \scripts\bind_stalker.script

 

После:

 

function actor_binder:update(delta)

object_binder.update(self, delta)

 

Добавить вот эту строчку:

 

if db.actor then news_manager.send_tip(db.actor,db.actor:game_vertex_id().." "..db.actor:position().x.." "..db.actor:position().y.." "..db.actor:position().z,0,mutant_hunter,10000,nil,"Gvertex X Y Z") end

 

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

 

4. hmtoggle_plus1Скриптеры никогда не делайте так!

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

Надо проверить наличие предмета, и что-то сделать.

Допустим, надо выяснить какой броник надет на ГГ и изменить какие-то параметры.

честно пишем:

 

local outfit_in_slot=db.actor:item_in_slot(7)

if outfit_in_slot~=nil and outfit_in_slot:section_name()=="чегототам" then

 

полагая, что LUA проверит первое условие, и , если ГГ голый не будет проверять второе. Однако LUA честно проверит оба условия, а потом сделает вывод true или false. Вот, а теперь представим, что ГГ голый.

Первое условие nil

Второе условие можно интерпретировать так nil:section() -т.е попытку применить функцию объекта к пустоте. Краш!!! Попытка смешать французское с нижегородским в данном случае приводит к печальным результатам! А как?

 

local outfit_in_slot=db.actor:item_in_slot(7)

if outfit_in_slot~=nil then --если голый валим отсюда, а не узнаём покрой пиджака

if outfit_in_slot:section_name()=="чегототам" then

....................

end

end

 

5. hmtoggle_plus1Где настроить уборку трупов?

В файле: scripts\release_body_manager.script

Строки:

IDLE_AFTER_DEATH = 40000 --через 40 секунд после смерти, труп помечается на удаление

body_max_count = 15 --максимальное количество трупов

 

6. Получаем координаты
hmtoggle_plus1Способ №1

В файле: ui_main_menu.script

 

Ищем следующую функцию:

function main_menu:OnButton_credits_clicked()

 

Заменяем ее содержимое на:

local text

local vid

local gvid

local a = vector()

local text

a = db.actor:position()

vid = db.actor:level_vertex_id()

gvid = db.actor:game_vertex_id()

text = "Позиция:\\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)

 

7. hmtoggle_plus1Проверяем кол-во денег у ГГ

Функция проверки денег ГГ:

Добавляем в скрипт такую функцию, либо создаем новый скрипт в папке gamedata\scripts\

 

В скобках после math.floor указываем нужное кол-во денег

Также операторы для предпоследней строки:

==

равно

>=

больше или равно

<=

меньше или равно

~=

Не равно

<

Меньше

>

больше

 

function Имя_Функции()

 local money = math.floor(Кол-во денег)

 return db.actor:money()ОПЕРАТОРmoney

end

 

Использование прекондишна:

 

<dialog id="Dialog_1"> - id диалога

   <precondition>ИМЯ_Скрипта.ИМЯ_Функции</precondition> - проверка денег

       <phrase_list> - ветки диалога

           <phrase id="1">

                       ...

           </phrase>

       </phrase_list>

   </dialog>

 

8. hmtoggle_plus1Какая функция отвечает за цены проводников по локации?

файл: scripts\travel_manager.script

 

Функция:

function get_price_by_distance(distance)

return math.ceil(distance/50)*50

end

 

distance - расстояние

50 - коэфициент

 

9. hmtoggle_plus1Добавляем отметку перехода между локациями

Создаем скрипт, например scripts\new_script.script

 

В него вставляем следующие функции:

 

-- Тут мы проверяем, получали ли мы раньше инфопоршень info_new_level

-- И если мы его не получали, то нам отмечается переход, и выдается этот инфопоршень

-- Нужно это для того, чтобы мы получали Отметку только один раз

function level_changer()

   if not has_alife_info("info_new_level") then

      otmetit_perehod()

      db.actor:give_info_portion("info_new_level")

   end

end

 

function otmetit_perehod()

for i=1,65534 do

   local obj = alife():object(i)

   if obj then

       if obj:name() == "Название 1-го левел чэнджера" then

           level.map_add_object_spot_ser(obj.id,"level_changer_up","Подпись 1")

       elseif obj:name() == "Название 2-го левел чэнджера" then

           level.map_add_object_spot_ser(obj.id,"level_changer_up","Подпись 2")

      --elseif .....

       end

   end

end

 

Название берётся из поля name level_changer'а в all.spawn;

Подпись - например, "На Кордон".

Далее, в bind_stalker.script после function actor_binder:update(delta) надо написать new_script.level_changer()

и в файле info_portions.xml зарегистрировать наш инфопоршень, добавив строку

<info_portion id="info_new_level"></info_portion>

 

10. Убираем персонажа

hmtoggle_plus1Способ №1

function del_nik()

local id, obj, kto

for id=0, 65535 do

obj = alife():object(id)--вот здесь

if obj then

if IsStalker(obj) then

kto = obj:section_name()

if (kto == "nikitka") then

alife():release(alife():object(id), true)

end

end

end

end

news_manager.send_tip(db.actor,"Персонаж удален",0,mutant_hunter,10000,nil,"Тест инфо")

end

hmtoggle_plus1Способ №2

local npc_id = get_story_object_id("nikitka")

if npc_id ~= nil then

alife():release(alife():object(npc_id), true)

end

 

11. hmtoggle_plus1Как сделать чтобы бандиты водили тебя по локации?

В файле scripts\travel_manager.script

Ищем:

 

function uni_traveler_precond(actor, npc)

local squad = get_object_squad(npc)

if squad ~= nil and squad:commander_id() ~= npc:id() then

return false

end

if npc:character_community() == "bandit" then

return false

end

if level.name() == "jupiter_underground" then

return false

end

 

Закомментируем проверку, что бандиты не могут водить, вот так:

 

function uni_traveler_precond(actor, npc)

local squad = get_object_squad(npc)

if squad ~= nil and squad:commander_id() ~= npc:id() then

return false

end

--теперь бандиты тоже водят по маршруту

--if npc:character_community() == "bandit" then

--return false

--end

if level.name() == "jupiter_underground" then

return false

end

 

12. hmtoggle_plus1Какой файл отвечает за статистику?

scripts\xr_statistic.script

 

13. hmtoggle_plus1Проверяем наличие предмета в слоте

Функция db.actor:item_in_slot(<номер слота>)

 

Номер слота

Описание

2

Пистолеты (цифра 2 на клавиатуре)

3

Автоматы (цифра 3 на клавиатуре)

7

Бронежилет

9

Детектор

12

Шлем

Например:

проверка db.actor:item_in_slot(9):section() == "detector_scientific"

выдаст "true" если детектор Велес в слоте детекторa (9)

 

14. hmtoggle_plus1Как проверить из скрипта наличие инфопоршня?

1. на F6 навешиваешь обработчик

db.actor:give_info_portion("твой_инфо")

2. на F7 навешиваешь обработчик

db.actor:disable_info_portion("твой_инфо")

8. на F8 навешиваешь обработчик

if db.actor:has_info("твой_инфо") then

news_manager.send_tip(db.actor,"инфо в игре",0,mutant_hunter,10000,nil,"Тест инфо")

end

if db.actor:dont_has_info("твой_инфо") then

news_manager.send_tip(db.actor,"инфо нет",0,mutant_hunter,10000,nil,"Тест инфо")

end

 

В игре: [ESC]=>[F6]=>[ESC]=>[ESC]=>[F7]=>[ESC]=>[ESC]=>[F8]=>[ESC]  и смотри чего тебе новости вякают.

 

15. hmtoggle_plus1Функция на отключение инфопоршня

db.actor:disable_info_portion("Имя_Infoportion")

 

16. hmtoggle_plus1Выдаем инфопоршень при взятии предмета

файл bind_stalker.script

 

function actor_binder:update(delta)

   object_binder.update(self, delta)

function Имя_функции()

if db.actor:object(a) ~= nil then

if a == "ИД_ПРЕДМЕТА" and not db.actor:has_info("Имя_поршня") then

db.actor:give_info_portion("Имя_поршня")

end

end

end

 

17. hmtoggle_plus1Спавн предмета в рюкзак NPC

function spawn_killers_pda()

   local id, npc

   if xr_conditions.is_alive(nil,nil,{"ID_NPC"}) then

       id = "ID_NPC"

       npc = get_story_object_id(id)

       npc = alife():object(npc)

       alife():create("wpn_rpg7", npc.position, npc.level_vertex_id,  npc.game_vertex_id, npc.id)

   end

end

 

18. hmtoggle_plus1Убиваем NPC

function kill()

local oNpc = level.object_by_id(ID_NPC)

if oNpc and db.actor:id()~= ID_NPC then

  oNpc:kill(oNpc)

end

 

19. hmtoggle_plus1Функция проверки нескольких предметов в инвентаре у ГГ

function actor_have_items(first_speaker, second_speaker)

local n=3 -- количество

local count=0

db.actor:iterate_inventory(function (dummy, item) if item:section()=="твой предмет" then count=count+1 end end, nil)

if count>=n then

 return true

else

 return false

end

end

 

20. hmtoggle_plus1Правильное использование Return

Это:

if <логическое выражение> then

  return true

else

  return false

end

 

Надо писать так:

return <логическое выражение>

Если true с false меняются местами, то так:

return not (<логическое выражение>)

 

21. hmtoggle_plus1Проверка: Мертв ли NPC?

local s_npc=alife():object(id) -- получаем по id серверный объект непися

 

if s_npc and s_npc.alive~=nil and not s_npc:alive() then

-- здесь он труп

end

 

Или так:

 

if s_npc and s_npc.health~=nil and s_npc:health()<=0 then

-- здесь он труп

end

 

22. hmtoggle_plus1Изменяем отношение группировки к ГГ

function goodwill_to_stalker()

xr_effects.inc_faction_goodwill_to_actor(db.actor, nil, {"stalker", +3000})

end

 

23. hmtoggle_plus1Запуск эффекта

float add_cam_effector(

string <имя анимации>, -- имя файла *.anm, адресуемого от папки anims

int <идентификатор>, -- произвольное целое число, которое можно использовать для удаления

boolean <зациклить>, -- проигрывать бесконечно

string <коллбек на окончание>) -- имя функции, которая выполнится по окончании

-- действия эффекта. Функция не принимает аргументов и не возвращает значений.

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

-- Функция возвращает некое число, для каждого файла анимации своё. Зачем нужно - не знаю.

float add_cam_effector2(string, number, boolean, string) -- в целом тоже самое,

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

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

void remove_cam_effector(number <идентификатор>) -- убрать эффектор с ранее заданным номером

----

void add_pp_effector(

string <имя постэффекта>, -- имя файла *.ppe, адресуемого от папки anims

int <произвольный идентификатор>, -- для дальнейшего удаления

boolean <зациклить>) -- проигрывать бесконечно

void set_pp_effector_factor(

int <идентификатор>, -- число, ранее заданное при установке эффекта

float <интенсивность>) -- (0, 1) -- интенсивность эффекта

void set_pp_effector_factor(

int <идентификатор>,

float <интенсивность>,

number <скорость изменения>) -- не до конца ясно, но вроде как скорость перехода

-- от текущего состояния к заданному. По какому принципу считается время перехода - непонятно

void remove_pp_effector(int <идентификатор>) -- убрать эффект

---

-- следующие две функции практически не используются. Задействованы незначительно только в ЗП

void add_complex_effector(

string <секция>, -- имя секции в system.ltx, с описанием эффекта

int <идентификатор>)

void remove_complex_effector(int <идентификатор>) -- отмена эффектора

 

24. hmtoggle_plus1Постоянный эффект на локации

if level.name() == <имя уровня> then

   level.add_pp_effector(<имя постэффекта>, <какой-либо номер>, true)

end

 

Имя постэффекта указывать относительно папки anims

 

25. hmtoggle_plus1Телепортируем ГГ

function new_teleport(actor, npc, p)

db.actor:set_actor_position(vector():set(X,Y,Z),GameVertex,LevelVertex) -- Позиция "Куда переместить ГГ"

level.add_pp_effector ("teleport.ppe", 333, false) -- Прокручиваемый эффект из папки anims

end

 

26. Включаем функцию printf

 

hmtoggle_plus1Способ №1

1. Заходим в _g.script и ищем функцию printf(fmt,...)

2. Закоментируйте все что внутри ее

3. Дальше в самый конец добавляем:

 

amk_dbg.log2(fmt)

amk_dbg.log2(string.format(fmt,...))

 

Чтобы получилось:

 

function printf(fmt,...)

--[[

local is_g = 0

local result = fmt

if debug == nil then

log(string.format(fmt,...))

return

end

local info_table = debug.getinfo(2)

local script_name = string.gsub(info_table.short_src, "%.script", "")

script_name = string.gsub(script_name, "gamedata\\scripts\\", "")

if scripts_to_print[script_name] == false then return end

script_name,is_g = string.gsub(script_name, "_g", "")

if is_g == 0 then

result = script_name..":("..info_table.currentline.."):"..fmt

else

result = fmt

end

log(string.format(result,...))

]]

amk_dbg.log2(fmt)

amk_dbg.log2(string.format(fmt,...))

end

 

4.Создаем файл amk_dbg.script и пишем в него:

 

function log(fmt, ...)

local msg = string.format(fmt, ...)

local msg_no_ws = string.gsub(msg, "%s", "_")

get_console():execute("load ~~~dbg:" .. msg_no_ws)

end

 

function log2(msg)

local msg_no_ws = string.gsub(msg, "%s", "_")

get_console():execute("load ~~~dbg:" .. msg_no_ws)

end

 

Все, функция восстановлена. Теперь можно смотреть что же там нам игра пишет

hmtoggle_plus1Способ №2

1. Качаем эту дллку: http://ifolder.ru/21002184

можно кататься в ЗП на машинках
добавлены консольные команды:
ofov - угол обзора игрока
oph_timefactor - скорость течения времени при просчете физики
в ПДА можно добавлять свои разделы. ГГ будет получать инфопорцию при выборе нового раздела.
разблокировано выкидывание из ящиков с помощью функций drop_item и drop_item_and_teleport
убран вылет "cannot find rank for ..." при выкидывании оружия, не прописанного в mp_ranks
добавлены глобальные функции

log1(string) - нормальный вывод текста в консоль вместо нерабочей log

flush1() - запись выведенного в консоль текста на диск, вместо нерабочей flush

* в пространство имён level добавлены функции:

level.get_target_dist() - возвращает float - расстояние до точки, на которую смотрит камера. Это то число, которое высвечивается под прицелом.

level.get_target_obj() - возвращает game_object - объект, на который смотрит камера. Если ни на кого, то возвращает nil.

в класс CUIStatic возвращена возможность вращать текстуру. Для этого добавлен метод:

SetHeading(Frect) - угол вращения в радианах передаётся в поле x объекта-аргумента.

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

 

Сделали ее Kolmogor и Malandrinus

 

2. Заходим в _g.script и находим function printf(fmt,...)

3. В этой функции меняем log на log1 чтобы получилось так:

 

function printf(fmt,...)

 

local is_g = 0

local result = fmt

if debug == nil then

log1(string.format(fmt,...))

return

end

local info_table = debug.getinfo(2)

local script_name = string.gsub(info_table.short_src, "%.script", "")

script_name = string.gsub(script_name, "gamedata\\scripts\\", "")

 

if scripts_to_print[script_name] == false then return end

 

script_name,is_g = string.gsub(script_name, "_g", "")

if is_g == 0 then

result = script_name..":("..info_table.currentline.."):"..fmt

else

result = fmt

end

log1(string.format(result,...))

end

 

27. hmtoggle_plus1Спавн монстра

function mutant_sim_attack()

alife():create("chimera_normal",vector():set(116.86434936523,-3.9353849887848,176.99018859863),1167207,138)

end

 

28. hmtoggle_plus1Спавн через скрипт единожды

function spawn_one ()

if not db.actor:has_info("spawn_one")

then

alife():create("NPC",vector():set(-118.155,12.919,-138.009),116155,934)

db.actor:give_info_portion("spawn_one")

end

 

Тут мы перед спавном проверяем: если у ГГ отсутвует поршень Spawn_one, то мы заспавним NPC и выдадим ему этот самый инфопоршень. А если у нас уже есть инфопоршень - то спавн не произойдет

 

29.hmtoggle_plus1 Передаем предмет ГГ

dialogs.relocate_item_section(second_speaker, "Предмет", "in")

 

30. hmtoggle_plus1Спавн аномалий с рандомной позицией

function spawn_anom(anom_name,plosh,position,level_vertex_id,game_vertex_id,powers_a,time_danger

os)

   local obj = alife():create(anom_name,position,level_vertex_id,game_vertex_id)

   local pac = net_packet()

   obj:STATE_Write(pac)

   local game_vertex_id = pac:r_u16()

   local distance = pac:r_float()

   local direction = pac:r_u32()

   local level_vertex_id = pac:r_u32()

   local object_flags = pac:r_s32()

   local custom_data = pac:r_stringZ()

   local story_id = pac:r_s32()

   local spawn_story_id = pac:r_s32()

   local shape_count = pac:r_u8()

   for i=1,shape_count do

       local shape_type = pac:r_u8()

       if shape_type == 0 then

           local center = pac:r_vec3()

           local plosh = pac:r_float()

       else

           local box = pac:r_matrix()

       end

   end

   local restrikror_type = pac:r_u8()

   local powers = pac:r_float()

   local owner_id = pac:r_s32()

   local on_off_mode_enabled_time = pac:r_u32()

   local on_off_mode_disabled_time = pac:r_u32()

   local on_off_mode_shift_time = pac:r_u32()

   local offline_interactive_radius = pac:r_float()

   local artefact_spawn_places_count = pac:r_u16()

   local artefact_position_offset = pac:r_s32()

   local last_spawn_time_present = pac:r_u8()

   if pac:r_elapsed()~= 0 then

       abort("left=%d",pac:r_elapsed())

   end

   pac:w_begin(game_vertex_id)

   pac:w_float(distance)

   pac:w_u32(direction)

   pac:w_u32(level_vertex_id)

   pac:w_u32(object_flags)

   pac:w_stringZ(custom_data)

   pac:w_s32(story_id)

   pac:w_s32(spawn_story_id)

   pac:w_u8(1)

   pac:w_u8(0)

   local sphere_center = vector()

   sphere_center:set(0,0,0)

   pac:w_vec3(sphere_center)

   pac:w_float(plosh)

   pac:w_u8(restrikror_type)

   if powers_a ~= nil then

       powers = powers_a

   end

   pac:w_float(powers)

   if time_dangeros == nil then

       owner_id = bit_not(0)

   else

       owner_id = time_dangeros

   end

   pac:w_u32(owner_id)

   pac:w_u32(on_off_mode_enabled_time)

   pac:w_u32(on_off_mode_disabled_time)

   pac:w_u32(on_off_mode_shift_time)

   pac:w_float(offline_interactive_radius)

   pac:w_u16(artefact_spawn_places_count)

   pac:w_u32(artefact_position_offset)

   pac:w_u8(last_spawn_time_present)

   pac:r_seek(0)

   obj:STATE_Read(pac,pac:w_tell())

return obj

end

 

31. hmtoggle_plus1На разных локациях - разная погода

Создать погодные настройки, привязать их к локации в game_maps_single.ltx

 

Через скрипт:

if level:name()=="что-то" then

if level:get_weather()~="что-то" then

  level:set_weather("что-то")

end

end

 

32. hmtoggle_plus1При получении инфопоршня запускаем квест

if has_alife_info("требуемая для выдачи квеста инфа") and not has_alife_info("инфа на выдачу квеста") then

db.actor:give_info_portion("инфа на выдачу квеста")

task_manager.get_task_manager():give_task("секция квеста")

end

 

33. hmtoggle_plus1Тушим костер

Подойти к костру вплотную и выполнить вот такой код:

 

for i=1,65535 do

   local s = sim:object(i)

   if s then

       local o = level.object_by_id(s.id)

       if o  then

           local cf = o:get_campfire()

           if cf and o:position():distance_to(cact:position()) < 5 then

               cf:turn_off() -- turn_on

           end

       end

   end

end

 

Гаснет не мгновенно и не полностью, просто меняет партиклы на "тление угольков с лёгким дымком"

 

34. hmtoggle_plus1Рандомный спавн объектов

function respawn()

local level_vertexes={

zaton = 1844793,

jupiter = 1422445,

pripyat = 477061

}

 

local game_vertexes={

zaton = {0,316},

jupiter = {317,665},

pripyat = {666,856}

}

 

local lname= "jupiter"

local gvn,gvx,lvx = game_vertexes[lname][1], game_vertexes[lname][2], level_vertexes[lname]

for i=1,1000 do

new_lv = math.random(1,lvx)

local pos = level.vertex_position(new_lv)

local new_gv = 0

local min_dist = 100000

for a = gvn, gvx do

g1 = game_graph():vertex(a):game_point()

if g1:distance_to(pos)<min_dist then

min_dist = g1:distance_to(pos)

new_gv = a

end

end

alife():create("wpn_ak74",pos,new_lv,new_gv)

pos = level.vertex_position(new_lv)

create_anomaly("zone_mine_electric",1,new_lv,new_gv,pos)

end

 

end

 

35. hmtoggle_plus1Заставляем всех NPC говорить с нами

В файле gulag_general.script найти:

 

; Строка 52-53

"use = {=is_wounded} false, {!is_squad_commander} false, {=actor_enemy} false, {=has_enemy} false, {=actor_has_weapon} false, {=dist_to_actor_le(3)} true, false\n"..

"snd_on_use = {=is_wounded} nil, {=actor_enemy} nil, {!is_squad_commander} meet_use_no_talk_leader, {=actor_has_weapon} meet_use_no_weapon, {=has_enemy} meet_use_no_fight, {=dist_to_actor_le(3)} meet_use_no_default, nil\n"..

 

Заменить на:

 

"use = {=is_wounded} false, {=actor_enemy} false, {=has_enemy} false, {=actor_has_weapon} false, {=dist_to_actor_le(3)} true, false\n"..

"snd_on_use = {=is_wounded} nil, {=actor_enemy} nil, {=actor_has_weapon} meet_use_no_weapon, {=has_enemy} meet_use_no_fight, {=dist_to_actor_le(3)} meet_use_no_default, nil\n"..

 

36. hmtoggle_plus1Играем звук, когда в инвентаре у ГГ есть "предмет"

В файле bind_stalker.script найти строки:

--' Апдейт саундменеджера

xr_sound.update(self.object:id())

После этих строк вставить эту:

actors_sound.play_sound()

Далее создаем в той-же папке файл actors_sound.script, и в него вставляем такие строки:

function play_sound()

local snd

if db.actor:object("predmet") then snd = [[Путь_до_звука_относительно_папки_sounds]]

end

if snd then

local snd_obj = xr_sound.get_safe_sound_object(snd)

snd_obj:play_no_feedback(db.actor, sound_object.s2d, 0, vector(), 1.0)

end

end

 

37. hmtoggle_plus1Проверям жив ли монстр

local stobj =alife():story_object(story_id_монстра)

if stobj then

  if stobj:alive() then

    --' Действия, если монстр жив

  else

    --' ... если мёртв

  end

end

 

38. hmtoggle_plus1Играем звук при получении\потери предмета\денег

В файле news_manager.script ищем функции relocate_money и relocate_item. После строчки

--' Играем дефолтный звук

Допишем:

xr_sound.set_sound_play(actor:id(), "pda_tips")

 

39. hmtoggle_plus1Отмечаем на карте тайник

treasure_manager.get_treasure_manager():give_treasure("ИМЯ_ТАЙНИКА")

 

40. hmtoggle_plus1Включаем\Выключаем режим скриншотов

Включение:

function screenshot_mode_on()

level.hide_indicators_safe()

local hud = get_hud()

hud:HideActorMenu()

hud:HidePdaMenu()

end

 

Выключение:

function screenshot_mode_off()

level.show_indicators()

end

 

41. hmtoggle_plus1Скрипт порчи предметов при старте игры

1. Актор при старте игры сразу активирует спейс рестриктор с логикой zat_a1_logic.ltx

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

 

function damage_actor_items_on_start(actor, npc)

  local actor = db.actor

 

  local obj = actor:object("helm_respirator")

  if obj ~= nil then

   obj:set_condition(0.8)

  end

 

  obj = actor:object("stalker_outfit")

  if obj ~= nil then

   obj:set_condition(0.76)

  end

 

  obj = actor:object("wpn_pm_actor")

  if obj ~= nil then

   obj:set_condition(0.9)

  end

 

  obj = actor:object("wpn_ak74u")

  if obj ~= nil then

   obj:set_condition(0.7)

  end

 

end

 

Соответственно для противогаза (helm_respirator), брони (stalker_outfit), пистолета (wpn_pm_actor) и автомата (wpn_ak74u) - причем сугубо конкретных

 

42. hmtoggle_plus1Функция вывода сообщения с разными иконками

local news_caption = game.translate_string("st_tip")

         local texture = "ui_iconsTotal_weapons"

         db.actor:give_game_news(news_caption, news_text, texture, 0, 15*1000)

play_snd_at_actor([[device\pda\pda_news]])

Где:

local news_caption = game.translate_string("st_tip") - заголовок "Сообщение"

local texture = "ui_iconsTotal_weapons" - иконка сообщения

db.actor:give_game_news(news_caption, news_text, texture, 0, 15*1000) - придется поставить первый цифровой параметр (задержка перед выводом сообщения) в ноль, так как нам нужно синхронизировать звук ПДА и сообщение

play_snd_at_actor([[device\pda\pda_news]]) - вывод звука ПДА

 

43. hmtoggle_plus1Создаем скрипт коллбеков, а-ля SGM

Зарегистрируем нашу функцию в файле bind_stalker.script:

 

Ищем:

function actor_binder:use_inventory_item(obj)

 

после второго end функции вставляем:

 

if obj~=nil then

новый_скрипт.on_use_item(obj)

end

 

(в конце должно получиться два end)

 

Далее создаем новый_скрипт.script и вставляем в него такую функцию:

 

function on_use_item(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)

--C переменными закончено, дальше пишем наши колбеки на предметы

if item_name=="money_10" then

dialogs.relocate_money_to_actor(first_speaker, second_speaker, 100)

elseif item_name=="money_50" then

dialogs.relocate_money_to_actor(first_speaker, second_speaker, 500)

end

end

 

44. hmtoggle_plus1Спавним монстров после выброса

в функции CSurgeManager:end_surge файла scripts\surge_manager.script, после строки self:respawn_artefacts_and_replace_anomaly_zone() добавляем вызов своей функции спавна монстров, например такой:

 

function spawn_monster_after_surge ()

xr_effects.create_squad(<Сквад1>,<Смарт1>)

xr_effects.create_squad(<Сквад2>,<Смарт2>)

xr_effects.create_squad(<Сквад3>,<Смарт3>)

end

 

45. hmtoggle_plus1Изменить состояние оружия выпадаемое с трупов

Функция set_weapon_drop_condition(item) в файле death_manager.script

По умолчанию выпадает оружие от 0.4 (40\100) до 0.8 (((0.0..0.4)+40)/40)

 

46. hmtoggle_plus1Как убрать выпадение оружия из рук ГГ при ударе прикладом

В файле scripts\xr_effects.script, функция actor_punch, закоментировать строку

db.actor:drop_item(active_item)

 

47. hmtoggle_plus1Как сделать отображение сталкеров в КПК наподобие ЧН

В файле configs\ui\map_spots.xml и configs\ui\map_spots_16.xml раскомментировать строки в разделе "Отряды":

 

<!--    <level_map spot="alife_presentation_squad_friend_spot"/> -->

...

<!--    <level_map spot="alife_presentation_squad_neutral_spot"/> -->

...

и т.д.

 

Заменить в файле scripts\sim_squad_scripted.script функцию sim_squad_scripted:get_squad_props() например на такую:

 

function sim_squad_scripted:get_squad_props()

local t = self.player_id

if t == "bandit" then

     t = "Сквад Бандитов"

    elseif t == "ecolog" then

     t = "Группа Экологов"

    elseif t == "killer" then

     t = "Сквад Наемников"

    elseif t == "dolg" then

     t = "ui_st_name_dolg"

    elseif t == "freedom" then

     t = "Сквад Свободы"

    elseif t == "stalker" then

     t = "Группа Сталкеров"

    elseif t == "army" then

     t = "Отряд Военных"

    elseif t == "monolith" then

     t = "Отряд Монолита"

    elseif t == "zombied" then

     t = "Группа Зомбированных"

end

return t

end

 

48. hmtoggle_plus1Отключить задание "Найти укрытие" при выбросах

В файле scripts\surge_manager.script в функции CSurgeManager:give_surge_hide_task, комментировать строки начинающиеся с task_manager.get_task_manager():give_task

 

49. hmtoggle_plus1Поставить метку на карту

--Установить метку на бармена Скадовска (story_id = zat_a2_stalker_barmen).

local obj_id = get_story_object_id("zat_a2_stalker_barmen")

level.map_add_object_spot(obj_id, "green_location", "Объект")

 

Удалить соответственно:

level.map_remove_object_spot(obj_id, "green_location")

 

50. hmtoggle_plus1Проверяем надличие предметов у ГГ

Вариант #1:

--Проверка наличия продуктов в рюкзаке Актора

function actor_has_food_to_half_zombi(first_speaker, second_speaker)

  if db.actor:object("bread") ~= nil and  

     db.actor:object("kolbasa") ~= nil and

     db.actor:object("conserva") ~= nil  

     then return true

  end

  return false

end

 

Вариант #2:

function actor_has_needed_item()

local item_sections = {"Предмет"}  

local needed = количество одинаковых предметов, ставится цифра без знаков  

local count = 0

local item_section

local function calc(temp, item)

  if item:section() == item_section then

  count = count + 1

  end

end

 

  for k,v in pairs(item_sections) do

  item_section = v

  get_story_object("actor"):iterate_inventory(calc, actor)

 

end

 

  return count >= needed

 

end

 

51. hmtoggle_plus1Сталкеры не умирают, а превращаются в зомби (15%)

В файле scripts\release_body_manager.script в функции Crelease_body:try_to_release() после строк:

 

if (IsStalker(release_object) or IsMonster(release_object)) and not release_object:alive() then

 

Добавить:

 

     --Снять координаты

     local p=vector(),lv,gv

     p.x=release_object.position.x

     p.y=release_object.position.y

     p.z=release_object.position.z

     lv=releas e_ob ject.m_level_vertex_id

     gv=release_object.m_game_vertex_id

         

     --Спавн зомби

     local random_number=math.random(1,100)

     if math.random(1,100) < 15 then

     random_number=math.random(1,100)  

      if random_number < 10 then  

       alife():create("sim_default_zombied_1",p,lv,gv)

      end

      if random_number >= 10 and random_number < 30 then  

       alife():create("sim_default_zombied_2",p,lv,gv)  

      end

      if random_number >= 30 and random_number < 80 then  

       alife():create("sim_default_zombied_3",p,lv,gv)  

      end

      if random_number >= 80 and random_number <= 100 then  

       alife():create("sim_default_zombied_4",p,lv,gv)  

      end

     end

 

где if math.random(1,100) < 15 - спавн зомби с вероятностью 15%.

Выбор визуала зомби осуществляется также по вероятности:

10% - sim_default_zombied_1

20% - sim_default_zombied_2

50% - sim_default_zombied_3

20% - sim_default_zombied_4

 

52. hmtoggle_plus1Неписи не подбирают новые предметы

Надо в скрипте xr_corpse_detection.script добавить предметы в таблицу.

 

53. hmtoggle_plus1Уборка тел

Для НПС скрипт release_body_manager.script основные параметры:

IDLE_AFTER_DEATH - время после смерти НПС, в течении которого труп не удаляется

max_distanse - максимальное расстояние между ГГ и трупом на котором тело не удаляется

self.body_max_count - количество тел которое одновременно может находится в игре

 

Для монстров файл monsters.ltx параметры:

corpse_remove_game_time_interval - интервал времени для удаления тел

stay_after_death_time_interval - время в течении которого труп остается

При изменении этих параметров нужна новая игра.

 

54. hmtoggle_plus1Как удалить катсцену при переходе на Юпитер

ГГ необходимо выдать следующие инфопоршни:

 

db.actor:give_info_portion("jup_first_meet_made")

db.actor:give_info_portion("jup_b217_welcome_faded")

db.actor:give_info_portion("jup_b217_welcome_guide_talked")

db.actor:give_info_portion("jup_b217_pp_end_in_scene")

db.actor:give_info_portion("jup_b217_welcome_tech_talked")

db.actor:give_info_portion("jup_b217_guide_welcome_end")

db.actor:give_info_portion("jup_b217_tech_welcome_end")

db.actor:give_info_portion("jup_b217_tech_instruments_start")

db.actor:give_info_portion("jup_b217_stalker_tech_met")

 

55. hmtoggle_plus1Как создать автосейв

В скрипте scripts\xr_effects.script есть функция scenario_autosave можно вызвать либо из другого скрипта либо из логики рестриктора, НПС и т.п. Аргумент - имя файла сохранения.

 

56. hmtoggle_plus1Функция удаления сквада

Функция kill_squad в скрипте xr_effects.script

 

57. hmtoggle_plus1Удалить объект из инвентаря

alife():release(alife():object(item_id),true)

 

58. hmtoggle_plus1Как сделать, чтобы костры тушились если рядом нету сталкеров

В файле scripts\bind_campfire.script раскомментировать блок строк после строки

 

function campfire_binder:update(delta)

 

59. hmtoggle_plus1Где прописать оружие для статистики "Любимое оружие"

В файле xr_statistic.script добавить свое оружие в таблицу weapons_table, иконка оружия будет браться из ui_actor_weapons.dds согласно координат upgr_icon_x, upgr_icon_y, upgr_icon_width, upgr_icon_height из файла конфигурации ствола.

 

60. hmtoggle_plus1Где отредактиировать награду за достижение "Охотник на мутантов"

Файл bind_stalker.script таблица с предметами награды mutant_hunter_achievement_items

 

61. hmtoggle_plus1NPC не открывают новые двери

Убедиться что двери заспавнены как physic_door

удалить в ph_door.script функции try_to_open_door и try_to_close_door строку

if true then return {} end

 

62. hmtoggle_plus1Таймеры on_timer и on_game_timer

on_timer измеряется в мс (1с = 1000мс)

on_game_timer измеряется в с

 

Применение on_game_timer:

 

on_game_timer = 36000 | %+atack%

 

По истечению 1 часа персонаж будет получать инфопоршень, который будет считаться сигналом к атаке

 

Аналог из xr_condition:

 

time_shift

 

Проверка на заданный период времени

Время задается в минутах

Параметры: (time_shift:period_min)

time_shift - периодичность срабатывания

period - период срабатывания на котором мы получаем true

 

Примеры:

time_period(60:10) - возвращает true каждый час на протяжении первых 10 минут

 

63. hmtoggle_plus1Первый член сквада - Лидер

Файл sim_squad_scripted.script

~580 строка

Замени:

 

for i = 1,random_count do

   local random_id = math.random(1, #random_spawn)

   self:add_squad_member(random_spawn[random_id], base_spawn_position, base_lvi, base_gvi,random_id)

end

 

на

 

self:add_squad_member(random_spawn[1], base_spawn_position, base_lvi, base_gvi,random_id)

for i = 2,random_count do

   local random_id = math.random(2, #random_spawn)

   self:add_squad_member(random_spawn[random_id], base_spawn_position, base_lvi, base_gvi,random_id)

end

 

64. hmtoggle_plus1Где отредактировать время включения фонарика неписями

В файле sr_light.script

 

if not forced then

--' Проверка по времени суток (ночью всегда включено)

local htime = level.get_time_hours()

if htime <= 4 or htime >= 22 then

light = true

end