Making Splinter clolonies more alive
Posted: Wed Aug 06, 2025 3:30 pm
Hello to everyone on this forum,
When playing I always found those human and teros splinter colonies too easy to capture and generally not much different from just native races.
So I've made a mod that makes them behave like regular empires, except:
Make a new type of economy for splinter empires by adding a new field
Remove the highly limiting monster economy
Add a new one (without any restrictions yet)
which means:
Change:
To:
In Lua state\Orders\colonization.lua
To prevent splinter colonies from colonizing add
Which means:
Change:
To:
In Lua state\Galaxy\apply_morale_effects.lua
To prevent assimilation of human refugees when they are not in a major empire yet add:
Change:
To:
In Lua state\AI\MonsterAI.lua
The refugee colonies often spawn with pirate ships in the system which would now bombard your splinter colony as soon as the game starts, to prevent it add
Pirates and splinters should now coexist together. Lore-wise I would say they could have a deal with pirates where splinter colony gives up some of their resources for peace
So:
Change:
To:
In Lua state\Orders\population.lua
To prevent system blockade by pirates add
Change:
To:
In Lua state\Orders\raiders.lua
To exclude Splinters from being a raider target add
Change:
To:
In Lua state\Setup\special_decks.lua
To give splinters a reasonable start with one lab mine etc and another farm to prevent starvation (as they still don't build improvements)
Change:
To:
In Lua state\Orders\encounters\splinter_colony.lua
To reduce the chance you can annex them without any effort now as they are more meaningful, set Instead of /30
Change:
To:
And that should be it!
Early game should now be a little more engaging when it comes to diplomacy and fighting
When playing I always found those human and teros splinter colonies too easy to capture and generally not much different from just native races.
So I've made a mod that makes them behave like regular empires, except:
- They can't colonize new planets
- They don't build new improvements on their planet
- They have simplified diplomacy as they used to
- Their fleets are not aggressive towards pirates
- Research (although slowly)
- build ships (and defend themselves in early game)
- build outposts
Make a new type of economy for splinter empires by adding a new field
Remove the highly limiting monster economy
Code: Select all
blank.monster_economy=true
Code: Select all
blank.spl_economy=true
Change:
Code: Select all
local function new_minor_empire(species,planet)
local count=0
for i,empire in pairs | all_empires
if empire.minor_faction==species
count++
end
end
local blank = blank_empire(
format("%s_minor_%d",species,count+1), -- this should be replaced by setup_splinter_leader()
--format('Independent (%s)',capitalize | species),
species,'cyan')
blank.monster_economy=true
blank.minor_faction=species
all_empires[#all_empires+1] = blank
local empire = all_empires[#all_empires]._ref
planet.empire=empire
add_planet(planet,empire)
SCOPE.SETUP_ENV.setup_splinter_leader(planet.empire,planet)
--blank.leader = copy | get_splinter_leader(species)
local empire in planet
empire.scientist = copy | get_default_scientist(species)
init_empire_tech(empire)
order.grant_all_techs(empire,initial_monster_tech)
return planet.empire
end
Code: Select all
local function new_minor_empire(species,planet)
local count=0
for i,empire in pairs | all_empires
if empire.minor_faction==species
count++
end
end
local blank = blank_empire(
format("%s_minor_%d",species,count+1), -- this should be replaced by setup_splinter_leader()
--format('Independent (%s)',capitalize | species),
species,'cyan')
blank.spl_economy=true
blank.minor_faction=species
all_empires[#all_empires+1] = blank
local empire = all_empires[#all_empires]._ref
planet.empire=empire
add_planet(planet,empire)
SCOPE.SETUP_ENV.setup_splinter_leader(planet.empire,planet)
--blank.leader = copy | get_splinter_leader(species)
local empire in planet
empire.scientist = copy | get_default_scientist(species)
init_empire_tech(empire)
order.grant_all_techs(empire,initial_monster_tech)
return planet.empire
end
In Lua state\Orders\colonization.lua
To prevent splinter colonies from colonizing add
Code: Select all
if empire.spl_economy
return false
end
Change:
Code: Select all
function Empire.could_colonize(empire,planet)
local type,size in planet!
if size=='Tiny'
return false
end
if easy_planet_colonization_type(empire!.species,type)
return true
end
if type=='Gas Giant' return false end
if type=='WarpNode' return false end
return empire:known 'Habitat Domes'
end
function Empire.can_colonize(empire,planet)
if planet.empire
-- we can colonize our own outposts, but otherwise, planets
-- already belonging to an empire can never be colonized
if not( (planet.empire==empire) and planet.no_colony )
return
end
end
return empire : could_colonize(planet)
end
Code: Select all
function Empire.could_colonize(empire,planet)
local type,size in planet!
if size=='Tiny'
return false
end
if easy_planet_colonization_type(empire!.species,type)
return true
end
if type=='Gas Giant' return false end
if type=='WarpNode' return false end
return empire:known 'Habitat Domes'
end
function Empire.can_colonize(empire,planet)
if planet.empire
-- we can colonize our own outposts, but otherwise, planets
-- already belonging to an empire can never be colonized
if not( (planet.empire==empire) and planet.no_colony )
return
end
end
return empire : could_colonize(planet)
end
In Lua state\Galaxy\apply_morale_effects.lua
To prevent assimilation of human refugees when they are not in a major empire yet add:
Code: Select all
if planet.empire.spl_economy
converts=0
end
Code: Select all
function suffix_morale_effects.refugee(planet,race,morale)
local chance = saturate( (morale-10)/40 )*.3 + .1
if chance > 0
local converts = min(
planet.pop[race],
bernoulli_trials(ceil(planet.pop[race]), chance) )
if converts > 0
local vanilla0 = planet.pop[remove_race_suffix | race]
order.convert_to_vanilla(planet,race,converts)
if (not vanilla0) or (not planet.pop[race])
order.add_report {
..planet.empire,
type = 'refugees_assimilated',
..planet,
..converts,
..race,
..vanilla0,
}
end
if (planet.empire==gui_player()) and (not planet.pop[race])
mark_achievement 'ACH_REFUGEE_ASSIMILATE'
end
end
end
end
Code: Select all
function suffix_morale_effects.refugee(planet,race,morale)
local chance = saturate( (morale-10)/40 )*.3 + .1
if chance > 0
local converts = min(
planet.pop[race],
bernoulli_trials(ceil(planet.pop[race]), chance) )
if planet.empire.spl_economy
converts=0
end
if converts > 0
local vanilla0 = planet.pop[remove_race_suffix | race]
order.convert_to_vanilla(planet,race,converts)
if (not vanilla0) or (not planet.pop[race])
order.add_report {
..planet.empire,
type = 'refugees_assimilated',
..planet,
..converts,
..race,
..vanilla0,
}
end
if (planet.empire==gui_player()) and (not planet.pop[race])
mark_achievement 'ACH_REFUGEE_ASSIMILATE'
end
end
end
end
In Lua state\AI\MonsterAI.lua
The refugee colonies often spawn with pirate ships in the system which would now bombard your splinter colony as soon as the game starts, to prevent it add
Code: Select all
-- never attack the spl
if their_empire.spl_economy
return
end
-- the spl never attacks
if r.empire.spl_economy
return
end
So:
Change:
Code: Select all
function desire_attack(r)
--print 'always attack'
local their_empire,star in r
-- don't attack people we're not at war with
if not at_war(r.empire,their_empire)
return
end
-- never attack the herald
if their_empire.monster_faction=='arda'
return
end
-- the herald never attacks
if r.empire.monster_faction=='arda'
return
end
--for i, instance in all_ongoing_events()
for i,r2 in all_non_removed_reports()
if ( r2.type=='diplo_encounter' ) and (r2.star==r.star) and (r2.their_empire==r.empire) and (not r2.resolved)
print('ongoing diplo_encounter prempting normal AI handing!')
return
end
end
-- star harpies won't attack if there are no ships to harvest
-- or if the empire in question has harpy repellant
if r.empire.monster_faction=='space_harpies'
if not has_military_fleet(their_empire,star)
return
end
if star.type~='hsa' and their_empire:known 'Harpy Repellant'
return
end
end
if their_empire.stars[star]
for i,planet in rpairs (star.planets,|)
function(p1,p2) return star.planets[p1].summed_pop > star.planets[p2].summed_pop end
if planet.empire==their_empire
return true,planet
end
end
error "couldn't find a planet"
end
--print(..star)
return true
--print('hi there')
end
Code: Select all
function desire_attack(r)
--print 'always attack'
local their_empire,star in r
-- don't attack people we're not at war with
if not at_war(r.empire,their_empire)
return
end
-- never attack the herald
if their_empire.monster_faction=='arda'
return
end
-- the herald never attacks
if r.empire.monster_faction=='arda'
return
end
-- never attack the spl
if their_empire.spl_economy
return
end
-- the spl never attacks
if r.empire.spl_economy
return
end
--for i, instance in all_ongoing_events()
for i,r2 in all_non_removed_reports()
if ( r2.type=='diplo_encounter' ) and (r2.star==r.star) and (r2.their_empire==r.empire) and (not r2.resolved)
print('ongoing diplo_encounter prempting normal AI handing!')
return
end
end
-- star harpies won't attack if there are no ships to harvest
-- or if the empire in question has harpy repellant
if r.empire.monster_faction=='space_harpies'
if not has_military_fleet(their_empire,star)
return
end
if star.type~='hsa' and their_empire:known 'Harpy Repellant'
return
end
end
if their_empire.stars[star]
for i,planet in rpairs (star.planets,|)
function(p1,p2) return star.planets[p1].summed_pop > star.planets[p2].summed_pop end
if planet.empire==their_empire
return true,planet
end
end
error "couldn't find a planet"
end
--print(..star)
return true
--print('hi there')
end
In Lua state\Orders\population.lua
To prevent system blockade by pirates add
Code: Select all
or (empire.spl_economy and (their_empire.monster_faction=='pirate'))
Code: Select all
function Empire.system_blockaded(empire,star)
for _,their_empire in pairs(all_empires) do
if at_war(their_empire,empire) and
(not their_empire.system_defeats[star]) and
their_empire: has_armed_ships(star)
if not ( empire:known 'Harpy Repellant' and (their_empire.monster_faction=='space_harpies') )
return true
end
end
end
end
Code: Select all
function Empire.system_blockaded(empire,star)
for _,their_empire in pairs(all_empires) do
if at_war(their_empire,empire) and
(not their_empire.system_defeats[star]) and
their_empire: has_armed_ships(star)
if not ( (empire:known 'Harpy Repellant' and (their_empire.monster_faction=='space_harpies')) or (empire.spl_economy and (their_empire.monster_faction=='pirate')) )
return true
end
end
end
end
In Lua state\Orders\raiders.lua
To exclude Splinters from being a raider target add
Code: Select all
or empire.spl_economy
Code: Select all
function neighboring_empires(raider_empire)
local push, candidates = pusher {}
local home_star = raider_empire!.monster_star
for i,empire ; all_empires
if not ( empire.monster_economy or empire.eliminated )
local _TRACE_INFO = empire.name
local closest,dist = get_min_key(empire.stars,|) function(star)
return star_dist(star,home_star)
end
push {..empire, dist=dist or 1e30,..closest}
end
end
table.sort(candidates,|)function(a,b) return a.dist<b.dist end
if not next | candidates
return _SAFE
end
--local max_dist = candidates[1].dist*1.2
local max_dist = 1.5*raider_empire.drive_range
local rval = {}
for i,v ; candidates
if v.dist <=max_dist
rval[v.empire]=v.closest
end
end
--print(..max_dist)
--print(v2s | candidates)
--print(v2s | rval)
return rval
end
Code: Select all
function neighboring_empires(raider_empire)
local push, candidates = pusher {}
local home_star = raider_empire!.monster_star
for i,empire ; all_empires
if not ( empire.monster_economy or empire.eliminated or empire.spl_economy)
local _TRACE_INFO = empire.name
local closest,dist = get_min_key(empire.stars,|) function(star)
return star_dist(star,home_star)
end
push {..empire, dist=dist or 1e30,..closest}
end
end
table.sort(candidates,|)function(a,b) return a.dist<b.dist end
if not next | candidates
return _SAFE
end
--local max_dist = candidates[1].dist*1.2
local max_dist = 1.5*raider_empire.drive_range
local rval = {}
for i,v ; candidates
if v.dist <=max_dist
rval[v.empire]=v.closest
end
end
--print(..max_dist)
--print(v2s | candidates)
--print(v2s | rval)
return rval
end
In Lua state\Setup\special_decks.lua
To give splinters a reasonable start with one lab mine etc and another farm to prevent starvation (as they still don't build improvements)
Change:
Code: Select all
decks.treasure.Arid = valid_special_deck {
[ {'splinter', species='human', pop={human_refugee=2,}, farms=1 } ] = 2,
[ {'splinter', species='haduir', pop={haduir=2,}, factories=1, farms=1 } ] = 1,
derelict_colony_draw =2,
}
decks.treasure.Glacier = valid_special_deck {
[ {'splinter', species='human', pop={human_refugee=2,}, farms=1 } ] = 2,
star_resource_draw =1,
derelict_colony_draw =2,
}
decks.treasure.Garden = valid_special_deck {
[ {'splinter', species='human', pop={human_refugee=2,}, factories=1 } ] = 2,
[ {'splinter', species='teros', pop={teros=2,}, factories=1 } ] = 1,
star_resource_draw =1,
derelict_colony_draw =1,
}
Code: Select all
decks.treasure.Arid = valid_special_deck {
[ {'splinter', species='human', pop={human_refugee=2,}, factories=1, farms=2, labs=1, mines=1, markets=1 } ] = 2,
[ {'splinter', species='haduir', pop={haduir=2,}, factories=1, farms=2, labs=1, mines=1, markets=1 } ] = 1,
derelict_colony_draw =2,
}
decks.treasure.Glacier = valid_special_deck {
[ {'splinter', species='human', pop={human_refugee=2,}, factories=1, farms=2, labs=1, mines=1, markets=1 } ] = 2,
star_resource_draw =1,
derelict_colony_draw =2,
}
decks.treasure.Garden = valid_special_deck {
[ {'splinter', species='human', pop={human_refugee=2,}, factories=1, farms=2, labs=1, mines=1, markets=1 } ] = 2,
[ {'splinter', species='teros', pop={teros=2,}, factories=1, farms=2, labs=1, mines=1, markets=1 } ] = 1,
star_resource_draw =1,
derelict_colony_draw =1,
}
In Lua state\Orders\encounters\splinter_colony.lua
To reduce the chance you can annex them without any effort now as they are more meaningful, set
Code: Select all
local positive_chance = their_empire : calc_reputation(empire) / 50
Change:
Code: Select all
function callbacks.on_searched()
--TODO! make this make some kind of sense.
local planet,empire,special in SCOPE.encounter_info!
if empire.monster_faction
return
end
local encounter = 'splinter'
local their_empire=planet.empire
local suffix = '_generic'
empire.contactable_empires[their_empire]=true
empire.known_empires[their_empire]=true
their_empire.contactable_empires[empire]=true
their_empire.known_empires[empire]=true
if not their_empire.minor_faction
-- looks like this is not the special we expected it to be
-- lets just quitely clean that up.
order.remove_special(special)
return
end
local positive_chance = their_empire : calc_reputation(empire) / 30
for i, issue in ipairs | their_empire : get_issue_list(empire)
if issue.liberate_case
suffix='_liberate'
end
end
positive_chance=min(.9, saturate (positive_chance) )
local reaction = random_chance(positive_chance) and 'friendly' or 'hostile'
local can_annex = reaction == 'friendly'
if (reaction=='friendly') and group_species[their_empire.species]==group_species[empire.species]
suffix='_splinter'
end
if reaction=='hostile' and suffix=='_liberate'
if random_chance(.5)
reaction='neutral'
end
end
reaction..=suffix
order.add_report {
type='settlement_encounter',
..encounter,
dialog_tree = {reaction},
star=planet.star,
..empire,
..special,
..planet,
..can_annex,
their_empire=planet.empire,
}
end
Code: Select all
function callbacks.on_searched()
--TODO! make this make some kind of sense.
local planet,empire,special in SCOPE.encounter_info!
if empire.monster_faction
return
end
local encounter = 'splinter'
local their_empire=planet.empire
local suffix = '_generic'
empire.contactable_empires[their_empire]=true
empire.known_empires[their_empire]=true
their_empire.contactable_empires[empire]=true
their_empire.known_empires[empire]=true
if not their_empire.minor_faction
-- looks like this is not the special we expected it to be
-- lets just quitely clean that up.
order.remove_special(special)
return
end
local positive_chance = their_empire : calc_reputation(empire) / 50
for i, issue in ipairs | their_empire : get_issue_list(empire)
if issue.liberate_case
suffix='_liberate'
end
end
positive_chance=min(.9, saturate (positive_chance) )
local reaction = random_chance(positive_chance) and 'friendly' or 'hostile'
local can_annex = reaction == 'friendly'
if (reaction=='friendly') and group_species[their_empire.species]==group_species[empire.species]
suffix='_splinter'
end
if reaction=='hostile' and suffix=='_liberate'
if random_chance(.5)
reaction='neutral'
end
end
reaction..=suffix
order.add_report {
type='settlement_encounter',
..encounter,
dialog_tree = {reaction},
star=planet.star,
..empire,
..special,
..planet,
..can_annex,
their_empire=planet.empire,
}
end
And that should be it!
Early game should now be a little more engaging when it comes to diplomacy and fighting