Bay 12 Games Forum

Dwarf Fortress => DF Modding => Utilities and 3rd Party Applications => Topic started by: expwnent on July 22, 2015, 09:34:37 am

Title: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: expwnent on July 22, 2015, 09:34:37 am
This is a beta version. Use at your own risk.

https://github.com/expwnent/dfhack/blob/create-unit/scripts/teleport.lua
https://github.com/expwnent/dfhack/blob/create-unit/scripts/modtools/create-item.lua
https://github.com/expwnent/dfhack/blob/create-unit/scripts/modtools/create-unit.lua
https://github.com/expwnent/dfhack/blob/create-unit/scripts/modtools/equip-item.lua

Install teleport to hack/scripts and install the rest to hack/scripts/modtools. Overwrite old versions with the new ones.

Please test thoroughly and post results here.

Notes:

1. Created units are naked. I will make a separate script for managing equipment later. Currently implemented. See modtools/equip-item.lua.

2. If you try to make a tame hydra in vanilla you're going to have "fun". Tame dogs seem to work fine. I'm not sure whether you're supposed to add tame animals to your civ / group or not. Test it and let me know so I can document it. If you use -flagClear [ resident ] then it should work on megabeasts.

3. Invaders probably won't work properly because that requires creating a new invasion id and a few other things. I'll make a separate script for managing custom invasions later.

4. Once this script has been beta tested I will do my best to maintain backwards compatibility, but I make no promises until then.

5. I wasn't sure what unit flags to set for different circumstances so I let the user manually specify the flags. See here (https://github.com/DFHack/df-structures/blob/master/df.units.xml) for the flags you can set. You can also clear flags if DF automatically sets them and you don't want it to.

6. Units are not named (in any useful way) by this script. Sometimes they're named something like "Dwarf -13568432", which doesn't seem to cause any other problems but it is strange and I'm not sure why it happens. As of version 0.2, use the "-name" argument to give the unit a random civilization-appropriate name. Use "-name MOUNTAIN" for dwarf names, "-name EVIL" for goblin names, etc.

7. Units may be placed in surprising places. Use the loo(k) mode to control it manually for now. You can specify location with the "-location" argument.

Examples:

Code: [Select]
modtools/create-unit -race DWARF -caste MALE -civ_id \\LOCAL -group_id \\LOCAL
modtools/create-unit -race DWARF -caste FEMALE -civ_id \\LOCAL -group_id \\LOCAL
modtools/create-unit -race HYDRA -caste FEMALE
modtools/create-unit -race DOG caste FEMALE -civ_id \\LOCAL -group-id \\LOCAL -domesticate
modtools/create-unit -race DWARF -caste MALE -civ_id \\LOCAL -group_id \\LOCAL -flagSet [ had_mood vision_good compute_health ]
modtools/create-unit -race DWARF -caste MALE -civ_id \\LOCAL -group_id \\LOCAL -name
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: Roses on July 22, 2015, 10:18:16 am
Awesome! I will definitely test this out.
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: expwnent on July 22, 2015, 10:19:03 am
Thanks!

PS: It should also be compatible with script_environment if you want to try more advanced features.
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: Meph on July 22, 2015, 10:21:38 am
ptw

(Quick work, I'm impressed)
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: Roses on July 22, 2015, 10:57:08 am
Thanks!

PS: It should also be compatible with script_environment if you want to try more advanced features.

Ooh, good call. Can definitely think of some fun things that could be done. Here are a couple questions to start;

Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: expwnent on July 22, 2015, 11:12:10 am
I plan on doing all of that. Randomization should already be in, but I didn't check.
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: lethosor on July 22, 2015, 11:51:20 am
It would be nice to have a user-friendly wrapper like the old spawn-unit script (e.g. treating the first two script arguments as race and caste, and possibly passing the rest directly to modtools/create-unit).
The weird numbers in unit names are probably due to the value(s) used in unit names in arena mode not being initialized.
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: Vattic on July 22, 2015, 02:35:01 pm
PTW.

Look forward to seeing where this goes.
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: expwnent on July 22, 2015, 03:36:45 pm
I can't upload it at the moment, but I implemented random appropriate naming. Next up is equipment management, followed by invasion management.
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: Dirst on July 22, 2015, 03:53:03 pm
Nice work.  I can't test this at the moment, but I have two questions based on what I see in the code:

1. Wouldn't \\LOCAL be passed to the script as \LOCAL?  Never mind.  The \\LOCAL in the code is passed to Lua as \LOCAL, just like the \\LOCAL from the command is.  It will work fine as written.

2. I assume the arena-mode stuff handles the unit's birth year and such... but what if we want to control that?  For my purposes (and Taldarus in the other thread) the age ought to be exactly zero.  Can we safely overwrite the birth_year and such inside arena mode?  An -age parameter would make this script more useful, even if it has to be restricted to adult ages.
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: lethosor on July 22, 2015, 04:19:09 pm
I'm a little confused about what you're saying about backslashes, unless you mean that the commands expwnent listed should be passed as strings to dfhack.run_command or dfhack.run_script:
Code: [Select]
[DFHack]# devel/print-args \LOCAL
\LOCAL
[DFHack]# devel/print-args \\LOCAL
\\LOCAL
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: expwnent on July 22, 2015, 04:24:40 pm
Dirst: that's quite reasonable. I'll have to be careful it computes size correctly for different ages because that's important for combat. I probably won't bother making things like hair length be age appropriate unless someone really wants it.
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: expwnent on July 22, 2015, 04:28:07 pm
I'm a little confused about what you're saying about backslashes, unless you mean that the commands expwnent listed should be passed as strings to dfhack.run_command or dfhack.run_script:
Code: [Select]
[DFHack]# devel/print-args \LOCAL
\LOCAL
[DFHack]# devel/print-args \\LOCAL
\\LOCAL

Keep in mind that the arguments get passed through processArgs, which will eat one of the backslashes. This is necessary, otherwise it would be impossible to pass negative numbers as values to named arguments.
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: mifki on July 22, 2015, 05:21:45 pm
What is the extra viewscreen_dwarfmodest for?
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: expwnent on July 22, 2015, 05:22:55 pm
What is the extra viewscreen_dwarfmodest for?

That makes it so that it works even if the current viewscreen is something else.
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: mifki on July 22, 2015, 05:33:45 pm
What is the extra viewscreen_dwarfmodest for?

That makes it so that it works even if the current viewscreen is something else.

That's not required even in this case. Just use df.global.gview.view.child instead of getCurViewscreen() - it will correctly place the new screen on the top of the stack even if the parent screen wasn't on top.

Spoiler (click to show/hide)
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: Dirst on July 22, 2015, 07:03:37 pm
Dirst: that's quite reasonable. I'll have to be careful it computes size correctly for different ages because that's important for combat. I probably won't bother making things like hair length be age appropriate unless someone really wants it.
It'd be fine for an initial version to only work for adults, the creatures I mentioned are full-sized from day 0.

Child sizes are tricky because growth is linear during the growth stage, rather than just a step function.
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: lethosor on July 22, 2015, 08:35:29 pm
What is the extra viewscreen_dwarfmodest for?

That makes it so that it works even if the current viewscreen is something else.

That's not required even in this case. Just use df.global.gview.view.child instead of getCurViewscreen() - it will correctly place the new screen on the top of the stack even if the parent screen wasn't on top.
You'd want to make sure that screen is actually a dwarf mode viewscreen, though. (Is this supposed to work in adventure mode?)
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: mifki on July 22, 2015, 08:56:42 pm
What is the extra viewscreen_dwarfmodest for?

That makes it so that it works even if the current viewscreen is something else.

That's not required even in this case. Just use df.global.gview.view.child instead of getCurViewscreen() - it will correctly place the new screen on the top of the stack even if the parent screen wasn't on top.
You'd want to make sure that screen is actually a dwarf mode viewscreen, though. (Is this supposed to work in adventure mode?)

In my case it can be dwarf mode only.
Oh, right, if this script is supposed to work in adv mode, then creating a new dwarf mode screen is required.
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: taldarus on July 23, 2015, 12:07:58 am
Spawned a Hydra, worked fine.

Trying to spawn a civilian. Got an error about arg5 civ_id in function 'processArgs' and in main chunk.

Saw something about this in the post, tried with \\LOCAL and \LOCAL, using my custom race atm. Will revert to standard dwarfs later to verify it's not my boys. Pretty sure I tried it with dwarfs hours ago, but can't remember (at the time, I thought I was messing up how to use the code)

Seems to be universal error, got it for the dog too.

ADDM: Used in arena crashed df and hack.
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: expwnent on July 23, 2015, 01:07:04 am
In later versions it will work in all modes. Currently it only works in dwarf mode.

Try civId and groupId instead of civ_id and group_id. A bug in the documentation.
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: taldarus on July 23, 2015, 02:03:26 am
Perfect!

Spawned me a Queen & Soldier! They are, however, not actually my civilians. Both fall into the 'Other' category and are classified as friendlies.

Gonna try a friendly hydra.

Is there a way to automate this? I read through all material I could find, but no luck. I assume its something you need to introduce into the scripts code?
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: expwnent on July 23, 2015, 02:04:55 am
Try setting both civId and groupId to \\LOCAL.
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: taldarus on July 23, 2015, 02:09:37 am
Command used: modtools/create-unit -race CHIDDRIN -caste T0QUEEN -civId \\LOCAL -groupId \\LOCAL

I don't see/understand the difference.

EDIT: Changed GroupID to correct form GroupId
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: expwnent on July 23, 2015, 02:12:00 am
That command should work, except you need groupId instead of groupID (but it would have complained if you did that wrong).

The difference between what?
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: taldarus on July 23, 2015, 02:14:03 am
Spawned me a Queen & Soldier! They are, however, not actually my civilians. Both fall into the 'Other' category and are classified as friendlies.

then you said

Try setting both civId and groupId to \\LOCAL.

But I already did that, so I don't see how this would help.
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: expwnent on July 23, 2015, 02:16:00 am
If you just set civId then they'll be members of your civilization but not members of your fort. They *should* be members of both if you use both -civId \\LOCAL and -groupId \\LOCAL, but it's possible it isn't working correctly. It seems to work fine for dwarves in vanilla.
Title: Re: [DFHack] modtools/create-unit (version 0.1) (beta)
Post by: taldarus on July 23, 2015, 02:17:46 am
ah, ok, suggestions?

Edit: Added Hydra as a pet, it worked right up until I unpaused the game.

Stray Hydra and all. When game started to run, it froze immediately, and then crashed shortly after. An error box appeared, but disappeared before I could read it. DF error log is clean of any reference, but I doubt a dfhack error shows there.

Edit2: Oh, both civ members names are just numbers, I can give them if you want. Anything else you want tested?

Edit3: Tried adding the -flags tag to my race. It came up with this error:
bad argument #1 to 'ipairs' (table expected, got string)
stack traceback:
  [C]: in function 'ipairs'
...modtools/create-unit.lua:312: in main chunk
Title: Re: [DFHack] modtools/create-unit (version 0.2) (beta)
Post by: expwnent on July 23, 2015, 02:36:56 am
Try version 0.2. It supports random civilization-appropriate names.

For the flags argument you need to do it like

-flags [ flag1 flag2 ]

and even if there's just one flag you have to do -flags [ flagName ]
Title: Re: [DFHack] modtools/create-unit (version 0.2) (beta)
Post by: taldarus on July 23, 2015, 02:54:57 am
You sir are a scripting machine, vn!

Name is now 'blank', or I assume it is blank (Just says Peasant). I haven't spent any time working on the entity file, I just strip mined the dwarf one for pieces I wanted.

Still reads as friendly, not a civ member...

Tested saving and loading, looks secure...

Tested dog, in order to verify it is my race...and the dog shows up as a tame stray dog... forgot to have loo(k)ed when i did it, but he shows in the unit list. So it's my race

tried to add entity and creature, but its too many characters...
Title: Re: [DFHack] modtools/create-unit (version 0.2) (beta)
Post by: expwnent on July 23, 2015, 02:56:28 am
I don't think there's a character limit.

Try the -name argument.
Title: Re: [DFHack] modtools/create-unit (version 0.2) (beta)
Post by: taldarus on July 23, 2015, 03:00:00 am
40,000 - the forum doesn't like the entity file. WAY too big IMO

Will try on my own, but it would be faster if you give me an example.
Title: Re: [DFHack] modtools/create-unit (version 0.2) (beta)
Post by: expwnent on July 23, 2015, 03:02:40 am
Oh, I thought you meant that the command string was too long for DFHack.

An example of what?
Title: Re: [DFHack] modtools/create-unit (version 0.2) (beta)
Post by: taldarus on July 23, 2015, 03:04:00 am
how to use -name argument. This is my first time using DFhack :)
Spent my morning just trying to run your code (almost gave up to, I was overcomplicating it)
Title: Re: [DFHack] modtools/create-unit (version 0.2) (beta)
Post by: expwnent on July 23, 2015, 03:04:57 am
modtools/create-unit -race DWARF -caste MALE -civ_id \\LOCAL -group_id \\LOCAL -name

I appreciate the beta testing!
Title: Re: [DFHack] modtools/create-unit (version 0.2) (beta)
Post by: taldarus on July 23, 2015, 03:06:53 am
 :'(

Doh!

Got a name on that, one 'Act Ongogushil'
Title: Re: [DFHack] modtools/create-unit (version 0.2) (beta)
Post by: taldarus on July 23, 2015, 03:08:19 am
Having fun, I don't mind this at all. I do have some errands I need to run, but not in a hurry.

Still no luck on the groupId part. Friendly but not member.

EDIT: LOL, retested the Hydra. It is 'functioning' as a civ pet. Shows up in my unit list and everything. Unfortunately, he seems to dislike my other pets. Lost my fort, but saved/loaded a good 10-20 times.

EDIT2: Hydra now has a name, don't think he did before he ate my civilization. It's name is a series of numbers.

EDIT3: Want to make sure store doesn't close, before I get shopping done. AFK for an hour or so. I would ENJOY helping you some more.
Title: Re: [DFHack] modtools/create-unit (version 0.2) (beta)
Post by: expwnent on July 23, 2015, 03:26:18 am
You may find the hydra doesn't like your dwarves either.

I'm getting the friendly but not member problem too. Working on it. It used to work.
Title: Re: [DFHack] modtools/create-unit (version 0.3) (beta)
Post by: expwnent on July 23, 2015, 03:50:45 am
Creating fort dwarves ought to work now.
Title: Re: [DFHack] modtools/create-unit (version 0.3) (beta)
Post by: taldarus on July 23, 2015, 04:01:38 am
My custom isn't working. Is it dwarf only?
Title: Re: [DFHack] modtools/create-unit (version 0.3.1) (beta)
Post by: expwnent on July 23, 2015, 04:02:28 am
It shouldn't be. Try now.
Title: Re: [DFHack] modtools/create-unit (version 0.3.1) (beta)
Post by: taldarus on July 23, 2015, 04:05:51 am
Ok, it is working. Expwnent, you did a lot of amazing work on this. Thank you so much!

Castes where not working until I added in the description tag for each class. (checked castes in therapist and in game). I have no reason to believe something else fixed the problem, but can remove the descriptions for a verification if you want.

Ran a series of test involving the names of the spawned dwarves. Each world followed the exact same pattern of names, each time. (tested accross three worlds). The first three sets of names matched. So the random seed, yes?

Edit: Cleaned up a really sloppy post
Title: Re: [DFHack] modtools/create-unit (version 0.3.1) (beta)
Post by: expwnent on July 23, 2015, 06:50:19 am
Yes, if you could retest that it would be helpful just to be certain. It ought to not matter.

I didn't do anything special to the random seed. I will do that in the full version.
Title: Re: [DFHack] modtools/create-unit (version 0.3.1) (beta)
Post by: taldarus on July 23, 2015, 07:02:22 am
 :-\

My mistake... nvm the caste thing... :'(
Title: Re: [DFHack] modtools/create-unit (version 0.3.1) (beta)
Post by: Meph on July 24, 2015, 02:09:04 am
Can random names be a thing? That was the only gripe I had with the old spawnunit... you make 10 units, they are all the same. Could it get a random name from a list of arguments in the script (so that modders can just copy+paste a list of names in there) or, if you want to get extra fancy, get it from the word/language file?

Because in my mod I have many things like "Create a skeleton" = Skeleton, the skeleton. Or "Hire a wizard" = Bob, the wizard.

And thank you for the work and testing you guys are doing. :)
Title: Re: [DFHack] modtools/create-unit (version 0.3.1) (beta)
Post by: mifki on July 24, 2015, 02:35:40 am
I think I posted a way to use the built-in name screen to generate random names, this could be incorporated into the create-unit script.

Yeah, here it is (excluding cleanup, etc.)

Code: [Select]
a = df.new(df.viewscreen_setupadventurest) ; a.subscreen = 3 ; gui = require 'gui' ; gui.simulateInput(a, 'A_RANDOM_NAME') ; gui.simulateInput(a, 'A_CUST_NAME') ; print(dfhack.TranslateName(dfhack.gui.getCurViewscreen().name))
Title: Re: [DFHack] modtools/create-unit (version 0.3.1) (beta)
Post by: expwnent on July 24, 2015, 03:38:38 am
Random civilization-appropriate names are already implemented.
Title: Re: [DFHack] modtools/create-unit (version 0.3.1) (beta)
Post by: Roses on July 24, 2015, 05:33:54 am
Did some basic testing so far everything is going well. Thin I ask going to write some scripts to handle specific instances like summoning familiars and making them pets of the summoner.

Question. Any idea why megabeasts aren't made friendly?
Title: Re: [DFHack] modtools/create-unit (version 0.3.1) (beta)
Post by: expwnent on July 24, 2015, 05:35:29 am
Actually, yes! It has to do with their flags. Hydras have the resident flag set which makes them hostile even if they're domesticated and civ members and fort members. I'll do a quick patch to let you clear flags with the command line instead of just set them.
Title: Re: [DFHack] modtools/create-unit (version 0.3.2) (beta)
Post by: expwnent on July 24, 2015, 05:46:08 am
Patched. Experiment thoroughly with flags.
Title: Re: [DFHack] modtools/create-unit (version 0.3.2) (beta)
Post by: Meph on July 24, 2015, 05:47:12 am
Random civilization-appropriate names are already implemented.
And for non-civ members? I play dwarves, spawn 10 hostile bears. These should have no names. I spawn 10 bandits, these should have names, but are not necessarily members of the human civ.

Sorry if I make it more complicated, if it's nonsense, just tell me. I'll life, even without fancy naming schemes. ;)
Title: Re: [DFHack] modtools/create-unit (version 0.3.2) (beta)
Post by: expwnent on July 24, 2015, 06:04:48 am
You can already spawn nameless ones (I think). I'll tweak it so if you want names you can specify what civ their names come from independently of the civ they are a member of (if any).
Title: Re: [DFHack] modtools/create-unit (version 0.3.2) (beta)
Post by: Meph on July 24, 2015, 06:18:26 am
Thank you for indulging me.  :)
Title: Re: [DFHack] modtools/create-unit (version 0.3.2) (beta)
Post by: expwnent on July 24, 2015, 06:26:53 am
In this case it's actually pretty easy. Equipment is slightly trickier. I'll do that next.
Title: Re: [DFHack] modtools/create-unit (version 0.3.2) (beta)
Post by: taldarus on July 24, 2015, 06:38:22 am
Meph: Just add the -name tag to the end and it should work fine.

Expwnent: No names work for the first one, but the later ones revert to the screwy number system. Also the hydra earned its name, I think, and that was a screwy number

Edit: Forgot why I got on, still haven't gotten a 100% straight answer on this. Cna I try connecting this code to a workshop reaction, or is that something to be implemented?
Title: Re: [DFHack] modtools/create-unit (version 0.3.2) (beta)
Post by: Meph on July 24, 2015, 06:44:06 am
Adding it to a workshop is easy, I did that A LOT with even the old spawnunit. You just have the reaction call the script, with a line in the onLoad.init in the DwarfFortress/raw folder.
Title: Re: [DFHack] modtools/create-unit (version 0.3.2) (beta)
Post by: Roses on July 24, 2015, 06:47:01 am
In this case it's actually pretty easy. Equipment is slightly trickier. I'll do that next.

For equipment I use to have a script that selected a random weapon available to a given civ but I can't seem to find it, I'll see if it's somewhere around. Are you planning on allowing random equipment and user defined equipment?

Edit: look up reaction-trigger
Title: Re: [DFHack] modtools/create-unit (version 0.3.2) (beta)
Post by: taldarus on July 24, 2015, 06:54:51 am
ty meph!

EDIT: Expwnent, you said to test tags thoroughly, any in particular? (I don't plan on needing to use any for my current project)
Title: Re: [DFHack] modtools/create-unit (version 0.3.2) (beta)
Post by: expwnent on July 24, 2015, 09:47:18 am
I mean, it should work, I just meant that you should make sure you figure out the right flags to set for various things, like how domesticated hydras need the resident flag cleared.
Title: Re: [DFHack] modtools/create-unit (version 0.3.2) (beta)
Post by: taldarus on July 24, 2015, 10:56:55 pm
Ok, ran into several small errors that I already fixed on my end. Now, I am looking at the errors in the dfhack screen. It seems to be the problem.

\lua\utils.lua:595: error: invalid arg: 1: reactionName
stacktaceback: modtools/create-unit.lua:313: in main chunk

despite tweaking several different values on my end, but can't find anything to get it working.

onload.init
Spoiler (click to show/hide)

reaction.txt
Spoiler (click to show/hide)

Despite the changes, I am still getting the same error...

EDIT: Cleaned up another awkward post.
Title: Re: [DFHack] modtools/create-unit (version 0.3.2) (beta)
Post by: expwnent on July 25, 2015, 07:20:45 am
Try this:

Code: [Select]
modtools/reaction-trigger -reactionName T0QUEENEGG -command [ modtools/create-unit -race CHIDDRIN -caste T0QUEEN -civId \\LOCAL -groupId \\LOCAL -name ]
Title: Re: [DFHack] modtools/create-unit (version 0.3.2) (beta)
Post by: taldarus on July 25, 2015, 08:37:32 am
Thanks again,

Spawned em inside of rock. When I dug em out, they were friendly. But I could never seem to get them to spawn in open space, always in the rock.
Title: Re: [DFHack] modtools/create-unit (version 0.3.2) (beta)
Post by: expwnent on July 25, 2015, 09:45:33 am
Uh, yes. That's because I haven't done the part that sets their location so they just end up wherever DF's arena code happens to spawn them.
Title: Re: [DFHack] modtools/create-unit (version 0.3.2) (beta)
Post by: taldarus on July 25, 2015, 10:25:12 am
Cool!

So nothing I can do on my end, yes? They weren't civ members is normal? Oh, and the name thing, names where numbers? All location problem?

Sorry for being a noob, just trying to be thorough (I think that is good Beta testing?)
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: expwnent on July 27, 2015, 07:55:11 am
Version 0.4 is up. Follow the installation instructions in the first post. It requires updates to a few existing scripts, and it also requires a few new scripts.

You can now equip items on units, and it is convenient to equip the most recently created item on the most recently created unit without knowing the id of either. You can equip items on any body part in any way, so feel free to have swords sewn in to spleens or haul stone blocks with your tongue if you really want to. I have no idea whether equipping armor on internal organs will grant extra protection or not. It would not surprise me if it did.

There isn't much documentation but if you look at validArgs you should be able to figure most of it out.

Code: [Select]
modtools/create-item -creator 110 -material CREATURE_MAT:HYDRA:TOOTH -item GLOVES:ITEM_GLOVES_GLOVES -rightHand -quality Masterful
modtools/equip-item -unit \\LAST -item \\LAST -mode Worn -bodyPart BRAIN

TODO:
  * make it so create-item accepts "-creator \\LAST"
  * make a tool for setting unit proficiencies
  * allow spawning existing historical figures
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: Roses on July 27, 2015, 12:11:59 pm
Hmm, did you try testing if the item stays equipped properly in a fight, or whenever it's inventory is checked by the game itself? And I assume both -unit and -item will also accept normal unit and item ids?
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: expwnent on July 27, 2015, 01:55:24 pm
I did not, and they do.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: Prismatic on August 04, 2015, 05:11:37 am
Pretty basic question, but how exactly do you spawn units that are hostile to everything?
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: Dirst on August 04, 2015, 12:18:47 pm
Pretty basic question, but how exactly do you spawn units that are hostile to everything?
Civ -1 is a special "I don't like anyone" team.  I haven't noticed creatures of the same species fight each other even in Civ  -1, but that could be an artifact of them seeing each other as too big to be easy prey.

Is there any real difference between spawning a cluster of wild animals and spawning a bunch of them independently?
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: expwnent on August 05, 2015, 02:59:04 pm
I don't think it's possible to make wild animals of the same race attack each other.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: Rumrusher on August 05, 2015, 06:55:38 pm
I don't think it's possible to make wild animals of the same race attack each other.
uhh slap a mood on one of the animals? or set one of their opponentjob id to one of the animals?
I'm away from the game to write up a script that would do this at the moment.
Code: [Select]
opponent.unit_id=using GM-editor or warmist Gm-unit might help out spawning better creatures.

there also fiddling around with Sites because some how you can edit just about EVERYTHING about a site population.
want necromantic vampire dogs with normal dwarves in a elf camp sure no mods about it.
also I think you can set them to be either alive or dead which explains tombs.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: expwnent on August 08, 2015, 03:30:53 pm
I meant making them "naturally" attack each other on sight. Putting them on opposing teams. It's probably possible but I don't know how.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: Dirst on August 08, 2015, 11:56:24 pm
Is there any chance of adding an age parameter, even if this version it's only valid for fully-mature creatures?  Pretty please?  I can customize the code for my mod, but I'd rather my players benefit from general DFHack bug-fixes.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: expwnent on August 09, 2015, 12:40:39 am
Yes, I can do that. I'll do that next. Thanks for reminding me.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: Dirst on August 09, 2015, 01:32:00 pm
Thank you, I really appreciate that.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: taldarus on September 28, 2015, 09:21:28 pm
haven't seen anything on this post in a while. was thinking that I should take a swing at this. The spawn unit part works wonderfully, but lacks location. Is there a copy/paste solution to this? Is there some reference material I could use? I have been idling on my personal project for too long, and want to get back to making my race :)

EDIT: I'm an idiot. See the location thing has been added. Going to tinker with it. Thanks expwnent!

You still want feed back I assume?
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: taldarus on September 28, 2015, 11:30:00 pm
Ok, so in reaction-trigger.lua it is able to pull up the command for the location as job.pos.x, y, z using the -command \\LOCATION, but how do I integrate that with...

Failed attempts:
Spoiler (click to show/hide)

Spoiler (click to show/hide)

Spoiler (click to show/hide)

Spoiler (click to show/hide)

Spoiler (click to show/hide)

I have tried a variety of locations and positions assuming -location [ job.pos.x job.pos.y job.pos.z ] is the correct call for the script. Still nothing. Oh, and I just overwrote ...Hold on, forgot the equip-item.lua (not trying to equip anything, but will check)

Don't see anything (in my obviously "expert" opinion) that says the equip script should be screwing, so I am not testing atm.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: expwnent on September 29, 2015, 09:25:16 am
You need to use [ \\LOCATION ]. Something like

Code: [Select]
modtools/reaction-trigger -reactionName T0QUEENEGG -command [ modtools/create-unit -race CHIDDRIN -caste T0QUEEN -civId \\LOCAL -groupId \\LOCAL -name -location [ \\LOCATION ] ]
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: taldarus on September 29, 2015, 09:44:00 am
hmmm, thought I did, let me check real quick.

EDIT:
Yeah, spawn works (many attempts didn't), but spawns in what appears to be the 'default' position.

EDIT2:
Spoiler (click to show/hide)

EDIT3:
Rechecked to make sure my input was correct. Also re-downloaded the reaction-trigger.lua just to be sure I had the most up to date trigger. No luck.

Hopefully this will be helpful.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: taldarus on September 29, 2015, 09:54:15 pm
Well, carp...
Thought I would work on my testing my civ's egg producing aspect, but got caught on the that. Hadn't noticed at the time, but civId doesn't seem to be working. Onload reaction and manually created creature where both friendly, but not members.

DFHACK errors:
BOTH:
Create-Unit.lua #274 & 495

ONLOAD:
dfhack.lua #447 & 462
reaction-trigger.lua #107 & 147
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: expwnent on September 30, 2015, 01:48:55 pm
hmmm, thought I did, let me check real quick.

EDIT:
Yeah, spawn works (many attempts didn't), but spawns in what appears to be the 'default' position.

EDIT2:
Spoiler (click to show/hide)

EDIT3:
Rechecked to make sure my input was correct. Also re-downloaded the reaction-trigger.lua just to be sure I had the most up to date trigger. No luck.

Hopefully this will be helpful.

What's the output of this:

Code: [Select]
modtools/reaction-trigger -reactionName T0QUEENEGG -command [ devel/print-args -race CHIDDRIN -caste T0QUEEN -civId \\LOCAL -groupId \\LOCAL -name -location [ \\LOCATION ] ]
DFHACK errors:
BOTH:
Create-Unit.lua #274 & 495

ONLOAD:
dfhack.lua #447 & 462
reaction-trigger.lua #107 & 147

I don't understand what this means.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: lethosor on September 30, 2015, 03:02:25 pm
I assume those are line numbers, but there's more than one error that can occur at a specific line, so it would be helpful to paste the full tracebacks (from stderr.log or the console).
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: taldarus on September 30, 2015, 05:21:13 pm
stderr.log output
Spoiler (click to show/hide)
What would seem relevant to me is in bold. Note that that is actually the very first input I used. I do remember that, I do not see any of the ten-fifteen alterations and tests.

console output:
Spoiler (click to show/hide)

Had an idea, would a clean install help?
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: expwnent on September 30, 2015, 07:15:07 pm
Try this:

Code: [Select]
modtools/reaction-trigger -reactionName T0WORKERNEGG -command [ modtools/create-unit -race CHIDDRIN -caste T0WORKER -civId \\\LOCAL -groupId \\\LOCAL -name -location [ \\LOCATION ] ]
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: taldarus on September 30, 2015, 07:26:30 pm
Absolutely nothing.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: taldarus on September 30, 2015, 07:48:07 pm
Since that uses ///LOCAL wouldn't I need to change the code?
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: expwnent on September 30, 2015, 07:55:41 pm
reaction-trigger strips off one of the backslashes before passing it to create-unit so it ought to work.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: taldarus on September 30, 2015, 08:23:32 pm
It's not even running....

Everything is console of hack is SOP for me, no reaction runs this way.
Spoiler (click to show/hide)

stderr.log
Spoiler (click to show/hide)

Doesn't seem to recognize it.

I went ahead and tried \\\\LOCAL for civId and groupId, same null signal.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: Dirst on October 21, 2015, 03:22:26 pm
The version of the script that I pulled from GitHub had a couple minor errors in it.

I got an error trying to create hostile units, and tracked it down to line 211.  It should read
Code: [Select]
if ( civ_id ) and civ_id ~= -1 thenso that it doesn't try to look up a "real" civ indexed -1.

I also replaced the entire location function with
Code: [Select]
if args.location then
  dfhack.run_command("teleport -unit " .. unitId .. " -x " .. args.location[1] .. " -y " .. args.location[2] .. " -z " .. args.location[3])
end

It now runs without bleeding red all over the console.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: lethosor on October 21, 2015, 03:35:52 pm
This is probably better, since it avoids potential issues with spaces in the variables being concatenated:
Code: [Select]
dfhack.run_command("teleport", "-unit", unitId, "-x", args.location[1], "-y", args.location[2], "-z", args.location[3])
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: Dirst on October 26, 2015, 07:16:05 am
Does anyone have an idea why any creature spawned by this script shows up as "Friendly" on the unit list, even if it has been induced to attack a fort member?  I even manually set all of its enemy_status_cache values to -1, but it still insists on being Friendly.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: expwnent on October 26, 2015, 07:17:11 am
What unit flags does it have?
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: Dirst on October 26, 2015, 08:00:49 am
What unit flags does it have?
Whatever the defaults are, since I don't know the flags at all.  I think I hear the sound of an impending facepalm on my part :)
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: expwnent on October 26, 2015, 08:28:19 am
https://github.com/DFHack/df-structures/blob/master/df.units.xml

marauder and active_invader are the most likely candidates if you want members of a siege. Wild animals should be hostile if you don't add them to your civ / group but there might be flags involved.

If you want a proper siege you'll have to do a custom lua script and do some stuff but I think that's only if you want them to be sort of "organized" and retreat under the right set of conditions.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: Dirst on October 26, 2015, 10:41:42 am
https://github.com/DFHack/df-structures/blob/master/df.units.xml

marauder and active_invader are the most likely candidates if you want members of a siege. Wild animals should be hostile if you don't add them to your civ / group but there might be flags involved.

If you want a proper siege you'll have to do a custom lua script and do some stuff but I think that's only if you want them to be sort of "organized" and retreat under the right set of conditions.
I'm looking to spawn a wild animal.  The old spawn-unit scripts seemed to get that part right (if you ignore that it spawned lobotomized wild animals), but the way create-unit is working for me I get two zeros in the enemy_status_cache (which seem to represent the fort) and a Friendly designation that won't go away.  Spamming -1 onto every enemy_status_cache value for the new creature doesn't have an effect.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: Warmist on October 26, 2015, 11:06:42 am
https://github.com/DFHack/df-structures/blob/master/df.units.xml

marauder and active_invader are the most likely candidates if you want members of a siege. Wild animals should be hostile if you don't add them to your civ / group but there might be flags involved.

If you want a proper siege you'll have to do a custom lua script and do some stuff but I think that's only if you want them to be sort of "organized" and retreat under the right set of conditions.
I'm looking to spawn a wild animal.  The old spawn-unit scripts seemed to get that part right (if you ignore that it spawned lobotomized wild animals), but the way create-unit is working for me I get two zeros in the enemy_status_cache (which seem to represent the fort) and a Friendly designation that won't go away.  Spamming -1 onto every enemy_status_cache value for the new creature doesn't have an effect.

Enemy cache is not all powerful. It's a cache that is recalculated every so often. Check if the civ_id is -1 (if not set to -1).
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: Dirst on October 26, 2015, 11:25:20 am
https://github.com/DFHack/df-structures/blob/master/df.units.xml

marauder and active_invader are the most likely candidates if you want members of a siege. Wild animals should be hostile if you don't add them to your civ / group but there might be flags involved.

If you want a proper siege you'll have to do a custom lua script and do some stuff but I think that's only if you want them to be sort of "organized" and retreat under the right set of conditions.
I'm looking to spawn a wild animal.  The old spawn-unit scripts seemed to get that part right (if you ignore that it spawned lobotomized wild animals), but the way create-unit is working for me I get two zeros in the enemy_status_cache (which seem to represent the fort) and a Friendly designation that won't go away.  Spamming -1 onto every enemy_status_cache value for the new creature doesn't have an effect.

Enemy cache is not all powerful. It's a cache that is recalculated every so often. Check if the civ_id is -1 (if not set to -1).
The civ is already -1, which makes "Friendly" all the stranger.  I did wonder if "cache" meant that there is an "original" somewhere that could be manipulated directly.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: Dirst on October 27, 2015, 05:19:06 pm
Wasn't able to make wild animals via flags.  Even making them an invader or uninvited guest didn't seem to faze their friendly ways  :'(

I hate to do it, but I'm going to have to roll back to using spawn-unit.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: Roses on October 27, 2015, 09:08:00 pm
Wasn't able to make wild animals via flags.  Even making them an invader or uninvited guest didn't seem to faze their friendly ways  :'(

I hate to do it, but I'm going to have to roll back to using spawn-unit.

You may have already tried it, but have you made sure to set the training_level to 9 (WildUntamed)?

EDIT: Also, I think you need to give them a world_population_ref in unit.animal. I was able to turn tame pets into wild animals by setting

flags1.tame = false
training_level = 9
animal.population.region_x = 50
animal.population.region_y = 50

I just randomly chose the region numbers, just so it's something other than -1
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: Dirst on October 28, 2015, 05:46:58 am
That's definitely worth trying.  I kept looking through HM-editor looking for differences between real wild animals and spawned ones, and all I could find was the animal population.  Didn't realize it was that easy to manipulate (had worries of a broken lookup pointer).

Thanks!

Edit: Success!  Here is the modified script...

Code: (modtools/create-unit.lua) [Select]
-- create-unit.lua
-- Originally created by warmist, edited by Putnam for the dragon ball mod to be used in reactions, modified by Dirst for use in The Earth Strikes Back mod, incorporating fixes discovered by Boltgun then Mifiki wrote the bit where it switches to arena mode briefly to do some of the messy work, then Expwnent combined that with the old script to make it function for histfigs
-- version 0.5
-- This is a beta version. Use at your own risk.

--[[
  TODO
    children and babies: set child/baby job
    confirm body size is computed appropriately for different ages / life stages
    incarnate pre-existing historical figures
    some sort of invasion helper script
      set invasion_id, etc
    announcement for fake natural birth if appropriate
]]

--[[
if dfhack.gui.getCurViewscreen()._type ~= df.viewscreen_dwarfmodest or df.global.ui.main.mode ~= df.ui_sidebar_mode.LookAround then
  print 'activate loo[k] mode'
  return
end
--]]

local utils=require 'utils'

function createUnit(race_id, caste_id)
  local curViewscreen = dfhack.gui.getCurViewscreen()
  local dwarfmodeScreen = df.viewscreen_dwarfmodest:new()
  curViewscreen.child = dwarfmodeScreen
  dwarfmodeScreen.parent = curViewscreen
  local oldMode = df.global.ui.main.mode
  df.global.ui.main.mode = df.ui_sidebar_mode.LookAround

  local gui = require 'gui'

  df.global.world.arena_spawn.race:resize(0)
  df.global.world.arena_spawn.race:insert(0,race_id) --df.global.ui.race_id)

  df.global.world.arena_spawn.caste:resize(0)
  df.global.world.arena_spawn.caste:insert(0,caste_id)

  df.global.world.arena_spawn.creature_cnt:resize(0)
  df.global.world.arena_spawn.creature_cnt:insert(0,0)

  --df.global.world.arena_spawn.equipment.skills:insert(0,99)
  --df.global.world.arena_spawn.equipment.skill_levels:insert(0,0)

  df.global.gametype = 4

  gui.simulateInput(dfhack.gui.getCurViewscreen(), 'D_LOOK_ARENA_CREATURE')
  gui.simulateInput(dfhack.gui.getCurViewscreen(), 'SELECT')

  df.global.gametype = 0

  curViewscreen.child = nil
  dwarfmodeScreen:delete()
  df.global.ui.main.mode = oldMode

  local id = df.global.unit_next_id-1
  return id
end

--local u = df.unit.find(df.global.unit_next_id-1)
--u.civ_id = df.global.ui.civ_id
--u.population_id = df.historical_entity.find(df.global.ui.civ_id).populations[0]
--local group = df.global.ui.group_id

-- Picking a caste or gender at random
function getRandomCasteId(race_id)
  local cr = df.creature_raw.find(race_id)
  local caste_id, casteMax

  casteMax = #cr.caste - 1

  if casteMax > 0 then
    return math.random(0, casteMax)
  end

  return 0
end

local function  allocateNewChunk(hist_entity)
  hist_entity.save_file_id=df.global.unit_chunk_next_id
  df.global.unit_chunk_next_id=df.global.unit_chunk_next_id+1
  hist_entity.next_member_idx=0
  print("allocating chunk:",hist_entity.save_file_id)
end

local function allocateIds(nemesis_record,hist_entity)
  if hist_entity.next_member_idx==100 then
    allocateNewChunk(hist_entity)
  end
  nemesis_record.save_file_id=hist_entity.save_file_id
  nemesis_record.member_idx=hist_entity.next_member_idx
  hist_entity.next_member_idx=hist_entity.next_member_idx+1
end

function createFigure(trgunit,he,he_group)
  local hf=df.historical_figure:new()
  hf.id=df.global.hist_figure_next_id
  hf.race=trgunit.race
  hf.caste=trgunit.caste
  hf.profession = trgunit.profession
  hf.sex = trgunit.sex
  df.global.hist_figure_next_id=df.global.hist_figure_next_id+1
  hf.appeared_year = df.global.cur_year
 
  hf.born_year = trgunit.relations.birth_year
  hf.born_seconds = trgunit.relations.birth_time
  hf.curse_year = trgunit.relations.curse_year
  hf.curse_seconds = trgunit.relations.curse_time
  hf.birth_year_bias = trgunit.relations.birth_year_bias
  hf.birth_time_bias = trgunit.relations.birth_time_bias
  hf.old_year = trgunit.relations.old_year
  hf.old_seconds = trgunit.relations.old_time
  hf.died_year = -1
  hf.died_seconds = -1
  hf.name:assign(trgunit.name)
  hf.civ_id = trgunit.civ_id
  hf.population_id = trgunit.population_id
  hf.breed_id = -1
  hf.unit_id = trgunit.id

  df.global.world.history.figures:insert("#",hf)

  hf.info = df.historical_figure_info:new()
  hf.info.unk_14 = df.historical_figure_info.T_unk_14:new() -- hf state?
  --unk_14.region_id = -1; unk_14.beast_id = -1; unk_14.unk_14 = 0
  hf.info.unk_14.unk_18 = -1; hf.info.unk_14.unk_1c = -1
  -- set values that seem related to state and do event
  --change_state(hf, dfg.ui.site_id, region_pos)


  --lets skip skills for now
  --local skills = df.historical_figure_info.T_skills:new() -- skills snap shot
  -- ...
  -- note that innate skills are automaticaly set by DF
  hf.info.skills = {new=true}


  he.histfig_ids:insert('#', hf.id)
  he.hist_figures:insert('#', hf)
  if he_group then
    he_group.histfig_ids:insert('#', hf.id)
    he_group.hist_figures:insert('#', hf)
    hf.entity_links:insert("#",{new=df.histfig_entity_link_memberst,entity_id=he_group.id,link_strength=100})
  end
  trgunit.flags1.important_historical_figure = true
  trgunit.flags2.important_historical_figure = true
  trgunit.hist_figure_id = hf.id
  trgunit.hist_figure_id2 = hf.id

  hf.entity_links:insert("#",{new=df.histfig_entity_link_memberst,entity_id=trgunit.civ_id,link_strength=100})

  --add entity event
  local hf_event_id=df.global.hist_event_next_id
  df.global.hist_event_next_id=df.global.hist_event_next_id+1
  df.global.world.history.events:insert("#",{new=df.history_event_add_hf_entity_linkst,year=trgunit.relations.birth_year,
  seconds=trgunit.relations.birth_time,id=hf_event_id,civ=hf.civ_id,histfig=hf.id,link_type=0})
  return hf
end

function createNemesis(trgunit,civ_id,group_id)
  local id=df.global.nemesis_next_id
  local nem=df.nemesis_record:new()

  nem.id=id
  nem.unit_id=trgunit.id
  nem.unit=trgunit
  nem.flags:resize(4)
  --not sure about these flags...
  -- [[
  nem.flags[4]=true
  nem.flags[5]=true
  nem.flags[6]=true
  nem.flags[7]=true
  nem.flags[8]=true
  nem.flags[9]=true
  --]]
  --[[for k=4,8 do
      nem.flags[k]=true
  end]]
  nem.unk10=-1
  nem.unk11=-1
  nem.unk12=-1
  df.global.world.nemesis.all:insert("#",nem)
  df.global.nemesis_next_id=id+1
  trgunit.general_refs:insert("#",{new=df.general_ref_is_nemesisst,nemesis_id=id})
  trgunit.flags1.important_historical_figure=true

  nem.save_file_id=-1

  local he=df.historical_entity.find(civ_id)
  he.nemesis_ids:insert("#",id)
  he.nemesis:insert("#",nem)
  local he_group
  if group_id and group_id~=-1 then
      he_group=df.historical_entity.find(group_id)
  end
  if he_group then
      he_group.nemesis_ids:insert("#",id)
      he_group.nemesis:insert("#",nem)
  end
  allocateIds(nem,he)
  nem.figure=createFigure(trgunit,he,he_group)
end

--createNemesis(u, u.civ_id,group)
function createUnitInCiv(race_id, caste_id, civ_id, group_id)
  local uid = createUnit(race_id, caste_id)
  local unit = df.unit.find(uid)
  if ( civ_id ) and civ_id ~= -1 then
    createNemesis(unit, civ_id, group_id)
  end
  return uid
end

function createUnitInFortCiv(race_id, caste_id)
  return createUnitInCiv(race_id, caste_id, df.global.ui.civ_id)
end

function createUnitInFortCivAndGroup(race_id, caste_id)
  return createUnitInCiv(race_id, caste_id, df.global.ui.civ_id, df.global.ui.group_id)
end

function domesticate(uid, group_id)
  local u = df.unit.find(uid)
  group_id = group_id or df.global.ui.group_id
  -- If a friendly animal, make it domesticated.  From Boltgun & Dirst
  local caste=df.creature_raw.find(u.race).caste[u.caste]
  if not(caste.flags.CAN_SPEAK and caste.flags.CAN_LEARN) then
    -- Fix friendly animals (from Boltgun)
    u.flags2.resident = false;
    u.flags3.body_temp_in_range = true;
    u.population_id = -1
    u.status.current_soul.unit_id = u.id

    u.animal.population.region_x = -1
    u.animal.population.region_y = -1
    u.animal.population.unk_28 = -1
    u.animal.population.population_idx = -1
    u.animal.population.depth = -1

    u.counters.soldier_mood_countdown = -1
    u.counters.death_cause = -1

    u.enemy.anon_4 = -1
    u.enemy.anon_5 = -1
    u.enemy.anon_6 = -1

    -- And make them tame (from Dirst)
    u.flags1.tame = true
    u.training_level = 7
  end
end

function wild(uid)
  local u = df.unit.find(uid)
  local caste=df.creature_raw.find(u.race).caste[u.caste]
  if not(caste.flags.CAN_SPEAK and caste.flags.CAN_LEARN) then
    u.animal.population.region_x = 1
    u.animal.population.region_y = 1
    u.animal.population.unk_28 = -1
    u.animal.population.population_idx = 1
    u.animal.population.depth = 0
  end
end

function nameUnit(id, entityRawName, civ_id)
  --pick a random appropriate name
  --choose three random words in the appropriate things
  local unit = df.unit.find(id)
  local entity_raw
  if entityRawName then
    for k,v in ipairs(df.global.world.raws.entities) do
      if v.code == entityRawName then
        entity_raw = v
        break
      end
    end
  else
    local entity = df.historical_entity.find(civ_id)
    entity_raw = entity.entity_raw
  end

  if not entity_raw then
    error('entity raw = nil: ', id, entityRawName, civ_id)
  end

  local translation = entity_raw.translation
  local translationIndex
  for k,v in ipairs(df.global.world.raws.language.translations) do
    if v.name == translation then
      translationIndex = k
      break
    end
  end
  --translation = df.language_translation.find(translation)
  local language_word_table = entity_raw.symbols.symbols1[0] --educated guess
  function randomWord()
    local index = math.random(0, #language_word_table.words[0] - 1)
    return index
  end
  local firstName = randomWord()
  local lastName1 = randomWord()
  local lastName2 = randomWord()
  local name = unit.status.current_soul.name
  name.words[0] = language_word_table.words[0][lastName1]
  name.parts_of_speech[0] = language_word_table.parts[0][lastName1]
  name.words[1] = language_word_table.words[0][lastName2]
  name.parts_of_speech[1] = language_word_table.parts[0][lastName2]
  name.first_name = df.language_word.find(language_word_table.words[0][firstName]).forms[language_word_table.parts[0][firstName]]
  name.has_name = true
  name.language = translationIndex
  name = unit.name
  name.words[0] = language_word_table.words[0][lastName1]
  name.parts_of_speech[0] = language_word_table.parts[0][lastName1]
  name.words[1] = language_word_table.words[0][lastName2]
  name.parts_of_speech[1] = language_word_table.parts[0][lastName2]
  name.first_name = df.language_word.find(language_word_table.words[0][firstName]).forms[language_word_table.parts[0][firstName]]
  name.has_name = true
  name.language = translationIndex
  if unit.hist_figure_id ~= -1 then
    local histfig = df.historical_figure.find(unit.hist_figure_id)
    name = histfig.name
    name.words[0] = language_word_table.words[0][lastName1]
    name.parts_of_speech[0] = language_word_table.parts[0][lastName1]
    name.words[1] = language_word_table.words[0][lastName2]
    name.parts_of_speech[1] = language_word_table.parts[0][lastName2]
    name.first_name = df.language_word.find(language_word_table.words[0][firstName]).forms[language_word_table.parts[0][firstName]]
    name.has_name = true
    name.language = translationIndex
  end
end

validArgs = --[[validArgs or]]utils.invert({
  'help',
  'race',
  'caste',
  'domesticate',
  'civId',
  'groupId',
  'flagSet',
  'flagClear',
  'name',
  'location',
  'age'
})

if moduleMode then
  return
end

local args = utils.processArgs({...}, validArgs)
if args.help then
  print(
[[scripts/modtools/create-unit.lua
arguments:
    -help
        print this help message
    -race raceName
        specify the race of the unit to be created
        examples:
            DWARF
            HUMAN
    -caste casteName
        specify the caste of the unit to be created
        examples:
            MALE
            FEMALE
    -domesticate
        if the unit can't learn or can't speak, then make it a friendly animal
    -civId id
        make the created unit a member of the specified civ (or none if id = -1)
        if id is \\LOCAL, then make it a member of the civ associated with the current fort
        otherwise id must be an integer
    -groupId id
        make the created unit a member of the specified group (or none if id = -1)
        if id is \\LOCAL, then make it a member of the group associated with the current fort
        otherwise id must be an integer
    -name entityRawName
        set the unit's name to be a random name appropriate for the given entity
        examples:
            MOUNTAIN
    -location [ x y z ]
        create the unit at the specified coordinates
    -age howOld
        set the birth date of the unit to the specified number of years ago
    -flagSet [ flag1 flag2 ... ]
        set the specified unit flags in the new unit to true
        flags may be selected from df.unit_flags1, df.unit_flags2, or df.unit_flags3
    -flagClear [ flag1 flag2 ... ]
        set the specified unit flags in the new unit to false
        flags may be selected from df.unit_flags1, df.unit_flags2, or df.unit_flags3
]])
  return
end

local race
local raceIndex
local casteIndex

if not args.race or not args.caste then
  error 'Specfiy a race and caste for the new unit.'
end

--find race
for i,v in ipairs(df.global.world.raws.creatures.all) do
  if v.creature_id == args.race then
    raceIndex = i
    race = v
    break
  end
end

if not race then
  error 'Invalid race.'
end

for i,v in ipairs(race.caste) do
  if v.caste_id == args.caste then
    casteIndex = i
    break
  end
end

if not casteIndex then
  error 'Invalid caste.'
end

local age
if args.age then
  age = tonumber(args.age)
  if not age and not age == 0 then
      error('Invalid age: ' .. args.age)
  end
end

local civ_id
if args.civId == '\\LOCAL' then
  civ_id = df.global.ui.civ_id
elseif args.civId and tonumber(args.civId) then
  civ_id = tonumber(args.civId)
end

local group_id
if args.groupId == '\\LOCAL' then
  group_id = df.global.ui.group_id
elseif args.groupId and tonumber(args.groupId) then
  group_id = tonumber(args.groupId)
end

local unitId = createUnitInCiv(raceIndex, casteIndex, civ_id, group_id)

if args.domesticate then
  domesticate(unitId, group_id)
 else
  wild(unitId)
end

if age or age == 0 then
  local u = df.unit.find(unitId)
  local oldYearDelta = u.relations.old_year - u.relations.birth_year
  u.relations.birth_year = df.global.cur_year - age
  u.relations.old_year = u.relations.birth_year + oldYearDelta
  --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
  u.flags2.calculated_nerves = false
  u.flags2.calculated_bodyparts = false
  u.flags3.body_part_relsize_computed = false
  u.flags3.size_modifier_computed = false
  u.flags3.compute_health = true
  u.flags3.weight_computed = false
  --TODO: if the unit is a child or baby it will still behave like an adult
end

if args.flagSet or args.flagClear then
  local u = df.unit.find(unitId)
  local flagsToSet = {}
  local flagsToClear = {}
  for _,v in ipairs(args.flagSet or {}) do
    flagsToSet[v] = true
  end
  for _,v in ipairs(args.flagClear or {}) do
    flagsToClear[v] = true
  end
  for _,k in ipairs(df.unit_flags1) do
    if flagsToSet[k] then
      u.flags1[k] = true;
    elseif flagsToClear[k] then
      u.flags1[k] = false;
    end
  end
  for _,k in ipairs(df.unit_flags2) do
    if flagsToSet[k] then
      u.flags2[k] = true;
    elseif flagsToClear[k] then
      u.flags2[k] = false;
    end
  end
  for _,k in ipairs(df.unit_flags3) do
    if flagsToSet[k] then
      u.flags3[k] = true;
    elseif flagsToClear[k] then
      u.flags3[k] = false;
    end
  end
end

if args.name then
  nameUnit(unitId, args.name, civ_id)
else
  local unit = df.unit.find(unitId)
  unit.name.has_name = false
  if unit.status.current_soul then
    unit.status.current_soul.name.has_name = false
  end
  --[[if unit.hist_figure_id ~= -1 then
    local histfig = df.historical_figure.find(unit.hist_figure_id)
    histfig.name.has_name = false
  end--]]
end

if civ_id then
  local u = df.unit.find(unitId)
  u.civ_id = civ_id
end

if args.location then
  --local u = df.unit.find(unitId)
  --local pos = df.coord:new()
  --pos.x = tonumber(args.location[1])
  --pos.y = tonumber(args.location[2])
  --pos.z = tonumber(args.location[3])
  --local teleport = dfhack.script_environment('teleport')
  --teleport.teleport(u, pos)
  dfhack.run_command("teleport", "-unit", unitId, "-x", args.location[1], "-y", args.location[2], "-z", args.location[3])
end

--[[if group_id then
  local u = df.unit.find(unitId)
  u.group_id = group_id
end--]]
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: Roses on October 28, 2015, 02:54:02 pm
Yeah, I was fairly certain making something up for the population region would cause the game to freak out and do something weird, but it seemed to work fine, even on save/reload so I guess that the game really just looks to see if the animal belongs to a population outside of the fort.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: expwnent on November 08, 2015, 09:38:32 pm
1. I think the above version didn't make it into r4. It's the most complete version I know of.

2. We will include it in the next version for sure.

3. I will also go back and tinker with it some more. It is probably still unstable.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: lethosor on November 08, 2015, 09:43:20 pm
I added a nickname option to the one included in r4, by the way, so merging that would be good (since spawnunit depends on it).
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: Teneb on November 16, 2015, 11:00:12 am
Since I have very little experience with using DFHack for modding, I wanted to ask how to use this script so the unit is spawned by the use of an interaction and (if at all possible) be part of the group of whomever did the interaction (in case a sieger uses it).

Any answers would be deeply appreciated.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: idgarad on November 16, 2015, 12:49:59 pm
Bug in the latest lazynewb pack. You cannot delete trackstop conditions. Keeps prompting to delete the stop, but not the conditions in the stop. Seems to think it is one menu level higher.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: lethosor on November 16, 2015, 04:19:18 pm
Are you using DFHack r4? That's a known bug in the confirm plugin that's fixed in the next/upcoming release. For now, you can add "confirm disable haul-delete" to the end of dfhack.init.

(Also, that's not related to create-unit, so it should be in the DFHack thread.)
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: Teneb on November 17, 2015, 12:39:55 pm
Since I have very little experience with using DFHack for modding, I wanted to ask how to use this script so the unit is spawned by the use of an interaction and (if at all possible) be part of the group of whomever did the interaction (in case a sieger uses it).

Any answers would be deeply appreciated.
Dug around the scrips and found interaction-trigger exists, so don't need answer on that anymore. That said, is there an option to make the spawned unit be of the same group as the one performing the interaction (if it's not the local group)? A yes or no is enough.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: Dirst on November 17, 2015, 03:54:02 pm
Since I have very little experience with using DFHack for modding, I wanted to ask how to use this script so the unit is spawned by the use of an interaction and (if at all possible) be part of the group of whomever did the interaction (in case a sieger uses it).

Any answers would be deeply appreciated.
Dug around the scrips and found interaction-trigger exists, so don't need answer on that anymore. That said, is there an option to make the spawned unit be of the same group as the one performing the interaction (if it's not the local group)? A yes or no is enough.
IIRC local is the player's civ.  To make it work for anyone you need to get a hold of the actor's civ and group.  That can be done with a script that calls create-unit.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: Teneb on November 18, 2015, 10:53:04 am
Since I have very little experience with using DFHack for modding, I wanted to ask how to use this script so the unit is spawned by the use of an interaction and (if at all possible) be part of the group of whomever did the interaction (in case a sieger uses it).

Any answers would be deeply appreciated.
Dug around the scrips and found interaction-trigger exists, so don't need answer on that anymore. That said, is there an option to make the spawned unit be of the same group as the one performing the interaction (if it's not the local group)? A yes or no is enough.
IIRC local is the player's civ.  To make it work for anyone you need to get a hold of the actor's civ and group.  That can be done with a script that calls create-unit.
Thanks. I'll try poking around to see if I can get the actor's group.
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: FantasticDorf on June 25, 2016, 07:12:33 am
Ressurecting this thread on behalf of asking a well meaning question.

From broadly looking at your github (i've been on github before with other applications modfication/pull-request codebase wise, like yeah ill leave it to the experts for DF code but i can grasp what does what broadly) teleportation does so to the cursor/prefixed place.

Would it be possible to teleport a being inside a container (cage/other) directly from the teleport command solely? As to say to simulate the game crashing effects of teleporting yourself then having someone drink you within a cup or eat you out of a bowl.

As to which, via running a dfhack script, you could via a workshop, spawn a creature then teleport it directly into a cage placed in a particular area adjacent to the workshop (in the same breadth you could just trigger a cage trap in the same configuration to get around it). same goes for objects, if you wished to create a 'sorter' between conveyorbelts if at all relevant, by having a block/workshop autonomously separate and deposit for example by use of teleporting goods around.

Im optimistic and i wont know a answer (or even a resulting question) if i dont ask.   :)
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: Evans on September 15, 2016, 09:49:54 am
create-unit script has some problems.

When I run this to create a different races of animal men for example, every member of another specie is giving the very first name.
for example if I use MOUNTAIN as a name base, and spawn wolf man, hyena man, lion man
each and every one of them will be named Abbey Oltarlikot.

This goes further - if I spawn 3 of each race, the following names will also be identical, so I end up with 1st named Abbey, second Something, third SomethigElse etc etc.

Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: Bogus on September 15, 2016, 10:55:46 am
Quote
Would it be possible to teleport a being inside a container (cage/other) directly from the teleport command solely? As to say to simulate the game crashing effects of teleporting yourself then having someone drink you within a cup or eat you out of a bowl.

As to which, via running a dfhack script, you could via a workshop, spawn a creature then teleport it directly into a cage placed in a particular area adjacent to the workshop (in the same breadth you could just trigger a cage trap in the same configuration to get around it). same goes for objects, if you wished to create a 'sorter' between conveyorbelts if at all relevant, by having a block/workshop autonomously separate and deposit for example by use of teleporting goods around.

should be possible to put things into cages using general refs, however this is not included in the teleport script afaik so you would have to add that functionality manually. creatures may need additional flag setting when being put in cages. as for creatures contained in other items, i dont know.

as for the eating part, i doubt there is code in the game to handle the process beginning with the fact that normal creatures cant be eaten whole at all. altho vermin can, so maybe part of the game logic can be used for it (doubt it tho). either way it would be a lot of work if possible at all.

unsure if i understood the question correctly, but in principle you can write a sorting script that detects items on position or in building A and teleports them to location B or C. using a teleport script you could also make a building that transports items into another building, either instantly or when a certain condition is met (timer, reaction, ...)
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: flyteofheart on September 18, 2016, 01:34:33 am
nvm delete
Title: Re: [DFHack] modtools/create-unit (version 0.4) (beta)
Post by: avnged7fold12 on October 10, 2020, 05:12:39 pm
Idk if this is the place to ask this since there haven't been any messages here in years but was gonna ask if there were still any plans to set up an invasion script with this. Would be something I would like to see