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

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

@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 10.04.24)


    Подарки

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

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

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

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

    naxac.gif


    Подарки

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

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

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

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

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

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

    Войти

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

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

    AMK-Team.ru

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