1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-01-24 03:47:58 +02:00
ComfyFactorio/score.lua

457 lines
16 KiB
Lua
Raw Normal View History

2018-10-03 21:17:12 +02:00
--scoreboard by mewmew
2018-09-19 06:51:25 +02:00
2018-10-03 21:17:12 +02:00
local event = require 'utils.event'
local sorting_symbol = {ascending = "", descending = ""}
2018-09-19 06:51:25 +02:00
2018-10-03 21:17:12 +02:00
local function create_score_button(player)
if not player.gui.top.score then
2019-06-11 01:52:49 +02:00
local button = player.gui.top.add({ type = "sprite-button", name = "score", sprite = "item/rocket-silo", tooltip = "Scoreboard" })
2018-09-19 06:51:25 +02:00
button.style.minimal_height = 38
button.style.minimal_width = 38
2019-10-02 21:13:14 +02:00
button.style.padding = 1
2018-09-19 06:51:25 +02:00
end
end
2019-06-11 01:52:49 +02:00
local function get_score_list(force)
local score = global.score[force]
local score_list = {}
for _, p in pairs(game.connected_players) do
if score.players[p.name] then
local score = score.players[p.name]
table.insert(score_list, {
name = p.name,
killscore = score.killscore or 0,
deaths = score.deaths or 0,
built_entities = score.built_entities or 0,
mined_entities = score.mined_entities or 0,
})
2018-10-03 21:17:12 +02:00
end
end
return score_list
2018-09-19 06:51:25 +02:00
end
2019-06-11 01:52:49 +02:00
local function get_sorted_list(method, column_name, score_list)
local comparators = {
["ascending"] = function(a,b) return a[column_name] < b[column_name] end,
["descending"] = function(a,b) return a[column_name] > b[column_name] end
}
table.sort(score_list, comparators[method])
return score_list
end
2018-10-25 13:00:38 +02:00
local biters = {"small-biter", "medium-biter", "big-biter", "behemoth-biter", "small-spitter", "medium-spitter", "big-spitter", "behemoth-spitter"}
local function get_total_biter_killcount(force)
local count = 0
for _, biter in pairs(biters) do
count = count + force.kill_count_statistics.get_input_count(biter)
end
return count
end
2019-06-11 01:52:49 +02:00
local function add_global_stats(frame, player)
2018-10-03 21:17:12 +02:00
local score = global.score[player.force.name]
local t = frame.add { type = "table", column_count = 5}
2019-06-11 01:52:49 +02:00
local l = t.add { type = "label", caption = "Rockets launched: "}
l.style.font = "default-game"
2018-10-03 21:17:12 +02:00
l.style.font_color = {r = 175, g = 75, b = 255}
l.style.minimal_width = 140
2019-06-11 01:52:49 +02:00
2018-10-03 21:17:12 +02:00
local str = "0"
if score.rocket_launches then str = tostring(score.rocket_launches) end
local l = t.add { type = "label", caption = str}
2019-02-26 20:05:31 +01:00
l.style.font = "default-listbox"
2018-10-03 21:17:12 +02:00
l.style.font_color = { r=0.9, g=0.9, b=0.9}
l.style.minimal_width = 123
2018-09-19 06:51:25 +02:00
2019-06-11 01:52:49 +02:00
local l = t.add { type = "label", caption = "Dead biters: "}
l.style.font = "default-game"
2018-10-03 21:17:12 +02:00
l.style.font_color = { r=0.90, g=0.3, b=0.3}
l.style.minimal_width = 100
2019-06-11 01:52:49 +02:00
2018-10-25 13:00:38 +02:00
local l = t.add { type = "label", caption = tostring(get_total_biter_killcount(player.force))}
2019-02-26 20:05:31 +01:00
l.style.font = "default-listbox"
2018-10-03 21:17:12 +02:00
l.style.font_color = { r=0.9, g=0.9, b=0.9}
l.style.minimal_width = 145
2019-06-11 01:52:49 +02:00
local l = t.add { type = "checkbox", caption = "Show floating numbers", state = global.show_floating_killscore[player.name], name = "show_floating_killscore_texts" }
2019-06-11 01:52:49 +02:00
l.style.font_color = { r=0.8, g=0.8, b=0.8}
end
local function show_score(player)
if player.gui.left["score_panel"] then
player.gui.left["score_panel"].destroy()
end
local frame = player.gui.left.add { type = "frame", name = "score_panel", direction = "vertical" }
-- Global stats : rockets, biters kills
add_global_stats(frame, player)
-- Separator
2018-10-03 21:17:12 +02:00
local l = frame.add { type = "label", caption = "---------------------------------------------------------------------------------------------------------------"}
2019-06-11 01:52:49 +02:00
l.style.font_color = { r=0.9, g=0.9, b=0.9 }
-- Score per player
local t = frame.add { type = "table", column_count = 5 }
-- Score headers
local headers = {
{ name = "score_player", caption = "Player" },
{ column = "killscore", name = "score_killscore", caption = "Killscore" },
{ column = "deaths", name = "score_deaths", caption = "Deaths" },
{ column = "built_entities", name = "score_built_entities", caption = "Built structures" },
{ column = "mined_entities", name = "score_mined_entities", caption = "Mined entities" }
}
local sorting_pref = global.score_sort_by[player.name]
for _, header in ipairs(headers) do
local cap = header.caption
-- Add sorting symbol if any
if header.column and sorting_pref.column == header.column then
local symbol = sorting_symbol[sorting_pref.method]
cap = symbol .. cap
end
2019-06-11 01:52:49 +02:00
-- Header
local label = t.add {
type = "label",
caption = cap,
name = header.name
}
label.style.font = "default-listbox"
label.style.font_color = { r=0.98, g=0.66, b=0.22 } -- yellow
label.style.minimal_width = 140
2018-10-03 21:17:12 +02:00
end
2019-06-11 01:52:49 +02:00
-- Score list
local score_list = get_score_list(player.force.name)
2018-10-03 21:17:12 +02:00
if #game.connected_players > 1 then
score_list = get_sorted_list(sorting_pref.method, sorting_pref.column, score_list)
2019-06-11 01:52:49 +02:00
end
-- New pane for scores (while keeping headers at same position)
2018-10-06 11:29:53 +02:00
local scroll_pane = frame.add({ type = "scroll-pane", name = "score_scroll_pane", direction = "vertical", horizontal_scroll_policy = "never", vertical_scroll_policy = "auto"})
2019-06-11 01:52:49 +02:00
scroll_pane.style.maximal_height = 400
local t = scroll_pane.add { type = "table", column_count = 5}
2019-06-11 01:52:49 +02:00
-- Score entries
for _, entry in pairs(score_list) do
2018-10-03 21:17:12 +02:00
local p = game.players[entry.name]
2019-06-11 01:52:49 +02:00
local special_color = {
r = p.color.r * 0.6 + 0.4,
g = p.color.g * 0.6 + 0.4,
b = p.color.b * 0.6 + 0.4,
a = 1
}
local line = {
{ caption = entry.name, color = special_color },
{ caption = tostring(entry.killscore) },
{ caption = tostring(entry.deaths) },
{ caption = tostring(entry.built_entities) },
{ caption = tostring(entry.mined_entities) }
}
local default_color = { r=0.9, g=0.9, b=0.9 }
for _, column in ipairs(line) do
local label = t.add {
type = "label",
caption = column.caption,
color = column.color or default_color
}
label.style.font = "default"
label.style.minimal_width = 140
label.style.maximal_width = 140
end -- foreach column
end -- foreach entry
end -- show_score
2018-10-03 21:17:12 +02:00
2018-10-06 11:29:53 +02:00
local function refresh_score_full()
for _, player in pairs(game.connected_players) do
if player.gui.left["score_panel"] then
show_score(player)
end
end
end
--[[
2018-10-06 11:29:53 +02:00
local function refresh_score()
for _, player in pairs(game.connected_players) do
if player.gui.left["score_panel"] then
if global.score[player.force.name].rocket_launches then player.gui.left["score_panel"].children[1].children[2].caption = global.score[player.force.name].rocket_launches end
2018-10-25 13:00:38 +02:00
player.gui.left["score_panel"].children[1].children[4].caption = get_total_biter_killcount(player.force)
2018-10-06 11:29:53 +02:00
local score = global.score[player.force.name]
local score_list = {}
for _, p in pairs(game.connected_players) do
local killscore = 0
if score.players[p.name].killscore then killscore = score.players[p.name].killscore end
local deaths = 0
if score.players[p.name].deaths then deaths = score.players[p.name].deaths end
local built_entities = 0
if score.players[p.name].built_entities then built_entities = score.players[p.name].built_entities end
local mined_entities = 0
if score.players[p.name].mined_entities then mined_entities = score.players[p.name].mined_entities end
2019-06-11 01:52:49 +02:00
table.insert(score_list, {name = p.name, killscore = killscore, deaths = deaths, built_entities = built_entities, mined_entities = mined_entities})
2018-10-06 11:29:53 +02:00
end
if #game.connected_players > 1 then
score_list = get_sorted_list(global.score_sort_by[player.name].method, global.score_sort_by[player.name].column, score_list)
2019-06-11 01:52:49 +02:00
end
2018-10-06 11:29:53 +02:00
local index = 1
2019-06-11 01:52:49 +02:00
for _, entry in pairs(score_list) do
2018-10-06 11:29:53 +02:00
player.gui.left["score_panel"].children[4].children[1].children[index].caption = entry.name
local p = game.players[entry.name]
local color = {r = p.color.r * 0.6 + 0.4, g = p.color.g * 0.6 + 0.4, b = p.color.b * 0.6 + 0.4, a = 1}
2019-06-11 01:52:49 +02:00
player.gui.left["score_panel"].children[4].children[1].children[index].style.font_color = color
2018-10-06 11:29:53 +02:00
index = index + 1
2019-06-11 01:52:49 +02:00
player.gui.left["score_panel"].children[4].children[1].children[index].caption = tostring(entry.killscore)
2018-10-06 11:29:53 +02:00
index = index + 1
player.gui.left["score_panel"].children[4].children[1].children[index].caption = tostring(entry.deaths)
index = index + 1
player.gui.left["score_panel"].children[4].children[1].children[index].caption = tostring(entry.built_entities)
index = index + 1
player.gui.left["score_panel"].children[4].children[1].children[index].caption = tostring(entry.mined_entities)
2019-06-11 01:52:49 +02:00
index = index + 1
end
2018-10-03 21:17:12 +02:00
end
end
2018-09-19 06:51:25 +02:00
end
]]
2018-09-19 06:51:25 +02:00
2018-10-25 14:13:15 +02:00
local function init_player_table(player)
2018-11-26 17:50:18 +01:00
if not player then return end
2018-10-25 14:13:15 +02:00
if not global.score[player.force.name] then global.score[player.force.name] = {} end
if not global.score[player.force.name].players then global.score[player.force.name].players = {} end
if not global.score[player.force.name].players[player.name] then global.score[player.force.name].players[player.name] = {} end
end
2018-10-03 21:17:12 +02:00
local function on_player_joined_game(event)
local player = game.players[event.player_index]
if not global.score then global.score = {} end
2019-06-11 01:52:49 +02:00
init_player_table(player)
2018-10-03 21:17:12 +02:00
if not global.score_sort_by then global.score_sort_by = {} end
if not global.score_sort_by[player.name] then
global.score_sort_by[player.name] = {method = "descending", column = "killscore"}
end
if not global.show_floating_killscore then global.show_floating_killscore = {} end
2019-06-11 01:52:49 +02:00
if not global.show_floating_killscore[player.name] then global.show_floating_killscore[player.name] = false end
2018-10-06 11:29:53 +02:00
create_score_button(player)
refresh_score_full()
2018-10-03 21:17:12 +02:00
end
local function on_player_left_game(event)
2018-10-06 11:29:53 +02:00
refresh_score_full()
2018-10-03 21:17:12 +02:00
end
2018-09-19 06:51:25 +02:00
local function on_gui_click(event)
if not event then return end
if not event.element then return end
if not event.element.valid then return end
2019-06-11 01:52:49 +02:00
2018-09-19 06:51:25 +02:00
local player = game.players[event.element.player_index]
2019-06-11 01:52:49 +02:00
local name = event.element.name
-- Handles click on the score button
if name == "score" then
2018-10-03 21:17:12 +02:00
if player.gui.left["score_panel"] then
player.gui.left["score_panel"].destroy()
else
global.score_sort_by[player.name].get_sorted_list = true
show_score(player)
2018-09-19 06:51:25 +02:00
end
2018-10-06 11:29:53 +02:00
return
2019-06-11 01:52:49 +02:00
end
-- Handles click on the checkbox, for floating score
if name == "show_floating_killscore_texts" then
2019-06-11 01:52:49 +02:00
global.show_floating_killscore[player.name] = event.element.state
return
end
-- Handles click on a score header
local element_to_column = {
["score_killscore"] = "killscore",
["score_deaths"] = "deaths",
["score_built_entities"] = "built_entities",
["score_mined_entities"] = "mined_entities"
}
local column = element_to_column[name]
if column then
local sorting_pref = global.score_sort_by[player.name]
if sorting_pref.column == column and sorting_pref.method == "descending" then
sorting_pref.method = "ascending"
else
2019-06-11 01:52:49 +02:00
sorting_pref.method = "descending"
sorting_pref.column = column
end
2019-06-11 01:52:49 +02:00
show_score(player)
2018-10-06 11:29:53 +02:00
return
end
2019-06-11 01:52:49 +02:00
-- No more to handle
2018-10-03 21:17:12 +02:00
end
local function on_rocket_launched(event)
local force_name = event.rocket_silo.force.name
2019-06-11 01:52:49 +02:00
if not global.score[force_name]
then global.score[force_name] = {}
end
local force_score = global.score[force_name]
force_score.rocket_launches = 1 + (force_score.rocket_launches or 0)
2019-06-11 01:52:49 +02:00
--game.print ("A rocket has been launched!", {r=0.98, g=0.66, b=0.22})
refresh_score_full()
2018-10-03 21:17:12 +02:00
end
local score_table = {
["small-biter"] = 5,
["medium-biter"] = 15,
["big-biter"] = 30,
["behemoth-biter"] = 100,
["small-spitter"] = 5,
["medium-spitter"] = 15,
["big-spitter"] = 30,
["behemoth-spitter"] = 100,
["biter-spawner"] = 200,
["spitter-spawner"] = 200,
["small-worm-turret"] = 50,
["medium-worm-turret"] = 150,
2018-10-03 21:32:38 +02:00
["big-worm-turret"] = 300,
2018-10-03 21:17:12 +02:00
["player"] = 1000
}
local function on_entity_died(event)
2018-10-03 21:17:12 +02:00
local player = false
local passenger = false
local train_passengers = false
local proximity_list = {}
-- Handles worm kills with no cause
2019-06-11 01:52:49 +02:00
if event.entity.type == "turret" then
local radius = 24
local position = event.entity.position
local insert = table.insert
--Since we cannot reliably get the player who killed the worm, get all players in a radius and award them xp
for _, p in pairs(game.connected_players) do
if p.position.x < position.x + radius and p.position.x > position.x - radius and p.position.y < position.y + radius and p.position.y > position.y - radius then
insert(proximity_list, {player = p})
end
end
2018-10-03 21:17:12 +02:00
end
2019-06-11 01:52:49 +02:00
-- Unit/Spawner Kills
if event.entity.type == "unit" or event.entity.type == "unit-spawner" then
2018-10-31 01:01:49 +01:00
if event.cause then
2019-06-11 01:52:49 +02:00
if event.cause.name == "character" then player = event.cause.player end
2019-06-11 01:52:49 +02:00
2018-10-31 01:01:49 +01:00
--Check for passengers
if event.cause.type == "car" then
player = event.cause.get_driver()
passenger = event.cause.get_passenger()
if player then player = player.player end
if passenger then passenger = passenger.player end
end
if event.cause.type == "locomotive" then
2018-11-11 01:26:24 +01:00
player = event.cause.get_driver()
train_passengers = event.cause.train.passengers
2018-10-31 01:01:49 +01:00
end
2019-06-11 01:52:49 +02:00
2018-10-31 01:01:49 +01:00
if not train_passengers and not passenger and not player then return end
if event.cause.force.name == event.entity.force.name then return end
init_player_table(player)
if not global.score[event.force.name] then global.score[event.force.name] = {} end
if not global.score[event.force.name].players then global.score[event.force.name].players = {} end
if not global.score[event.force.name].players then global.score[event.force.name].players[player.name] = {} end
end
2018-10-03 21:17:12 +02:00
end
2019-06-11 01:52:49 +02:00
if score_table[event.entity.name] then
local show_floating_text = false
local color = {r=0.98, g=0.66, b=0.22}
2019-06-11 01:52:49 +02:00
-- Color based on main player color
if #proximity_list <= 0 and player then
color = player.color
color.r = color.r * 0.6 + 0.4
color.g = color.g * 0.6 + 0.4
color.b = color.b * 0.6 + 0.4
end
local rewarded_players = {}
if player then
table.insert(rewarded_players, player)
end
for _,p in pairs(proximity_list) do
table.insert(rewarded_players, p.player)
2018-10-03 21:17:12 +02:00
end
if passenger then
2019-06-11 01:52:49 +02:00
table.insert(rewarded_players, passenger)
2018-10-03 21:17:12 +02:00
end
if train_passengers then
2019-06-11 01:52:49 +02:00
for _,p in pairs(train_passengers) do
table.insert(rewarded_players, p)
2018-10-03 21:17:12 +02:00
end
end
2019-06-11 01:52:49 +02:00
-- Add killscore
local points = score_table[event.entity.name]
for _, p in pairs(rewarded_players) do
-- Handles floating text
2019-06-16 18:49:06 +02:00
if global.show_floating_killscore[p.name] == true then
2019-06-11 01:52:49 +02:00
show_floating_text = true
end
-- Add
2019-06-16 18:49:06 +02:00
local score = global.score[event.force.name].players[p.name]
2019-10-12 08:30:38 +02:00
if score then
score.killscore = points + (score.killscore or 0)
end
2019-06-11 01:52:49 +02:00
end
if show_floating_text == true then
2019-06-11 01:52:49 +02:00
event.entity.surface.create_entity({name = "flying-text", position = event.entity.position, text = tostring(points), color = color})
end
end
2018-10-03 21:17:12 +02:00
end
local function on_player_died(event)
local player = game.players[event.player_index]
2018-10-25 14:13:15 +02:00
init_player_table(player)
2019-06-11 01:52:49 +02:00
local score = global.score[player.force.name].players[player.name]
score.deaths = 1 + (score.deaths or 0)
2018-09-19 06:51:25 +02:00
end
2018-10-03 21:17:12 +02:00
local function on_player_mined_entity(event)
local player = game.players[event.player_index]
2018-10-25 14:13:15 +02:00
init_player_table(player)
2019-06-11 01:52:49 +02:00
local score = global.score[player.force.name].players[player.name]
score.mined_entities = 1 + (score.mined_entities or 0)
2018-10-03 21:17:12 +02:00
end
local function on_built_entity(event)
2019-01-04 09:06:26 +01:00
if not event.created_entity.valid then return end
if event.created_entity.type == "entity-ghost" then return end
2018-10-03 21:17:12 +02:00
local player = game.players[event.player_index]
2018-10-25 14:13:15 +02:00
init_player_table(player)
2019-06-11 01:52:49 +02:00
local score = global.score[player.force.name].players[player.name]
score.built_entities = 1 + (score.built_entities or 0)
2018-10-06 23:49:29 +02:00
end
local function on_tick(event)
if game.tick % 300 == 0 then
refresh_score_full()
2018-10-06 23:49:29 +02:00
end
2018-09-19 06:51:25 +02:00
end
2018-10-06 23:49:29 +02:00
event.add(defines.events.on_tick, on_tick)
2018-10-03 21:17:12 +02:00
event.add(defines.events.on_player_mined_entity, on_player_mined_entity)
event.add(defines.events.on_player_died, on_player_died)
event.add(defines.events.on_built_entity, on_built_entity)
event.add(defines.events.on_entity_died, on_entity_died)
event.add(defines.events.on_gui_click, on_gui_click)
event.add(defines.events.on_player_joined_game, on_player_joined_game)
event.add(defines.events.on_player_left_game, on_player_left_game)
2019-06-11 01:52:49 +02:00
event.add(defines.events.on_rocket_launched, on_rocket_launched)