local math_random = math.random local nom_msg = { 'munch', 'munch', 'yum' } local Public = {} local function feed_floaty_text(unit) unit.surface.create_entity( { name = 'flying-text', position = unit.position, text = nom_msg[math_random(1, #nom_msg)], color = { math_random(50, 100), 0, 255 } } ) end local function floaty_hearts(entity, c) local position = { x = entity.position.x - 0.75, y = entity.position.y - 1 } local b = 1.35 for _ = 1, c, 1 do local p = { (position.x + 0.4) + (b * -1 + math_random(0, b * 20) * 0.1), position.y + (b * -1 + math_random(0, b * 20) * 0.1) } entity.surface.create_entity({ name = 'flying-text', position = p, text = '♥', color = { math_random(150, 255), 0, 255 } }) end end local function tame_unit_effects(player, entity) floaty_hearts(entity, 7) rendering.draw_text { text = '~' .. player.name .. "'s pet~", surface = player.surface, target = { entity = entity, offset = { 0, -2.6 }, }, color = { r = player.color.r * 0.6 + 0.25, g = player.color.g * 0.6 + 0.25, b = player.color.b * 0.6 + 0.25, a = 1 }, scale = 1.05, font = 'default-large-semibold', alignment = 'center', scale_with_zoom = false } end local function find_unit(player, entity) local units = player.surface.find_entities_filtered( { type = 'unit', area = { { entity.position.x - 1, entity.position.y - 1 }, { entity.position.x + 1, entity.position.y + 1 } }, limit = 1 } ) return units[1] end local function feed_pet(unit) if unit.max_health == unit.health then return end unit.health = unit.health + 8 + math.floor(unit.max_health * 0.05) feed_floaty_text(unit) floaty_hearts(unit, math_random(1, 2)) return true end local function is_valid_player(player, unit) if not player.character then return end if not player.character.valid then return end if player.surface.index ~= unit.surface.index then return end return true end function Public.biter_pets_tame_unit(player, unit, forced) if storage.biter_pets[player.index] then return false end if not forced then if math_random(1, math.floor(unit.max_health * 0.01) + 1) ~= 1 then feed_floaty_text(unit) return true end end if unit.force.index == player.force.index then return false end unit.ai_settings.allow_destroy_when_commands_fail = false unit.ai_settings.allow_try_return_to_spawner = false unit.force = player.force unit.set_command({ type = defines.command.wander, distraction = defines.distraction.by_enemy }) storage.biter_pets[player.index] = { last_command = 0, entity = unit } tame_unit_effects(player, unit) return true end function Public.tame_unit_for_closest_player(unit) local valid_players = {} for _, player in pairs(game.connected_players) do if is_valid_player(player, unit) then table.insert(valid_players, player) end end local nearest_player = valid_players[1] if not nearest_player then return end -- for i = 2, #valid_players, 1 do -- local player = valid_players[i + 1] -- if player.position.x ^ 2 + player.position.y ^ 2 < nearest_player.position.x ^ 2 + nearest_player.position.y ^ 2 then -- end -- end Public.biter_pets_tame_unit(nearest_player, unit, true) end local function command_unit(entity, player) local square_distance = (player.position.x - entity.position.x) ^ 2 + (player.position.y - entity.position.y) ^ 2 --Pet will follow, if the player is between a distance of 8 to 160 tiles away from it. if square_distance < 64 or square_distance > 25600 then entity.set_command({ type = defines.command.wander, distraction = defines.distraction.by_enemy }) else entity.set_command( { type = defines.command.go_to_location, destination_entity = player.character, radius = 4, distraction = defines.distraction.by_damage } ) end end local function on_player_changed_position(event) if math_random(1, 100) ~= 1 then return end local player = game.players[event.player_index] if not storage.biter_pets[player.index] then return end if not storage.biter_pets[player.index].entity then storage.biter_pets[player.index] = nil return end if not storage.biter_pets[player.index].entity.valid then storage.biter_pets[player.index] = nil return end if not player.character then return end if storage.biter_pets[player.index].last_command + 600 > game.tick then return end storage.biter_pets[player.index].last_command = game.tick command_unit(storage.biter_pets[player.index].entity, player) end local function on_player_dropped_item(event) local player = game.players[event.player_index] if event.entity.stack.name ~= 'raw-fish' then return end local unit = find_unit(player, event.entity) if not unit then return end if Public.biter_pets_tame_unit(player, unit, false) then event.entity.destroy() return end if unit.force.index == player.force.index then feed_pet(unit) end end local function on_init() storage.biter_pets = {} end local Event = require 'utils.event' Event.on_init(on_init) Event.add(defines.events.on_player_dropped_item, on_player_dropped_item) Event.add(defines.events.on_player_changed_position, on_player_changed_position) return Public