From f8eed9baab02f587ab7743dce28fd9d4adf630bf Mon Sep 17 00:00:00 2001 From: Gerkiz Date: Fri, 21 Oct 2022 21:49:17 +0200 Subject: [PATCH] Scrap Towny - minor changes --- maps/scrap_towny_ffa/building.lua | 4 +- maps/scrap_towny_ffa/combat_balance.lua | 88 +---------- maps/scrap_towny_ffa/info.lua | 15 +- maps/scrap_towny_ffa/limited_radar.lua | 4 - maps/scrap_towny_ffa/main.lua | 86 ++++++++--- maps/scrap_towny_ffa/market.lua | 29 ---- maps/scrap_towny_ffa/pvp_shield.lua | 185 ------------------------ maps/scrap_towny_ffa/reset.lua | 137 ++++++++++++------ maps/scrap_towny_ffa/suicide.lua | 96 ++++++------ maps/scrap_towny_ffa/table.lua | 6 +- maps/scrap_towny_ffa/team.lua | 4 - maps/scrap_towny_ffa/town_center.lua | 73 +--------- 12 files changed, 224 insertions(+), 503 deletions(-) delete mode 100644 maps/scrap_towny_ffa/pvp_shield.lua diff --git a/maps/scrap_towny_ffa/building.lua b/maps/scrap_towny_ffa/building.lua index dc87bc31..e1536346 100644 --- a/maps/scrap_towny_ffa/building.lua +++ b/maps/scrap_towny_ffa/building.lua @@ -4,7 +4,6 @@ local math_floor = math.floor local table_insert = table.insert local table_size = table.size local ScenarioTable = require 'maps.scrap_towny_ffa.table' -local PvPShield = require 'maps.scrap_towny_ffa.pvp_shield' local town_zoning_entity_types = { "wall", "gate", "electric-pole", "ammo-turret", "electric-turret", "fluid-turret"} @@ -236,11 +235,10 @@ local function process_built_entities(event) force_name = force.name end - if PvPShield.in_other_zones(surface, position, force) or Public.near_another_town(force_name, position, surface, 32) == true then + if Public.near_another_town(force_name, position, surface, 32) == true then if neutral_whitelist[name] then entity.force = game.forces['neutral'] else - -- Prevent entities from being built near towns entity.destroy() if player_index ~= nil then local player = game.players[player_index] diff --git a/maps/scrap_towny_ffa/combat_balance.lua b/maps/scrap_towny_ffa/combat_balance.lua index 77b78009..26ddefe0 100644 --- a/maps/scrap_towny_ffa/combat_balance.lua +++ b/maps/scrap_towny_ffa/combat_balance.lua @@ -1,8 +1,7 @@ +local Event = require 'utils.event' local Public = {} local player_ammo_damage_starting_modifiers = { - --['artillery-shell'] = -0.75, - --['biological'] = -0.5, ['bullet'] = 0, ['cannon-shell'] = -0.5, ['capsule'] = 0, @@ -12,13 +11,9 @@ local player_ammo_damage_starting_modifiers = { ['flamethrower'] = 0, ['grenade'] = -0.5, ['landmine'] = -0.75, - --['melee'] = 2, - --['rocket'] = -0.75, ['shotgun-shell'] = 0 } local player_ammo_damage_modifiers = { - --['artillery-shell'] = -0.75, - --['biological'] = -0.5, ['bullet'] = 0, ['cannon-shell'] = -0.5, ['capsule'] = 0, @@ -28,13 +23,9 @@ local player_ammo_damage_modifiers = { ['flamethrower'] = 0, ['grenade'] = -0.5, ['landmine'] = -0.5, - --['melee'] = 0, - --['rocket'] = -0.5, ['shotgun-shell'] = 0 } local player_gun_speed_modifiers = { - --['artillery-shell'] = -0.75, - --['biological'] = -0.5, ['bullet'] = 0, ['cannon-shell'] = -0.5, ['capsule'] = -0.5, @@ -44,51 +35,9 @@ local player_gun_speed_modifiers = { ['flamethrower'] = 0, ['grenade'] = -0.5, ['landmine'] = 0, - --['melee'] = 1, - --['rocket'] = -0.75, ['shotgun-shell'] = 0 } ---local player_turrets_research_modifiers = { --- ['gun-turret'] = 0, --- ['laser-turret'] = 1.5, --- ['flamethrower-turret'] = 0 ---} - ---local enemy_ammo_starting_modifiers = { --- ['artillery-shell'] = 3, --- ['biological'] = 3, --- ['bullet'] = 2, --- ['cannon-shell'] = 0, --- ['capsule'] = 0, --- ['beam'] = 0, --- ['laser'] = 0, --- ['electric'] = 0, --- ['flamethrower'] = 0, --- ['grenade'] = 0, --- ['landmine'] = 0, --- ['melee'] = 1, --- ['rocket'] = 0, --- ['shotgun-shell'] = 0 ---} - ---local enemy_ammo_evolution_modifiers = { --- ['artillery-shell'] = 1, --- ['biological'] = 2, --- ['bullet'] = 1, --- --['cannon-shell'] = 1, --- ['capsule'] = 1, --- ['beam'] = 1, --- ['laser'] = 1, --- ['electric'] = 1, --- ['flamethrower'] = 2, --- --['grenade'] = 1, --- --['landmine'] = 1, --- ['melee'] = 2 --- --['rocket'] = 1, --- --['shotgun-shell'] = 1 ---} - function Public.init_player_weapon_damage(force) for k, v in pairs(player_ammo_damage_starting_modifiers) do force.set_ammo_damage_modifier(k, v) @@ -101,27 +50,6 @@ function Public.init_player_weapon_damage(force) force.set_turret_attack_modifier('laser-turret', 3) end ---local function init_enemy_weapon_damage() --- local e_force = game.forces['enemy'] --- --- for k, v in pairs(enemy_ammo_starting_modifiers) do --- e_force.set_ammo_damage_modifier(k, v) --- end ---end --- ---local function enemy_weapon_damage() --- local f = game.forces.enemy --- --- local ef = f.evolution_factor --- --- for k, v in pairs(enemy_ammo_evolution_modifiers) do --- local base = enemy_ammo_starting_modifiers[k] --- --- local new = base + v * ef --- f.set_ammo_damage_modifier(k, new) --- end ---end - -- After a research is finished and the game applied the modifier, we reduce modifiers to achieve the reduction local function research_finished(event) local r = event.research @@ -138,15 +66,6 @@ local function research_finished(event) local current_m = p_force.get_ammo_damage_modifier(category) p_force.set_ammo_damage_modifier(category, current_m + factor * e.modifier) end - --elseif t == 'turret-attack' then -- NOTE: this doesn't trigger for laser turrets :-( - -- local category = e.turret_id - -- local factor = player_turrets_research_modifiers[category] - -- game.print("XDB cat " .. category) - -- if factor then - -- local current_m = p_force.get_turret_attack_modifier(category) - -- game.print("XDB mod " .. current_m .. " -> " .. current_m + factor * e.modifier) - -- p_force.set_turret_attack_modifier(category, current_m + factor * e.modifier) - -- end elseif t == 'gun-speed' then local category = e.ammo_category local factor = player_gun_speed_modifiers[category] @@ -159,8 +78,5 @@ local function research_finished(event) end end -local Event = require 'utils.event' ---Event.on_init(init_enemy_weapon_damage) ---Event.on_nth_tick(18000, enemy_weapon_damage) Event.add(defines.events.on_research_finished, research_finished) -return Public \ No newline at end of file +return Public diff --git a/maps/scrap_towny_ffa/info.lua b/maps/scrap_towny_ffa/info.lua index 3a1a24be..5f009e6a 100644 --- a/maps/scrap_towny_ffa/info.lua +++ b/maps/scrap_towny_ffa/info.lua @@ -1,20 +1,20 @@ local Public = {} -local info = - [[This is the wasteland. Who will survive? +local info = [[This is the wasteland. Who will survive? In this mode, players build towns and fight against other towns and the biters. +The Comfy gui has been disabled since it contains too many goodies. Have fun and be comfy ^.^]] local info_adv = [[ -# Changelog (10th-16th October 2022): - - PvP shields now prevent building inside +# Changelog (21th October 2022): + - Suicide command has been added. The poison pill will kill the character after 3 minutes + - Game will automatically reset whenever a town reaches 48h of survival time + - PvP Shield has been removed - Combat balance overhaul (see "Bonuses" button top right to check modifiers) - Town player limit fixes - - Towns have an initial PvP protection shield - size and duration is scaled with the biggest town size - - Temporary PvP shield available in market for breaks / AFK - Improved base defenses and offline survivability - Loads of bugfixes including freezes and desyncs @@ -34,9 +34,6 @@ Survive as long as you can. Raid other towns. Defend your town. Tip: use filter inserters with to get coins/iron/.. out of the market - Fishes procreate near towns. The more fishes, the quicker they multiply. Automated fish farm, anyone? - Use /rename-town NEWNAME (chat command) to rename your town -- PvP shields prevent players from entering and building inside, but they can still shoot inside! -- Your town has a AFK PvP shield that you can use to safely take a quick break - without other players killing your town. Deploy it from the market. # Town members and alliances - Once a town is formed, members may invite other players and teams using a coin. To invite another player, drop a coin diff --git a/maps/scrap_towny_ffa/limited_radar.lua b/maps/scrap_towny_ffa/limited_radar.lua index 2300e1b3..3303bbe3 100644 --- a/maps/scrap_towny_ffa/limited_radar.lua +++ b/maps/scrap_towny_ffa/limited_radar.lua @@ -58,10 +58,6 @@ local function on_chunk_charted(event) local health_text = town_center.health_text update_forces(health_text) add_force(health_text, force.name) - -- protection text - local shield_text = town_center.shield_text - update_forces(shield_text) - add_force(shield_text, force.name) end end diff --git a/maps/scrap_towny_ffa/main.lua b/maps/scrap_towny_ffa/main.lua index 7aac5e93..48a81df0 100644 --- a/maps/scrap_towny_ffa/main.lua +++ b/maps/scrap_towny_ffa/main.lua @@ -21,6 +21,7 @@ require 'maps.scrap_towny_ffa.vehicles' require 'maps.scrap_towny_ffa.suicide' local Event = require 'utils.event' +local Alert = require 'utils.alert' local Autostash = require 'modules.autostash' local MapDefaults = require 'maps.scrap_towny_ffa.map_defaults' local BottomFrame = require 'utils.gui.bottom_frame' @@ -36,24 +37,21 @@ local Evolution = require 'maps.scrap_towny_ffa.evolution' local mod_gui = require('mod-gui') local Gui = require 'utils.gui' local Color = require 'utils.color_presets' +local Server = require 'utils.server' local Where = require 'utils.commands.where' local Inventory = require 'modules.show_inventory' -local function spairs(t, order) +local function spairs(t) local keys = {} for k in pairs(t) do keys[#keys + 1] = k end - if order then - table.sort( - keys, - function(a, b) - return order(t, a, b) - end - ) - else - table.sort(keys) - end + table.sort( + keys, + function(a, b) + return t[b] < t[a] + end + ) local i = 0 return function() i = i + 1 @@ -79,6 +77,50 @@ end local function update_score() local this = ScenarioTable.get_table() + if this.winner then + if not this.game_won then + this.game_won = true + this.game_reset_tick = 5400 + Alert.alert_all_players(900, 'Winner winner chicken dinner!\n[color=red]' .. this.winner.name .. '[/color] has won the game!', Color.white, 'restart_required', 1.0) + for _, player in pairs(game.connected_players) do + player.play_sound {path = 'utility/game_won', volume_modifier = 0.75} + end + local winner = this.winner + local message = { + title = 'Game over', + description = 'Town statistics is below', + color = 'success', + field1 = { + text1 = 'Town won:', + text2 = winner.name, + inline = 'false' + }, + field2 = { + text1 = 'Town researched:', + text2 = winner.name .. ' with a score of ' .. winner.research_counter .. ' techs!', + inline = 'false' + }, + field3 = { + text1 = 'Town upgrades:', + text2 = winner.name .. ' upgraded their town with:\nCrafting speed:' .. winner.upgrades.crafting_speed .. '\nMining speed:' .. winner.upgrades.mining_speed, + inline = 'false' + }, + field4 = { + text1 = 'Town health:', + text2 = winner.name .. ' had a health of ' .. winner.health .. ' left!', + inline = 'false' + }, + field5 = { + text1 = 'Town coins:', + text2 = winner.name .. ' had ' .. winner.coin_balance .. ' coins stashed!', + inline = 'false' + } + } + Server.to_discord_embed_parsed(message) + end + return + end + for _, player in pairs(game.connected_players) do local frame = this.score_gui_frame[player.index] if not (frame and frame.valid) then @@ -118,12 +160,7 @@ local function update_score() local rank = 1 - for town_center, age in spairs( - town_ages, - function(t, a, b) - return t[b] < t[a] - end - ) do + for town_center, age in spairs(town_ages) do local position = information_table.add {type = 'label', caption = '#' .. rank} if town_center == this.town_centers[player.force.name] then position.style.font = 'default-semibold' @@ -137,9 +174,20 @@ local function update_score() label.style.font = 'default-semibold' label.style.font_color = town_center.color local age_hours = age / 60 / 3600 - information_table.add {type = 'label', caption = string.format('%.1f', age_hours) .. 'h'} + local total_age = string.format('%.1f', age_hours) + information_table.add {type = 'label', caption = total_age .. 'h'} rank = rank + 1 + + if tonumber(total_age) >= this.required_time_to_win then + this.winner = { + name = town_center.town_name, + research_counter = town_center.research_counter, + upgrades = town_center.upgrades, + health = town_center.health, + coin_balance = town_center.coin_balance + } + end end -- Outlander section @@ -229,7 +277,7 @@ Event.on_nth_tick(60, on_nth_tick) -- once every second Event.on_nth_tick(60 * 30, ui_smell_evolution) Event.on_nth_tick(60, update_score) ---Disable the comfy main gui since we good too many goodies there. +--Disable the comfy main gui since we got too many goodies there. Event.add( defines.events.on_gui_click, function(event) diff --git a/maps/scrap_towny_ffa/market.lua b/maps/scrap_towny_ffa/market.lua index 4aaf70e2..1dd2b17b 100644 --- a/maps/scrap_towny_ffa/market.lua +++ b/maps/scrap_towny_ffa/market.lua @@ -2,7 +2,6 @@ local table_insert = table.insert local ScenarioTable = require 'maps.scrap_towny_ffa.table' local Town_center = require 'maps.scrap_towny_ffa.town_center' -local PvPShield = require 'maps.scrap_towny_ffa.pvp_shield' local upgrade_functions = { -- Upgrade Town Center Health @@ -87,33 +86,6 @@ local upgrade_functions = { this.spawn_point[player.index] = spawn_point surface.play_sound({path = 'utility/scenario_message', position = player.position, volume_modifier = 1}) return false - end, - -- Pause-mode PvP Shield - [8] = function(town_center, player) - local this = ScenarioTable.get_table() - local market = town_center.market - local force = market.force - local surface = market.surface - local shield_lifetime_ticks = 10 * 60 * 60 - - if not this.pvp_shields[player.force.name] then - -- Double-check with the player to prevent accidental clicks - if this.pvp_shield_warned[player.force.name] ~= nil and game.tick - this.pvp_shield_warned[player.force.name] < 60 * 60 then - if not Town_center.enemy_players_nearby(town_center, 100) then - PvPShield.add_shield(surface, force, market.position, 120, shield_lifetime_ticks, 2 * 60 * 60, true) - surface.play_sound({path = 'utility/scenario_message', position = player.position, volume_modifier = 1}) - this.pvp_shield_warned[player.force.name] = nil - else - player.print("Enemy players are too close, can't deploy PvP shield") - end - else - player.force.print('You have requested a temporary PvP shield. This will freeze all players in your town for ' .. string.format("%.0f", shield_lifetime_ticks / 60 / 60) .. ' minutes to take a break. Click again to confirm.') - this.pvp_shield_warned[player.force.name] = game.tick - end - else - player.print("Your town already has a PvP shield") - end - return false end } @@ -162,7 +134,6 @@ local function set_offers(town_center) special_offers[6] = {{{'coin', (town_center.upgrades.laser_turret.slots * 200)}}, laser_turret} local spawn_point = 'Set Spawn Point' special_offers[7] = {{}, spawn_point} - special_offers[8] = {{}, 'Temporary PvP Shield for pause/AFK'} for _, v in pairs(special_offers) do table_insert(market_items, {price = v[1], offer = {type = 'nothing', effect_description = v[2]}}) end diff --git a/maps/scrap_towny_ffa/pvp_shield.lua b/maps/scrap_towny_ffa/pvp_shield.lua deleted file mode 100644 index 24bc942a..00000000 --- a/maps/scrap_towny_ffa/pvp_shield.lua +++ /dev/null @@ -1,185 +0,0 @@ -local Public = {} - -local math_sqrt = math.sqrt - -local Event = require 'utils.event' -local ScenarioTable = require 'maps.scrap_towny_ffa.table' -local CommonFunctions = require 'utils.common' - -local beam_type = 'electric-beam-no-sound' - -local function draw_borders(shield) - local surface = shield.surface - local right = shield.box.right_bottom.x - local left = shield.box.left_top.x - local top = shield.box.left_top.y - local bottom = shield.box.right_bottom.y - - surface.create_entity({name = beam_type, position = {right, top}, - 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 + 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 - 0.5}, - source = {left, top - 0.5}, target = {right, top}}) -end - -local function remove_drawn_borders(shield) - for _, e in pairs(shield.surface.find_entities_filtered({area = shield.box, name = beam_type})) do - if e.valid then - e.destroy() - end - end -end - -local function scale_size_by_lifetime(shield) - local time_scale = math.min(1, (game.tick - shield.lifetime_start) / shield.time_to_full_size_ticks) - local scaled_size = time_scale * shield.max_size - - local center = shield.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}} - shield.box = box - shield.size = scaled_size -end - -function Public.add_shield(surface, force, center, max_size, lifetime_ticks, time_to_full_size_ticks, is_pause_mode) - local this = ScenarioTable.get_table() - - local shield = {surface = surface, force = force, center = center, max_size = max_size, max_lifetime_ticks = lifetime_ticks, - time_to_full_size_ticks = time_to_full_size_ticks, lifetime_start = game.tick, is_pause_mode = is_pause_mode} - - if is_pause_mode then - -- Freeze players to avoid AFK abuse - shield.force.character_running_speed_modifier = -1 - -- Kick players out of vehicles if needed - for _, player in pairs(force.connected_players) do - if player.character.driving then - player.character.driving = false - end - end - shield.force.print("Your AFK PvP shield is now rolling out. You will be frozen until it expires in " .. - string.format("%.0f", (Public.remaining_lifetime(shield)) / 60 / 60) .. ' minutes') - end - - scale_size_by_lifetime(shield) - this.pvp_shields[force.name] = shield -end - -function Public.remove_shield(shield) - local this = ScenarioTable.get_table() - remove_drawn_borders(shield) - - if shield.is_pause_mode then - shield.force.character_running_speed_modifier = 0 - end - - this.pvp_shields[shield.force.name] = nil - shield.force.print("Your PvP Shield has expired", {r = 1, g = 0, b = 0}) -end - -function Public.remaining_lifetime(shield) - return shield.max_lifetime_ticks - (game.tick - shield.lifetime_start) -end - -local function update_shield_lifetime() - local this = ScenarioTable.get_table() - for _, shield in pairs(this.pvp_shields) do - if Public.remaining_lifetime(shield) > 0 then - if shield.size < shield.max_size then - remove_drawn_borders(shield) - scale_size_by_lifetime(shield) - draw_borders(shield) - - -- 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_shield(shield) - end - end -end - -local function vector_norm(vector) - return math_sqrt(vector.x ^ 2 + vector.y ^ 2) -end - -function Public.in_other_zones(surface, position, force) - local this = ScenarioTable.get_table() - for _, shield in pairs(this.pvp_shields) do - if not (shield.force == force or surface ~= shield.surface) then - if CommonFunctions.point_in_bounding_box(position, shield.box) then - return true - end - end - end - return false -end - -function Public.push_enemies_out(player) - local this = ScenarioTable.get_table() - for _, shield in pairs(this.pvp_shields) do - if not (shield.force == player.force or shield.force.get_friend(player.force) or player.surface ~= shield.surface) then - if CommonFunctions.point_in_bounding_box(player.position, shield.box) then - if player.character then - -- Push player away from center - local center_diff = { x = player.position.x - shield.center.x, y = player.position.y - shield.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 needed - if player.character.driving then - player.character.driving = false - end - - -- Damage player - player.character.health = player.character.health - 25 - player.character.surface.create_entity({name = 'water-splash', position = player.position}) - if player.character.health <= 0 then - player.character.die('enemy') - end - end - end - 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 - - Public.push_enemies_out(player) -end - -local function on_player_driving_changed_state(event) - local player = game.players[event.player_index] - if not player or not player.valid then - return - end - local this = ScenarioTable.get_table() - for _, shield in pairs(this.pvp_shields) do - if shield.force == player.force and shield.is_pause_mode then - local vehicle = player.vehicle - if vehicle and vehicle.valid then - -- Kick players out of vehicles if needed - if player.character.driving then - player.character.driving = false - player.print("Can't drive around while AFK PvP Shield is active") - end - end - end - end -end - -Event.add(defines.events.on_player_driving_changed_state, on_player_driving_changed_state) -Event.add(defines.events.on_player_changed_position, on_player_changed_position) -Event.on_nth_tick(60, update_shield_lifetime) - -return Public diff --git a/maps/scrap_towny_ffa/reset.lua b/maps/scrap_towny_ffa/reset.lua index fb7de7d0..47e80737 100644 --- a/maps/scrap_towny_ffa/reset.lua +++ b/maps/scrap_towny_ffa/reset.lua @@ -47,57 +47,106 @@ local function armageddon() end end -local function reset_map() - local this = ScenarioTable.get_table() +local function has_the_game_ended() + local game_reset_tick = ScenarioTable.get('game_reset_tick') + if game_reset_tick then + if game_reset_tick < 0 then + return + end - if this.shutdown then - Server.to_discord_bold('*** Soft-reset is disabled! Server will shutdown. Most likely because of updates. ***', true) - return Server.stop_scenario() - end + local this = ScenarioTable.get_table() - if this.restart then - Server.to_discord_bold('*** Soft-reset is disabled! Server will restart to load new changes. ***', true) - return Server.start_scenario('Towny') - end + this.game_reset_tick = this.game_reset_tick - 30 + if this.game_reset_tick % 1800 == 0 then + if this.game_reset_tick > 0 then + local cause_msg + if this.restart then + cause_msg = 'restart' + elseif this.shutdown then + cause_msg = 'shutdown' + elseif this.soft_reset then + cause_msg = 'soft-reset' + end - for _, player in pairs(game.players) do - local frame = this.score_gui_frame[player.index] - if frame and frame.valid then - frame.destroy() + game.print(({'main.reset_in', cause_msg, this.game_reset_tick / 60}), {r = 0.22, g = 0.88, b = 0.22}) + end + + if this.soft_reset and this.game_reset_tick == 0 then + for _, player in pairs(game.players) do + local frame = this.score_gui_frame[player.index] + if frame and frame.valid then + frame.destroy() + end + end + this.game_reset_tick = nil + this.game_won = false + ScenarioTable.reset_table() + local surface = game.surfaces['nauvis'] + if get_victorious_force() then + surface.play_sound({path = 'utility/game_won', volume_modifier = 1}) + else + surface.play_sound({path = 'utility/game_lost', volume_modifier = 1}) + end + game.reset_time_played() + game.reset_game_state() + for _, player in pairs(game.players) do + player.teleport({0, 0}, game.surfaces['limbo']) + end + Nauvis.initialize() + Team.initialize() + if game.forces['rogue'] == nil then + log('rogue force is missing!') + end + for _, player in pairs(game.players) do + Player.increment() + Player.initialize(player) + Team.set_player_color(player) + Player.spawn(player) + Player.load_buffs(player) + Player.requests(player) + end + + Alert.alert_all_players(5, 'The world has been reset!', Color.white, 'restart_required', 1.0) + game.print('The world has been reset!', {r = 0.22, g = 0.88, b = 0.22}) + + Server.to_discord_embed('*** The world has been reset! ***') + return + end + + if this.restart and this.game_reset_tick == 0 then + if not this.announced_message then + game.print(({'entity.notify_restart'}), {r = 0.22, g = 0.88, b = 0.22}) + local message = 'Soft-reset is disabled! Server will restart from scenario to load new changes.' + Server.to_discord_bold(table.concat {'*** ', message, ' ***'}) + Server.start_scenario('Towny') + this.announced_message = true + return + end + end + if this.shutdown and this.game_reset_tick == 0 then + if not this.announced_message then + game.print(({'entity.notify_shutdown'}), {r = 0.22, g = 0.88, b = 0.22}) + local message = 'Soft-reset is disabled! Server will shutdown. Most likely because of updates.' + Server.to_discord_bold(table.concat {'*** ', message, ' ***'}) + Server.stop_scenario() + this.announced_message = true + return + end + end end end - ScenarioTable.reset_table() - local surface = game.surfaces['nauvis'] - if get_victorious_force() then - surface.play_sound({path = 'utility/game_won', volume_modifier = 1}) - else - surface.play_sound({path = 'utility/game_lost', volume_modifier = 1}) - end - game.reset_time_played() - game.reset_game_state() - for _, player in pairs(game.players) do - player.teleport({0, 0}, game.surfaces['limbo']) - end - Nauvis.initialize() - Team.initialize() - if game.forces['rogue'] == nil then - log('rogue force is missing!') - end - for _, player in pairs(game.players) do - Player.increment() - Player.initialize(player) - Team.set_player_color(player) - Player.spawn(player) - Player.load_buffs(player) - Player.requests(player) - end - Alert.alert_all_players(5, 'The world has been reset!', Color.white, 'restart_required', 1.0) - Server.to_discord_embed('*** The world has been reset! ***') end local function on_tick() local tick = game.tick if tick > 0 then + if tick % 40 == 0 then + local game_won = ScenarioTable.get('game_won') + if game_won then + has_the_game_ended() + end + end + if (tick + armageddon_duration + warning_duration) % game_duration == 0 then warning() end @@ -109,7 +158,7 @@ local function on_tick() Team.reset_all_forces() end if tick % game_duration == 0 then - reset_map() + has_the_game_ended() end end end @@ -193,12 +242,12 @@ commands.add_command( else game.print(mapkeeper .. ' server, has reset the game!', {r = 0.98, g = 0.66, b = 0.22}) end - reset_map() + has_the_game_ended() p('[WARNING] Game has been reset!') return end end ) -Event.add(defines.events.on_tick, on_tick) +Event.on_nth_tick(10, on_tick) Event.add(defines.events.on_rocket_launched, on_rocket_launched) diff --git a/maps/scrap_towny_ffa/suicide.lua b/maps/scrap_towny_ffa/suicide.lua index cd2cae0a..cd93db7f 100644 --- a/maps/scrap_towny_ffa/suicide.lua +++ b/maps/scrap_towny_ffa/suicide.lua @@ -2,10 +2,10 @@ local Scheduler = require 'utils.scheduler' local ScenarioTable = require 'maps.scrap_towny_ffa.table' local Event = require 'utils.event' -local yellow = { r = 200, g = 200, b = 0 } +local yellow = {r = 200, g = 200, b = 0} -- Must be at least 1 minute -local minutes_to_die = 10 +local minutes_to_die = 5 local one_minute = 60 * 60 @@ -17,56 +17,58 @@ end Event.add(defines.events.on_player_died, on_player_died) -local suicide_handler = Scheduler.set(function(data) - for i = 1, #data do - local this = ScenarioTable.get_table() - local player_index = data[i].player_index - local player = game.get_player(player_index) - if not player or not player.valid or not player.character then - return - end - - if not this.suicides[player.index] then - -- the suicide was cancelled (the character died) - return - end - - local minutes_remaining = this.suicides[player.index].minutes_remaining - - if minutes_remaining <= 0 then - player.character.die(player.force, player.character) - this.suicides[player.index] = nil - else - if minutes_remaining == 1 then - player.print(minutes_remaining .. " minute remaining until death.", yellow) - else - player.print(minutes_remaining .. " minutes remaining until death.", yellow) +local suicide_handler = + Scheduler.set( + function(data) + for i = 1, #data do + local this = ScenarioTable.get_table() + local player_index = data[i].player_index + local player = game.get_player(player_index) + if not player or not player.valid or not player.character then + return + end + + if not this.suicides[player.index] then + -- the suicide was cancelled (the character died) + return + end + + local minutes_remaining = this.suicides[player.index].minutes_remaining + + if minutes_remaining <= 0 then + player.character.die() + this.suicides[player.index] = nil + else + if minutes_remaining == 1 then + player.print(minutes_remaining .. ' minute remaining until death.', yellow) + else + player.print(minutes_remaining .. ' minutes remaining until death.', yellow) + end + this.suicides[player.index].minutes_remaining = this.suicides[player.index].minutes_remaining - 1 + Scheduler.timer(game.tick + one_minute, data[i].handler, {player_index = player.index, handler = data[i].handler}) end - this.suicides[player.index].minutes_remaining = this.suicides[player.index].minutes_remaining - 1 - Scheduler.timer(game.tick + one_minute, data[i].handler, { player_index = player.index, handler = data[i].handler}) end end - -end) +) commands.add_command( - 'suicide', - 'Kills the player', - function() - local this = ScenarioTable.get_table() - local player = game.player + 'suicide', + 'Kills the player', + function() + local this = ScenarioTable.get_table() + local player = game.player - if not player or not player.valid then - return - end - - if this.suicides[player.index] then - player.print("You are already dying!", yellow) - return - end - - this.suicides[player.index] = {minutes_remaining = minutes_to_die - 1} - Scheduler.timer(game.tick + one_minute, suicide_handler, { player_index = player.index, handler = suicide_handler }) - player.print("You ate a poison pill. You will die in " .. minutes_to_die .. " minutes.", yellow) + if not player or not player.valid then + return end + + if this.suicides[player.index] then + player.print('You are already dying!', yellow) + return + end + + this.suicides[player.index] = {minutes_remaining = minutes_to_die - 1} + Scheduler.timer(game.tick + one_minute, suicide_handler, {player_index = player.index, handler = suicide_handler}) + player.print('You ate a poison pill. You will die in ' .. minutes_to_die .. ' minutes.', yellow) + end ) diff --git a/maps/scrap_towny_ffa/table.lua b/maps/scrap_towny_ffa/table.lua index 515324ee..e6a46143 100644 --- a/maps/scrap_towny_ffa/table.lua +++ b/maps/scrap_towny_ffa/table.lua @@ -36,9 +36,11 @@ function Public.reset_table() this.mining_entity = {} this.mining_target = {} this.spaceships = {} - this.pvp_shields = {} - this.pvp_shield_warned = {} this.suicides = {} + this.required_time_to_win = 48 + this.announced_message = nil + this.soft_reset = true + this.winner = nil end function Public.get_table() diff --git a/maps/scrap_towny_ffa/team.lua b/maps/scrap_towny_ffa/team.lua index 43cd4617..464e7915 100644 --- a/maps/scrap_towny_ffa/team.lua +++ b/maps/scrap_towny_ffa/team.lua @@ -9,7 +9,6 @@ local math_min = math.min local Server = require 'utils.server' local Map = require 'maps.scrap_towny_ffa.map' local ScenarioTable = require 'maps.scrap_towny_ffa.table' -local PvPShield = require 'maps.scrap_towny_ffa.pvp_shield' local CombatBalance = require 'maps.scrap_towny_ffa.combat_balance' local outlander_color = {150, 150, 150} @@ -804,9 +803,6 @@ local function kill_force(force_name, cause) e.destroy() end end - if this.pvp_shields[force_name] then - PvPShield.remove_shield(this.pvp_shields[force_name]) - end game.merge_forces(force_name, 'neutral') this.town_centers[force_name] = nil diff --git a/maps/scrap_towny_ffa/town_center.lua b/maps/scrap_towny_ffa/town_center.lua index edfa22bd..b2f07025 100644 --- a/maps/scrap_towny_ffa/town_center.lua +++ b/maps/scrap_towny_ffa/town_center.lua @@ -4,7 +4,6 @@ local math_random = math.random local table_insert = table.insert local math_floor = math.floor local math_sqrt = math.sqrt -local math_min = math.min local table_shuffle = table.shuffle_table local table_size = table.size @@ -16,8 +15,6 @@ 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 PvPShield = require 'maps.scrap_towny_ffa.pvp_shield' -local Evolution = require 'maps.scrap_towny_ffa.evolution' local town_radius = 27 local radius_between_towns = 120 @@ -378,10 +375,9 @@ function Public.enemy_players_nearby(town_center, max_radius) for _, player in pairs(game.connected_players) do if player.surface == town_center.market.surface then - local distance = math_floor(math_sqrt((player.position.x - town_position.x) ^ 2 - + (player.position.y - town_position.y) ^ 2)) + local distance = math_floor(math_sqrt((player.position.x - town_position.x) ^ 2 + (player.position.y - town_position.y) ^ 2)) if distance < max_radius then - if player.force ~= "enemy" and (own_force ~= player.force and not own_force.get_friend(player.force)) then + if player.force ~= 'enemy' and (own_force ~= player.force and not own_force.get_friend(player.force)) then return true end end @@ -390,38 +386,6 @@ function Public.enemy_players_nearby(town_center, max_radius) return false end -local function update_pvp_shields_display() - local this = ScenarioTable.get_table() - for _, town_center in pairs(this.town_centers) do - local shield = this.pvp_shields[town_center.market.force.name] - local info - if shield then - info = 'PvP Shield: ' .. string.format("%.0f", (PvPShield.remaining_lifetime(shield)) / 60 / 60) .. ' minutes' - else - info = '' - end - rendering.set_text(town_center.shield_text, info) - end -end - -local function add_pvp_shield_scaled(position, force, surface) - local evo = Evolution.get_highest_evolution() - - local min_size = 70 - local max_size = 150 - local min_duration = 0.5 * 60 * 60 * 60 - local max_duration = 8 * 60 * 60 * 60 - local lifetime_ticks = math_min(min_duration + 2 * evo * (max_duration - min_duration), max_duration) - local size = math_min(min_size + 2 * evo * (max_size - min_size), max_size) - - PvPShield.add_shield(surface, force, position, size, lifetime_ticks, 60 * 60) - update_pvp_shields_display() - force.print("Based on the highest tech on map, your town deploys a PvP shield of " - .. string.format("%.0f", size) .. " tiles" - .. " for " .. string.format("%.0f", lifetime_ticks/60/60) .. " minutes." - .. " Enemy players will not be able to enter and build in the shielded area.") -end - local function found_town(event) local entity = event.created_entity -- is a valid entity placed? @@ -568,19 +532,6 @@ local function found_town(event) scale_with_zoom = false } - town_center.shield_text = rendering.draw_text { - text = 'PvP Shield: (..)', - surface = surface, - forces = {force_name, game.forces.player, game.forces.rogue}, - target = town_center.market, - target_offset = {0, -2.25}, - color = {200, 200, 200}, - scale = 1.00, - font = 'default-game', - alignment = 'center', - scale_with_zoom = false - } - Enemy.clear_enemies(position, surface, town_radius * 5) draw_town_spawn(force_name) @@ -592,31 +543,12 @@ local function found_town(event) Team.add_player_to_town(player, town_center) Team.remove_key(player.index) Team.add_chart_tag(town_center) - add_pvp_shield_scaled({ x = position.x + 0.5, y = position.y + 0.5}, force, surface) -- Market center is slightly shifted game.print('>> ' .. player.name .. ' has founded a new town!', {255, 255, 0}) Server.to_discord_embed(player.name .. ' has founded a new town!') player.print('Your town color is ' .. crayola.name, crayola.color) end -local Token = require 'utils.token' -local Task = require 'utils.task' - -local do_something_token = - Token.register( - function(event) - local player_index = event.player_index - local player = game.get_player(player_index) - if not player or not player.valid then - return - end - end -) - -local function some_event_that_fires_the_callback() - Task.set_timeout_in_ticks(do_something_token, params) -end - local function on_built_entity(event) found_town(event) end @@ -689,7 +621,6 @@ 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_pvp_shields_display) --Event.add(defines.events.on_robot_repaired_entity, on_robot_repaired_entity) Event.add(defines.events.on_entity_damaged, on_entity_damaged)