mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-02-03 13:12:11 +02:00
Gradual PvP Shield rollout
This commit is contained in:
parent
9c83a364de
commit
34f9c9b2b4
@ -4,9 +4,10 @@ local Event = require 'utils.event'
|
||||
local ScenarioTable = require 'maps.scrap_towny_ffa.table'
|
||||
local CommonFunctions = require 'utils.common'
|
||||
|
||||
local zone_size = 120
|
||||
local max_size = 120
|
||||
local beam_type = 'electric-beam-no-sound'
|
||||
local lifetime_ticks = 4 * 60 * 60 * 60
|
||||
local max_lifetime_ticks = 4 * 60 * 60 * 60
|
||||
local time_to_full_size_ticks = 60 * 60
|
||||
|
||||
local function draw_borders(zone)
|
||||
local surface = zone.surface
|
||||
@ -14,14 +15,15 @@ local function draw_borders(zone)
|
||||
local left = zone.box.left_top.x
|
||||
local top = zone.box.left_top.y
|
||||
local bottom = zone.box.right_bottom.y
|
||||
|
||||
surface.create_entity({name = beam_type, position = {right, top},
|
||||
source = {right, top}, target = {right, bottom + 1}}) -- intentional offset here to correct visual appearance
|
||||
source = {right, top}, target = {right, bottom + 0.5}}) -- intentional offset here to correct visual appearance
|
||||
surface.create_entity({name = beam_type, position = {right, bottom},
|
||||
source = {right, bottom}, target = {left, bottom}})
|
||||
source = {right, bottom}, target = {left, bottom + 0.5}})
|
||||
surface.create_entity({name = beam_type, position = {left, bottom},
|
||||
source = {left, bottom}, target = {left, top}})
|
||||
surface.create_entity({name = beam_type, position = {left, top},
|
||||
source = {left, top}, target = {right, top}})
|
||||
surface.create_entity({name = beam_type, position = {left, top - 0.5},
|
||||
source = {left, top - 0.5}, target = {right, top}})
|
||||
end
|
||||
|
||||
local function remove_drawn_borders(zone)
|
||||
@ -32,56 +34,72 @@ local function remove_drawn_borders(zone)
|
||||
end
|
||||
end
|
||||
|
||||
local function scale_size_and_box(zone)
|
||||
local time_scale = math.min(1, (game.tick - zone.lifetime_start) / time_to_full_size_ticks)
|
||||
local scaled_size = time_scale * max_size
|
||||
|
||||
local center = zone.center
|
||||
local box = {left_top = { x = center.x - scaled_size / 2, y = center.y - scaled_size / 2},
|
||||
right_bottom = { x = center.x + scaled_size / 2, y = center.y + scaled_size / 2}}
|
||||
zone.box = box
|
||||
zone.size = scaled_size
|
||||
end
|
||||
|
||||
function Public.add_zone(surface, force, center)
|
||||
local this = ScenarioTable.get_table()
|
||||
|
||||
local box = {left_top = {x = center.x - zone_size / 2, y = center.y - zone_size / 2},
|
||||
right_bottom = {x = center.x + zone_size / 2, y = center.y + zone_size / 2}}
|
||||
local zone = {surface = surface, force = force, center = center, box = box,
|
||||
lifetime_end = game.tick + lifetime_ticks}
|
||||
this.exclusion_zones[force.name] = zone
|
||||
|
||||
draw_borders(zone)
|
||||
local zone = {surface = surface, force = force, center = center, box = box, lifetime_start = game.tick}
|
||||
scale_size_and_box(zone)
|
||||
this.pvp_shields[force.name] = zone
|
||||
end
|
||||
|
||||
function Public.remove_zone(zone)
|
||||
local this = ScenarioTable.get_table()
|
||||
|
||||
remove_drawn_borders(zone)
|
||||
this.exclusion_zones[zone.force.name] = nil
|
||||
this.pvp_shields[zone.force.name] = nil
|
||||
zone.force.print("Your PvP Shield has expired", {r = 1, g = 0, b = 0})
|
||||
end
|
||||
|
||||
function Public.remaining_lifetime(zone)
|
||||
return max_lifetime_ticks - (game.tick - zone.lifetime_start)
|
||||
end
|
||||
|
||||
local function vector_norm(vector)
|
||||
return math.sqrt(vector.x ^ 2 + vector.y ^ 2)
|
||||
end
|
||||
|
||||
local function update_zone_lifetime()
|
||||
local this = ScenarioTable.get_table()
|
||||
for _, zone in pairs(this.exclusion_zones) do
|
||||
if game.tick > zone.lifetime_end then
|
||||
for _, zone in pairs(this.pvp_shields) do
|
||||
if Public.remaining_lifetime(zone) > 0 then
|
||||
if zone.size < max_size then
|
||||
remove_drawn_borders(zone)
|
||||
scale_size_and_box(zone)
|
||||
draw_borders(zone)
|
||||
|
||||
-- Push everyone out as we grow (even if they're just standing)
|
||||
for _, player in pairs(game.connected_players) do
|
||||
Public.push_enemies_out(player)
|
||||
end
|
||||
end
|
||||
else
|
||||
Public.remove_zone(zone)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_player_changed_position(event)
|
||||
local player = game.get_player(event.player_index)
|
||||
local surface = player.surface
|
||||
if not surface or not surface.valid then
|
||||
return
|
||||
end
|
||||
|
||||
function Public.push_enemies_out(player)
|
||||
local this = ScenarioTable.get_table()
|
||||
for _, zone in pairs(this.exclusion_zones) do
|
||||
if not (zone.force == player.force or zone.force.get_friend(player.force)) then
|
||||
for _, zone in pairs(this.pvp_shields) do
|
||||
if not (zone.force == player.force or zone.force.get_friend(player.force) or player.surface ~= zone.surface) then
|
||||
if CommonFunctions.point_in_bounding_box(player.position, zone.box) then
|
||||
local center_diff = { x = player.position.x - zone.center.x, y = player.position.y - zone.center.y}
|
||||
center_diff.x = center_diff.x / vector_norm(center_diff)
|
||||
center_diff.y = center_diff.y / vector_norm(center_diff)
|
||||
player.teleport({ player.position.x + center_diff.x, player.position.y + center_diff.y}, surface)
|
||||
|
||||
if player.character then
|
||||
-- Push player away from center
|
||||
local center_diff = { x = player.position.x - zone.center.x, y = player.position.y - zone.center.y}
|
||||
center_diff.x = center_diff.x / vector_norm(center_diff)
|
||||
center_diff.y = center_diff.y / vector_norm(center_diff)
|
||||
player.teleport({ player.position.x + center_diff.x, player.position.y + center_diff.y}, player.surface)
|
||||
|
||||
-- Kick players out of vehicles if they try to drive in
|
||||
if player.character.driving then
|
||||
player.character.driving = false
|
||||
@ -99,6 +117,16 @@ local function on_player_changed_position(event)
|
||||
end
|
||||
end
|
||||
|
||||
local function on_player_changed_position(event)
|
||||
local player = game.get_player(event.player_index)
|
||||
local surface = player.surface
|
||||
if not surface or not surface.valid then
|
||||
return
|
||||
end
|
||||
|
||||
Public.push_enemies_out(player)
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_player_changed_position, on_player_changed_position)
|
||||
Event.on_nth_tick(60, update_zone_lifetime)
|
||||
|
@ -37,7 +37,7 @@ function Public.reset_table()
|
||||
this.mining_entity = {}
|
||||
this.mining_target = {}
|
||||
this.spaceships = {}
|
||||
this.exclusion_zones = {}
|
||||
this.pvp_shields = {}
|
||||
end
|
||||
|
||||
function Public.get_table()
|
||||
|
@ -8,7 +8,7 @@ local string_lower = string.lower
|
||||
local Server = require 'utils.server'
|
||||
local Map = require 'maps.scrap_towny_ffa.map'
|
||||
local ScenarioTable = require 'maps.scrap_towny_ffa.table'
|
||||
local ExclusionZone = require 'maps.scrap_towny_ffa.exclusion_zone'
|
||||
local PvPShield = require 'maps.scrap_towny_ffa.pvp_shield'
|
||||
|
||||
local outlander_color = {150, 150, 150}
|
||||
local outlander_chat_color = {170, 170, 170}
|
||||
@ -832,8 +832,8 @@ local function kill_force(force_name, cause)
|
||||
end
|
||||
end
|
||||
|
||||
if this.exclusion_zones[force_name] then
|
||||
ExclusionZone.remove_zone(this.exclusion_zones[force_name])
|
||||
if this.pvp_shields[force_name] then
|
||||
PvPShield.remove_zone(this.pvp_shields[force_name])
|
||||
end
|
||||
game.merge_forces(force_name, 'neutral')
|
||||
this.town_centers[force_name] = nil
|
||||
|
@ -13,7 +13,7 @@ local Building = require 'maps.scrap_towny_ffa.building'
|
||||
local Colors = require 'maps.scrap_towny_ffa.colors'
|
||||
local Enemy = require 'maps.scrap_towny_ffa.enemy'
|
||||
local Color = require 'utils.color_presets'
|
||||
local ExclusionZone = require 'maps.scrap_towny_ffa.exclusion_zone'
|
||||
local PvPShield = require 'maps.scrap_towny_ffa.pvp_shield'
|
||||
|
||||
local town_radius = 27
|
||||
local radius_between_towns = 120
|
||||
@ -371,10 +371,10 @@ end
|
||||
local function update_protection_display()
|
||||
local this = ScenarioTable.get_table()
|
||||
for _, town_center in pairs(this.town_centers) do
|
||||
local zone = this.exclusion_zones[town_center.market.force.name]
|
||||
local zone = this.pvp_shields[town_center.market.force.name]
|
||||
local info
|
||||
if zone then
|
||||
info = 'PvP Shield: ' .. string.format("%.0f", (zone.lifetime_end - game.tick) / 60 / 60) .. ' minutes'
|
||||
info = 'PvP Shield: ' .. string.format("%.0f", (PvPShield.remaining_lifetime(zone)) / 60 / 60) .. ' minutes'
|
||||
else
|
||||
info = ''
|
||||
end
|
||||
@ -490,7 +490,7 @@ local function found_town(event)
|
||||
rendering.draw_text {
|
||||
text = town_center.town_name,
|
||||
surface = surface,
|
||||
forces = {force_name},
|
||||
forces = {force_name, game.forces.player, game.forces.rogue},
|
||||
target = town_center.market,
|
||||
target_offset = {0, -4.25},
|
||||
color = town_center.color,
|
||||
@ -504,7 +504,7 @@ local function found_town(event)
|
||||
rendering.draw_text {
|
||||
text = 'HP: ' .. town_center.health .. ' / ' .. town_center.max_health,
|
||||
surface = surface,
|
||||
forces = {force_name},
|
||||
forces = {force_name, game.forces.player, game.forces.rogue},
|
||||
target = town_center.market,
|
||||
target_offset = {0, -3.25},
|
||||
color = {200, 200, 200},
|
||||
@ -531,7 +531,7 @@ local function found_town(event)
|
||||
town_center.zone_text = rendering.draw_text {
|
||||
text = 'PvP Shield: (..)',
|
||||
surface = surface,
|
||||
forces = {force_name},
|
||||
forces = {force_name, game.forces.player, game.forces.rogue},
|
||||
target = town_center.market,
|
||||
target_offset = {0, -2.25},
|
||||
color = {200, 200, 200},
|
||||
@ -545,7 +545,7 @@ local function found_town(event)
|
||||
|
||||
Enemy.clear_enemies(position, surface, town_radius * 5)
|
||||
draw_town_spawn(force_name)
|
||||
ExclusionZone.add_zone(surface, force, position, Public.update_protection_display)
|
||||
PvPShield.add_zone(surface, force, { x = position.x + 0.5, y = position.y + 0.5}) -- Market center is slightly shifted
|
||||
update_protection_display()
|
||||
|
||||
-- set the spawn point
|
||||
@ -634,7 +634,7 @@ commands.add_command(
|
||||
|
||||
Event.add(defines.events.on_built_entity, on_built_entity)
|
||||
Event.add(defines.events.on_player_repaired_entity, on_player_repaired_entity)
|
||||
Event.on_nth_tick(60, update_protection_display) -- TODO: use callback from exclusion_zones instead
|
||||
Event.on_nth_tick(60, update_protection_display)
|
||||
--Event.add(defines.events.on_robot_repaired_entity, on_robot_repaired_entity)
|
||||
Event.add(defines.events.on_entity_damaged, on_entity_damaged)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user