Перейти к контенту

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

@I am Dead ну, либо лезть в движок, либо костыльно как-то перебирать все предметы в ящике.

Как вариант, попробуй так:

Скрытый текст

local cnt = box:object_count()
	for i=0, cnt-1 do
		local item = box:object(i)
		--нужные действия
	end

 

Сразу говорю, что не ручаюсь за работоспособность у inventory_box, я эту функцию раньше использовал только для актора

@Stalkersof и вообще, зачем тебе обратно ссылаться на биндер монстров? Можно же в скрипте с ГУИ выдать все нужные предметы и не забивать себе голову.

Изменено пользователем ARTLantist
Ссылка на комментарий
11 минут назад, ARTLantist сказал(а):

 

@Stalkersof и вообще, зачем тебе обратно ссылаться на биндер монстров? Можно же в скрипте с ГУИ выдать все нужные предметы и не забивать себе голову.

У меня там не только предметы(запчасти) чтение конфига монстра, удар ножом, хит монстру и анимация. Мне вот это и актор нужен там и монстр(obj,who) надо. 

Ссылка на комментарий
1 минуту назад, Stalkersof сказал(а):

и актор нужен там и монстр(obj,who)

Перешли их в скрипт с ГУИ окном:

NewUI4.main(obj,who)

и там уже устанавливай в той функции

function main(obj,who)
	self.actor = who
	self.monstr = obj
	--и далее нужное

и всё.

  • Нравится 1
Ссылка на комментарий

Попросил помощи с проверкой скрипта на предыдущей странице, но в виду "оживлённой" беседы моё сообщение, видимо, просто осталось без внимания... Попрошу ешо раз:

 

Ссылка на комментарий

@ARTLantist я все переправил уже. Сделал плюс-минус как ты, только естесн, параметры назвал по-другому

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

  • Нравится 1
Ссылка на комментарий
9 часов назад, Biblia сказал(а):

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

Пробуй, экспериментируй - что-то да получится. Это самый лучший способ научиться что-то делать.

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

Изменено пользователем ARTLantist
  • Нравится 1
  • Согласен 2
Ссылка на комментарий

@Stalkersof , тебе надо при вызове гуя сохранить ссылку на биндер. Например, так:

 

function generic_object_binder:use_callback(obj, who)

  if self.use_flag == nil and self.object:section()~="m_trader" then

    self.object:set_nonscript_usable(false)

    self.use_flag = true

  end

  local wnd = NewUI4.main()

  level.start_stop_menu( wnd, true )

  wnd.owner = self -- сохраняем ссылку на биндер

  --self:mutanter_use(obj,who)

end

 

А потом в гуе вызывать нужную функцию так:

 

function NewUI4:button1_button_clicked()
	 self.owner:mutanter_use()
	 self:Hide()
end
Изменено пользователем naxac
  • Спасибо 1
  • Согласен 1

Аддон для ОП-2.09.2: Яндекс/Google/GitHub

naxac.gif

Ссылка на комментарий

@ARTLantist были бы у меня исходники движка СТКоПа версии 3.4 - я бы так и сделал. Но так как вынужден работать с тем, что имею - только фейк-слоты. 

Ссылка на комментарий

@Biblia не поверишь, точно такая же проблема у меня была. Я просто скачал более старый пак, который не требует установки библиотек движка, и всё. Поверь, возможность править движок куда важнее, чем красивый оружейный пак.

  • Согласен 1
Ссылка на комментарий

@ARTLantist на красивый ОП мне как-то по-барабану. Туеву кучу моделей сейчас можно найти и добавить в стулкер. Просто оптимизация 3д прицелов и их реализация лучшая, что я встречал. Товарищ Мортан там потрудился на славу. Да и я просто хочу накатить маленькую сборку для души. 

И заключительный вопрос: кол-во артов на поясе в ЗП зашито в двигле? 

Ссылка на комментарий

Господа, доброго времени! Возникла необходимость перманентно держать на экране определенную информацию. Решил использовать шаблон из туториала: "нажмите "клавиша" чтобы присесть"

В конфиге имеем:

Скрытый текст

<item><!-- Для того чтобы пройти под невысоким препятствием - нажмите клавишу "ctrl" $$ACTION_CROUCH$$-->
			<length_sec>5</length_sec>
			<pause_state>off</pause_state>
			<guard_key/>
			<sound/>
			<cursor_pos/>
			<pda_section/>
			<grab_input>0</grab_input>
			<main_wnd>
				<auto_static start_time="0" length_sec="5000" x="712" y="475" width="400" height="150" alignment="c" stretch="1"
							light_anim="" la_cyclic="1" la_texture="1" la_alpha="1">
					<window_name>w1</window_name>
					<text font="graffiti22" r="225" g="225" b="250" a="255">crouch_tutorial</text>
				</auto_static>
			</main_wnd>
		</item>

 

<length_sec>5</length_sec> - время показа 5 секунд (если я правильно понял). А как сделать вывод информации бесконечным?

Ссылка на комментарий
5 часов назад, Biblia сказал(а):

кол-во артов на поясе в ЗП зашито в двигле

да.

 

1 час назад, _Sk8_AsTeR_ сказал(а):

А как сделать вывод информации бесконечным?

function xxx()
	local hud = get_hud()
    if (hud) then
        hud:AddCustomStatic("static", true)
        hud:GetCustomStatic("static"):wnd():TextControl():SetTextST(game.translate_string("text"))
    end
end

static - название твоего статического элемента в ui_custom_msgs.xml

Скрытый текст

<static x="200" y="70" width="600" height="50" ttl="3">
	<text font="graffiti32"  r="240" g="217" b="182" a="255" align="c">text(нужный текст)</text>
</static>

 

потом удаляешь тогда, когда тебе захочется:

Скрытый текст


function yyy()
	local hud = get_hud()
	if (hud) then
		local custom_static = hud:GetCustomStatic("dosimeter_rad")
		if custom_static ~= nil	then
			hud:RemoveCustomStatic("dosimeter_rad")
		end
	end
end

 

 

Изменено пользователем ARTLantist
  • Спасибо 1
Ссылка на комментарий
32 минуты назад, ARTLantist сказал(а):
5 часов назад, Biblia сказал(а):

кол-во артов на поясе в ЗП зашито в двигле

да.

Ля, тогда придется постигать тяготы движкоправства. Но надо будет и фейк-слоты опробовать 

Ссылка на комментарий
10 часов назад, naxac сказал(а):

@Stalkersof , тебе надо при вызове гуя сохранить ссылку на биндер. Например, так:

Спасибо 100% рабочий вариант. Правда с who были проблемы но там спавнить запчасти не кому кроме актора. Все работает так как надо.

Ссылка на комментарий

Дано: скрипт db.script, использующийся для правленой боевой схемы БТР (ph_car.script)... Выдержка отличающейся от оригинала части:

Скрытый текст

 

creature            = {}    -- true - человек, false - животное (исключая торговца)

FlagEsc = 0
Flag2 = 0
Dead2 = 0

creatures={}
monster_stock = {}
btr_target = {}


function add_obj( obj )
  creatures[obj:id()]=obj
end

function del_obj( obj )
  storage   [obj:id()] = nil
  creatures[obj:id()]=nil
end

 

function add_obj( obj )
    if IsStalker(obj) then
        creature[obj:id()] = true
    elseif IsMonster(obj) then
        creature[obj:id()] = false
    end

if IsMonster(obj) then
monster_stock[obj:id()] = obj
end

    if IsStalker(obj) and IsMonster(obj) then
        btr_target[obj:id()] = true
end


end

function del_obj( obj )
    storage   [obj:id()] = nil
    if IsStalker(obj) or IsMonster(obj) then
        creature[obj:id()] = nil
    end
if IsMonster(obj) then
monster_stock[obj:id()] = nil
end

    if IsStalker(obj) and IsMonster(obj) then
        btr_target[obj:id()] = nil
end
end

 


Почему-то повторяются функции function add_obj( obj ) и function del_obj( obj ) и мне это кажется странным. Такое вообще допустимо? Не лучше ли совместить функции как-то так:

Скрытый текст

 

function add_obj( obj )
  creatures[obj:id()] = obj

    if IsStalker(obj) then
        creature[obj:id()] = true
    elseif IsMonster(obj) then
        creature[obj:id()] = false
    end

if IsMonster(obj) then
monster_stock[obj:id()] = obj
end

    if IsStalker(obj) and IsMonster(obj) then
        btr_target[obj:id()] = true
end
end

 

function del_obj( obj )
   storage[obj:id()] = nil

   creatures[obj:id()] = nil
    if IsStalker(obj) or IsMonster(obj) then
        creature[obj:id()] = nil
    end
if IsMonster(obj) then
monster_stock[obj:id()] = nil
end

    if IsStalker(obj) and IsMonster(obj) then
        btr_target[obj:id()] = nil
end
end

 

 

Скрипт правленого ph_car вот:

Скрытый текст

 

----------------------------------------------------------------------------------------------------
-- Обновленная боевая схема БТР - Мишаня_Лютый aka CRAZY_STALKER666. Old Episodes - Epilogue
----------------------------------------------------------------------------------------------------
-- Исходный скрипт: Evgeniy Negrobov (Jon) jon@gsc-game.kiev.ua
-- Перевод на xr_logic: Andrey Fidrya (Zmey) af@svitonline.com
-- Доработка для БТР: Oleg Kreptul (Haron) haronk@ukr.net
-- ВНИМАНИЕ! Для монстров используется db.monster_stock. При желании можно перевести и на перебор цифрами, ничего не поменятся, но лагов будет больше
----------------------------------------------------------------------------------------------------
function printf() end

local pi_2 = math.pi / 3 -- 60 degree

local def_min_delta_per_sec = 0.2
local def_min_car_explode_time = 1000
local def_moving_speed = 10
--local def_arriving_factor = 0.4
local def_arriving_dist = 1.0
local def_not_rotating_angle = 0.4
local def_min_fire_time = 0
local def_update_time = 1.6
local def_fire_range = 50

local def_max_fc_upd_num = 1000 -- default maximum fastcall updates num
local def_arriving_koef = 3 --70

local delay_after_ignition = 500

local state_none = 0

local state_moving_fwd = 1
local state_moving_rot_left = 2
local state_moving_rot_right = 3
local state_moving_stop = 4
local state_moving_end = 5

local state_cannon_rotate = 1
local state_cannon_follow = 2
local state_cannon_delay = 3
local state_cannon_stop = 4

local state_shooting_on = 1

local state_firetarget_points = 1
local state_firetarget_enemy = 2

-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
class "action_car"

function action_car:__init(obj, storage)
    --printf("car <state>: init.")
    self.object = obj
    self.car = self.object:get_car()
    self.st = storage
    self.friends = {}
end

function action_car:reset_scheme(loading)
    --printf("car <state>: START INITIALIZING ======================================================")
    --printf("car <state>: action_car:reset_scheme: self.object:name()='%s'", self.object:name())

    self.destroyed = false
    self.object:set_nonscript_usable(false)

    self.object:set_tip_text("")
    self.show_tips = self.st.show_tips
    self.tip_use = self.st.tip_use
    self.tip_locked = self.st.tip_locked

    if self.st.invulnerable then
        self.object.health = 1
        self.car:SetfHealth(1)
    end

    self.headlights = object.deactivate
    if self.st.headlights == "on" then
        self.headlights = object.activate
    end
    --printf("car <state>: headlights %s", self.st.headlights)
    xr_logic.mob_capture(self.object, true)
    action(self.object, object("left_light",  self.headlights), cond(cond.time_end, time_infinite))
    xr_logic.mob_capture(self.object, true)
    action(self.object, object("right_light", self.headlights), cond(cond.time_end, time_infinite))

    self.usable = self.st.usable
    
    --if self.usable ~= nil then
    --    self.car_holder = self.object.get_current_holder() --engaged()
    --else
    if self.usable == nil then
        self.car:SetExplodeTime(0) -- (-1)

        if self.car:HasWeapon() then
        --printf("car <fire>: car has weapon.")
        self.car:Action(CCar.eWpnActivate,1)
        self.hasWeapon = true
        else
            --printf("car <fire>: car hasn't weapon.")
            self.hasWeapon = false
        end

        if loading then
            self.speed = xr_logic.pstor_retrieve(self.object, "speed")
            self.loop = xr_logic.pstor_retrieve(self.object, "loop")
            self.min_delta_per_sec = xr_logic.pstor_retrieve(self.object, "min_delta_per_sec")
            self.min_car_explode_time = xr_logic.pstor_retrieve(self.object, "min_car_explode_time")
            self.state_moving = xr_logic.pstor_retrieve(self.object, "state_moving")
        else
            self.speed = def_moving_speed
            self.loop = false
            self.min_delta_per_sec = def_min_delta_per_sec
            self.min_car_explode_time = def_min_car_explode_time
            self.state_moving = state_none
        end

        --xr_logic.mob_capture(self.object, true)
        self.st.signals = {}

        self.fc_upd_num = 0 -- fastcall updates num
        self.fc_upd_avg = 10 -- average time of the fastcall updates (in millisecond)
        self.fc_last_upd_tm = -1 -- fastcall last update time

        self.last_pos = nil
        self.last_pos_time = 0
        
        self.state_delaying = false

        --self.state_moving = state_none

        self.target_walk_pt = -1
        -- path_walk
        if self.st.path_walk then
            self.path_walk = patrol(self.st.path_walk)
            if not self.path_walk then
                abort("object '%s': unable to find path_walk '%s' on the map", self.object:name(), self.st.path_walk)
            end

            self:start_car()
            self.path_walk_count = self.path_walk:count()

            --if not self.path_walk_info then
            self.path_walk_info = utils.path_parse_waypoints(self.st.path_walk)
            if not self.path_walk_info then
                abort("object '%s': path_walk ('%s'): unable to obtain path_walk_info from path",
                    self.object:name(), self.st.path_walk)
            end
            --end

            self.arrival_signalled = false
            self.target_dist = -1

            if loading then
                self.target_walk_pt = xr_logic.pstor_retrieve(self.object, "target_walk_pt")
                if self.target_walk_pt == -1 then
                    self.target_walk_pt = self:get_nearest_walkpoint()
                end
            else
                self.target_walk_pt = self:get_nearest_walkpoint()
            end
            --printf("car <move>: target_walk_pt.1(%d)", self.target_walk_pt)

            if self:at_target_walkpoint() then
                self:walk_arrival_callback(self.target_walk_pt)
            end
            
            self:go_to_walkpoint(self.target_walk_pt)
        else
            --printf("car <state>: target_walk_pt.2(-2)")
            self.target_walk_pt = -2
            self.state_moving = state_moving_stop
        end
        --printf("car <move>: start target_pt1 = %d", self.target_walk_pt)
        
        self.state_firetarget = state_none
        self.state_cannon = state_none
        self.state_shooting = state_none
        
        self.target_fire_pt = nil
        self.target_fire_pt_idx = 0
        self.target_obj = nil
        
        self.on_target_vis = nil
        self.on_target_nvis = nil

        if self.hasWeapon then
            --if loading then
            --    self.state_cannon = xr_logic.pstor_retrieve(self.object, "state_cannon")
            --    self.state_shooting = xr_logic.pstor_retrieve(self.object, "state_shooting")
            --end
            
            self:set_shooting(self.state_shooting)

            --printf("car <fire>: target = %s", self.st.fire_target)
            local n = 0
            if self.st.fire_target == "points" then
                self.state_firetarget = state_firetarget_points
            else
                if self.st.fire_target == "actor" and db.actor:alive() then
                    self.target_obj = db.actor
                    self.state_firetarget = state_firetarget_enemy
                else
                    n = tonumber(self.st.fire_target)
                    if n then
                        obj = level_object_by_sid(n)
                        if obj and obj:alive() then
                            self.target_obj = obj
                            self.state_firetarget = state_firetarget_enemy
                        end
                    end
                end
                --if self.target_obj then
                --    self.target_ph_shell = self.target_obj:get_physics_shell()
                --end
            end
            self.fire_track_target = self.st.fire_track_target

            if self.st.on_target_vis then
                vis = self.st.on_target_vis
                if vis.v1 == "actor" then
                    vis.v1 = db.actor
                    self.on_target_vis = vis
                    --printf("car <vis>: target actor")
                else
                    n = tonumber(vis.v1)
                    if n then
                        obj = level_object_by_sid(n)
                        if obj and obj:alive() then
                            vis.v1 = obj
                            self.on_target_vis = vis
                            --printf("car <vis>: target %d", n)
                        end
                    end
                end
            end
            if self.st.on_target_nvis then
                nvis = self.st.on_target_nvis
                if nvis.v1 == "actor" then
                    nvis.v1 = db.actor
                    self.on_target_nvis = nvis
                    --printf("car <nvis>: target actor")
                else
                    n = tonumber(nvis.v1)
                    if n then
                        obj = level_object_by_sid(n)
                        if obj and obj:alive() then
                            nvis.v1 = obj
                            self.on_target_nvis = nvis
                            --printf("car <nvis>: target %d", n)
                        end
                    end
                end
            end
            
            self.path_fire = nil
            self.path_fire_info = nil
            self.fire_pt_count = 0
            
            self.def_fire_time = self.st.fire_time
            if self.st.fire_rep then
                if self.st.fire_rep == "inf" then
                    self.def_fire_rep = -1
                else
                    local c = tonumber(self.st.fire_rep)
                    self.def_fire_rep = if_then_else(c > 0, c, 0)
                end
            else
                self.def_fire_rep = 0
            end
            self.fire_rep = self.def_fire_rep
            --printf("car <fire>: def_rep = %d (%s)", self.fire_rep, utils.to_str(self.st.fire_rep))
            
            self.fire_range_sqr = self.st.fire_range * self.st.fire_range

            -- path_fire
            if self.state_firetarget == state_firetarget_points and self.st.path_fire then
                --printf("car <state>: firetarget = points")
                self.path_fire = patrol(self.st.path_fire)
                if not self.path_fire then
                    abort("object '%s': unable to find path_fire '%s' on the map",
                        self.object:name(), self.st.path_fire)
                end

                if not self.path_fire_info then
                    self.path_fire_info = utils.path_parse_waypoints(self.st.path_fire)
                    if not self.path_fire_info then
                        abort("object '%s': path_fire ('%s'): unable to obtain path_fire_info from path",
                            self.object:name(), self.st.path_fire)
                    end
                end
                
                -- точки прострела для первой точки движения
                self:change_fire_pts()
                
                if self.st.auto_fire then
                    self.car:Action(CCar.eWpnAutoFire, 1)
                else
                    self.car:Action(CCar.eWpnAutoFire, 0)
                end
                
                self:fire_arrival_callback(self.target_fire_pt_idx)
                
                --self:rot_to_firepoint(self.target_fire_pt)
                --self:set_shooting(self.state_shooting)
            elseif self.state_firetarget == state_firetarget_enemy then
                --printf("car <state>: firetarget = enemy")
                self.state_shooting = state_none
                self.state_cannon = state_cannon_follow
                --self.target_fire_pt = db.actor:position()
                --self:rot_to_firepoint(self.target_fire_pt)
            else
                --printf("car <state>: firetarget = none")
                self.state_firetarget = state_none
                self.state_cannon = state_none
                self.state_shooting = state_none
            end
            --self:set_shooting(self.state_shooting)
        end
        
        --if self.st.path_walk then
        --    if self:at_target_walkpoint() and self.state_firetarget == state_none then
        --        self:walk_arrival_callback(self.target_walk_pt)
        --    end
        --    
        --    self:go_to_walkpoint(self.target_walk_pt)
        --end
        --printf("car <move>: start target_pt2 = %d", self.target_walk_pt)
    end

    self.object:set_fastcall(self.fastcall, self)
    --printf("car <state>: END INITIALIZING ========================================================\n")
end

function action_car:save()
    --printf("car <state>: saving")
    if self.usable == nil then
        xr_logic.pstor_store(self.object, "speed", self.speed)
        xr_logic.pstor_store(self.object, "loop", self.loop)
        xr_logic.pstor_store(self.object, "min_delta_per_sec", self.min_delta_per_sec)
        xr_logic.pstor_store(self.object, "min_car_explode_time", self.min_car_explode_time)
        xr_logic.pstor_store(self.object, "state_moving", self.state_moving)
        xr_logic.pstor_store(self.object, "target_walk_pt", self.target_walk_pt) -- or -2)
        --printf("car <save>: target_walk_pt(%d)", self.target_walk_pt)
    end
end

--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
--++++++++++++++++++++-- MOVE SECTION --++++++++++++++++++++--
--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--

function action_car:get_nearest_walkpoint()
    return utils.get_nearest_waypoint(self.object, self.st.path_walk,
         self.path_walk, self.path_walk_count)
end

function action_car:get_next_walkpoint()
    if self.target_walk_pt >= 0 and self.target_walk_pt < self.path_walk_count - 1 then
        --printf("car <move>: action_car:get_next_walkpoint(%d)", self.target_walk_pt + 1)
        return self.target_walk_pt + 1
    elseif self.target_walk_pt == -1 or self.loop then
        --printf("car <move>: action_car:get_next_walkpoint(0)")
        return 0
    end
    --printf("car <move>: action_car:get_next_walkpoint(-2)")
    return -2
end

function action_car:at_target_walkpoint()
    --printf("car <move>: action_car:at_target_walkpoint(%s)", utils.to_str(self.target_walk_pt))
    if self.target_walk_pt == -2 then return true end

    local curVel = self.car:CurrentVel():magnitude()
    local dist = self.object:position():distance_to(self.path_walk:point(self.target_walk_pt))

    --local arrived = 2 * dist < def_update_time * (curVel.x + self.speed) --def_update_time > 2 * dist / (curVel.x + self.speed)
    --local arrived = dist < curVel.x * def_arriving_factor --8

    -- def_arriving_koef * self.fc_upd_avg / 1000 > 2 * dist / (curVel.x + self.speed)
    local arrived = false --2000 * dist < def_arriving_koef * self.fc_upd_avg * (curVel + self.speed)
    
    if self.fc_upd_avg < 100 then
        arrived = 2000 * dist < def_arriving_koef * self.fc_upd_avg * (curVel + self.speed)
        --printf("car <move>: check formula (%f < %f)", 2000 * dist, def_arriving_koef * self.fc_upd_avg * (curVel + self.speed))
        if arrived then
            --printf("car <move>: at target pt by formula.")
        end
    end
    
    if not arrived then
        local diff_angle = angle_xz(self.object, self.path_walk:point(self.target_walk_pt))
        --printf("car <move>: dist(%f), angle(%f).", dist, diff_angle)
        arrived = dist < 2 or diff_angle >= math.pi
        if arrived then
            --printf("car <move>: at target pt by dist(%f) and angle(%f).", dist, diff_angle)
            --printf("car <move>: at target pt by dist and angle.")
        end
    end
    
    local diff = dist - self.target_dist
    --printf("car <move>: dist = %f, target = %f, diff = %f, curVel = %f, speed = %f", dist, self.target_dist, diff, curVel, self.speed)
    if self.target_dist ~= -1 and not arrived then
        if diff > 0 then
            if diff > def_arriving_dist then
                arrived = true
                --printf("car <move>: at target pt by diff(%f).", diff)
            end
        else
            self.target_dist = dist
        end
    else
        self.target_dist = dist
    end
--[[
    --printf("car <move>: action_car:at_target_walkpoint(self.target_walk_pt=%d) = %d (arrived = %s)",        self.target_walk_pt, dist, utils.to_str(arrived))
    --if arrived then
        --printf("car <move>: arrived = %f > %f, dist(%f), diff(%f), curSpd(%f), spd(%f)",
               --def_arriving_koef * self.fc_upd_avg / 1000,
               --2 * dist / (curVel.x + self.speed),
               def_arriving_koef * self.fc_upd_avg * (curVel + self.speed),
               2000 * dist,
               dist, diff, curVel, self.speed)
        --printf("car <move>: arrived = %f < (%f,%f,%f) * %f, spd(%f)", dist, curVel.x, curVel.y, curVel.z, def_arriving_factor, self.speed)
    --end
--]]
    if arrived then
        self.target_dist = -1
    end
    return arrived
end

function action_car:go_to_walkpoint(pt)
    --action(self.object, object("left_light", object.activate), cond(cond.time_end, 1000))
    --action(self.object, object("right_light", object.activate), cond(cond.time_end, 1000))
    --printf("car <move>: action_car:go_to_walkpoint(%s)", utils.to_str(pt))
    if self.state_delaying then
        if time_global() - self.delay_time_start >= delay_after_ignition then
            --printf("car <state>: stop delaying after ignition")
            self.state_delaying = false
        else
            --printf("car <state>: delaying after ignition")
            self.state_moving = state_moving_stop
            return
        end
    end

    if pt == nil or pt < 0 then
        if self.state_cannon ~= state_cannon_stop then
            self:stop_car()
            self.state_moving = state_moving_end
        end
        --printf("car <state>: pt < 0 or pt == nil")
        return
    end

    local diff_angle = angle_xz(self.object, self.path_walk:point(pt))
    local accel = move.none
    local curVel = self.car:CurrentVel():magnitude()
    --printf("car <move>: curVel = %f, speed = %f", curVel, self.speed)
    if curVel < self.speed then
        accel = move.fwd
        --printf("car <move>: forward")
    elseif curVel > self.speed * 1.15 or diff_angle >= math.pi then
        accel = move.back
        --printf("car <move>: backward")
    end
    --printf("car <move>: diff_angle = %f, katet = %f", diff_angle, get_katet(self.object, self.path_walk:point(pt)))
    --if utils.no_need_to_rotate_xz(self.object, self.path_walk:point(pt)) then
    if diff_angle < def_not_rotating_angle then
        if self.state_moving ~= state_moving_fwd and accel ~= move.none then
            --printf("car <move>: no_need_to_rotate. speed = %f, time = %f", self.speed, self.fc_upd_avg)
               xr_logic.mob_capture(self.object, true)
            action(self.object,
                move(accel, self.speed), --move.on + 
                --object("right_light", self.headlights),
                --object("left_light", self.headlights),
                cond(cond.time_end, time_infinite)) --self.fc_upd_avg))
            self.state_moving = state_moving_fwd
        end
    else
        -- Поворачиваться нужно, но в какую сторону?
        local rotate_left = utils.angle_left_xz(self.object:direction(), 
                                                utils.vector_copy_by_val(self.path_walk:point(pt)
                                                                        ):sub(self.object:position()))
        --printf("car <move>: must rotate: left? %s. speed = %f, time = %f", utils.to_str(rotate_left), self.speed, self.fc_upd_avg)
        if rotate_left then
            if self.state_moving ~= state_moving_rot_left then 
                xr_logic.mob_capture(self.object, true)
                action(self.object,
                    move(accel + move.left, self.speed), --move.on + 
                    --object("right_light", self.headlights),
                    --object("left_light", self.headlights),
                    cond(cond.time_end, time_infinite)) --self.fc_upd_avg))
                self.state_moving = state_moving_rot_left
            end
        else
            if self.state_moving ~= state_moving_rot_right then
                xr_logic.mob_capture(self.object, true)
                action(self.object,
                    move(accel + move.right, self.speed), --move.on + 
                    --object("right_light", self.headlights),
                    --object("left_light", self.headlights),
                    cond(cond.time_end, time_infinite)) --self.fc_upd_avg))
                self.state_moving = state_moving_rot_right
            end
        end
    end
end

function action_car:start_car()
    --printf("car <move>: car started.")
    xr_logic.mob_capture(self.object, true)
    action(self.object, move(move.on + move.fwd, 100), cond(cond.time_end, 5000))
    --self.speed = 0
    self.state_delaying = true
    self.delay_time_start = time_global()
end

function action_car:stop_car()
    --printf("car <move>: car stopping.")
    self.state_delaying = false
    self.speed = 0
    xr_logic.mob_capture(self.object, true)
    action(self.object, move(move.off + move.handbrake, 0), cond(cond.time_end, 3000)) --cond(cond.move_end))
    --self.target_walk_pt = -1
end

function action_car:walk_arrival_callback(index)
    --printf("car <move>: action_car:walk_arrival_callback(%d)", index)
    if index == -2 then return end

    local suggested_explode = self.path_walk_info[index]["explode"]
    if suggested_explode == "true" then
                --printf("action_car:walk_arrival_callback(): EXPLODE")
        --self:car_explode()
        self.object.health = 0
        self.car:Action(CCar.eWpnActivate, 0)
    end

    local suggested_spd = self.path_walk_info[index]["spd"]
    if suggested_spd then
        self.speed = tonumber(suggested_spd)
    else
        self.speed = def_moving_speed
    end
    --printf("car <move>: new spd = %f", self.speed)

    local suggested_loop = self.path_walk_info[index]["loop"]
    if suggested_loop == "true" then
        self.loop = true
    else
        self.loop = false
    end

    local suggested_dps = self.path_walk_info[index]["dps"]
    if suggested_dps then
        self.min_delta_per_sec = tonumber(suggested_dps)
    else
        self.min_delta_per_sec = def_min_delta_per_sec
    end

    local suggested_exptm = self.path_walk_info[index]["exptm"]
    if suggested_exptm then
        self.min_car_explode_time = tonumber(suggested_exptm)
    else
        self.min_car_explode_time = def_min_car_explode_time
    end

    local sig = self.path_walk_info[index]["sig"]
    --printf("car <sig>: try")
    if sig then
        --self.st.signals[sig] = true
        self:set_signal(sig)
        --printf("car <sig>: %s", sig)
    end

    if self.hasWeapon and self.state_firetarget == state_firetarget_points then
        local next_idx = self:get_next_walkpoint()
        --local next_idx = self.target_walk_pt
        if next_idx >= 0 then
            local fw = self.path_walk_info[next_idx]["fw"]
            if fw then
                self.fire_wait = if_then_else(fw == "true", true, false)
            else
                self.fire_wait = false
            end

            local fr = self.path_walk_info[next_idx]["fr"]
            if fr then
                if fr == "inf" then
                    self.fire_rep = -1
                else
                    local c = tonumber(fr)
                    self.fire_rep = if_then_else(c > 0, c, 0)
                end
            else
                self.fire_rep = self.def_fire_rep
            end
        else
            self.fire_wait = false
            self.fire_rep = self.def_fire_rep
        end
        --printf("car <fire>: fire_wait = %s", if_then_else(self.fire_wait, "true", "false"))
        --printf("car <fire>: fire_rep = %d", self.fire_rep)
    end

    -- Выбрать следующую точку езды:
    self.target_walk_pt = self:get_next_walkpoint()
    --printf("car <move>: target_walk_pt = %s.", utils.to_str(self.target_walk_pt))
    --if not self.target_walk_pt then
    --printf("car <move>: stop moving.")
    --    self:stop_car()
        -- Остановить машину
        --if self.state_cannon == state_cannon_stop then
        --    xr_logic.mob_capture(self.object, true)
        --end
        --action(self.object, move(move.off, 0), cond(cond.time_end, 1000))
        --self.state_moving = state_moving_end
    --    return
    --end

    if self.target_walk_pt >= 0 then
        -- Если эта точка рядом и уже приехали - не ждать апдейта, чтобы вызвать callback
        if self:at_target_walkpoint() then
            self:walk_arrival_callback(self.target_walk_pt)
        else
            --self.target_dist = -1
            self:go_to_walkpoint(self.target_walk_pt)
        end
    else
        --printf("car <move>: stop moving.")
        self.target_walk_pt = -2
        if self.state_moving ~= state_moving_stop and self.state_moving ~= state_moving_end then
            self:stop_car()
            self.state_moving = state_moving_end
        end
    end
end

--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
--++++++++++++++++++++-- FIRE SECTION --++++++++++++++++++++--
--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--

function action_car:change_fire_pts()
    --printf("car <fire>: action_car:change_fire_pts()")

    self.state_cannon = state_none
    self.state_shooting = state_none
    
    self.fire_pt_arr = {}
    self.fire_pt_count = 0
    self.target_fire_pt_idx = 0
    self.target_fire_pt = nil
    self.fire_rot_dir = 1
    self.fire_start_time = 0

    if not self.path_fire then return end
    
    local fire_idx
    if self.target_walk_pt >= 0 then
        -- Значение флагов огневых точек, котые будем искать:
        local fire_flags = self.path_walk_info[self.target_walk_pt].flags
        
        if fire_flags:get() == 0 then
            return
        end

        local this_val
        for fire_idx = 0, self.path_fire:count() - 1 do
            this_val = self.path_fire_info[fire_idx].flags
            if this_val:equal(fire_flags) then
                table.insert(self.fire_pt_arr, fire_idx)
                self.fire_pt_count = self.fire_pt_count + 1
            end
        end
    else
        for fire_idx = 0, self.path_fire:count() - 1 do
            table.insert(self.fire_pt_arr, fire_idx)
        end
        self.fire_pt_count = self.path_fire:count()
    end
    
    --printf("car <fire>: points")
    print_table(self.fire_pt_arr)

    if self.fire_pt_count == 0 then
        self.state_cannon = state_cannon_stop
        return
    end
    
    --if self.fire_pt_count > 0 then
    --    self.target_fire_pt_idx = 0
    --    self.target_fire_pt = self.path_fire:point(self.fire_pt_arr[0])
    --end
end

function action_car:get_next_firepoint()
    if self.fire_pt_count < 1 then return nil end

    --printf("car <fire>: action_car:get_next_firepoint(%d,%d,%d)", self.target_fire_pt_idx, self.fire_pt_count, self.fire_rep)
    local pt_idx
    if self.target_fire_pt_idx > 0 then -- not first time
        if self.fire_pt_count > 1 then -- we have at least 2 point to switch
            pt_idx = self.target_fire_pt_idx + self.fire_rot_dir
            if (pt_idx < 1 or pt_idx > self.fire_pt_count) then
                self.fire_rot_dir = -self.fire_rot_dir -- change rotate direction [-1,1]
                --printf("car <fire>: changing direction")
                if self.fire_rep == -1 then
                    pt_idx = self.target_fire_pt_idx + self.fire_rot_dir
                elseif self.fire_rep > 0 then
                    pt_idx = self.target_fire_pt_idx + self.fire_rot_dir
                    self.fire_rep = self.fire_rep - 1
                else
                    pt_idx = 0
                end
            end
        elseif self.fire_rep == -1 then -- left same point in the infinity loop
            pt_idx = 1
        elseif self.fire_rep > 0 then -- left same point if loop defined
            pt_idx = 1
            self.fire_rep = self.fire_rep - 1
        end
    else
        pt_idx = 1
    end
    --self.target_fire_pt_idx = pt_idx
    
    --printf("car <fire>: pt_idx = %d", pt_idx)

    if pt_idx > 0 then
        return pt_idx, self.path_fire:point(self.fire_pt_arr[pt_idx])
    end

    self.state_firetarget = state_none
    return pt_idx, nil
end

function action_car:rot_to_firepoint(pt)
--[[
    if pt then
        self.car:SetParam(CCar.eWpnDesiredPos, pt)
    end
    --printf("car <fire>: action_car:rot_to_firepoint(%d)", shooting)
    self.car:Action(CCar.eWpnFire, shooting)
--]]
    if self.target_fire_pt then
    --    self.state_cannon = state_cannon_rotate
        self.car:SetParam(CCar.eWpnDesiredPos, self.target_fire_pt)
        --printf("car <fire>: action_car:rot_to_firepoint(%d)", self.target_fire_pt_idx)
    --else
    --    self.state_cannon = state_cannon_stop
    end
end

function action_car:set_shooting(shooting)
    self.car:Action(CCar.eWpnFire, shooting)
    --printf("car <fire>: action_car:set_shooting(%d)", shooting)
end

function action_car:fire_arrival_callback(cur_index)
    if self.fire_pt_count < 1 or self.state_cannon == state_cannon_stop then return end
    
    --printf("car <fire>: action_car:fire_arrival_callback(%s)", utils.to_str(cur_index))
    if self.state_cannon == state_cannon_delay then
        --printf("car <fire>: 1.delay mode off.")
        -- Выбрать следующую точку езды:
        self.target_fire_pt_idx, self.target_fire_pt = self:get_next_firepoint()

        if self.target_fire_pt then
            --printf("car <fire>: 1.rotate mode on.")
            self.state_cannon = state_cannon_rotate
            if self.fire_rot_dir == 1  and self.fire_forward or
               self.fire_rot_dir == -1 and self.fire_backward then
                --printf("car <fire>: 1.shooting on.")
                self.state_shooting = state_shooting_on
            else
                --printf("car <fire>: 1.shooting off.")
                self.state_shooting = state_none
            end
            self:rot_to_firepoint(self.target_fire_pt)
            self:set_shooting(self.state_shooting)
        else
            --printf("car <fire>: 1.cannon stopped.")
            self.state_cannon = state_cannon_stop
            if self.state_shooting ~= state_none then
                self.state_shooting = state_none
                self:set_shooting(self.state_shooting)
                self:set_signal("fire_end")
            end
        end
        return
    end

    --printf("car <fire>: action_car: fire_arrival_callback(%s)", utils.to_str(cur_index))
    if cur_index > 0 then
        local idx = self.fire_pt_arr[cur_index]

        local ff = self.path_fire_info[idx]["ff"]
        if ff then
            self.fire_forward = if_then_else(ff == "true", true, false)
        else
            self.fire_forward = false
        end

        local fb = self.path_fire_info[idx]["fb"]
        if fb then
            self.fire_backward = if_then_else(fb == "true", true, false)
        else
            self.fire_backward = false
        end

        local f = self.path_fire_info[idx]["f"]
        if f then
            self.state_shooting = if_then_else(f == "true", state_shooting_on, state_none)
        else
            self.state_shooting = if_then_else(self.st.auto_fire, state_shooting_on, state_none)
        end

        local ft = self.path_fire_info[idx]["ft"]
        if ft then
            self.fire_time = tonumber(ft)
        else
            self.fire_time = self.def_fire_time
        end
    else
            self.fire_forward = false
            self.fire_backward = false
            self.state_shooting = if_then_else(self.st.auto_fire, state_shooting_on, state_none)
            self.fire_time = def_min_fire_time
    end
    --printf("car <fire>: state_shooting = %s", if_then_else(self.state_shooting ~= 0, "true", "false"))
    --printf("car <fire>: auto_fire = %s", if_then_else(self.st.auto_fire, "true", "false"))
    --printf("car <fire>: fire_time = %f", self.fire_time)

    if self.fire_time > 0 then
        --printf("car <fire>: 2.delay mode on.")
        self.state_cannon = state_cannon_delay
        self.fire_start_time = time_global()
        --printf("car <fire>: state_shooting = %s", if_then_else(self.state_shooting ~= 0, "true", "false"))
        --self:rot_to_firepoint(nil)
        self:set_shooting(self.state_shooting)
    else
        -- Выбрать следующую точку стрельбы:
        self.target_fire_pt_idx, self.target_fire_pt = self:get_next_firepoint()

        -- Если мы уже целимся в эту точку - не ждать апдейта, чтобы вызвать callback
        if self.target_fire_pt then
            --printf("car <fire>: 2.rotate mode on.")
            self.state_cannon = state_cannon_rotate
            if self.fire_rot_dir == 1  and self.fire_forward or
               self.fire_rot_dir == -1 and self.fire_backward then
                self.state_shooting = state_shooting_on
                --printf("car <fire>: 2.shooting on.")
            else
                self.state_shooting = state_none
                --printf("car <fire>: 2.shooting off.")
            end
            self:rot_to_firepoint(self.target_fire_pt)
            self:set_shooting(self.state_shooting)
        else
            --printf("car <fire>: 2.cannon stopped.")
            self.state_cannon = state_cannon_stop
            if self.state_shooting ~= state_none then
                self.state_shooting = state_none
                self:set_shooting(self.state_shooting)
                self:set_signal("fire_end")
            end
        end
    end
end

--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
--+++++++++++++++++++-- COMMON SECTION --+++++++++++++++++++--
--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
function action_car:set_signal(sig)
    local stor = db.storage[self.object:id()]
    stor[stor.active_scheme].signals[sig] = true
    --printf("car <sig>: %s", sig)
end

function angle_xz(npc, target_pos)
    local dir1 = npc:direction()
    dir1.y = 0
    local dir2 = utils.vector_copy_by_val(target_pos):sub(npc:position())
    dir2.y = 0
    local dp = dir1:dotproduct(dir2)
    if dp < 0 then
        return math.pi - yaw(dir1, dir2)
    end
    return yaw(dir1, dir2)
end

function get_katet(npc, target_pos)
    local p = utils.vector_copy_by_val(target_pos):sub(npc:position())
    local q = npc:direction()
    local k = p.x * q.x + p.y * q.y
    if k ~= 0 then
        return target_pos:distance_to(npc:position()) * (p.x * q.y - p.y * q.x) / k
    end
    return -1
end

function action_car:fastcall()
    if db.storage[self.object:id()].active_scheme ~= "ph_car" then
        -- Если активная схема - не машина, снять быстрый апдейт
        return true
    end
    
    if self.usable ~= nil then
        local cu = xr_logic.pick_section_from_condlist(db.actor, self.object, self.usable.condlist)
        local u = (cu == "true" or cu == "")

        if u then
            if self.show_tips and self.tip_use then
                self.object:set_tip_text(self.st.tip_use)
            end
        elseif self.show_tips and self.tip_locked then
            self.object:set_tip_text(self.st.tip_locked)
        end

        self.object:set_nonscript_usable(u)

        return false
    end

    return self:fast_update()
end

function action_car:update(delta)
    self:update_friends_and_target()
        
    if xr_logic.try_switch_to_another_section(self.object, self.st, db.actor) then
        return
    end
    
    if self.destroyed then
        xr_logic.switch_to_section(self.object, self.st, "nil")
        return
    end
    
    if self.st.invulnerable then
        self.object.health = 1
        self.car:SetfHealth(1)
    end
end

function action_car:destroy_car()
    --printf("car <destroy>: START ===============================")
    self.state_moving = state_moving_end
    self:stop_car()
    self.state_cannon = state_none
    self.state_firetarget = state_none
    self.state_shooting = state_none
    self.car:Action(CCar.eWpnAutoFire, 0)
    self:set_shooting(self.state_shooting)

    -- turn off lights
    xr_logic.mob_capture(self.object, true)
    action(self.object, object("left_light",  object.deactivate), cond(cond.time_end, time_infinite))
    xr_logic.mob_capture(self.object, true)
    action(self.object, object("right_light", object.deactivate), cond(cond.time_end, time_infinite))

    xr_logic.mob_release(self.object)
    if self.st.on_death_info ~= nil then
        db.actor:give_info_portion(self.st.on_death_info)
        --printf("car <destroy>: on_death_info [%s]", self.st.on_death_info)
    end
    if self.st.on_death_func then
        loadstring(self.st.on_death_func)()
    end
    self.destroyed = true
    --printf("car <destroy>: END =================================")
end

-- Вернуть true, если апдейты больше не нужны
function action_car:fast_update()
    --printf("car <state>: START FAST UPDATE ======================================================")
    --printf("car <state>: check moving1 - [%d][%d]", self.state_moving, self.target_walk_pt)
        --printf("car <state>: action_car:update(): state=%d", self.state_moving)

    --if not self.object:action() then
    --printf("_pc: CAR EXPLODE")
    --self.object:explode(0)
    --self.object:Explode()
    --end
    
    if self.car:GetfHealth() <= 0 then
        --printf("car <state>: killed.")
        --self:car_explode()
        self:destroy_car()
        return true
    end
    
    local cur_time = time_global()

    if self.fc_upd_num < def_max_fc_upd_num then
        local last_upd = self.fc_last_upd_tm
        if last_upd ~= -1 then
            local n = self.fc_upd_num
            if n < 3000 then
                self.fc_upd_avg = (self.fc_upd_avg * n + (cur_time - last_upd))/(n + 1)
                self.fc_upd_num = n + 1
            else
                self.fc_upd_num = 1
            end
        end
        self.fc_last_upd_tm = cur_time
        --printf("car <state>: average update = %f, time(%f)", self.fc_upd_avg, cur_time)
    end

    if self.state_moving == state_moving_end and
       self.state_cannon == state_cannon_stop and
       self.state_firetarget == state_none
    then
        if xr_logic.mob_captured(self.object) and not self.object:action() then
            --printf("car <state>: stop fast updating. moving(%s) cannon(%s)", utils.to_str(self.state_moving), utils.to_str(self.state_cannon))
            --xr_logic.mob_release(self.object)
            --if self.st.on_death_info ~= nil then
            --    printf("car <death>: stopped")
            --    db.actor:give_info_portion(self.st.on_death_info)
            --end
            printf("car <state>: stopped")
            self:destroy_car()
            return true -- апдейты больше не нужны
        end
        return false
    end

    if self.state_moving ~= state_moving_end and
       self.state_moving ~= state_moving_stop and 
       cur_time >= self.last_pos_time + self.min_car_explode_time
    then
        --printf("car <state>: moving(%s)", utils.to_str(self.state_moving))
        if not self.last_pos then
            self.last_pos = self.object:position()
            self.last_pos_time = cur_time
        else
            local cur_pos = self.object:position()
            local diff = self.last_pos:distance_to(cur_pos)
            if diff < self.min_delta_per_sec then
                --printf("car <move>: got stuck (%f < %f) - stop.", diff, self.min_delta_per_sec)
                self:stop_car()
                --self:car_explode()
                self.state_moving = state_moving_end
                --return false
            else
                self.last_pos = cur_pos
            end
            self.last_pos_time = cur_time
        end
    end
    
    --printf("car <state>: check moving2 - [%d][%d]", self.state_moving, self.target_walk_pt)
    if self.state_moving ~= state_moving_end and
       self.state_moving ~= state_none
    then
        --printf("car <move>: try")
        if self.target_walk_pt >= 0 then
            if self:at_target_walkpoint() then
                --printf("car <move>: at target point")
                -- если нет флага ожидания стрельбы или мы уже отстрелялись или пошли в цикле обратно
                if not self.fire_wait or self.state_cannon == state_cannon_stop then --self.fire_rot_dir == -1 then
                        --printf("car <move>: car go to the new point.")
                        -- Прибыли, выбрать новую точку
                        self:walk_arrival_callback(self.target_walk_pt)
                        --printf("car <move>: new target = %s", utils.to_str(self.target_walk_pt))
                        -- меняем точки отстрела
                        self:change_fire_pts()
                else
                    --printf("car <move>: 1.car stopped.")
                    if self.state_moving ~= state_moving_stop then
                        self:stop_car()
                    end
                    self.state_moving = state_moving_stop
                end
            else
                --printf("car <move>: car keep going.")
                -- Продолжать ехать, или поворачиваться
                self:go_to_walkpoint(self.target_walk_pt)
            end
        else
            --printf("car <move>: 2.car stopped.")
            if self.state_cannon ~= state_cannon_stop then
                self:stop_car()
                self.state_moving = state_moving_stop
            end
        end
    end
    
    --printf("car <fire>: TEST")
    if self.hasWeapon then
        --printf("car <fire>: target(%d)", self.state_firetarget)
        if self.on_target_vis and self.on_target_vis.v1:alive() and self.car:IsObjectVisible(self.on_target_vis.v1) then
            --printf("car <vis>: try")
            local new_section = xr_logic.pick_section_from_condlist(db.actor, self.object, self.on_target_vis.condlist)
            if new_section then
                --printf("car <vis>: switch to section [%s]", new_section)
                xr_logic.switch_to_section(self.object, self.st, new_section)
            end
        end

        if self.on_target_nvis and self.on_target_nvis.v1:alive() and not self.car:IsObjectVisible(self.on_target_nvis.v1) then
            --printf("car <nvis>: try")
            local new_section = xr_logic.pick_section_from_condlist(db.actor, self.object, self.on_target_nvis.condlist)
            if new_section then
                --printf("car <nvis>: switch to section [%s]", new_section)
                xr_logic.switch_to_section(self.object, self.st, new_section)
            end
        end

        if self.state_firetarget == state_firetarget_points then
            if self.fire_pt_count > 0 and self.state_cannon ~= state_cannon_stop then
                --printf("car <fire>: shooting points")
                if self.state_cannon == state_cannon_delay then
                    if self.fire_start_time + self.fire_time < cur_time then
                        --printf("car <fire>: stop delaying(%.2f + %.2f < %.2f)", self.fire_start_time, self.fire_time, time_global())
                        --printf("car <fire>: 1.new fire point.")
                        self:fire_arrival_callback(self.target_fire_pt_idx)
                    else
                        --printf("car <fire>: delaying(%.2f + %.2f < %.2f)", self.fire_start_time, self.fire_time, cur_time)
                    end
                else
                    if self.car:CanHit() or self.target_fire_pt_idx == 0 then
                        --printf("car <fire>: 2.new fire point.")
                        -- Прибыли, выбрать новую точку
                        self:fire_arrival_callback(self.target_fire_pt_idx)
                    end
                end
            end
        elseif self.state_firetarget == state_firetarget_enemy then
                
            local target_dist = self.object:position():distance_to_sqr(self.target_obj:position())
                
            local has_friends_on_fire_line = self:check_friends_on_fire_line()
                
            if self.target_obj:alive() and
               target_dist <= self.fire_range_sqr and
               self.car:IsObjectVisible(self.target_obj) and
                         not has_friends_on_fire_line
            then
                printf("car <fire>: enemy(%s) is visible.", self.target_obj:name())

                self.target_fire_pt = self:extrapolate_pos(self.target_obj)
                --[[
                if self.target_obj:id() ~= db.actor:id() then
                  if self.target_obj:target_body_state() == move.crouch then
                      self.target_fire_pt.y = self.target_fire_pt.y + 0.6 -- FAKE
                  elseif not xr_wounded.is_heavy_wounded_by_id(self.target_obj:id()) then
                      self.target_fire_pt.y = self.target_fire_pt.y + 1.4 -- FAKE
                  else
                      self.target_fire_pt.y = self.target_fire_pt.y + 0.15 -- FAKE
                  end
                end
                ]]
                self:rot_to_firepoint(self.target_fire_pt)

                if self.car:CanHit() then
                    if self.state_shooting == state_none then
                        printf("car <fire>: shooting enemy (first).")
                        self.state_shooting = state_shooting_on
                    else
                        self:set_shooting(self.state_shooting)
                        --self:set_signal("fire_start")
                    end
                    printf("car <fire>: shooting enemy.")
                else
                    if self.state_shooting ~= state_none then
                        printf("car <fire>: targeting enemy (first).")
                      self.state_shooting = state_none
                      self:set_shooting(self.state_shooting)
                      --self:set_signal("fire_end")
                    end
                    printf("car <fire>: targeting enemy.")
                end
            else
                if self.state_shooting ~= state_none then
                    --printf("car <fire>: enemy isn't visible (first).")
                    self.state_shooting = state_none
                    self:set_shooting(self.state_shooting)
                    --self:set_signal("fire_end")
                end
                --printf("car <fire>: enemy isn't visible.")

                if self.fire_track_target then
                    self.target_fire_pt = self:extrapolate_pos(self.target_obj)
                    self:rot_to_firepoint(self.target_fire_pt)
                    --printf("car <fire>: target tracking.")
                end
            end
        end
    end
    
    --printf("car <state>: check moving3 - [%d][%d]", self.state_moving, self.target_walk_pt)
    --printf("car <state>: END FAST UPDATE ========================================================\n")
    return false
end

function action_car:extrapolate_pos(obj)
  local mypos=self.object:position()
  if not self.prev_pos then
    self.prev_pos=obj:bone_position("bip01_spine1")
    self.prev_delta=vector():set(0,0,0)
  end
  local curpos=obj:bone_position("bip01_spine1")
  local hcorr=mypos:distance_to_sqr(curpos)/180/180*1.3
  local delta=obj:bone_position("bip01_spine1"):sub(self.prev_pos)
  self.prev_delta:mul(1):add(delta):mul(0.5)
  local extrapos=vector():set(self.prev_delta.x,self.prev_delta.y,self.prev_delta.z):mul(10):add(curpos):add(vector():set(0,hcorr,0))
  self.prev_pos=curpos
  return extrapos
end

function action_car:car_explode()
    self.object:explode(time_global())
end

function action_car:net_destroy()
    --self:destroy_car()
    if self.object and xr_logic.mob_captured(self.object) then
        xr_logic.mob_release(self.object)
        if self.st.on_death_info ~= nil then
            db.actor:give_info_portion(self.st.on_death_info)
            --printf("car <death>: give info")
        end
        if self.st.on_death_func then
            loadstring(self.st.on_death_func)()
        end
    end
end

function action_car:check_friends_on_fire_line()
    if self.target_fire_pt then
        local pos=self.object:bone_position("mashine_gun_fire_point")
        local dir_aim = vector():set(self.target_fire_pt.x - pos.x, self.target_fire_pt.y - pos.y , self.target_fire_pt.z - pos.z)    
        local target_dist = pos:distance_to(self.target_obj:position())
--проверяем позиции солдат и текущего сектора обстрела
        for a,v in pairs(self.friends) do
            tmp=level.object_by_id(a)
            if tmp and tmp:alive() then
                local pos_soldier = tmp:position()
                local radius=4
                if v=="vehicle_btr" then
                    radius=4
                else
                    radius=1.7
                end
                local friend_dist=self.object:position():distance_to(pos_soldier)-radius

                if friend_dist < target_dist then
                    --считаем попадает ли текущий солдат в сектор обстрела
                    local dir_soldier = vector():set(pos_soldier.x - pos.x, pos_soldier.y - pos.y , pos_soldier.z - pos.z)
                    local x = dir_soldier.x*dir_aim.x+dir_soldier.z*dir_aim.z
                    local y = -dir_soldier.z*dir_aim.x+dir_soldier.x*dir_aim.z -- повернули систему координат     
                    local angle = math.atan2(y,x) -- угол доворота от -180 до 180
                    local div = radius/friend_dist
                    if angle >= -div and angle <= div then return true end
                end
            end
        end
    end

    return false
end

function action_car:update_friends_and_target()

--get_console():execute("CHEKING!!!")
 if self.st.fire_target == "monsters" then
for k in pairs(db.monster_stock) do
    local obj = level.object_by_id(k)
if obj and IsMonster(obj) and obj:alive() and self.car:IsObjectVisible(obj) then
                    self.target_obj = obj
                    self.state_firetarget = state_firetarget_enemy
--get_console():execute(" !!_"..obj:name().."_!!")
end
end
end

 --end obj:section()=="vehicle_btr"
  if self.st.fire_target == "all_heli" then
--get_console():execute("CHEKING_HELI")
for a=1,65534,1 do
    local obj = level.object_by_id(a)
if obj and obj:section()=="helicopter" and obj:alive() and self.car:IsObjectVisible(obj) then
                    self.target_obj = obj
                    self.state_firetarget = state_firetarget_enemy
--get_console():execute(" !!_"..obj:name().."_!!")
end
end
end

 if self.st.fire_target == "stalker_group" then --- character_community() - группировка по которой БТР будет вести огонь.
--get_console():execute("CHEKING_STALKER")
for a=1,65534,1 do
    local obj = level.object_by_id(a)
if obj and IsStalker(obj) and obj:alive() and obj:character_community()=="stalker" and self.car:IsObjectVisible(obj) then
                    self.target_obj = obj
                    self.state_firetarget = state_firetarget_enemy
--get_console():execute(" !!_"..obj:name().."_!!")
end
end
end

end
---------------------------------------------------------------------------------------------------------------------
function add_to_binder(npc, ini, scheme, section, storage)
        --printf("DEBUG: add_to_binder: scheme='%s', section='%s'", scheme, section)
    local new_action = action_car(npc, storage)

    -- Зарегистрировать все actions, в которых должен быть вызван метод reset_scheme при изменении настроек схемы:
    xr_logic.subscribe_action_for_events(npc, storage, new_action)
end

function set_scheme(npc, ini, scheme, section, gulag_name)
    local st = xr_logic.assign_storage_and_bind(npc, ini, scheme, section)

    st.logic            = xr_logic.cfg_get_switch_conditions(ini, section, npc)

    st.usable          = xr_logic.cfg_get_condlist(ini, section, "usable", npc)
    if st.usable == nil then
        st.path_walk        = utils.cfg_get_string(ini, section, "path_walk",       npc, false, gulag_name)
        st.path_fire        = utils.cfg_get_string(ini, section, "path_fire",       npc, false, gulag_name, nil)
        st.auto_fire        = utils.cfg_get_bool(ini,   section, "auto_fire",       npc, false, false)
        st.fire_time        = utils.cfg_get_number(ini, section, "fire_time",       npc, false, def_min_fire_time)
        st.fire_rep         = utils.cfg_get_string(ini, section, "fire_repeat",     npc, false, gulag_name, nil)
        st.fire_range       = utils.cfg_get_number(ini, section, "fire_range",      npc, false, def_fire_range)
        st.fire_target      = utils.cfg_get_string(ini, section, "target",          npc, false, gulag_name, "points")
        st.fire_track_target= utils.cfg_get_bool(ini,   section, "track_target",    npc, false, false)

        st.on_target_vis    = xr_logic.cfg_get_string_and_condlist(ini, section, "on_target_vis", npc)
        st.on_target_nvis   = xr_logic.cfg_get_string_and_condlist(ini, section, "on_target_nvis", npc)

        st.path_walk_info   = nil -- Будут инициализированы в reset(), сейчас пути могут быть еще не загружены.
        st.path_fire_info   = nil
    else
        st.show_tips    = utils.cfg_get_bool(ini,   section, "show_tips",  npc, false, true)
        st.tip_use      = utils.cfg_get_string(ini, section, "tip_use",    npc, false, "", "tip_car_use")
        st.tip_locked   = utils.cfg_get_string(ini, section, "tip_locked", npc, false, "", "tip_car_locked")
    end

    st.invulnerable     = utils.cfg_get_bool(ini,   section, "invulnerable",    npc, false, false)
    st.headlights       = utils.cfg_get_string(ini, section, "headlights",      npc, false, gulag_name, "off")
    st.on_death_info    = utils.cfg_get_string(ini, section, "on_death_info",   npc, false, gulag_name, nil)
    st.on_death_func    = utils.cfg_get_string(ini, section, "on_death_func",   npc, false, gulag_name, nil)
end

 

 

Ссылка на комментарий
5 часов назад, Капрал Хикс сказал(а):

Почему-то повторяются функции function add_obj( obj ) и function del_obj( obj ) и мне это кажется странным. Такое вообще допустимо?

Как ни странно, да. Примеры двойного объявления одних и тех же функций встречаются даже в скриптах оригинала (хотя, может быть, это-то как раз и не странно). Если кому интересно - загляните в чистонебовский скрипт task_objects.script, функция CHideFromSurgeTask:check_task(). Там внутри есть две встроенные функции, описанные дважды в пределах одного пространства.

На практике, если представить, что содержимое повторяющихся функций различно, работать будет та, которая объявлена второй (третьей, четвёртой и так далее).

Что конкретно должно быть в примере выше, сказать не могу. Всё зависит от логики, которую хотелось вложить в код автору. Возможно, заполняться должна только таблица creatures, возможно - creature, а возможно и обе сразу. Надо изучать те скрипты, где они используются далее.

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

function add_obj( obj )
    -- ... <skip> ...

    if IsStalker(obj) and IsMonster(obj) then --> если И сталкер И монстр
        btr_target[obj:id()] = true
    end
end

Ничего не смущает?

Ссылка на комментарий
20 минут назад, Kirgudu сказал(а):

Ничего не смущает?

Ох уж этот чужой код... Да, там лучше or поставить, думаю.

  • Согласен 1
Ссылка на комментарий
9 часов назад, Капрал Хикс сказал(а):

Скрипт правленого ph_car вот:

А где в нём используются функции add_obj и del_obj?

S.T.A.L.K.E.R. CoP Objects (upd 11.03.24)

Ссылка на комментарий

@WinCap , эти функции вызываются в биндерах неписей и монстров. В скрипте используются заполняемые этими функциями таблицы.

Изменено пользователем naxac
  • Согласен 1
  • Полезно 1

Аддон для ОП-2.09.2: Яндекс/Google/GitHub

naxac.gif

Ссылка на комментарий

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

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

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

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

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

Войти

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

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

AMK-Team.ru

×
×
  • Создать...