Skip to content

Commit 9fbd247

Browse files
create-unit: added 'quantity' and random caste selection
- added 'quantity' argument for spawning several units simultaneously - implemented random caste selection for use upon omission of 'caste' argument - changed several instances of 'error' to 'qerror'
1 parent 5bd8f0d commit 9fbd247

1 file changed

Lines changed: 111 additions & 83 deletions

File tree

modtools/create-unit.lua

Lines changed: 111 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
-- sets baby/child profession and mood for creatures of the appropriate age where relevant
1111
-- properly assigns civ_id to historical_figure to eliminate a number of hostility issues
1212
-- removes the arena-generated string of numbers from the first name of units
13+
-- added 'quantity' arg for spawning multiple creatures simultaneously
14+
-- creature caste is now randomly selected if left unspecified
15+
1316
--[[
1417
TODO
1518
confirm body size is computed appropriately for different ages / life stages
@@ -36,6 +39,7 @@ Creates a unit. Usage::
3639
HUMAN
3740
-caste casteName
3841
specify the caste of the unit to be created
42+
if not specified, the caste is randomly selected
3943
examples:
4044
MALE
4145
FEMALE
@@ -54,14 +58,20 @@ Creates a unit. Usage::
5458
Can be used instead of -civId \\LOCAL and -groupId \\LOCAL
5559
-name entityRawName
5660
set the unit's name to be a random name appropriate for the
57-
given entity. examples:
61+
given entity
62+
examples:
5863
MOUNTAIN
64+
EVIL
5965
-nick nickname
6066
set the unit's nickname directly
6167
-location [ x y z ]
6268
create the unit at the specified coordinates
6369
-age howOld
6470
set the birth date of the unit by current age
71+
chosen randomly if not specified
72+
-quantity howMany
73+
replace "howMany" with the number of creatures you want to create
74+
defaults to 1 if not specified
6575
-flagSet [ flag1 flag2 ... ]
6676
set the specified unit flags in the new unit to true
6777
flags may be selected from df.unit_flags1, df.unit_flags2,
@@ -316,7 +326,7 @@ function createNemesis(trgunit,civ_id,group_id)
316326
he_group.nemesis_ids:insert("#",id)
317327
he_group.nemesis:insert("#",nem)
318328
end
319-
nem.figure=createFigure(trgunit,he,he_group)
329+
nem.figure = trgunit.hist_figure_id ~= -1 and df.historical_figure.find(trgunit.hist_figure_id) or createFigure(trgunit,he,he_group) -- the histfig check is there just in case this function is called by another script to create nemesis data for a historical figure which somehow lacks it
320330
return nem
321331
end
322332

@@ -470,7 +480,8 @@ validArgs = utils.invert({
470480
'nick',
471481
'location',
472482
'age',
473-
'setUnitToFort' -- added by amostubal to get past an issue with \\LOCAL
483+
'setUnitToFort', -- added by amostubal to get past an issue with \\LOCAL
484+
'quantity'
474485
})
475486

476487
if moduleMode then
@@ -487,8 +498,8 @@ local race
487498
local raceIndex
488499
local casteIndex
489500

490-
if not args.race or not args.caste then
491-
error 'Specfiy a race and caste for the new unit.'
501+
if not args.race then
502+
qerror('Specify a race for the new unit.')
492503
end
493504

494505
--find race
@@ -501,25 +512,27 @@ for i,v in ipairs(df.global.world.raws.creatures.all) do
501512
end
502513

503514
if not race then
504-
error 'Invalid race.'
515+
qerror('Invalid race: '..args.race)
505516
end
506517

507-
for i,v in ipairs(race.caste) do
508-
if v.caste_id == args.caste then
509-
casteIndex = i
510-
break
518+
if args.caste then -- if args.caste is omitted, casteIndex is randomly selected within the spawn loop below
519+
for i,v in ipairs(race.caste) do
520+
if v.caste_id == args.caste then
521+
casteIndex = i
522+
break
523+
end
511524
end
512-
end
513525

514-
if not casteIndex then
515-
error 'Invalid caste.'
526+
if not casteIndex then
527+
qerror('Invalid caste: '..args.caste)
528+
end
516529
end
517530

518531
local age
519532
if args.age then
520533
age = tonumber(args.age)
521534
if not age and not age == 0 then
522-
error('Invalid age: ' .. args.age)
535+
qerror('Invalid age: ' .. args.age)
523536
end
524537
end
525538

@@ -543,88 +556,103 @@ if args.setUnitToFort then
543556
group_id = df.global.ui.group_id
544557
end
545558

546-
local unitId
547-
if civ_id == -1 then
548-
unitId = createUnit(raceIndex, casteIndex, args.location, args.name)
549-
else
550-
unitId = createUnitInCiv(raceIndex, casteIndex, civ_id, group_id, args.location, args.name)
551-
end
552-
553-
if args.domesticate then
554-
domesticate(unitId, group_id)
555-
else
556-
wild(unitId)
559+
local spawnNumber = 1
560+
if args.quantity then
561+
spawnNumber = tonumber(args.quantity)
562+
if not spawnNumber or spawnNumber < 1 then
563+
qerror('Invalid spawn quantity: '..args.quantity)
564+
end
557565
end
558566

559-
local u = df.unit.find(unitId)
560-
u.counters.soldier_mood_countdown = -1
561-
u.counters.death_cause = -1
562-
u.enemy.unk_450 = -1
563-
u.enemy.unk_454 = -1
564-
u.enemy.army_controller_id = -1
567+
for n = 1,spawnNumber do
565568

566-
--these flags are an educated guess of how to get the game to compute sizes correctly: use -flagSet and -flagClear arguments to override or supplement
567-
u.flags2.calculated_nerves = false
568-
u.flags2.calculated_bodyparts = false
569-
u.flags3.body_part_relsize_computed = false
570-
u.flags3.size_modifier_computed = false
571-
u.flags3.compute_health = true
572-
u.flags3.weight_computed = false
569+
if not args.caste then -- randomly select caste each time
570+
casteIndex = getRandomCasteId(raceIndex)
571+
end
573572

574-
if age or age == 0 then
575-
if age == 0 then
576-
u.birth_time = df.global.cur_year_tick
573+
local unitId
574+
if civ_id == -1 then
575+
unitId = createUnit(raceIndex, casteIndex, args.location, args.name)
576+
else
577+
unitId = createUnitInCiv(raceIndex, casteIndex, civ_id, group_id, args.location, args.name)
577578
end
578-
local u = df.unit.find(unitId)
579-
local oldYearDelta = u.old_year - u.birth_year
580-
u.birth_year = df.global.cur_year - age
581-
if u.old_year ~= -1 then
582-
u.old_year = u.birth_year + oldYearDelta
583-
end
584-
if u.flags1.important_historical_figure == true and u.flags2.important_historical_figure == true then
585-
local hf = df.historical_figure.find(u.hist_figure_id)
586-
hf.born_year = u.birth_year
587-
hf.born_seconds = u.birth_time
588-
hf.old_year = u.old_year
589-
hf.old_seconds = u.old_time
579+
580+
if args.domesticate then
581+
domesticate(unitId, group_id)
582+
else
583+
wild(unitId)
590584
end
591-
end
592-
setAgeProfession(u)
593585

594-
if args.flagSet or args.flagClear then
595586
local u = df.unit.find(unitId)
596-
local flagsToSet = {}
597-
local flagsToClear = {}
598-
for _,v in ipairs(args.flagSet or {}) do
599-
flagsToSet[v] = true
600-
end
601-
for _,v in ipairs(args.flagClear or {}) do
602-
flagsToClear[v] = true
603-
end
604-
for _,k in ipairs(df.unit_flags1) do
605-
if flagsToSet[k] then
606-
u.flags1[k] = true;
607-
elseif flagsToClear[k] then
608-
u.flags1[k] = false;
587+
u.counters.soldier_mood_countdown = -1
588+
u.counters.death_cause = -1
589+
u.enemy.unk_450 = -1
590+
u.enemy.unk_454 = -1
591+
u.enemy.army_controller_id = -1
592+
593+
--these flags are an educated guess of how to get the game to compute sizes correctly: use -flagSet and -flagClear arguments to override or supplement
594+
u.flags2.calculated_nerves = false
595+
u.flags2.calculated_bodyparts = false
596+
u.flags3.body_part_relsize_computed = false
597+
u.flags3.size_modifier_computed = false
598+
u.flags3.compute_health = true
599+
u.flags3.weight_computed = false
600+
601+
if age or age == 0 then
602+
if age == 0 then
603+
u.birth_time = df.global.cur_year_tick
609604
end
610-
end
611-
for _,k in ipairs(df.unit_flags2) do
612-
if flagsToSet[k] then
613-
u.flags2[k] = true;
614-
elseif flagsToClear[k] then
615-
u.flags2[k] = false;
605+
local u = df.unit.find(unitId)
606+
local oldYearDelta = u.old_year - u.birth_year
607+
u.birth_year = df.global.cur_year - age
608+
if u.old_year ~= -1 then
609+
u.old_year = u.birth_year + oldYearDelta
610+
end
611+
if u.flags1.important_historical_figure == true and u.flags2.important_historical_figure == true then
612+
local hf = df.historical_figure.find(u.hist_figure_id)
613+
hf.born_year = u.birth_year
614+
hf.born_seconds = u.birth_time
615+
hf.old_year = u.old_year
616+
hf.old_seconds = u.old_time
616617
end
617618
end
618-
for _,k in ipairs(df.unit_flags3) do
619-
if flagsToSet[k] then
620-
u.flags3[k] = true;
621-
elseif flagsToClear[k] then
622-
u.flags3[k] = false;
619+
setAgeProfession(u)
620+
621+
if args.flagSet or args.flagClear then
622+
local u = df.unit.find(unitId)
623+
local flagsToSet = {}
624+
local flagsToClear = {}
625+
for _,v in ipairs(args.flagSet or {}) do
626+
flagsToSet[v] = true
627+
end
628+
for _,v in ipairs(args.flagClear or {}) do
629+
flagsToClear[v] = true
630+
end
631+
for _,k in ipairs(df.unit_flags1) do
632+
if flagsToSet[k] then
633+
u.flags1[k] = true;
634+
elseif flagsToClear[k] then
635+
u.flags1[k] = false;
636+
end
637+
end
638+
for _,k in ipairs(df.unit_flags2) do
639+
if flagsToSet[k] then
640+
u.flags2[k] = true;
641+
elseif flagsToClear[k] then
642+
u.flags2[k] = false;
643+
end
644+
end
645+
for _,k in ipairs(df.unit_flags3) do
646+
if flagsToSet[k] then
647+
u.flags3[k] = true;
648+
elseif flagsToClear[k] then
649+
u.flags3[k] = false;
650+
end
623651
end
624652
end
625-
end
626653

627-
if args.nick and type(args.nick) == 'string' then
628-
dfhack.units.setNickname(df.unit.find(unitId), args.nick)
654+
if args.nick and type(args.nick) == 'string' then
655+
dfhack.units.setNickname(df.unit.find(unitId), args.nick)
656+
end
629657
end
630658

0 commit comments

Comments
 (0)