1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2024-12-30 23:17:53 +02:00

Scrap Towny - minor changes

This commit is contained in:
Gerkiz 2022-10-21 21:49:17 +02:00
parent ebed7f49e0
commit f8eed9baab
12 changed files with 224 additions and 503 deletions

View File

@ -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]

View File

@ -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
return Public

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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
)

View File

@ -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()

View File

@ -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

View File

@ -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)