1
0
mirror of https://github.com/Oarcinae/FactorioScenarioMultiplayerSpawn.git synced 2025-02-05 13:05:09 +02:00

Trying to polish the new regrowth and player reset features. Will require lots of testing.

This commit is contained in:
Oarcinae 2020-06-20 14:13:44 -04:00
parent 01cf0fd922
commit 6df4bbd629
6 changed files with 127 additions and 25 deletions

View File

@ -234,11 +234,20 @@ end)
script.on_event(defines.events.on_player_left_game, function(event)
ServerWriteFile("player_events", game.players[event.player_index].name .. " left the game." .. "\n")
local player = game.players[event.player_index]
-- If players leave early, say goodbye.
if ((player.online_time < (global.ocfg.minimum_online_time * TICKS_PER_MINUTE)) and
game.players[event.player_index]) then
RemoveOrResetPlayer(game.players[event.player_index], true, true)
if (player and (player.online_time < (global.ocfg.minimum_online_time * TICKS_PER_MINUTE))) then
RemoveOrResetPlayer(player, true, true, true)
SendBroadcastMsg(player.name .. "'s base was marked for immediate clean up because they left within "..global.ocfg.minimum_online_time.." minutes of joining.")
-- Otherwise check if they are on the removal list.
else
for _,p in pairs(global.ocore.player_removal_list) do
if (p == player) then
RemoveOrResetPlayer(player, true, false, false)
end
end
end
end)

View File

@ -30,6 +30,7 @@ function GameOptionsGuiClick(event)
if (pIndex ~= 0) then
local resetPlayer = event.element.parent.ban_players_dropdown.get_item(pIndex)
if (game.players[resetPlayer]) then
RemoveOrResetPlayer(player, false, true, true)
SeparateSpawnsPlayerCreated(resetPlayer, true)
log("Resetting " .. resetPlayer)
end

View File

@ -9,7 +9,7 @@ OARC_STORE_MAP_CATEGORIES =
{
special_chests = "Special buildings for sharing or monitoring items and energy. This will convert the closest wooden chest (to you) within 16 tiles into a special building of your choice. Make sure to leave enough space! The combinators and accumulators can take up several tiles around them.",
special_chunks = "Map features that can be built on the special empty chunks found on the map. You must be standing inside an empty special chunk to be able to build these. Each player can only build one of each type. [color=red]THESE FEATURES ARE PERMANENT AND CAN NOT BE REMOVED![/color]",
special_buttons = "Special actions. Like teleporting home. (For now this is the only one...)",
special_buttons = "Special actions. Like teleporting home. (For now this is the only one...)"
}
-- N = number already purchased
@ -87,6 +87,21 @@ OARC_STORE_MAP_FEATURES =
["assembling-machine-1"] = {
initial_cost = 10,
text="Teleport home."},
["crash-site-generator"] = {
initial_cost = 5000,
solo_force = true,
text="DESTROY your base and restart. This allows you to choose a new spawn and will completely remove all your buildings and your force. All technology progress will be reset."
},
["crash-site-lab-broken"] = {
initial_cost = 10000,
solo_force = true,
text="ABANDON your base and restart. This allows you to choose a new spawn and will move all your buildings to a neutral force. They will still be on the map and can be interacted with, but will not be owned by any player or player force. All radars will be destroyed to help trim map size."
},
["crash-site-chest-1"] = {
initial_cost = 5000,
main_force = true,
text="Restart your player. This will kick you from the game and delete your player. Any buildings that you created or interacted with (last_user = you) will be destroyed."
}
}
}
@ -113,6 +128,14 @@ function CreateMapFeatureStoreTab(tab_container, player)
{bottom_margin=5, maximal_width = 400, single_line = false})
local flow = tab_container.add{name = category, type="flow", direction="horizontal"}
for item_name,item in pairs(section) do
if (item.solo_force and (player.force ~= global.ocfg.main_force)) then
goto SKIP_ITEM
end
if (item.main_force and (player.force == global.ocfg.main_force)) then
goto SKIP_ITEM
end
local count = OarcMapFeaturePlayerCountGet(player, category, item_name)
local cost = OarcMapFeatureCostScaling(player, category, item_name)
local color = "[color=green]"
@ -135,6 +158,7 @@ function CreateMapFeatureStoreTab(tab_container, player)
else
btn.tooltip = item.text.." Cost: "..color..cost.."[/color] [item=coin]"
end
::SKIP_ITEM::
end
local line2 = tab_container.add{type="line", direction="horizontal"}
line2.style.top_margin = 5
@ -241,10 +265,19 @@ function OarcMapFeatureStoreButton(event)
elseif (button.name == "centrifuge") then
result = RequestSpawnSpecialChunk(player, SpawnAssemblyChunk, button.name)
elseif (button.name == "rocket-silo") then
result = RequestSpawnSpecialChunk(player, SpawnSiloChunk, button.name)
result = RequestSpawnSpecialChunk(player, SpawnSiloChunk, button.name)
elseif (button.name == "assembling-machine-1") then
SendPlayerToSpawn(player)
result = true
elseif (button.name == "crash-site-generator") then
DestroyForce(player)
result = true
elseif (button.name == "crash-site-lab-broken") then
AbandonForce(player)
result = true
elseif (button.name == "crash-site-chest-1") then
KickAndMarkPlayerForRemoval(player)
result = true
end
-- On success, we deduct money

View File

@ -381,9 +381,9 @@ end
-- Set all forces to ceasefire
function SetCeaseFireBetweenAllForces()
for name,team in pairs(game.forces) do
if name ~= "neutral" and name ~= "enemy" then
if name ~= "neutral" and name ~= "enemy" and name ~= global.ocore.abandoned_force then
for x,y in pairs(game.forces) do
if x ~= "neutral" and x ~= "enemy" then
if x ~= "neutral" and x ~= "enemy" and name ~= global.ocore.abandoned_force then
team.set_cease_fire(x,true)
end
end
@ -394,9 +394,9 @@ end
-- Set all forces to friendly
function SetFriendlyBetweenAllForces()
for name,team in pairs(game.forces) do
if name ~= "neutral" and name ~= "enemy" then
if name ~= "neutral" and name ~= "enemy" and name ~= global.ocore.abandoned_force then
for x,y in pairs(game.forces) do
if x ~= "neutral" and x ~= "enemy" then
if x ~= "neutral" and x ~= "enemy" and name ~= global.ocore.abandoned_force then
team.set_friend(x,true)
end
end

View File

@ -318,6 +318,30 @@ function WorldEaterSingleStep()
return -- Chunk isn't in our map so we don't care?
end
-- Search for any abandoned radars and destroy them?
local entities = game.surfaces[GAME_SURFACE_NAME].find_entities_filtered{area=next_chunk.area,
force={global.ocore.abandoned_force},
name="radar"}
for k,v in pairs(entities) do
v.die(nil)
end
-- Search for any entities with _DESTROYED_ force and kill them.
entities = game.surfaces[GAME_SURFACE_NAME].find_entities_filtered{area=next_chunk.area,
force={global.ocore.destroyed_force}}
for k,v in pairs(entities) do
v.die(nil)
end
-- Text for visual debugging.
rendering.draw_text{text="WORLD EATER",
surface=game.surfaces[GAME_SURFACE_NAME],
target=GetCenterTilePosFromChunkPos(next_chunk),
color={0.7,0.7,0.7,0.7},
scale=1,
font="compi",
time_to_live=60*3}
-- If the chunk isn't marked permament, then check if we can remove it
local c_timer = global.rg.map[next_chunk.x][next_chunk.y]
if (c_timer == -1) then

View File

@ -93,6 +93,12 @@ function InitSpawnGlobalsAndForces()
-- This is what any new player is assigned to when they join, even before they spawn.
local main_force = CreateForce(global.ocfg.main_force)
main_force.set_spawn_position({x=0,y=0}, GAME_SURFACE_NAME)
-- Special forces for when players with their own force want a reset.
global.ocore.abandoned_force = "_ABANDONED_"
global.ocore.destroyed_force = "_DESTROYED_"
game.create_force(global.ocore.abandoned_force)
game.create_force(global.ocore.destroyed_force)
end
@ -115,14 +121,11 @@ function SeparateSpawnsPlayerCreated(player_index, clear_inv)
SetOarcGuiTabEnabled(player, OARC_SPAWN_CTRL_GUI_NAME, false)
SwitchOarcGuiTab(player, OARC_GAME_OPTS_GUI_TAB_NAME)
-- If they are NOT a new player, reset them.
if (player.force.name ~= "player") then
RemoveOrResetPlayer(player, false, true)
else
-- If they are a new player, put them on the main force.
if (player.force.name == "player") then
player.force = global.ocfg.main_force
end
-- Reset counts for map feature usage for this player.
OarcMapFeaturePlayerCreatedEvent(player)
@ -526,8 +529,45 @@ end
--]]
function DestroyForce(player)
local player_old_force = player.force
player.force = global.ocfg.main_force
if ((#player_old_force.players <= 1) and (player_old_force.name ~= global.ocfg.main_force)) then
SendBroadcastMsg("Team " .. player_old_force.name .. " has been destroyed! All buildings will slowly be destroyed now.")
log("DestroyForce - FORCE DESTROYED: " .. player_old_force.name)
game.merge_forces(player_old_force, global.ocore.destroyed_force)
end
RemoveOrResetPlayer(player, false, false, false)
end
function AbandonForce(player)
local player_old_force = player.force
player.force = global.ocfg.main_force
if ((#player_old_force.players <= 1) and (player_old_force.name ~= global.ocfg.main_force)) then
SendBroadcastMsg("Team " .. player_old_force.name .. " has been abandoned!")
log("AbandonForce - FORCE ABANDONED: " .. player_old_force.name)
game.merge_forces(player_old_force, global.ocore.abandoned_force)
end
RemoveOrResetPlayer(player, false, false, false)
end
function KickAndMarkPlayerForRemoval(player)
game.kick_player(player, "KickAndMarkPlayerForRemoval")
if (not global.ocore.player_removal_list) then
global.ocore.player_removal_list = {}
end
table.insert(global.ocore.player_removal_list, player)
end
-- Call this if a player leaves the game early (or a player wants an early game reset)
function RemoveOrResetPlayer(player, remove_player, remove_force)
function RemoveOrResetPlayer(player, remove_player, remove_force, remove_base)
if (not player) then
log("ERROR - CleanupPlayer on NIL Player!")
return
@ -543,12 +583,11 @@ function RemoveOrResetPlayer(player, remove_player, remove_force)
CleanupPlayerGlobals(player.name) -- Except global.ocore.uniqueSpawns
-- Clear their unique spawn (if they have one)
UniqueSpawnCleanupRemove(player.name) -- Specifically global.ocore.uniqueSpawns
UniqueSpawnCleanupRemove(player.name, remove_base) -- Specifically global.ocore.uniqueSpawns
-- Remove a force if this player created it and they are the only one on it
if (remove_force) then
if ((#player_old_force.players == 0) and (player_old_force.name ~= global.ocfg.main_force)) then
SendBroadcastMsg("FORCE REMOVED?!")
log("RemoveOrResetPlayer - FORCE REMOVED: " .. player_old_force.name)
game.merge_forces(player_old_force, "neutral")
end
@ -560,7 +599,7 @@ function RemoveOrResetPlayer(player, remove_player, remove_force)
end
end
function UniqueSpawnCleanupRemove(playerName)
function UniqueSpawnCleanupRemove(playerName, cleanup)
if (global.ocore.uniqueSpawns[playerName] == nil) then return end -- Safety
log("UniqueSpawnCleanupRemove - " .. playerName)
@ -576,7 +615,7 @@ function UniqueSpawnCleanupRemove(playerName)
end
-- Unused Chunk Removal mod (aka regrowth)
if (global.ocfg.enable_abandoned_base_removal and (not nearOtherSpawn) and global.ocfg.enable_regrowth) then
if (cleanup and global.ocfg.enable_abandoned_base_removal and (not nearOtherSpawn) and global.ocfg.enable_regrowth) then
if (global.ocore.uniqueSpawns[playerName].vanilla) then
log("Returning a vanilla spawn back to available.")
@ -587,10 +626,6 @@ function UniqueSpawnCleanupRemove(playerName)
RegrowthMarkAreaForRemoval(spawnPos, math.ceil(global.ocfg.spawn_config.gen_settings.land_area_tiles/CHUNK_SIZE))
TriggerCleanup()
SendBroadcastMsg(playerName .. "'s base was marked for immediate clean up because they left within "..global.ocfg.minimum_online_time.." minutes of joining.")
else
SendBroadcastMsg(playerName .. " base was abandoned because they left within "..global.ocfg.minimum_online_time.." minutes of joining.")
end
global.ocore.uniqueSpawns[playerName] = nil
@ -890,7 +925,7 @@ function CreateForce(force_name)
-- Check if force already exists
if (game.forces[force_name] ~= nil) then
log("Force already exists!")
return game.forces[global.ocfg.main_force]
return CreateForce(force_name .. "_") -- Append a character to make the force name unique.
-- Create a new force
elseif (TableLength(game.forces) < MAX_FORCES) then