--'****************************************************** --'* Объект группировки. --'****************************************************** local TASK_DISTANCE = 300*300 -- Квадрат радиуса, в котором выдаются таски игроку class "faction_brain_human" function faction_brain_human:__init(faction) self.faction = faction self.human = true self.use_issue_order = true self.use_cover_attack = true self.use_prepare_phase = true self.use_delay_attack = false if self.faction.player_name == "killer" then self.use_counter_attack = false else self.use_counter_attack = true end end -- Рассчет текущей экспансии function faction_brain_human:calculate_current_expansion() local faction = self.faction local relative_power = faction:get_relative_power() --callstack() --printf("faction [%s] brain update %s", faction.player_name, relative_power) for k, expansion in pairs(faction.expansion_level) do --printf("check %s, current %s", k, faction.current_expansion_level) if faction.current_expansion_level > k then -- Если проверяемый уровень экспансии ниже, чем текущий local power_valid = relative_power > expansion.precondition_power local advance_valid = self:check_sim_targets_advance(expansion) local cond_valid = xr_logic.pick_section_from_condlist(db.actor, self, expansion.precondition_cond) == "true" local actor_valid = expansion.precondition_actor_in_faction ~= true or faction.community_player == true -- Проверяем все ли условия выполняются if not (cond_valid and power_valid and advance_valid and actor_valid) then -- Если не выполняются - выдаем сообщение о потери уровня, ресетим квесты, прекращаем работу цикла. --printf("LEVEL DOWN %s %s %s %s", self.faction.player_name, tostring(cond_valid), tostring(power_valid), tostring(advance_valid)) if faction.community_player == true then if db.actor ~= nil and faction.expansion_level[faction.current_expansion_level].level_down_snd ~= nil then xr_sound.set_sound_play(faction.id, faction.expansion_level[faction.current_expansion_level].level_down_snd, faction.player_name) end end faction.current_expansion_level = k break end elseif faction.current_expansion_level == k then -- Если проверяемый уровень равен текущему. -- Проверяем, все ли условия выполняются. local power_valid = relative_power > expansion.precondition_power local advance_valid = self:check_sim_targets_advance(expansion) local cond_valid = xr_logic.pick_section_from_condlist(db.actor, self, expansion.precondition_cond) == "true" local actor_valid = expansion.precondition_actor_in_faction ~= true or faction.community_player == true if not (cond_valid and power_valid and advance_valid and actor_valid) then -- Если не выполняются - прекращаем работу цикла. break end else -- Если проверяемый уровень выше текущего. -- Выдаем сообщение о поднятии уровня, ресетим квесты, прекращаем работу цикла. --printf("LEVEL UP %s from %s", faction.player_name, faction.current_expansion_level) if faction.community_player == true then local old_exp = faction.expansion_level[faction.current_expansion_level] if db.actor ~= nil and old_exp.level_up_snd ~= nil then xr_sound.set_sound_play(faction.id, old_exp.level_up_snd, faction.player_name) end end faction.current_expansion_level = k break end end self:calculate_expansion_targets() end -- Формирование целей на основе текущей экспансии function faction_brain_human:calculate_expansion_targets() local faction = self.faction local relative_power = faction:get_relative_power() faction.target_smart_value = {} --printf("faction %s calculate_expansion_targets for %s", faction.player_name, faction.current_expansion_level) if faction.current_expansion_level == 0 then return end -- Сперва определяем нужно ли нам больше силы self:get_sim_targets_power(relative_power < faction.expansion_level[faction.current_expansion_level].precondition_power) -- Потом определяем ключевые точки. for i = 1,faction.current_expansion_level do --printf("%s", i) self:get_sim_targets_advance(faction.expansion_level[i]) end -- Добавляем просто важные точки for k,v in pairs(self.faction.secondary_targets) do local smart_obj = self.faction.board.smarts_by_names[k] self:register_target_point(smart_obj, false, false, true) end if db.actor ~= nil and self.faction.community_player == true then self:reset_actor_tasks() end --' Считаем максимальный потолок отрядов. faction:calculate_total_squads() -- Раздаем цели faction:calculate_squad_tasks() end --' Составляет список нужных для захвата смартов, в который включает ресурсные и территориальные смарты. function faction_brain_human:get_sim_targets_power(need_power_targets) --printf("faction [%s] check_sim_targets_power [%s]", self.faction.player_name, tostring(need_power_targets)) --' Итерируемся по всем смартам, выискиваем попадающие под наше определение --' и устанавливаем им стартовую оценку. local faction = self.faction for k,v in pairs(faction.board.smarts) do if v.smrt.sim_type == "territory" or v.smrt.sim_type == "resource" then -- Если не need_power_targets, то добавляем только те точки, которые уже под нашим контролем. if need_power_targets or v.smrt.player_name == faction.player_name then if sim_board.is_point_avail(v.smrt, faction.player_name) then self:register_target_point(v.smrt, false) end end end end end -- Проверяем, все ли у нас захвачено из важных точек. Автоматом добавляет их в список задач (НО НЕ КВЕСТОВ) function faction_brain_human:check_sim_targets_advance(expansion) for k,v in pairs(expansion.precondition_target) do local smart_obj = self.faction.board.smarts_by_names[v] if smart_obj.player_name ~= self.faction.player_name then return false end end for k,v in pairs(expansion.precondition_target_optional) do local smart_obj = self.faction.board.smarts_by_names[v] if smart_obj.player_name ~= self.faction.player_name then return false end end for k,v in pairs(expansion.precondition_target_eliminate) do local smart_obj = self.faction.board.smarts_by_names[v] local smart_owner = smart_obj.player_name --printf(" check target advance %s owner %s", smart_obj:name(), tostring(smart_owner)) if smart_owner ~= "none" then if game_relations.is_factions_enemies(self.faction.player_name, smart_owner) then return false end end end return true end -- Проверяем, все ли у нас захвачено из важных точек. Автоматом добавляет их в список задач (НО НЕ КВЕСТОВ) function faction_brain_human:get_sim_targets_advance(expansion) for k,v in pairs(expansion.precondition_target) do local smart_obj = self.faction.board.smarts_by_names[v] self:register_target_point(smart_obj, true) end for k,v in pairs(expansion.precondition_target_optional) do local smart_obj = self.faction.board.smarts_by_names[v] self:register_target_point(smart_obj, true) end for k,v in pairs(expansion.precondition_target_eliminate) do local smart_obj = self.faction.board.smarts_by_names[v] local smart_owner = smart_obj.player_name if smart_owner ~= "none" then if game_relations.is_factions_enemies(self.faction.player_name, smart_owner) then self:register_target_point(smart_obj, false, true) end end end end -- Регистрит таргет смарт. При этом может изменить его капасити function faction_brain_human:register_target_point(smart_obj, advance_point, eliminate, no_task) local point_capacity = smart_obj.squad_capacity --printf("faction [%s] register_target_point [%s]", self.faction.player_name, smart_obj:name()) --printf(" name %s == %s", smart_obj.player_name, self.faction.player_name) if smart_obj.player_name == self.faction.player_name or smart_obj.player_name == "none" then -- Если точка уже захвачена или пустая -- Проверяем есть ли в соседних точках враги local enemy_exist = false for k,v in pairs(self.faction.board:get_nearest_smarts(smart_obj)) do if game_relations.is_factions_enemies(v.player_name, self.faction.player_name) then enemy_exist = true break end end --printf(" enemy exist %s", tostring(enemy_exist)) -- if not enemy_exist then -- Если точка принадлежит группировке и вокруг нет врагов - уменьшаем капасити до 1. -- Однако если точка мегаважная (есть флажок), то всегда стараемся заполнить до максимума. --printf(" important_point %s", tostring(smart_obj.important_point)) if not smart_obj.important_point then point_capacity = 1 else if smart_obj.respawn_sector ~= nil then point_capacity = point_capacity - 1 end end -- else -- Если точка - место появления отряда, то оставляем окошко в 1, чтобы мог появиться новый отряд. -- if smart_obj.respawn_sector ~= nil then -- point_capacity = point_capacity - 1 -- end -- end end self.faction.target_smart_value[smart_obj.id] = {smart = smart_obj, cap = point_capacity, num = 0, smart_name = smart_obj:name(), smart_id = smart_obj.id, advance_point = advance_point, eliminate = eliminate, no_task = no_task} --printf(" cap %s", point_capacity) end -- Выдаем игроку квесты на основе выбранных целей для группировки function faction_brain_human:reset_actor_tasks() --printf("faction [%s] reset_actor_tasks", self.faction.player_name) --callstack() --print_table(self.faction.target_smart_value) local tm = task_manager.get_task_manager() local faction = self.faction self.interfirience_points = {} -- Теперь определяем точки, которые мешают пройти нашим отрядам. for k,squad in pairs(faction.squads) do -- бежим по отрядам -- Выбираем которые stay_point local current_action = squad.current_action if current_action ~= nil then if current_action.name == "stay_point" then --printf("CHECK interfirience squad %s next_point_id %s", squad.squad_id, tostring(current_action.next_point_id)) if current_action.next_point_id ~= nil then -- Берем у них next_point_id local point = faction.board.smarts[current_action.next_point_id].smrt if faction.target_smart_value[current_action.next_point_id] ~= nil then --printf("found allies [%s] for [%s]", squad.squad_id, point:name()) faction.target_smart_value[current_action.next_point_id].allies_exist = true else -- Из next_point убираем точки, которые под атакой. --printf("CHECK interfirience %s under_attack %s", point:name(), tostring(point.combat_manager:point_under_attack())) if not point.combat_manager:point_under_attack() and game_relations.is_factions_enemies(squad.player_id, point.player_name) then -- Добавляем в список помех. --printf("ADD interfirience point %s", point:name()) self.interfirience_points[point.id] = point end end end else -- На случай атаки более сильного противника. local point = faction.board.smarts[current_action.dest_smrt_id].smrt if faction.target_smart_value[current_action.dest_smrt_id] ~= nil then --printf("found allies [%s] for [%s]", squad.squad_id, point:name()) faction.target_smart_value[current_action.dest_smrt_id].allies_exist = true else --printf("CHECK attack interfirience %s", point:name()) if not point.combat_manager:point_under_attack() and game_relations.is_factions_enemies(squad.player_id, point.player_name) then -- Добавляем в список помех. --printf("ADD attack interfirience point %s", point:name()) self.interfirience_points[point.id] = point end end end end end end --' Выдача таска игроку на точку для захвата function faction_brain_human:init_player_task(target_data) --printf("IPT [%s] smart %s", self.faction.player_name, target_data.smart_name) --if target_data.no_task == true then -- return --end -- Важная ли точка. local advance_point = target_data.advance_point local eliminate_point = target_data.eliminate local allies_exist = target_data.allies_exist == true local smart = target_data.smart if smart.player_name == self.faction.player_name then --printf(" my smart") return end if sim_board.faction_cluster[self.faction.player_name] ~= sim_board.sim_level_cluster[smart.smart_level] then --printf(" cluster") return end local obj_gv = game_graph():vertex(db.actor:game_vertex_id()) local job_gv = game_graph():vertex(smart.m_game_vertex_id ) local empty_point = smart.player_name == "none" local enemy_point = game_relations.is_factions_enemies(self.faction.player_name, smart.player_name) local actor_in_radius = db.actor:position():distance_to_sqr(smart.position) <= TASK_DISTANCE local actor_in_level = obj_gv:level_id() == job_gv:level_id() -- Определяем какой тип таска, мы должны щас выдать local task_type = nil --[[if eliminate_point == true then if enemy_point then task_type = "eliminate_smart" end elseif advance_point then if actor_in_level then task_type = "capture_smart" end elseif not empty_point then if enemy_point then if allies_exist then task_type = "capture_smart" else if actor_in_level and actor_in_radius then task_type = "eliminate_smart" end end end end]]-- if task_type == nil then --printf(" no type") return end local tm = task_manager.get_task_manager() local faction = self.faction -- Сравниваем с текущим. Если они разные, то дизаблим текущий таск и выдаем новый. local current_faction_task = faction.random_tasks[smart.id] if current_faction_task ~= nil then local current_task = tm:get_task_by_entity_id(current_faction_task) if current_task.type == task_type then return end task.last_check_task = "reversed" return end local task = tm:select_task(task_type, smart, self.faction.player_name) task.faction = self.faction self.faction.random_tasks[smart.id] = task.entity_id if task.status ~= "selected" then task:give_task(self.faction.player_name) end end