Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simple child Tracking #179

Merged
merged 8 commits into from
Feb 17, 2024
9 changes: 7 additions & 2 deletions sote/engine/ui.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1433,8 +1433,13 @@ function ui.table(rect, data, columns, state, circle_style, slider_arrow_images)
:position(rect.x, rect.y)
:spacing(0)
:build()
local total_weight = 0
for index = 1, #columns do
local header_rect = layout:next(columns[index].width, state.individual_height)
total_weight = total_weight + columns[index].width
end
local weight = (rect.width - 20) / total_weight
for index = 1, #columns do
local header_rect = layout:next(columns[index].width * weight, state.individual_height)
header_rect.height = rect.height
if not columns[index].active and ui.text_button("", header_rect) then
if state.sorted_field == index then
Expand Down Expand Up @@ -1477,7 +1482,7 @@ function ui.table(rect, data, columns, state, circle_style, slider_arrow_images)
:spacing(0)
:build()
for index = 1, #columns do
local temp = columns[index].render_closure(layout:next(columns[index].width, state.individual_height), entry.key, entry.value)
local temp = columns[index].render_closure(layout:next(columns[index].width * weight, state.individual_height), entry.key, entry.value)
if temp then
result = temp
end
Expand Down
18 changes: 10 additions & 8 deletions sote/game/economy/production-and-consumption.lua
Original file line number Diff line number Diff line change
Expand Up @@ -832,14 +832,16 @@ function pro.run(province)
end

-- community helps children as well
local siphon_to_child = math.min(food_price * 0.5, province.local_wealth * 1 / 512)
if siphon_to_child > 0 then
economic_effects.add_pop_savings(pop, siphon_to_child, economic_effects.reasons.Donation)
economic_effects.change_local_wealth(
province,
- siphon_to_child,
economic_effects.reasons.Donation
)
if pop.home_province == pop.province then
local siphon_to_child = math.min(food_price * 0.5, province.local_wealth * 1 / 512)
if siphon_to_child > 0 then
economic_effects.add_pop_savings(pop, siphon_to_child, economic_effects.reasons.Donation)
economic_effects.change_local_wealth(
province,
- siphon_to_child,
economic_effects.reasons.Donation
)
end
end

-- children spend time on games and growing up:
Expand Down
2 changes: 2 additions & 0 deletions sote/game/entities/pop.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
---@field name string
---@field savings number
---@field parent POP?
---@field children table<POP, POP>
---@field life_needs_satisfaction number from 0 to 1
---@field basic_needs_satisfaction number from 0 to 1
---@field popularity table<Realm, number|nil>
Expand Down Expand Up @@ -73,6 +74,7 @@ function rtab.POP:new(race, faith, culture, female, age, home, location, charact
r.owned_buildings = {}
r.inventory = {}
r.price_memory = {}
r.children = {}
r.successor_of = {}
r.need_satisfaction = {}

Expand Down
14 changes: 14 additions & 0 deletions sote/game/entities/province.lua
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,14 @@ function prov.Province:transfer_pop(pop, target)
target.all_pops[pop] = pop

pop.province = target

local children = tabb.filter(pop.children, function(c)
return self.all_pops[c] and c.home_province ~= self
and not c.unit_of_warband and not c.employer
end)
for _,c in pairs(children) do
self:transfer_pop(c,target)
end
end

--- Changes home province of a pop/character to the target province
Expand Down Expand Up @@ -353,6 +361,12 @@ function prov.Province:kill_pop(pop)
if pop.home_province then
pop.home_province:unset_home(pop)
end

if pop.parent then pop.parent.children[pop] = nil end
for _,c in pairs(pop.children) do
c.parent = nil
pop.children[c] = nil
end
end

function prov.Province:local_army_size()
Expand Down
6 changes: 6 additions & 0 deletions sote/game/raws/effects/death.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ function effects.death(character)
WORLD:emit_notification(character.name .. " had died.")
end

if character.parent then character.parent.children[character] = nil end
for _,c in pairs(character.children) do
c.parent = nil
character.children[c] = nil
end

for _, target in pairs(character.successor_of) do
target.successor = nil
character.successor_of[target] = nil
Expand Down
116 changes: 110 additions & 6 deletions sote/game/scenes/game/inspector-character.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ local TRAIT_ICONS = require "game.raws.traits.trait_to_icon"
local trade_good = require "game.raws.raws-utils".trade_good

local characters_list_widget = require "game.scenes.game.widgets.character-list"
local custom_characters_list_widget = require "game.scenes.game.widgets.list-widget"
local character_decisions_widget = require "game.scenes.game.widgets.decision-selection-character"
local character_name_widget = require "game.scenes.game.widgets.character-name"

Expand All @@ -20,6 +21,7 @@ local decision_target_secondary = nil

local traits_slider = 0
local inventory_slider = 0
local character_list_tab = "Local"

---@return Rect
function window.rect()
Expand Down Expand Up @@ -111,6 +113,7 @@ function window.draw(game)
local decisions_label_panel = layout:next(unit * 16, unit * 1)
local decisions_panel = layout:next(unit * 16, unit * 7)
local decisions_confirmation_panel = layout:next(unit * 16, unit * 1)
local character_tab = layout:next(unit * 16, unit * 1)
local characters_list = layout:next(unit * 16, unit * 8)

character_name_widget(name_panel, character)
Expand Down Expand Up @@ -152,7 +155,7 @@ function window.draw(game)
location_panel.y = location_panel.y - unit
ui.left_text("Location: ", location_panel)

ut.data_entry("", character.culture.name, culture_panel, "Culture")
ut.data_entry("", character.culture.name, culture_panel, character.culture.name)
culture_panel.y = culture_panel.y - unit
ut.data_entry("", character.faith.name, culture_panel, "Faith")

Expand Down Expand Up @@ -229,15 +232,116 @@ function window.draw(game)
decision_target_primary = nil
decision_target_secondary = nil
end

---@type table<number, Tab>
local tabs = {}
if province and province_visible then
local response = characters_list_widget(characters_list, character.province.characters, "Local Characters", true)()
if response then
game.selected.character = response
tabs[1] = {
text = "Local",
tooltip = "Characters in the same province.",
closure = function ()
local response = characters_list_widget(characters_list, character.province.characters, nil, true)()
if response then
game.selected.character = response
end
end
}
end
tabs[2] = {
text = "Children",
tooltip = "This character's children.",
closure = function ()
local response = characters_list_widget(characters_list, character.children, nil, true)()
if response then
game.selected.character = response
end
end
}
if character.leading_warband then
local function pop_sex(pop)
local f = "m"
if pop.female then f = "f" end
return f
end
local function render_name(rect, k, v)
if ut.text_button(v.name, rect) then
return v
end
end
tabs[3] = {
text = "Warriors",
tooltip = "Warriors in the character's warband.",
closure = function()
local response = custom_characters_list_widget(characters_list, character.leading_warband.pops, {
{
header = ".",
render_closure = function(rect, k, v)
require "game.scenes.game.widgets.portrait" (rect, v)
end,
width = UI_STYLE.scrollable_list_small_item_height,
value = function(k, v)
---@type POP
v = v
return v.race.name
end
},
{
header = "race",
render_closure = function (rect, k, v)
ui.right_text(v.race.name, rect)
end,
width = ut.BASE_HEIGHT * 4,
value = function(k, v)
return v.race.name
end
},
{
header = "culture",
render_closure = function (rect, k, v)
ui.right_text(v.culture.name, rect)
end,
width = ut.BASE_HEIGHT * 4,
value = function(k, v)
return v.culture.name
end
},
{
header = "faith",
render_closure = function (rect, k, v)
ui.right_text(v.faith.name, rect)
end,
width = ut.BASE_HEIGHT * 3,
value = function(k, v)
return v.faith.name
end
},
{
header = "age",
render_closure = function (rect, k, v)
ui.right_text(tostring(v.age), rect)
end,
width = ut.BASE_HEIGHT * 2,
value = function(k, v)
return v.age
end
},
{
header = "sex",
render_closure = function (rect, k, v)
ui.centered_text(pop_sex(v), rect)
end,
width = ut.BASE_HEIGHT * 1,
value = function(k, v)
return pop_sex(v)
end
}
}, nil, true)()
end
}
end
local tab_layout = ui.layout_builder():position(character_tab.x, character_tab.y):horizontal():build()
character_list_tab = ut.tabs(character_list_tab, tab_layout, tabs, 1, ut.BASE_HEIGHT * 4)

ut.coa(character.realm, coa)
end

return window
return window
64 changes: 64 additions & 0 deletions sote/game/scenes/game/widgets/list-widget.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
local tabb = require "engine.table"
local ui = require "engine.ui"
local ut = require "game.ui-utils"

---@type TableState
local state = nil

---comment
---@param compact boolean
local function init_state(compact)
local entry_height = UI_STYLE.scrollable_list_item_height
if compact then
entry_height = UI_STYLE.scrollable_list_small_item_height
end

if state == nil then
state = {
header_height = UI_STYLE.table_header_height,
individual_height = entry_height,
slider_level = 0,
slider_width = UI_STYLE.slider_width,
sorted_field = 1,
sorting_order = true
}
else
state.header_height = UI_STYLE.table_header_height
state.individual_height = entry_height
state.slider_width = UI_STYLE.slider_width
end
end

---@generic K, V
---@param rect Rect
---@param table table<K, V>
---@param columns TableColumn[]
---@param title string?
---@param compact boolean?
return function(rect, table, columns, title, compact)
if compact == nil then
compact = false
end

local portrait_width = UI_STYLE.scrollable_list_item_height
if compact then
portrait_width = UI_STYLE.scrollable_list_small_item_height
end

local rest_width = rect.width - portrait_width
local width_unit = rest_width / 12
return function()

init_state(compact)
local bottom_height = rect.height
local bottom_y = 0
if title then
bottom_height = bottom_height - UI_STYLE.table_header_height
bottom_y = UI_STYLE.table_header_height
local top = rect:subrect(0, 0, rect.width, UI_STYLE.table_header_height, "left", "up")
ui.centered_text(title, top)
end
local bottom = rect:subrect(0, bottom_y, rect.width, bottom_height, "left", "up")
return ut.table(bottom, table, columns, state)
end
end
19 changes: 18 additions & 1 deletion sote/game/society/pop-growth.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
local pg = {}

local POP = require "game.entities.pop".POP
local tabb = require "engine.table"

---Runs natural growth and decay on a single province.
---@param province Province
Expand All @@ -18,6 +19,8 @@ function pg.growth(province)
---@type POP[]
local to_add = {}

local race_sex = {}

for _, pp in pairs(province.outlaws) do
if pp.age > pp.race.max_age then
to_remove[#to_remove + 1] = pp
Expand All @@ -33,6 +36,19 @@ function pg.growth(province)
end
else
local sex_prob = 0.1

if not race_sex[pp.race] then
race_sex[pp.race] = {}
race_sex[pp.race][pp.female] = true
elseif race_sex[pp.race][not pp.female] == nil then
if tabb.size(tabb.filter(province.all_pops, function (a)
return a.race == pp.race and a.female ~= pp.female
end)) > 0 then
race_sex[pp.race][not pp.female] = true
else race_sex[pp.race][not pp.female] = false end
end
if race_sex[pp.race][not pp.female] then sex_prob = 0 end

if pp.female then
sex_prob = 1.0
end
Expand Down Expand Up @@ -77,9 +93,10 @@ function pg.growth(province)
pp.culture,
love.math.random() > pp.race.males_per_hundred_females / (100 + pp.race.males_per_hundred_females),
0,
province, province
pp.home_province, province
)
newborn.parent = pp
pp.children[newborn] = newborn
end

-- province:validate_population()
Expand Down
13 changes: 13 additions & 0 deletions sote/game/world-gen/spawn-tribes.lua
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,19 @@ local function make_new_realm(capitol, race, culture, faith)

-- capitol:validate_population()

-- try to assign a parent to generated children
for _,x in pairs(capitol.all_pops) do
if x.age > x.race.adult_age then
local potentials = tabb.filter(capitol.all_pops,
function(a) return a.age >= x.age + x.race.adult_age and a.age < x.race.elder_age + x.age end)
local size = #potentials
local parent = tabb.nth(potentials, math.random(1,size))
if parent then
parent.children[x] = x
x.parent = parent
end
end
end

-- print("test battle")
-- local size_1, size_2 = love.math.random(50) + 10, love.math.random(50) + 10
Expand Down