Skip to content

Instantly share code, notes, and snippets.

@warmist
Forked from pronvit/s-gen.lua
Created March 1, 2021 16:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save warmist/2c3d50c265b14ec60c749a04fbdc0132 to your computer and use it in GitHub Desktop.
Save warmist/2c3d50c265b14ec60c749a04fbdc0132 to your computer and use it in GitHub Desktop.
function find_race(name)
name = name:lower()
for i,v in ipairs(df.global.world.raws.creatures.all) do
if v.creature_id:lower() == name:lower() then
return i
end
end
end
--NOTE(warmist): named_civ changed to player_civ but does not make sense?
function find_entity_for_race(race)
for i,v in ipairs(df.global.world.entities.all) do
if --[[v.flags.named_civ and--]] v.race == race then
return i
end
end
end
function find_entity_by_name(name)
name = name:lower()
for i,v in ipairs(df.global.world.entities.all) do
if --[[v.flags.named_civ and--]] dfhack.TranslateName(v.name, true):lower():find(name) then
return i
end
end
end
function find_cultural_identity(civ)
for i,v in ipairs(df.global.world.cultural_identities.all) do
if v.civ_id == civ then
return i
end
end
end
local utils = require 'utils'
validArgs = validArgs or utils.invert({
'civ',
'race',
'count',
'undead',
'cleanup',
'debug',
})
local args = utils.processArgs({...}, validArgs)
if not args.race or not args.count then
print 'You need to specify at least one race with -race parameter, and count with -count parameter'
return
end
local race_names = type(args.race) == 'table' and args.race or { args.race }
if type(args.count) == 'table' and #args.race ~= #args.count then
print 'Number of counts and races provided do not match'
return
end
local civ_id
if args.civ == 'self' then
civ_id = df.global.ui.civ_id
elseif args.civ then
local race_id = find_race(args.civ)
if race_id then
civ_id = find_entity_for_race(race_id)
if not civ_id then
print ('Could not find a named civilization for race ' .. args.civ)
return
end
else
civ_id = find_entity_by_name(args.civ)
if not civ_id then
print ('Could not find civilization ' .. args.civ)
return
end
end
else
local race_id = find_race(race_names[1])
civ_id = race_id and find_entity_for_race(race_id)
if not civ_id then
print ('Could not find a named civilization for race ' .. race_names[1])
return
end
end
local pop_id = df.historical_entity.find(civ_id).populations[0]
local cult_id = find_cultural_identity(civ_id)
if args.debug then
print ('Civilization "'.. dfhack.TranslateName(df.historical_entity.find(civ_id).name, true) .. '" ID ' .. civ_id)
end
-- Army
a = df.army:new()
a.id = df.global.army_next_id
df.global.army_next_id = df.global.army_next_id + 1
a.pos.x = 1000 -- can be anything
a.pos.y = 1000
a.last_pos.x = -1
a.last_pos.y = -1
a.unk_10 = 8 -- wait timer, decreased by 16 each tick, siege occurs when reaches zero
for i,race_name in ipairs(race_names) do
local race_id = find_race(race_name)
if not race_id then
print ('Could not find race ' .. race_name)
--todo: cleanup
return
end
a.squads:insert('#',{
new=true,
count = type(args.count) == 'table' and args.count[i] or args.count,
race = race_id,
entity_id = civ_id,
population_id = pop_id,
cultural_identity = cult_id,
unk_18 = args.undead and 100 or 0, -- from xml: made creatures undead, so not sure maybe affliction?
unk_10 = 0, -- -> unit.unk_c0
unk_1c = 0, -- from xml: crashed df...
subordinate_entity_id = 0, -- -> unit.enemy.anon_4
unk_24 = 0, -- -> unit.enemy.anon_5
unk_28 = 0,
})
end
a.unk_3c = 50
a.block_path_x:insert(0,df.global.world.map.region_x*3)
a.block_path_y:insert(0,df.global.world.map.region_y*3)
--NOTE(warmist): not sure if it needs empty path?
a.path_x:insert(0,100)
a.path_y:insert(0,100)
a.unk_9c = 50
a.unk_a0 = 50
a.unk_a4 = 100
s = df.new('string')
s.value='GENERAL_POISON'
a.creature_class:insert(0,s)
-- Max(TM) pointed out these might be a tent material
a.item_type = 54
a.mat_type = 37
a.mat_index = 184
ac = df.army_controller:new()
ac.id=df.global.army_controller_next_id
df.global.army_controller_next_id = df.global.army_controller_next_id + 1
-- also ac.id -> unit.enemy.anon_6
-- Army controller
ac.entity_id = civ_id
ac.site_id = df.global.ui.site_id
ac.pos_x = df.global.world.map.region_x*3
ac.pos_y = df.global.world.map.region_y*3
--NOTE(warmist): these look like moved around
ac.unk_18 = 50
ac.unk_1c = -1
ac.year = df.global.cur_year
ac.year_tick = df.global.cur_year_tick
ac.unk_34 = -1 -- these two are ids of other army controllers, some kind of relationship
ac.unk_38 = -1
-- Hesperid mentioned these are army leader and the civ leader, they will be visible in legends if present
ac.master_hf = -1
ac.general_hf = -1 -- -> history_event_war_attacked_sitest.attacker_general_hf
--ac.unk_54 = 0 --NOTE(warmist): very fishy in new version it's a vector?!
ac.type = df.army_controller.T_type.InvasionOrder
-- Something
--[[
t = df.new('char',100)
t[0]=4 --4
t[4]=1 --1
t[8]=-1 -- all -1
t[9]=-1
t[10]=-1
t[11]=-1
t[12]=-1 -- all -1
t[13]=-1
t[14]=-1
t[15]=-1
--0x42 0x07 0x00 0x00 0x7f 0x1b 0x00 0x00
t[0x5c] = 0x42 --1858
t[0x5d] = 0x7
t[0x60] = 0x7f --7039
t[0x61] = 0x1b
--]]
--was: ac.unk_58 = t
ac.data.InvasionOrder={
new=df.army_controller_invasion_order,
unk_1=4,unk_2=1,unk_3=-1,unk_4=-1}
if args.debug then
print('Army ID ' .. a.id)
print('Controller ID ' .. ac.id)
end
a.controller_id=ac.id
a.controller=ac
df.global.world.army_controllers.all:insert(#df.global.world.army_controllers.all,ac)
df.global.world.armies.all:insert(#df.global.world.armies.all,a)
-- Experimental
if args.cleanup then
df.global.pause_state = false
df.global.gview.view.child:logic()
df.global.pause_state = true
utils.erase_sorted_key(df.global.world.army_controllers.all, ac.id, 'id')
for i,unit in ipairs(df.global.world.units.all) do
if unit.enemy.anon_6 == ac.id then
unit.enemy.anon_6 = -1
end
end
df.delete(t)
ac.unk_58 = nil
ac:delete()
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment