1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2024-12-28 23:06:38 +02:00

Crew related changes

Changes:
- Added protected run checkbox when creating new run proposal. This locks captain role when captain becomes afk or leaves the afk.
- Increased crew run limit from 2 to 3.
- Public crew will no longer have captain protection when captain goes afk.
- Fixed an exploit where player could join private run bypassing password protection.
- Fixed an issue where spectator could take a class.
- Adjusted some GUI elements to look nicer.
This commit is contained in:
Piratux 2023-02-02 21:44:44 +02:00
parent 032c4d9d4f
commit 0d9be8e524
12 changed files with 215 additions and 44 deletions

View File

@ -76,7 +76,9 @@ parrot_cave_tip_1=That island looks suspiciously dark... I'm scared! Squawk!
parrot_captain_first_time_in_cabin_hint=Squawk! Captains and officers can buy rail signals to steer the ship!
parrot_cliff_explosive_tip=Cliff explosives? These look so powerful, they could blow away those annoying chests in the hold. Squawk!
parrot_buried_treasure_tip=Squawk! If X marks the spot - use an item to dig with!
parrot_captain_left_protected_run=Uh oh, looks like the captain left. Since this is protected run, the captain role will not be redistributed.
parrot_player_joins_protected_run_with_no_captain=This run has captain protection turned on, so you will have to wait for captain to come back to control the ship.
parrot_create_new_crew_tip=You can always join/create another run from the lobby by exiting current run by clicking red flag on top then clicking Quit Crew.
difficulty_easy=Easy
difficulty_normal=Normal
@ -105,6 +107,7 @@ victory_continue_reminder=If you wish to continue the game, click up top.
crew_disband_tick_message=The crew will disband in 20 seconds.
protected_run_lock_expired=Protection of __1__ run has expired. Captain role will not be locked anymore when the captain leaves.
private_run_lock_expired=Private lock of __1__ run has expired. Anyone can join this crew now.
plank=__1__ planked __2__!
@ -536,14 +539,18 @@ gui_runs_proposal_maker_capacity=Capacity
gui_runs_proposal_maker_capacity_disabled=This capacity setting isn't available at the moment.
gui_runs_proposal_maker_propose=Propose
gui_runs_proposal_maker_no_limit=No limit
gui_runs_proposal_maker_protected=Protected
gui_runs_proposal_maker_protected_tooltip=Enables captain protection, which locks captain role when captain leaves or becomes afk instead of distributing the role to random crew member.\nCaptain protection expires if the crew is empty or inactive for __1__ hours.
gui_runs_proposal_maker_private=Private
gui_runs_proposal_maker_private_tooltip=Sets your run to private, which protects the run by password.\nOnce the run has launched, only people who know password will be able to join the crew.\nPrivate run becomes public if the crew is empty or inactive for __1__ hours.
gui_runs_proposal_maker_password=Password
gui_runs_proposal_maker_confirm_password=Confirm Password
gui_runs_proposal_maker_error_protected_run_limit=All protected run slots are occupied. Wait until protected run slots free up to create your own.
gui_runs_proposal_maker_error_private_run_limit=All private run slots are occupied. Wait until private run slots free up to create your own.
gui_runs_proposal_maker_error_private_run_password_no_match=Passwords do not match.
gui_runs_proposal_maker_error_private_run_password_empty=Passwords can't be empty.
gui_join_private_run_info=This run is private and protected.\nPlease enter a password to join the crew.\nThis run will become public in __1__:__2__:__3__
gui_join_protected_run_info=This run is protected.\nThis means when captain leaves the game, other members won't get the captain role.\nCaptain protection expires in __1__:__2__:__3__
gui_join_private_run_info=This run is private.\nPlease enter a password to join the crew.\nThis run will become public in __1__:__2__:__3__
gui_join_private_run_error_wrong_password=The password you've entered is incorrect.

View File

@ -1406,7 +1406,7 @@ local function event_on_player_joined_game(event)
Crew.join_crew(player, crew_to_put_back_in, true)
local memory = global_memory.crew_memories[crew_to_put_back_in]
if #memory.crewplayerindices <= 1 then
if (not memory.run_is_protected) and #memory.crewplayerindices <= 1 then
memory.playerindex_captain = player.index
end
@ -1463,7 +1463,7 @@ local function event_on_player_joined_game(event)
Crew.join_crew(player, ages[1].id)
local memory = global_memory.crew_memories[ages[1].id]
if #memory.crewplayerindices <= 1 then
if (not memory.run_is_protected) and #memory.crewplayerindices <= 1 then
memory.playerindex_captain = player.index
end
@ -1474,6 +1474,11 @@ local function event_on_player_joined_game(event)
Common.notify_player_announce(player, {'pirates.goto_oldest_crew'})
end
end
if memory.run_is_protected and (not Roles.captain_exists()) then
Common.parrot_speak(memory.force, {'pirates.parrot_player_joins_protected_run_with_no_captain'})
Common.parrot_speak(memory.force, {'pirates.parrot_create_new_crew_tip'})
end
end
end

View File

@ -1626,6 +1626,25 @@ function Public.revealed_buried_treasure_distance_check()
end
end
function Public.update_protected_run_lock_timer(tickinterval)
local memory = Memory.get_crew_memory()
if memory.run_is_protected then
if Common.activecrewcount() <= 0 then
if memory.protected_run_lock_timer > 0 then
memory.protected_run_lock_timer = memory.protected_run_lock_timer - tickinterval
if memory.protected_run_lock_timer <= 0 then
Common.notify_game({'pirates.protected_run_lock_expired', memory.name})
memory.run_is_protected = false
Roles.assign_captain_based_on_priorities()
end
end
else
memory.protected_run_lock_timer = 60 * 60 * 60 * CoreData.protected_run_lock_amount_hr
end
end
end
function Public.update_private_run_lock_timer(tickinterval)
local memory = Memory.get_crew_memory()
if memory.run_is_private then

View File

@ -21,9 +21,9 @@ local LootRaffle = require 'functions.loot_raffle'
local Public = {}
-- Public.active_crews_cap = 1
Public.activeCrewsCap = 2
Public.activeCrewsCap = 3
Public.private_run_cap = 1
Public.protected_run_cap = 1 -- more precisely protected, but not private run cap
Public.minimumCapacitySliderValue = 1
Public.minimum_run_capacity_to_enforce_space_for = 22
-- auto-disbanding when there are no players left in the crew:
@ -850,7 +850,9 @@ end
function Public.crew_get_crew_members_and_spectators()
local memory = Memory.get_crew_memory()
if not Public.is_id_valid(memory.id) then return {} end
if not Public.is_id_valid(memory.id) then
return {}
end
local playerlist = {}
for _, id in pairs(memory.crewplayerindices) do
@ -864,6 +866,30 @@ function Public.crew_get_crew_members_and_spectators()
return playerlist
end
function Public.is_spectator(player)
local global_memory = Memory.get_global_memory()
local previous_id = global_memory.working_id
local player_crew_id = Public.get_id_from_force_name(player.force.name)
if not player_crew_id then
return false
end
Memory.set_working_id(player_crew_id)
local memory = Memory.get_crew_memory()
local spectating = false
for _, playerindex in pairs(memory.spectatorplayerindices) do
if player.index == playerindex then
spectating = true
break
end
end
Memory.set_working_id(previous_id)
return spectating
end

View File

@ -21,6 +21,7 @@ Public.total_max_biters = 2200
Public.lobby_surface_name = '000-000-Lobby'
Public.private_run_lock_amount_hr = 24 -- how many hours need to pass, when crew is empty or inactive, until private run becomes public
Public.protected_run_lock_amount_hr = 24 -- how many hours need to pass, when crew is empty or inactive, until captain protection expires
Public.colors = {
coal = {r=0.5, g=0.5, b=0.5},

View File

@ -394,7 +394,9 @@ function Public.join_crew(player, crewid, rejoin)
end
end
Roles.confirm_captain_exists(player)
if not memory.run_is_protected then
Roles.confirm_captain_exists(player)
end
if #Common.crew_get_crew_members() == 1 and memory.crew_disband_tick then
memory.crew_disband_tick = nil --to prevent disbanding the crew after saving the game (booting everyone) and loading it again (joining the crew as the only member)
@ -495,7 +497,7 @@ function Public.plank(captain, player)
local memory = Memory.get_crew_memory()
if Utils.contains(Common.crew_get_crew_members(), player) then
if (not (captain.index == player.index)) then
if captain.index ~= player.index then
Server.to_discord_embed_raw(CoreData.comfy_emojis.despair .. string.format("%s planked %s!", captain.name, player.name))
Common.notify_force(player.force, {'pirates.plank', captain.name, player.name})
@ -728,6 +730,8 @@ function Public.initialise_crew(accepted_proposal)
memory.difficulty = CoreData.difficulty_options[accepted_proposal.difficulty_option].value
memory.capacity = CoreData.capacity_options[accepted_proposal.capacity_option].value
-- memory.mode = CoreData.mode_options[accepted_proposal.mode_option].value
memory.run_is_protected = accepted_proposal.run_is_protected
memory.protected_run_lock_timer = 60 * 60 * 60 * CoreData.protected_run_lock_amount_hr
memory.run_is_private = accepted_proposal.run_is_private
memory.private_run_password = accepted_proposal.private_run_password
memory.private_run_lock_timer = 60 * 60 * 60 * CoreData.private_run_lock_amount_hr

View File

@ -218,6 +218,10 @@ function Public.full_update(player, force_refresh)
button.style.clicked_font_color = black
button.enabled = false
end
if Common.is_spectator(player) then
button.enabled = false
end
else
log('Error: Non-existant label index, here some debug info.')
log(_inspect(class_list_panel_table))

View File

@ -45,6 +45,10 @@ Public.default_window_positions = {
color = {x = 160, y = 96},
}
-- Player who created the proposal is already an endorser
function Public.proposal_endorsers_required()
return Math.min(4, Math.ceil((#game.connected_players or 0)/5))
end
function Public.new_window(player, name)
@ -280,6 +284,7 @@ function Public.flow_add_section(flow, name, caption)
direction = 'vertical',
})
flow3.style.left_margin = 5
flow3.style.right_margin = 5
return flow3
end
@ -376,7 +381,7 @@ function Public.crew_overall_state_bools(player_index)
ret.crew_count_capped = true
elseif global_memory.active_crews_cap > 1 and #global_memory.crew_active_ids == (global_memory.active_crews_cap - 1) and not ((global_memory.crew_memories[1] and global_memory.crew_memories[1].capacity >= Common.minimum_run_capacity_to_enforce_space_for) or (global_memory.crew_memories[2] and global_memory.crew_memories[2].capacity >= Common.minimum_run_capacity_to_enforce_space_for) or (global_memory.crew_memories[3] and global_memory.crew_memories[3].capacity >= Common.minimum_run_capacity_to_enforce_space_for)) and not (CoreData.capacity_options[proposal.capacity_option].value >= Common.minimum_run_capacity_to_enforce_space_for) then
ret.needs_more_capacity = true
elseif proposal.endorserindices and #global_memory.crew_active_ids > 0 and #proposal.endorserindices < Math.min(4, Math.ceil((#game.connected_players or 0)/5)) then
elseif proposal.endorserindices and #global_memory.crew_active_ids > 0 and #proposal.endorserindices < Public.proposal_endorsers_required() then
ret.needs_more_endorsers = true
end
if (not (ret.sloops_full or ret.needs_more_capacity or ret.needs_more_endorsers or ret.crew_count_capped)) then

View File

@ -44,7 +44,7 @@ function Public.toggle_window(player)
name = 'scroll_pane',
direction = 'vertical',
horizontal_scroll_policy = 'never',
vertical_scroll_policy = 'auto'
vertical_scroll_policy = 'auto-and-reserve-space'
}
flow.style.maximal_height = 500
flow.style.bottom_margin = 10
@ -162,7 +162,7 @@ function Public.toggle_window(player)
type = 'list-box'
}
)
flow3.style.margin = 2
flow3.style.margin = 5
flow3.style.maximal_height = 350
flow3 =
@ -433,7 +433,7 @@ function Public.full_update(player)
end
end
end
flow.membership_buttons.spectator_join_crew.visible = playercrew_status.spectating and (not (count >= memory.capacity))
flow.membership_buttons.spectator_join_crew.visible = playercrew_status.spectating and (not (count >= memory.capacity)) and (not memory.run_is_private)
flow.membership_buttons.leave_crew.visible = playercrew_status.adventuring
-- flow.membership_buttons.crewmember_join_spectators.visible = playercrew_status.adventuring
@ -513,6 +513,11 @@ function Public.click(event)
if eventname == 'spectator_join_crew' then
Crew.join_crew(player, memory.id)
if memory.run_is_protected and (not Roles.captain_exists()) then
Common.parrot_speak(memory.force, {'pirates.parrot_player_joins_protected_run_with_no_captain'})
Common.parrot_speak(memory.force, {'pirates.parrot_create_new_crew_tip'})
end
return
end

View File

@ -6,7 +6,7 @@ local CoreData = require 'maps.pirates.coredata'
local Utils = require 'maps.pirates.utils_local'
local Math = require 'maps.pirates.math'
-- local Surfaces = require 'maps.pirates.surfaces.surfaces'
-- local Roles = require 'maps.pirates.roles.roles'
local Roles = require 'maps.pirates.roles.roles'
local Crew = require 'maps.pirates.crew'
local Progression = require 'maps.pirates.progression'
-- local Structures = require 'maps.pirates.structures.structures'
@ -177,7 +177,7 @@ function Public.toggle_window(player)
name = 'scroll_pane',
direction = 'vertical',
horizontal_scroll_policy = 'never',
vertical_scroll_policy = 'auto'
vertical_scroll_policy = 'auto-and-reserve-space'
}
flow.style.maximal_height = 500
flow.style.bottom_margin = 10
@ -200,10 +200,19 @@ function Public.toggle_window(player)
type = 'list-box',
})
flow3.style.margin = 2
flow3.style.right_margin = 5
flow3.style.horizontally_stretchable = true
flow3 = flow2.add({
name = 'join_crew_info',
name = 'join_protected_crew_info',
type = 'label',
caption = {'pirates.gui_join_protected_run_info', 0, 0, 0},
visible = false,
})
flow3.style.single_line = false
flow3 = flow2.add({
name = 'join_private_crew_info',
type = 'label',
caption = {'pirates.gui_join_private_run_info', 0, 0, 0},
visible = false,
@ -277,6 +286,8 @@ function Public.toggle_window(player)
type = 'list-box',
})
flow3.style.margin = 2
flow3.style.right_margin = 5
flow3.style.horizontally_stretchable = true
flow3 = flow2.add({
name = 'flow_buttons',
@ -344,6 +355,16 @@ function Public.toggle_window(player)
flow5.style.top_margin = -3
flow5.style.bottom_margin = 3
-- PROTECTED RUN ELEMENTS --
flow4.add({
name = 'protected_checkbox',
type = 'checkbox',
caption = {'pirates.gui_runs_proposal_maker_protected'},
state = false,
tooltip = {'pirates.gui_runs_proposal_maker_protected_tooltip', CoreData.protected_run_lock_amount_hr}
})
-- PRIVATE RUN ELEMENTS --
flow4.add({
@ -525,11 +546,12 @@ function Public.full_update(player)
flow.ongoing_runs.body.leaving_prompt.visible = playercrew_status.leaving
local show_protected_info = crewid and global_memory.crew_memories[crewid].run_is_protected
flow.ongoing_runs.body.join_protected_crew_info.visible = show_protected_info
local show_password_info = crewid and global_memory.crew_memories[crewid].run_is_private
flow.ongoing_runs.body.join_crew_info.visible = show_password_info
flow.ongoing_runs.body.password_namefield.visible = show_password_info
local show_private_info = crewid and global_memory.crew_memories[crewid].run_is_private
flow.ongoing_runs.body.join_private_crew_info.visible = show_private_info
flow.ongoing_runs.body.password_namefield.visible = show_private_info
end
flow.proposals.visible = (memory.crewstatus == nil and not playercrew_status.leaving)
@ -598,13 +620,22 @@ function Public.full_update(player)
crewid = tonumber((flow.ongoing_runs.body.ongoing_runs_listbox.get_item(flow.ongoing_runs.body.ongoing_runs_listbox.selected_index))[2])
end
-- Update timer when captain protection expires
if crewid and flow.ongoing_runs.body.join_protected_crew_info.visible then
local lock_timer = global_memory.crew_memories[crewid].protected_run_lock_timer
local sec = Math.floor((lock_timer / (60)) % 60)
local min = Math.floor((lock_timer / (60 * 60)) % 60)
local hrs = Math.floor((lock_timer / (60 * 60 * 60)) % 60)
flow.ongoing_runs.body.join_protected_crew_info.caption = {'pirates.gui_join_protected_run_info', hrs, min, sec}
end
-- Update timer when run will become public
if crewid and flow.ongoing_runs.body.join_crew_info.visible then
if crewid and flow.ongoing_runs.body.join_private_crew_info.visible then
local lock_timer = global_memory.crew_memories[crewid].private_run_lock_timer
local sec = Math.floor((lock_timer / (60)) % 60)
local min = Math.floor((lock_timer / (60 * 60)) % 60)
local hrs = Math.floor((lock_timer / (60 * 60 * 60)) % 60)
flow.ongoing_runs.body.join_crew_info.caption = {'pirates.gui_join_private_run_info', hrs, min, sec}
flow.ongoing_runs.body.join_private_crew_info.caption = {'pirates.gui_join_private_run_info', hrs, min, sec}
end
end
@ -678,17 +709,29 @@ function Public.click(event)
local listbox = flow.ongoing_runs.body.ongoing_runs_listbox
local crewid = tonumber(listbox.get_item(listbox.selected_index)[2])
local memory = global_memory.crew_memories[crewid]
-- If run is private
if global_memory.crew_memories[crewid].run_is_private then
if global_memory.crew_memories[crewid].private_run_password == flow.ongoing_runs.body.password_namefield.text then
Crew.join_crew(player, crewid)
flow.ongoing_runs.body.join_crew_info.visible = false
flow.ongoing_runs.body.join_private_crew_info.visible = false
flow.ongoing_runs.body.password_namefield.visible = false
if memory.run_is_protected and (not Roles.captain_exists()) then
Common.parrot_speak(memory.force, {'pirates.parrot_player_joins_protected_run_with_no_captain'})
Common.parrot_speak(memory.force, {'pirates.parrot_create_new_crew_tip'})
end
else
Common.notify_player_error(player, {'pirates.gui_join_private_run_error_wrong_password'})
end
else
Crew.join_crew(player, crewid)
if memory.run_is_protected and (not Roles.captain_exists()) then
Common.parrot_speak(memory.force, {'pirates.parrot_player_joins_protected_run_with_no_captain'})
Common.parrot_speak(memory.force, {'pirates.parrot_create_new_crew_tip'})
end
end
return
@ -700,17 +743,25 @@ function Public.click(event)
return
end
-- If proposal was set as private
-- Count private runs
local private_run_count = 0
for _, id in pairs(global_memory.crew_active_ids) do
if global_memory.crew_memories[id].run_is_private then
private_run_count = private_run_count + 1
end
end
-- Count protected but not private runs
local protected_but_not_private_run_count = 0
for _, id in pairs(global_memory.crew_active_ids) do
if global_memory.crew_memories[id].run_is_protected and (not global_memory.crew_memories[id].run_is_private) then
protected_but_not_private_run_count = protected_but_not_private_run_count + 1
end
end
local run_is_protected = flow.proposals.body.proposal_maker.body.protected_checkbox.state
local run_is_private = flow.proposals.body.proposal_maker.body.private_checkbox.state
if run_is_private then
-- Count private runs
local private_run_count = 0
for _, id in pairs(global_memory.crew_active_ids) do
if global_memory.crew_memories[id].run_is_private then
private_run_count = private_run_count + 1
end
end
-- Make sure private run can be created
if private_run_count >= global_memory.private_run_cap then
Common.notify_player_error(player, {'pirates.gui_runs_proposal_maker_error_private_run_limit'})
@ -728,6 +779,12 @@ function Public.click(event)
Common.notify_player_error(player, {'pirates.gui_runs_proposal_maker_error_private_run_password_empty'})
return
end
elseif run_is_protected then
-- Make sure protected run can be created
if protected_but_not_private_run_count >= global_memory.protected_run_cap then
Common.notify_player_error(player, {'pirates.gui_runs_proposal_maker_error_protected_run_limit'})
return
end
end
local private_run_password = flow.proposals.body.proposal_maker.body.password_namefield.text
@ -778,6 +835,7 @@ function Public.click(event)
capacity_option = capacity_option,
-- mode_option = mode_option,
endorserindices = {player.index},
run_is_protected = run_is_protected,
run_is_private = run_is_private,
private_run_password = private_run_password,
}
@ -840,6 +898,18 @@ function Public.click(event)
Common.notify_player_error(player, {'pirates.gui_runs_proposal_maker_error_private_run_limit'})
return
end
elseif proposal.run_is_protected then
local protected_but_not_private_run_count = 0
for _, id in pairs(global_memory.crew_active_ids) do
if global_memory.crew_memories[id].run_is_protected and (not global_memory.crew_memories[id].run_is_private) then
protected_but_not_private_run_count = protected_but_not_private_run_count + 1
end
end
if protected_but_not_private_run_count >= global_memory.protected_run_cap then
Common.notify_player_error(player, {'pirates.gui_runs_proposal_maker_error_protected_run_limit'})
return
end
end
Crew.initialise_crew(proposal)
@ -851,7 +921,6 @@ function Public.click(event)
end
end
end
end
return Public

View File

@ -112,6 +112,7 @@ local function on_init()
Common.init_game_settings(Balance.technology_price_multiplier)
global_memory.active_crews_cap = Common.activeCrewsCap
global_memory.protected_run_cap = Common.protected_run_cap
global_memory.private_run_cap = Common.private_run_cap
global_memory.minimumCapacitySliderValue = Common.minimumCapacitySliderValue
@ -188,6 +189,7 @@ local function crew_tick()
PiratesApiOnTick.check_for_cliff_explosives_in_hold_wooden_chests()
PiratesApiOnTick.equalise_fluid_storages() -- Made the update less often for small performance gain, but frequency can be increased if players complain
PiratesApiOnTick.revealed_buried_treasure_distance_check()
PiratesApiOnTick.update_protected_run_lock_timer(60)
PiratesApiOnTick.update_private_run_lock_timer(60)
PiratesApiOnTick.victory_continue_reminder()
Kraken.overall_kraken_tick()

View File

@ -33,7 +33,7 @@ function Public.make_officer(captain, player)
local force = memory.force
if Utils.contains(Common.crew_get_crew_members(), player) then
if (not (captain.index == player.index)) then
if captain.index ~= player.index then
if Common.validate_player(player) then
memory.officers_table[player.index] = true
@ -188,7 +188,7 @@ function Public.player_confirm_captainhood(player)
local memory = Memory.get_crew_memory()
local captain_index = memory.playerindex_captain
if not (player.index == captain_index) then
if player.index ~= captain_index then
Common.notify_player_error(player,{'pirates.roles_confirm_captain_error_1'})
else
if memory.captain_acceptance_timer then
@ -208,12 +208,19 @@ function Public.player_confirm_captainhood(player)
end
function Public.player_left_so_redestribute_roles(player)
-- local memory = Memory.get_crew_memory()
if not (player and player.index) then return end
local memory = Memory.get_crew_memory()
if Common.is_captain(player) then
Public.assign_captain_based_on_priorities()
if memory.run_is_protected then
if memory.crewplayerindices and #memory.crewplayerindices > 0 then
Common.parrot_speak(memory.force, {'pirates.parrot_captain_left_protected_run'})
Common.parrot_speak(memory.force, {'pirates.parrot_create_new_crew_tip'})
end
else
Public.assign_captain_based_on_priorities()
end
end
-- no need to do this, as long as officers get reset when the captainhood changes hands
@ -221,8 +228,6 @@ function Public.player_left_so_redestribute_roles(player)
-- memory.officers_table[player.index] = nil
-- end
local memory = Memory.get_crew_memory()
local class = Classes.get_class(player.index)
-- free up the class
@ -278,13 +283,30 @@ function Public.resign_as_officer(player)
end
end
function Public.captain_exists()
local memory = Memory.get_crew_memory()
if Common.is_id_valid(memory.id) and
memory.crewstatus == 'adventuring' and --@fixme: enum hacked
memory.playerindex_captain and
game.players[memory.playerindex_captain] and
Common.validate_player(game.players[memory.playerindex_captain])
then
local crew_members = Common.crew_get_crew_members()
for _, player in pairs(crew_members) do
if player.index == memory.playerindex_captain then
return true
end
end
end
return false
end
function Public.confirm_captain_exists(player_to_make_captain_otherwise)
local memory = Memory.get_crew_memory()
-- Currently this catches an issue where a crew drops to zero players, and then someone else joins.
if (Common.is_id_valid(memory.id) and memory.crewstatus and memory.crewstatus == 'adventuring') and (not (memory.playerindex_captain and game.players[memory.playerindex_captain] and Common.validate_player(game.players[memory.playerindex_captain]))) then --fixme: enum hacked
if not Public.captain_exists() then
if player_to_make_captain_otherwise then
Public.make_captain(player_to_make_captain_otherwise)
-- game.print('Auto-reassigning captain.')
@ -315,7 +337,7 @@ function Public.afk_player_tick(player)
-- local global_memory = Memory.get_global_memory()
local memory = Memory.get_crew_memory()
if Common.is_captain(player) and #Common.crew_get_nonafk_crew_members() >= 6 then
if Common.is_captain(player) and (not memory.run_is_protected) then
-- in this case, lose captainhood
local force = memory.force
@ -426,6 +448,8 @@ end
function Public.captain_tax(captain_index)
if not captain_index then return end
local memory = Memory.get_crew_memory()
local any_taken = false