Svoboда 3 Опубликовано 23 Апреля 2009 Поделиться Опубликовано 23 Апреля 2009 Тема для обсуждения скриптов всего и всех в серии игр STALKER. Задавая вопрос (!): 1. Внимательно изучите суть вопроса. Вопрос должен соответствовать выбранной Вами темы. Это поможет сохранить порядок и читабельность темы, а также облегчит поиск и понимание сего; 2. Изучите то, что уже есть в теме (пролистайте "руками", воспользуйтесь поиском на форуме); 3. Изучите информацию которая может вам помочь: Stalkerin. Там есть много хороших статей касательно данной темы.Уроки по модостроению. Есть рабочие примеры готовых скриптов различного назначения. Справочное руководство по языку Lua 5.1https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual/ruСправочник по функциям и классам. Собрано много информации по функциям и классам, не всем, но по основные сведения предоставлены. Логика со вступлением и четырьмя частями: ВступлениеЧасть перваяЧасть втораяЧасть третьяЧасть четвертая. Smart_terrain (в простонароде - гулаг)Интересный способ настроики логики для гулаговСкриптовая часть игровой логики 4. Дабы не превращать обсуждение в "кашу" разной информативной направленности, задавайте несколько вопросов по порядку (в разных постах) после того, как получите ответ на предыдущий вопрос; 5. "Спасибо" и тому подобное - будьте так любезны в ПМ. Если не любите писать в ПМ, в конце вопроса напишите фразу: "Заранее спасибо!" - или что-то в этом духе; 6. ПОЖАЛУЙСТА! Указывайте, для какой игры Вам необходима информация (ТЧ, ЧН, ЗП), если стоит мод - укажите название мода; 7. Если Вы что-то сделали и результат не такой, какой Вами задумывался, то, пожалуйста, приводите коды которые Вы изменяли/писали целиком! Это поможет другим правильно ответить на Ваш вопрос, а также оградит Вас от лишней писанины. 8. Оформляйте сообщение. Пользуйтесь тегами для того, чтобы отделить код от текста. Пишите грамотно - ПОЛЬЗУЙТЕСЬ ЗНАКАМИ ПРЕПИНАНИЯ. 9. И помните: «Правильно заданный вопрос – половина ответа». Какие вопросы следует задавать, а какие нет... Задавайте вопросы, которые касаются непосредственно скриптов и их работы, т.е. Вы что-то делаете, а у Вас что-то не получается, при этом у Вас на руках должен быть хотя бы какой-то код, свидетельствующий о Вашей причастности к вопросу. Вопросы которые будут удалятся, следовательно их задавать не нужно:-- Где находится та или иная функция? Для ответа используем поиск по словам среди файлов оригинальной игры или мода, если объект поиска относится к нему, при помощью программы, которая Вам наиболее симпатизирует;-- Как сделать что-то/то-то? С подобными вопросами, либо в "ковырялки", где Вам вероятнее всего так же не ответят, либо выдвигаем мысли, подкреплённые теорией, практикой (идеальный вариант) и здравым рассудком;-- Вопросы со смыслом: "сделайте", "совместите" и подобными глаголами повелительного наклонения.-- К тому же удалению будут подвергаться вопросы, в которых масштабно не используются теги, для отделения кода и цитат от основного текста, а также не вписан в спойлер код размером превышающие семь строк.Ответ на возможно возникший вопрос: В какую тему можно обратиться по поводу логики и спавна объектов? В тему "ковырялок" соответствующей версии игры, для которой Вы задаёте вопрос. И последнее: очень рекомендовано к прочтению Правила форума 1 2 Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/
Space.Marine 466 Опубликовано 28 Апреля 2021 Поделиться Опубликовано 28 Апреля 2021 Попросил помощи с проверкой скрипта на предыдущей странице, но в виду "оживлённой" беседы моё сообщение, видимо, просто осталось без внимания... Попрошу ешо раз: Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/558/#findComment-1381974
Biblia 4 Опубликовано 28 Апреля 2021 Поделиться Опубликовано 28 Апреля 2021 @ARTLantist я все переправил уже. Сделал плюс-минус как ты, только естесн, параметры назвал по-другому Вот еще вопрос: может кто-то может подсказать мод на ЗП, в котором была перенесена из ТЧ скриптовая система фейк слотов с ножом, фонариком и т.д. Просто ввиду того, что еще новичок - скрипты-то совместить я умею, и даже что-то элементарное написать, но вот перенести с одной платформы на другую... Ибо я просто не знаю различий в функциях и т.д. Потому и спрашиваю, может что-то готовое есть 1 Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/558/#findComment-1382000
ARTLantist 14 Опубликовано 28 Апреля 2021 Поделиться Опубликовано 28 Апреля 2021 (изменено) 9 часов назад, Biblia сказал(а): Просто ввиду того, что еще новичок - скрипты-то совместить я умею, и даже что-то элементарное написать, но вот перенести с одной платформы на другую... Ибо я просто не знаю различий в функциях и т.д. Пробуй, экспериментируй - что-то да получится. Это самый лучший способ научиться что-то делать. А вообще, я не вижу смысла всех этих костылей-фейк слотов, когда можно залезть в движок и за 5 минут прописать настоящие, нормально работающие слоты. Изменено 28 Апреля 2021 пользователем ARTLantist 1 2 Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/558/#findComment-1382099
naxac 2 578 Опубликовано 28 Апреля 2021 Поделиться Опубликовано 28 Апреля 2021 (изменено) @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 Изменено 29 Апреля 2021 пользователем naxac 1 1 Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/558/#findComment-1382107
Biblia 4 Опубликовано 29 Апреля 2021 Поделиться Опубликовано 29 Апреля 2021 @ARTLantist были бы у меня исходники движка СТКоПа версии 3.4 - я бы так и сделал. Но так как вынужден работать с тем, что имею - только фейк-слоты. Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/558/#findComment-1382110
ARTLantist 14 Опубликовано 29 Апреля 2021 Поделиться Опубликовано 29 Апреля 2021 @Biblia не поверишь, точно такая же проблема у меня была. Я просто скачал более старый пак, который не требует установки библиотек движка, и всё. Поверь, возможность править движок куда важнее, чем красивый оружейный пак. 1 Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/558/#findComment-1382113
Biblia 4 Опубликовано 29 Апреля 2021 Поделиться Опубликовано 29 Апреля 2021 @ARTLantist на красивый ОП мне как-то по-барабану. Туеву кучу моделей сейчас можно найти и добавить в стулкер. Просто оптимизация 3д прицелов и их реализация лучшая, что я встречал. Товарищ Мортан там потрудился на славу. Да и я просто хочу накатить маленькую сборку для души. И заключительный вопрос: кол-во артов на поясе в ЗП зашито в двигле? Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/558/#findComment-1382114
_Sk8_AsTeR_ 122 Опубликовано 29 Апреля 2021 Поделиться Опубликовано 29 Апреля 2021 Господа, доброго времени! Возникла необходимость перманентно держать на экране определенную информацию. Решил использовать шаблон из туториала: "нажмите "клавиша" чтобы присесть" В конфиге имеем: Скрытый текст <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 секунд (если я правильно понял). А как сделать вывод информации бесконечным? Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/558/#findComment-1382135
ARTLantist 14 Опубликовано 29 Апреля 2021 Поделиться Опубликовано 29 Апреля 2021 (изменено) 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 Изменено 29 Апреля 2021 пользователем ARTLantist 1 Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/558/#findComment-1382137
Biblia 4 Опубликовано 29 Апреля 2021 Поделиться Опубликовано 29 Апреля 2021 32 минуты назад, ARTLantist сказал(а): 5 часов назад, Biblia сказал(а): кол-во артов на поясе в ЗП зашито в двигле да. Ля, тогда придется постигать тяготы движкоправства. Но надо будет и фейк-слоты опробовать Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/558/#findComment-1382142
Stalkersof 202 Опубликовано 29 Апреля 2021 Поделиться Опубликовано 29 Апреля 2021 10 часов назад, naxac сказал(а): @Stalkersof , тебе надо при вызове гуя сохранить ссылку на биндер. Например, так: Спасибо 100% рабочий вариант. Правда с who были проблемы но там спавнить запчасти не кому кроме актора. Все работает так как надо. Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/558/#findComment-1382143
Капрал Хикс 561 Опубликовано 30 Апреля 2021 Поделиться Опубликовано 30 Апреля 2021 Дано: скрипт 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 Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/558/#findComment-1382214
Kirgudu 1 328 Опубликовано 30 Апреля 2021 Поделиться Опубликовано 30 Апреля 2021 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 Ничего не смущает? Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/558/#findComment-1382238
I am Dead 918 Опубликовано 30 Апреля 2021 Поделиться Опубликовано 30 Апреля 2021 @Kirgudu Хмм, действительно тут уж правильней будет "сталкер или монстр" 1 Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/558/#findComment-1382240
Капрал Хикс 561 Опубликовано 30 Апреля 2021 Поделиться Опубликовано 30 Апреля 2021 20 минут назад, Kirgudu сказал(а): Ничего не смущает? Ох уж этот чужой код... Да, там лучше or поставить, думаю. 1 Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/558/#findComment-1382241
WinCap 323 Опубликовано 30 Апреля 2021 Поделиться Опубликовано 30 Апреля 2021 9 часов назад, Капрал Хикс сказал(а): Скрипт правленого ph_car вот: А где в нём используются функции add_obj и del_obj? Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/558/#findComment-1382245
naxac 2 578 Опубликовано 30 Апреля 2021 Поделиться Опубликовано 30 Апреля 2021 (изменено) @WinCap , эти функции вызываются в биндерах неписей и монстров. В скрипте используются заполняемые этими функциями таблицы. Изменено 30 Апреля 2021 пользователем naxac 1 1 Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/558/#findComment-1382246
WinCap 323 Опубликовано 1 Мая 2021 Поделиться Опубликовано 1 Мая 2021 (изменено) 16 минут назад, naxac сказал(а): эти функции вызываются в биндерах неписей и монстров. Да... это понятно... Это был наводящий вопрос. 16 минут назад, naxac сказал(а): В скрипте используются заполняемые этими функциями таблицы. Я на это и хотел обратить внимание вопрошающего. Кроме monster_stock ни одна таблица не используется. И вообще... Функция update_friends_and_target тот ещё "шедевр". Изменено 1 Мая 2021 пользователем WinCap Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/558/#findComment-1382248
gam 118 Опубликовано 1 Мая 2021 Поделиться Опубликовано 1 Мая 2021 Только что, naxac сказал(а): эти функции вызываются в биндерах неписей и монстров Полностью согласен. 3 часа назад, I am Dead сказал(а): Хмм, действительно тут уж правильней будет 3 часа назад, Kirgudu сказал(а): Как ни странно Посвятите в нужном направлении, или похмелитесь. 1 2 Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/558/#findComment-1382252
Graff46 621 Опубликовано 1 Мая 2021 Поделиться Опубликовано 1 Мая 2021 У меня вопрос, почему для управления транспортом скриптами используется FSM, все эти экшены команды и тд... (почитать об этом). На сколько корректно будет, если создам методы для управления техникой в классе CCar ? Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/558/#findComment-1382314
Рекомендуемые сообщения
Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий
Комментарии могут оставлять только зарегистрированные пользователи
Создать аккаунт
Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!
Зарегистрировать новый аккаунтВойти
Есть аккаунт? Войти.
Войти