Code Monkey home page Code Monkey logo

df-structures's Introduction

DFHack Readme

Build Status Documentation Status License Discord

DFHack is a Dwarf Fortress memory access library, distributed with scripts and plugins implementing a wide variety of useful functions and tools.

The full documentation is available online here. If you have DFHack installed, it is also accessible as raw text in the hack/docs folder. If you're an end-user, modder, or interested in contributing to DFHack -- go read those docs.

If the docs are unclear or you need more help, please check out our support page for ways to contact the DFHack developers.

df-structures's People

Contributors

20k avatar ab9rf avatar angavrilov avatar atomicchicken avatar benlubar avatar bumber64 avatar cvuchener avatar dscorbett avatar eswald avatar expwnent avatar jjyg avatar lethosor avatar myk002 avatar ncommander avatar patriklundell avatar peterix avatar pre-commit-ci[bot] avatar pronvit avatar putnam3145 avatar quietust avatar ragundo avatar rosarymala avatar sedb-dfh avatar suokko avatar sv-esk avatar tachytaenius avatar thebloke avatar thehologram avatar therahedwig avatar warmist avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

df-structures's Issues

Include README.UPDATE in SYNTAX.rst

...in order to have a complete set of docs built by Sphinx for DFHack.

There are three ways to do this, in order from best-but-hardest to easy-but-ugly:

  1. Migrate content and add formatting.
  2. Format the doc with rst markup, then use a rst .. include: README.UPDATE at the end
  3. Just add a heading, then .. include: README.UPDATE with the :literal: directive.

item_totemst unk_a0, unk_a2, and unk_a4 determine the totem type

unk_a0 appears to be the creature ID, unk_a2 appears to be the side of the body (0 for left, 1 for right) at least for bilateral creatures, and unk_a4 is the specific body part.

unk_a0 matches the mat_index for bonecrafts made of the same animal (so, if a totem has an unk_a0 of 100, that's an albatross-bone totem, same as a mat_type of 22 and mat_index of 100 means an item is made of albatross-bone).

Since "left or right side of the body" doesn't apply to all body plans, there's probably a bit more to unk_a2 than that, but it's consistent for bilaterally-symmetrical creatures, at least.

It appears that mat_type and mat_index are ignored for totems. They're set, initially, from the body part you use to make it (so, mat_index starts out the same as unk_a0), but if you edit them afterward nothing appears to change.

df.world-data.xml:world_region field identification

  • The unk_94 field seems to always contain a value equal to #world_region.region_coords.x, i.e. the number of tiles the region consists of.
  • unk_1e8 seems to actually be two Boolean values: Evil and Good. The field has a value of 1 for Evil regions, 0 for Neutral ones, and 256 for Good ones. World gen hacking showed that goblins refused to spawn (i.e. place their starting site) in formerly Good regions where all world tiles were converted to Evil, but this field was left unchanged at 256. Doing the same but changing the field value to 1 caused them to spawn. Going one step further to set the field to the value of 257 caused goblins to spawn only if the world tiles were also Evil.

Failed investigations:
It can be noted that unk_1e4 seems to have a value of either 0 or 256, but I found no correlation between Savagery and this field, however.

unk_98, unk_9c, and unk_a0 seem to have a value of at most the number of world tiles of the region, but I don't have any good lead on what properties they would track.

df.world.xml:world.unk_59dc4 is probably "available grasses"

The "regions" field is organized in a 7*7 world tile grid centered on the current embark (like the entries in world.populations). Note that I haven't looked at any embark close to the map edge: numbers in various places may be lower there, to account for non existent world tiles.
The "unk1" field is currently described as an array of 294 elements, but these elements are actually grouped into groups of 6, where the first one is the surface, followed by the 3 caverns, the magma sea, and the underworld (the latter 5 organized as in the world.world_data.underworld_regions field). Thus, it can be described as an array of 49 elements each consisting of an array of 6 elements.
the unk1[index].ref field describes the world tile the unk1[index].unk fields belongs to, with the x/y coordinates of the corresponding world tile, the cave_id in the underground regions array (unless surface) and the depth of that cavern. This part has been described previously, and I don't have any new insight here.
The unk1[index].unk field is a list of grass types available for ground cover on that world tile and that cavern (or surface) level. The field could e.g. be called grass_index, or something like that (The indices are the ones in world.raws.plants.all). The odd part is that muddy caverns get empty lists, despite sporting both cave moss and floor fungus just like the Underground Water biome cavern which does list those.

I've run a script over the list to check that all references present are to plants whose flags.GRASS value is true. When printing all entries that weren't grasses it came up empty, which matches the impression of printing the complete list and looking at it manually.

I have previously performed experiments where I've embarked on locations having only bubble bulb as ground cover and then tried to add an additional grass type legal to the region to the region's population list as well as inserting this new entry into the world.populations list at to no effect. I've also replaced bubble bulb with dallisgrass (legal) and manipulated the world.populations list to refers to dallisgrass without effect.
However, by embarking with only bubble bulb as a legal grass type and then adding dallisgrass to the world.unk_59dc4.unk[144].unk list using DFHack the embark started getting both bubble bulb and dallisgrass as ground cover on tiles the embarkees were ordered to channel out (to get bare tiles DF could cover).

Looking into unk_v40_1a and b

Both vectors are a full list of the professions in the game, each list item having none to several numbers attached.

1a assigns most professions a single value which jives with the skill token listing. One example is the bowyer coming in at number 49, right past siege engineers (47) and operators (48). Umbrella professions like metalsmith and woodworker don't have their own number, but instead contain all the identifiers of their sub-professions. For instance, woodworkers have 2 (carpenter), 1 (woodcutter) and 49 (bowyer) in that order.
On the surface it seems just like a big list of which skill means which profession and what umbrella term gets used when skills x, y and z are all present. Of course, the fact that this only went in with version 0.40 suggests that it's got more to do with the living history feature than everyday practice.

1b is weirder. The list format is the same, but most civilian professions are blank. The only values are located in the following list items, with all the values listed in order:

  • rangers and hunters (44, 105)
  • doctors, diagnosers, bone setters, suturers and surgeons (59)
  • hammer/spear/axe/swords-/mace/whipmen (105, 45, 46, 88, 116, 89)
  • blowgun/bow/crossbow/pikemen (105, 46, 88, 116, 89)
  • wrestlers (105, 88, 116, 89)

Translated into human language, hunters have CROSSBOW and DODGING, medical professions all get WOUND_DRESSING and nothing more (notable since the distinct wound dresser profession isn't listed at all!), melee fighters aside from pikemen get DODGING, SHIELD, ARMOR, DISCIPLINE, CLIMBING and SITUATIONAL_AWARENESS, archers and pikemen have all the above except for SHIELD and wrestlers lose ARMOR as well.
This seems like it lists all the secondary skills that don't really have a job title as such, but are intimately connected to the profession and would go up as well during their simulated careers.

Manually mangling these lists at any point from in-game to just before worldgen doesn't seem to do anything, not in gameplay or in during history generation. What exactly is looking at these lists?

viewscreen_choose_start_sitest.site_* inconsistent

DFHack usually crashes when attempting to access the contents of site_abandoned or site_created, although in some cases these pointers are null. (This could be due to DF failing to initialize these pointers properly, as the crash doesn't seem to depend on the currently-loaded world.)

Bitfields cannot be used inside unions

Bitfields cannot be used inside unions because they have non-trivial default constructors. This necessitates the use of int32_t in a few places a bitfield would be preferable (see 22819e2). The default constructor, generated by Bitfield.pm, looks like foo(int32_t whole_ = 0) : whole(whole_) {};. This allows constructing a bitfield with some flags set.

I propose that the non-trivial constructor be removed. The compiler-synthesized constructor will set all the flags to 0. The convenience of bitfields in unions outweighs the inconvenience of not having the current constructor, especially for Lua.

A quick check indicates that the one-argument form is not even used (except with 0, which is unnecessary), so this change would not break anything:

$ gawk 'match($0, /<bitfield(-type)? .*name=.(\w*)/, a) { print "\\<" (a[1] ? "" : "T_") a[2] " *\\(\\w\\+ *\\)\\?(" }' df-structures/df.*.xml | grep -f - -r dfhack
dfhack/library/include/modules/MapCache.h:    df::tile_designation DesignationAt(df::coord2d p)
dfhack/library/include/modules/MapCache.h:    df::tile_occupancy OccupancyAt(df::coord2d p)
dfhack/library/include/modules/MapCache.h:    df::tile_designation designationAt (DFCoord tilecoord)
dfhack/library/include/modules/MapCache.h:        return b ? b->DesignationAt(tilecoord) : df::tile_designation(0);
dfhack/library/include/modules/MapCache.h:    df::tile_occupancy occupancyAt (DFCoord tilecoord)
dfhack/library/include/modules/MapCache.h:        return b ? b->OccupancyAt(tilecoord) : df::tile_occupancy(0);
dfhack/library/modules/Gui.cpp:    df::announcement_flags mode(0);
dfhack/library/modules/Gui.cpp:    df::announcement_flags mode(0);
dfhack/library/modules/Gui.cpp:    df::announcement_flags flags(0);
dfhack/library/modules/Maps.cpp:    df::tile_designation dsgn(0);
dfhack/plugins/burrows.cpp:    df::tile_designation mask(0);
dfhack/plugins/burrows.cpp:    df::tile_designation value(0);
dfhack/plugins/workflow.cpp:    df::dfhack_material_category mat_mask(0);
dfhack/plugins/workflow.cpp:    df::dfhack_material_category mat_mask(0);

On the organization of df.world_data.xml:world_data.feature_map

I believe this structure to be a two dimensional array ceiling (map_width/16) * ceiling (map_height/16). However, these top level elements seem to be allocated only when needed, i.e. the pointers to the cells may be null pointers, leading to DF crashing when trying to access them. Once allocated the cells seem to be retained, however for the rest of the game session.
The allocation of a cell does not mean the contents is allocated, though, only that the top structure is. The
'features' element is frequently a null pointer which doesn't get allocated until it's needed, i.e. when one of the world tiles in the cell needs to have its feature data defined.
Once the features structure is allocated it still isn't complete, as the 'feature_init' 16*16 matrix over the world map tiles of the cell only populates the feature lists of the world tiles it needs data for, with the other tiles having zero length lists. Again, once a list has been populated during the current session it remains populated.

If verified, it would be useful to have the structure and its probable state of incompleteness being documented in a legible fashion in the XML file (The explanation of the world_region_details.edges field is a precedence of a larger description in the same file).

Conversation structures research

This was all done in 0.42.06.

In ui_advmode.T_conversation:

  • unk4: current page, starting at 0
  • unk5: vector of the first indices on each page
  • unk6: vector of the last indices on each page

For example, given 38 talk choices on 4 pages, unk5 might be [0, 12, 24, 37] and unk6 might be [11, 23, 36, 37], and unk4 would be in the range 0 to 3.

In ui_advmode.T_conversation.T_targets:

  • unk_8: the conversation type
    • 0: Talk to the figure identified by unit_id and histfig_id.
    • 3: Shout out to everybody.
    • 4: Begin a performance.

In activity_event_conversationst:

  • anon_1: vector of participants (see below). The first participant in the vector started the conversation.
  • unk1: what event is the topic of this turn, if any
  • anon_2: which menu and prompt to show next
    • 0: Respond to greeting/Ignore/Impersonate
    • 1: main menu
    • 2: incident or rumor menu: "What will you say about the trouble?"
    • 3: "What will you say about the incident?"
    • 4: "What will you say about the trouble?"
    • 5: "What will you say about the incident?"
    • 6: Ask for whereabouts of a person or state opinion.
    • 7: Respond to a goodbye.
    • 8: crash
    • 9: Deny sleep permission
    • 10: Ask listener to join you
    • 11: Respond to join request
    • 12: "What will you say about the rescue?"
    • 13: "What will you say about the agreement?"
    • 14: "What will you say about the trade?"
    • 15: "What will you say about the surrounding area?"
    • 16: "How will you respond to the accusation?"
    • 17: "How will you respond about your profession?"
    • 18: "What will you say about your family?"
    • 19: "How will you respond to the request to cease hostilities?"
    • 20: "How will you respond to the demand to yield?"
    • 21: "What will you say about the trouble?"
    • 22: "What will you say about the trouble?"
    • 23: Ask for directions
    • 24: "How will you respond to the request for directions?"
    • 25: "How will you respond to the request for directions?"
    • 26: "How will you respond to the request for a guide?"
    • 27: "How will you respond to the request for a guide?"
    • 28: "Where do you want to go?"
    • 29: "What will you say about the structure?"
    • 30: demand menu
    • 31: ?
    • 32: Respond to request for something
    • 33: Respond to request for something else
    • 34: Initiate bartering
    • 35: Respond to request for what to do as a hearthperson, e.g. "enjoy these times of peace"
    • 36: ?
    • 37: "What will you say about the journey?"
    • 38: "What will you say about the group?"
    • 39: "What will you say about the conflict?"
    • 40: "What will you say about the site?"
    • 41: Agree/refuse to comply with demand
    • 42: ignorance/refuse to comply
    • 43: Respond to demand for tribute
    • 44: Respond to offer of tribute
    • 45: Give opinion on trade cancellation
    • 46: Respond to offer of peace
    • 47: Give opinion on conclusion of agreement
    • 48: Respond to adoption request
    • 49: ?
    • 50: Give opinion on something
    • 51: Respond to position offer
    • 52: "How will you respond to the invocation?"
    • 53: ?
    • 54: "About whom do you ask?"
    • 55: "How will you respond to the request for information?"
    • 56: "What will you say about how you are feeling?"
    • 57: "What will you say about services?" with option to deny working here
    • 58: "What will you say about services?" without that option
    • 59: crash
    • 60: "How will you respond?" – Respond to join request
    • 61: ?
    • 62: ?
    • 63: state opinion
    • 64: state opinion
    • 65: Say something general about your emotional state or thoughts
    • 66: State the value/worthlessness/nuances of value_type
    • 67: "How will you respond to this statement of values?"
    • 68: "How will you respond to this passive reply?"
    • 69: "How will you respond to this flattery?"
    • 70: "How will you respond to this dismissal?"
    • 71: ?
    • 72: ?
    • out of range: goodbye menu
  • anon_4: current topic
    • the historical_figure ID of a beast after asking its whereabouts
    • the world_site ID of a site after asking directions to it
    • a trouble type (see below) after asking about troubles
    • the historical_entity ID of an entity after asking about the local ruler
    • the number 294 after someone said they were "out for some water"; 748: tavern
    • a value_type when discussing values
  • anon_5: more information about the current topic
    • value strength when discussing values
  • anon_6: more information about the current topic
    • the other participant’s value strength when discussing values?
  • anon_9: vector of conversation turns (see below)
  • unk_80_unit: unit ID of whosever turn it is to speak, or -1 if no one’s turn, in which case a (random?) participant will speak next
  • anon_10: historical_figure ID of the unit given by unk_80_unit
  • anon_11: number of instants since the last turn
  • anon_12: a bitfield
    • 2: Use the string "Continue shouting" instead of listing all the non-adventurer participants.
  • anon_13: copy of anon_2
  • anon_14anon_23: copy of unk1
  • anon_24: copy of anon_3

In activity_event_conversationst.T_anon_1 (participant):

  • anon_1: unit ID of participant
  • anon_2: HF ID of participant

In activity_event_conversationst.T_anon_9 (turn):

  • anon_1: speaker unit ID
  • anon_2: speaker HF ID
  • anon_3: the talk_choice_type of the turn
  • anon_4: the entity_event in question, if applicable, else garbage
  • anon_6: foreground color of report text
  • anon_7: background color
  • anon_8: brightness
  • anon_9: year the turn happened
  • anon_10: when the turn happened, in instants
  • anon_11anon_13 + unk_v4014_1: copies of anon_2anon_5 from the talk_choice that was chosen for this turn

The meanings of the fields in a talk_choice depend on its type.

  • anon_2:
    • StateOpinion: opinion
      • 0: State opinion that it must be stopped with violent force
      • 1: State opinion that it is not your problem
      • 2: State opinion that it was inevitable
      • 3: State opinion that this is the life for you
      • 4: State opinion that it is terrifying
      • 5: State that you don't know anything about it
      • 6: State that you are right in all matters
      • 7: State that it is for the best
      • 8: State that you don't care
      • 9: State your general hatred
      • 10: State your general fear
      • 11: State opinion that it is sad but not unexpected
      • 12: State opinion that it is terrible
      • 13: State that it is terrific
      • 14: State that you enjoyed performing
      • 15: State that it was legendary
      • 16: State that it was fantastic
      • 17: State that it was great
      • 18: State that it was good
      • 19: State that it was okay
      • 20: Agree completely
      • 21: State that this is fantastic
      • 22: State that this is great
      • 23: State that this is good
      • 24: State that this is okay
      • 25: State that this is no good
      • 26: State that this is your favorite dance
      • 27: State that this is your favorite music (TODO: flag for melody vs. accompaniment)
      • 28: State that this is your favorite poetry
      • 29: State that you love reflective poetry
      • 30: State that you hate reflective poetry
      • 31: State that you love riddles
      • 32: State that you hate riddles
      • 33: State that you are embarrassed by this kind of humor
      • 34: State your amusement
      • 35: State that you love raunchy poems
      • 36: State that you love ribald poems
      • 37: State that you disapprove of ribald poems
      • 38: State that you love light poems
      • 39: State that you hate light poems
      • 40: State that you love solemn poems
      • 41: State that you hate solemn poems
      • 42: State that listener's hunt saved you from an enemy (legendary/mighty)
      • 43: State that listener's hunt saved you from an enemy (magnificent/fearsome)
      • 44: State that listener's hunt saved you from an enemy (great/dangerous)
      • 45: State that listener's hunt saved you from an enemy (worthy/)
      • 46: State that listener's hunt saved you from an enemy (/nuisance)
      • 47: State that listener had a good hunt (legendary)
      • 48: State that listener had a good hunt (magnificent)
      • 49: State that listener had a good hunt (great)
      • 50: State that listener had a good hunt (worthy)
      • 51: State that listener had a good hunt (hunter's work)
      • 52: State that listener saved you from an enemy (mighty)
      • 53: State that listener saved you from an enemy (fearsome)
      • 54: State that listener saved you from an enemy (dangerous)
      • 55: State that listener saved you from an enemy ()
      • 56: State that listener saved you from an enemy (nuisance)
      • 57: State that they are outlaws
      • 58: State that listener protected the defenseless from outlaws
    • respond to invitation to insurrection (27), RespondJoin, RespondJoin2, respond to something else (112), respond to invitation to entertain (181): invitation response:
      • -1: "I would... rather not."
      • 0: "Hey... that sounds like a great idea!"
      • 1: "Surely any place is better than this. Let's set off immediately!"
      • 2: "I've always wanted to travel the world. Let us be off!"
      • 3: "Excitement! Adventure! I am thrilled to join you."
      • 4: "I will agree to travel with you if you lead me to glory and death."
      • 5: "I'm sorry. My duty is here."
      • 6: "It is I that would lead you, but I have no need of your protection."
      • 7: "Ha! Such enthusiasm from one such as yourself."
      • 8: "With a band so large, what share of the glory would I have?"
      • 9: "Take me away from here."
      • 10: ditto
      • 11: "I'm sorry. I can't go with you."
      • 12: "I have no interest in your objectives."
      • 13: "Let us leave as soon as possible."
      • 14: "This is a cause worthy of struggle."
      • 15: "Keep practicing!"
      • 16: "Maybe after you've improved. Prove you have what it takes. The life of the traveling performer is a hard one."
      • 17: "Can you manage a troupe so large?"
      • 18: "That's such a fantastic idea. I can't wait to be off!"
      • 19: "It's such a noble pursuit. Let's go immediately!"
      • 20: "It would be so great to perform and make people happy."
      • 21: "I so love the performing arts. It's time to go!"
      • 22: "I'd love to travel and create art."
      • 23: "The performing arts are so important. Let's go!"
      • 24: "Let's spread the joy!"
      • 25: "The performances will be great."
      • 26: "A demonstration of your skill might convince me."
    • SuggestTravel, AskDirectionsPlace, RequestGuide, ProvideDirections: world_site ID of destination
    • SuggestTalk, StateUnitLocation, AskWhereabouts, RequestGuide2, ProvideWhereabouts, TellTargetDead, RecommendGuide, SummarizeViews, ExpressAstonishment, ask about someone (170), respond to question about someone (171): historical_figure ID
    • HawkWares, AskLocationObject, DemandDropWeapon: item ID
    • ExpressOverwhelmingEmotion, ExpressGreatEmotion, ExpressEmotion, ExpressMinorEmotion, ExpressLackEmotion: emotion_type
    • AskAboutIncident: trouble type (see below)
    • CancelAgreement: agreement ID
    • SummarizeConflict: activity_entry ID
    • DemandTribute, OfferGiveTribute, CancelTribute, OfferPeace, OfferService: historical_entity ID of the first entity (tributary)
    • AskAboutIncident: whether the trouble should be singular (≤1) or plural (>1) for troubles that have both forms, e.g. "army"/"armies"
    • order drink (176): index of the drink in the list of available drinks
    • ask to join an existing troupe (182), invite to join a troupe (184), kick out of troupe (188), leave troupe (190): historical_entity ID of the troupe
    • leave group (190): historical_entity ID of the group to leave
    • state values (198), argue values (201), acquiesce (205): value_type
    • give directions to building (200): the index of the building in the world_site’s buildings
    • ask for work for group (211): historical_entity ID of the prospective employee
    • give order (216): squad_order_type (only DRIVE_ENTITY_OFF_SITE and kill (7) seem to work)
  • anon_3:
    • StateOpinion, ExpressOverwhelmingEmotion, ExpressGreatEmotion, ExpressEmotion, ExpressMinorEmotion, ExpressLackEmotion: unit_thought_type
    • DemandTribute, OfferGiveTribute, CancelTribute, OfferPeace: historical_entity ID of the second entity (receiver of tribute)
    • StateUnitLocation, give directions to building (200): world_site ID
    • InvokeNameBanish, InvokeNameService: identity ID
    • state values (198), argue values (201), acquiesce (205): value strength (very negative = worthlessness; around 0 = nuances; very positive = value)
    • ask for work for oneself (210), ask for work for group (211): historical_entity ID of prospective employer
    • give order (216): It depends on anon_2:
      • DRIVE_ENTITY_OFF_SITE: -1
      • kill (7): historical_figure ID
  • anon_4:
    • StateOpinion, ExpressOverwhelmingEmotion, ExpressGreatEmotion, ExpressEmotion, ExpressMinorEmotion, ExpressLackEmotion: It depends on anon_3:
      • UnexpectedDeath, Death, LoveSeparated, LoveReunited, NewRomance, MadeFriend, FormedGrudge, Prayer: historical_figure ID
      • Kill: incident ID of an incident with a valid killer_hfid
      • MadeArtifact: artifact_record ID
      • MasterSkill, LearnSkill, TeachSkill, ImproveSkill: job_skill ID
      • Complained, ReceivedComplaint, UnableComplain: complaint:
        • 25: "I brought up the lack of jobs in a meeting."
        • 26: "I made a suggestion about work allocations in a meeting."
        • 27: "I requested that more weapons be produced in a meeting."
        • 28: "I yelled at somebody in charge."
        • 29: "I cried on somebody in charge."
      • AdmireBuilding, AdmireOwnBuilding, AdmireArrangedBuilding, AdmireOwnArrangedBuilding: building_type ID
      • GhostNightmare, GhostHaunt, SpouseGaveBirth, Talked, Decay: unit_relationship_type
        • Note that SpouseGaveBirth can produce "I got married.", "I have a new sibling.", or "I have become a parent." A better name would be NewFamilyMember.
      • RoomPretension: unit_demand.T_place
      • AnnoyedVermin, NearVermin, PesteredVermin, NearCaged, NearCaged2: creature_raw index
      • AttackedByDead: histfig_relationship_type
      • GaveBirth: -1=child, 0=girl, 1=boy
        • This is the same pattern as historical_figure.sex, unit.sex, item_body_component.sex, and caste_raw.gender. Perhaps an enum should be defined and referred to by all of them.
      • NeedsUnfulfilled: need_type
      • ResearchBreakthrough, ResearchStalled, PonderTopic, DiscussTopic, LearnTopic, TeachTopic: an integer in [0, 13], equivalent to knowledge_scholar_category_flag.flags
      • Syndrome: syndrome ID
      • LearnBook, ReadBook, WroteBook: written_content ID
      • LearnInteraction: interaction ID
      • LearnPoetry: poetic_form ID
      • LearnMusic: musical_form ID
      • LearnDance: dance_form ID
      • BecomeResident, DenyResident: world_site ID
      • BecomeCitizen, DenyCitizen: historical_entity ID of site government
      • PlayToy: itemdef_toyst ID
      • Argument: historical_figure ID of the other arguer
      • RealizeValue: value_type
      • simulated musical instrument (220), played musical instrument (221): itemdef_instrumentst ID
    • CancelAgreement: reason for cancellation?
      • 13: "We can no longer travel together."
      • 52: "We haven't performed for some time. We were going to entertain the world! It's a shame, but I'll have to make my own way now."
    • ask for work for oneself (210), ask for work for group (211), grant work request: occupation_type
    • give order (216): It depends on anon_2:
      • DRIVE_ENTITY_OFF_SITE: world_site ID
      • kill (7): -1
  • anon_5:
    • StateOpinion: It depends on anon_3:
      • OfficeQuality: quality of the setting:
        • 1: good
        • 2: very good
        • 3: great
        • 4: fantastic
        • 5: worthy of legends
      • NeedsUnfulfilled: It depends on anon_4:
        • PrayOrMedidate: historical_entity ID to pray to, or -1 for meditation
      • ResearchBreakthrough, ResearchStalled, PonderTopic, DiscussTopic, LearnTopic, TeachTopic: an integer in [0, 31], equivalent to log2 of the knowledge_scholar_category_flag.category in the bitfield identified by anon_4
      • WearItem: item_quality
    • ExpressOverwhelmingEmotion, ExpressGreatEmotion, ExpressEmotion, ExpressMinorEmotion, ExpressLackEmotion: It depends on anon_3:
      • GhostHaunt: haunting type
        • 0: haunted
        • 1: tormented
        • 2: possessed
        • 3: tortured
      • GaveBirth, SpouseGaveBirth: how many new family members
        • GaveBirth: not in range 1–15 is "many babies"
        • SpouseGaveBirth: ≤1 is singular, >1 is plural; applies to new sibling(s) only
      • RealizeValue: value strength
    • give order (216): It depends on anon_2:
      • DRIVE_ENTITY_OFF_SITE: historical_entity ID
      • kill (7): -1

A trouble type is an enum:

  • 0: deaths
  • 1: law-breaking
  • 2: the fighting
  • 3: armies on the march
  • 4: abductions
  • 5: occupations
  • 6: beasts
  • 7: criminals
  • 8: bandits
  • 9: skulking vermin
  • 10: bone-chilling horror
  • 11: ruffians
  • 12: open war
  • 13: brewing trouble with our neighbors

Meanings for anonymous talk_choice_type values:

  • 27: respond to proposal of insurrection
  • 28: "I'm with you on this."; respond to proposal of rescue? (TODO: unattested)
  • 44: "Thank you!" (as a response to "Come with me and I'll bring you to safety.")
  • 104: Claim this site for yourself (group naming menu)
  • 112: respond to some kind of proposal; I’m not sure what
  • 169: Ask about somebody (new menu)
  • 170: ask about somebody
  • 171: give information about somebody
  • 172: "How are you feeling right now?"
  • 173: Say something general about your emotional state or thoughts
  • 174: Ask about available services, drinks, rooms, etc.
  • 175: List available services ("We have many drinks to choose from." / "This is not that kind of establishment.")
  • 176: Order drink
  • 177: Rent room
  • 178: Extend room rental
  • 179: Confirm service order ("I'll be back with your drink in a moment." / "Your room is up the stairs, the first door on your right." / "You'll have the room for another day. I'm glad you're enjoying your stay.")
  • 180: Ask listener to join you as entertainer
  • 181: Respond to join request (entertainer)
  • 182: ask to join an existing troupe
  • 183: "I am confused." (probably a fallback message)
  • 184: Refuse request to join your troupe
  • 185: Invite listener to join troupe
  • 186: Accept invitation to join troupe
  • 187: Refuse invitation to join troupe
  • 188: Kick listener out of troupe
  • 189: Create a performance troupe together (group naming menu)
  • 190: leave troupe
  • 191: "Tavern keeper! Uh... nevermind." (TODO)
  • 192: "Please be patient. I'll have your order ready in a moment."
  • 193: "We don't offer any specific services here."
  • 194: "Yes, I can serve you when we're both there."
  • 195: "I don't work here."
  • 196: Express your emotions (new menu)
  • 197: State your values (new menu)
  • 198: state value/worthlessness/nuances
  • 199: try to trade or settle debts when you don’t owe anything
  • 200: Give directions to building
  • 201: Argue
  • 202: Flatter the listener
  • 203: Dismiss the listener's argument
  • 204: Respond passively
  • 205: Acquiesce (changes your values)
  • 206: Deride flattery
  • 207: Express outrage over dismissal
  • 208: Press the argument
  • 209: Agree to drop the argument
  • 210: ask for work for oneself
  • 211: ask for work for a group
  • 212: Grant listener work (one person)
  • 213: Refuse listener work (one person)
  • 214: Grant listener work (a group)
  • 215: Refuse listener work (a group)
  • 216: Give order

Meanings for anonymous squad_order_type values:

  • 7: kill historical figure
  • 8: drive armies off site

world_site_type changes

Reported on IRC

Is there a reason for the differing names for world_site_type values between df and dfhack? For example MountainHalls is exported as "fortress", Fortress as "tower"
comparing a world_sites_and_pops.txt from export with dfhack data highlights the differences
like df.global.world.world_data.sites[61].type

df.world_data.xml world_geo_layer.vein_unk_38 is probably abundance

The current comment 'density??' does not seem correct, as the same material can have different values in different layers.
My guess after looking at the info is that it's some kind of "random" number to guide the amount of the material generated. I looked at a random embark that, unfortunately, ended up having two biomes rather than one (my layer examination looks only at the biome of the embark world tile).
4 small cluster gem types were found in the same layer of the 3*3 embark's geo biome and 'prospect all' was used to get the actual count.
Name vein_unk_38 actual count
Smoky Quartz; 23; 346
Green Tourmaline; 56; 608
Clear Zircon; 26; 369
Opal Redflash; 73; 955
A guess is that the number roughly controls the number of clusters/veins and that random development of those yield the exact numbers. The lowest number I've seen was 3 and the highest was 100, so a further guess is that it's a percentage.

EnumItem feature_underworld_from_layer should be underworld_from_layer

enum feature_type : int32_t 
{

        outdoor_river,
        cave,
        pit,
        magma_pool,
        volcano,
        deep_special_tube,
        deep_surface_portal,
        subterranean_from_layer,
        magma_core_from_layer,
        feature_underworld_from_layer
      };

The word "feature" in feature_underworld_from_layer is redundant and should be removed, as is in all the others values of this enum.

This complicates the automatic deduction of the subclass name using this enum:
enum name -> class_name
outdoor_river -> feature_outdoor_river: OK
feature_underworld_from_layer -> feature_feature_underworld_from_layer: WRONG

Typo error

Small one in df.world-site.xml line 752
It says soor_e_elevation when it should be door_e_elevation

df.entities.xml:historical_entity.unknown2.unk14 and .unk.15 probably reversed

Printing the values of these pointers as well as the values of the world_region and world_landmass entries referenced by the world tile of the site resulted in an exact match of the pointers when reversed. Thus, the types of these fields should probably be reversed.

Edit: The results above are valid for civ entities. For site governments these fields are used for something completely different, as unk14 was displayed as nil (=0) and unk15 had various very low "pointer" values (2, 77, 79) that were still usually too large to be region or landmass indices for the test world.

ui_advmode research

Migrated from DFHack/dfhack#942

df.global.ui_advmode.anon_9
This is initially equal to df.global.cur_year_tick_advmode and they both increase at the same rate. However, it does not seem to update when sleeping and fast-travelling, resulting in a value which differs from df.global.cur_year_tick_advmode

df.global.ui_advmode.anon_50
Hours of sleep. This value is updated whenever the player changes the number of hours to be slept when viewing the sleep menu.

df.global.ui_advmode.anon_56
Is usually set to 0
Is set to 2 when the adventurer unit is unconscious/falling
Setting it to 0 when the adventurer is unconscious allows the player to move the adventurer, but it is immediately set to 2 again if the unit is still unconscious
Hence, it seems that this is what prevents a player from controlling the adventurer when such a status effect is in play.

df.global.ui_advmode.anon_59
df.global.ui_advmode.anon_60
df.global.ui_advmode.anon_61

anon_59 is an x coordinate, anon_60 is y, anon_61 is z
These coordinates appear to be set when the adventurer becomes a projectile via jumping/falling; they are the coordinates where the flight trajectory ends (not necessarily the chosen target coordinates when jumping).

df.global.ui_advmode.anon_15
df.global.ui_advmode.anon_16
df.global.ui_advmode.anon_17

anon_15 appears to contain a list of x coordinates
anon_16 appears to contain a list of y coordinates
anon_17 appears to contain a list of z coordinates
(values in each list are initially set to -1000000)
Each entry is likely combined with its equivalents in the other anons, but the overall function remains unknown.

df.global.ui_advmode.anon2
df.global.ui_advmode.anon3

and
df.global.ui_advmode.unk23
df.global.ui_advmode.unk24

The above two pairs appear to be linked with the adventurer’s position on the map, though I’m not yet sure about the specifics. The values appear to be updated only when the map is reloaded, or when the adventurer enters travel mode.

df.global.ui_advmode.menu = 30
The “select target” screen for interactions

The following are set when the adventurer loads the interaction target selection screen:

df.global.ui_advmode.unk_1e8
Used when the interaction is a “natural ability” (otherwise, it is set to -1)
Relates to the interaction's index in the adventurer's unit.curse.own_interaction

df.global.ui_advmode.unk_1ec
Used for acquired interactions (otherwise set to -1)
This relates to the interaction as shown below: df.interaction.find(df.global.world.raws.effects.interactions[df.global.ui_advmode.unk_1ec])

df.global.ui_advmode.unk_f4
The maximum number of targets for the interaction

df.global.ui_advmode.unk_f8
The maximum range of the interaction

df.global.ui_advmode.unk_fc
Possibly relates to the interaction target type?
For example, changing it to “4” made “disturber only” show up on the target selection screen.
“2” = adjacent only , “6” = adjacent only, disturber only
However, higher values seem to be repetitions, so I am uncertain about this.

df.global.ui_advmode.unk_1e4
df.global.ui_advmode.unk_f0
df.global.ui_advmode.unk_200

Unknown function, but changing their value crashes the game upon attempting to view the interaction screen.
unk_f0 and unk_200 appear to be reset to 0 once the interaction is carried out

df.global.ui_advmode.unk37
df.global.ui_advmode.unk38

Contain userdata which seems to be created upon when the interaction target selection screen is loaded. Deleting the userdata in unk38 causes any available target choices to disappear. Moving the cursor causes it to reappear, with userdata being generated again. Userdata in unk37 does not seem to regenerate.

df.world.xml:worldgen_status field have misleading names

As far as I've seen by using callbacks on each frame during world gen the fields placed_caves, placed_good_evil, placed_megabeasts, placed_other_beasts, made_cave_pops, made_cave_civs, and placed_civs are all set when the corresponding placement phase starts, not when it's finished. Thus, when placed_civs is set you can then see the site list being populated and sites starting to appear on the map.
The setting of these flags also coincides with DF displaying similar messages about commencing those tasks.

Edit: The fields 'width' and 'height' seem to be misleading as well. As far as I can see they are actually world map cursor position x and y respectively. When world gen was paused, these fields matched the position of the cursor, and changing the value of these fields moved the cursor.

Edit2: The fields anon_28 and anon_29 seems to be the number of civilizations and the number of civilizations left to place. These fields are probably valid only during the civ placement phase, with anon_28 having a value of -1 at the start of the phase.

New global - the type of building being linked to a lever/pressure plate

I seem to have found a new global, it's a one byte value immediately following ui_workshop_in_add and specifies the type of building being linked to a lever/pressure plate. Interesting thing is that it takes not values from building_type, but character code of a key you use to initiate linkage, e.g. b for bridge, ... , T for track stop. It's set to 0xff when not in the linkage mode.

EDIT: Also it's set to t when choosing a mechanism for the target, and to l when choosing a mechanism for the lever/pressure plate (with ui_building_assign_items holding the list of choices).

Since globals need to be updated manually for new DF versions, what's the procedure of adding a new one?

Prepared meal FISH ingredients are weird.

Prepared meal ingredients made from FISH items do not work as expected. It seems like the material type field is a caste number and the material index field is the creature index. Reversing the fields (putting the type in the index field and the index in the type field) also works, but I think that is because a creature material type is the same as its creature index?

Would it be possible that these fields are unions or something?

Are there any other item types that cause this behaviour?

df.interaction.xml: A couple of observations of anonymous fields

interaction_target_materialst.anon_1 and anon_2 is probably the mat info reference:

In the fortress I look at, all the evil rain interactions have interaction_target_materialst.anon_1 = 44 and anon_2 = creature index of .material_str [1] (e.g. 572 for dwarf), and feeding this into dfhack.matinfo.decode (.interaction_target_materialst.anon_1, .anon_2) returns dwarf/elf/goblin/human blood. The "INDEX025" value of .material_str [2] matches up with df.global.world.raws.creatures.all [572].material [25] which refers to dwarf blood.

interaction_effect.anon_3 seems to match the index of the parent interaction.

Edit: Modified the above to try to make it clearer that .interaction_target_materialst.anon_1 is referenced rather than .anon_1.

df.entities field claims.unk2 is probably the area border

I looked at the area claimed by a dwarven civ using Legends Mode, and the coordinates in the unk2 structure traced out the border of the claimed region when I compared the data. It's a single case though, but might serve as a starting point for further examination.

df.world-data.xml:world_river elements unk_8c and unk_9c are probably flow and exit tile

As far as I could see an unk_8c value of 0 corresponds to the pre embark region to calling the river a 'brook', while it changes to 'stream' for larger values. It also seems the values are increasing the further down the course you get. As a speculation, that value ought to correspond to the width, but I haven't investigated that. Edit: Hacking the values and then moving to the region to embark did NOT change the 'brook' designation, nor did an embark show any changed brook width.

unk_9c seems to match the region exit tile of the river. The edge on which tile this exit occurs is given by the side on which the world coordinates for the next segment is located. Edit: Hacking those values did change where exits appeared as expected.

Edit 2: A new attempt with unk_8c showed it is related to width, but I had used to small values previously. Width (2 m tiles); "flow"
4: <= 3478
5: 3579
6: 4348
7: 5218
8: 6087
9: 6957
10: 7827
11: 8696
12: 9566
13: 10435
14: 11305
15: 12174
16: 13044
17: 13914
18: 14783
19: 15653
20: 16522
21: 17392
22: 18261
23: 19131
24: 20000
25: 20870
26: 21740
27: 22609
28: 23479
29: 24348
30: 25218
31: 26087
32: 26957
33: 27827
34: 28696
35: 29566
36: 30435
37: 31305
38: 32174
39: 33044
40: 33914
41: 34783
42: 35653
43: 36522
44: 37392
45: 38261
46: 39131
47: 40000

The formula seems to be: width = (flow / 40000 * 46) + 1, with a minimum width of 4.

In addition to the above, I've found the following relations (I haven't tested with a brook):
< 5000 => Stream
5000 - 9999 => Minor River
10000 - 19999 => River
20000 -> => Major River. It seems the maximum river width is 47, although the flow can be higher than 40000.

Edit3:
Rather than tedious manual river width determination, I've made a script to measure it and edited edit2 above with the results:

``-- Purpose: Determine the flow values at which the width of a river increases.
-- Usage: Locate a water course that flows through 3 world tiles horizontally
-- on the embark screen. The middle tile mustn't have any other river joining.
-- Then place the DF focus (i.e. the embark rectangle) in the middle tile and
-- invoke the script.

function rivermeasurer()
local x = df.global.gview.view.child.location.region_pos.x
local y = df.global.gview.view.child.location.region_pos.y
local river
local center
local found = false
local widhth
local previous_width = 0
local previous_index = 0
local tile_x = 8
local tile_y

for i, riv in ipairs (df.global.world.world_data.rivers) do
for k, pos_x in ipairs (riv.path.x) do
if x == pos_x and y == riv.path.y[k] then
river = i
center = k
found = true
break
end

  if found then
    break
  end
end

end

dfhack.println ("River: " .. tostring (river) .. " center world tile " .. tostring (center))

for i = 0, 15 do
if df.global.world.world_data.region_details[0].rivers_horizontal.active [tile_x] [i] ~= 0 then
tile_y = i
break
end
end

for i = 0, 100000 do
df.global.world.world_data.rivers[river].unk_8c [center - 1] = i
df.global.world.world_data.rivers[river].unk_8c [center] = i
df.global.world.world_data.rivers[river].unk_8c [center + 1] = i

df.global.gview.view.child:feed_key (df.interface_key.CURSOR_UP)	  
df.global.gview.view.child:feed_key (df.interface_key.CURSOR_DOWN)	  

width = df.global.world.world_data.region_details[0].rivers_horizontal.y_max [tile_x] [tile_y] -
        df.global.world.world_data.region_details[0].rivers_horizontal.y_min [tile_x] [tile_y] + 1
		
if width > previous_width then
  dfhack.println ("Width " .. tostring(width) ..  " at river flow " ..  tostring (i) .. " diff " .. tostring (i - previous_index))
  previous_width = width
  previous_index = i
  if width == 47 then
    break
  end
end

end
end

rivermeasurer()``

Writings: item_flags2[3] and itemimprovement_writingst::anon_1

Couple of things associated with quires and scrolls:

item_toolst::item_flags2[3], on a quire or scroll, is the flag that indicates if the item is has a writing improvement. It's used by, among other things, workshops to determine if an object might meet the [HAS_WRITING_IMPROVEMENT] requirement. The game also checks to see if there actually is an itemimprovement_writingst in the improvements list, but it won't even look if this flag isn't set.

itemimprovement_writingst::anon_1 is a vector of ints, which are the indices into df.global.world.written_contents.all for the things written on a quire, scroll, or codex. Currently, anon_1 is really hard to access, because it apparently has the same name as a subclass variable that's just an int primitive, which is shadowing it for some reason? So in the Lua interpreter you have to use the special syntax to access it, and gm-editor can't insert into it because it can't create int32_ts (or any other primitive, I think).

job_item_ref.role notes

Enum item 0 seems to be used for the item being consumed by a personal task. Examples: the food from Eat, the drink from Drink, the equipment from Pickup Equipment.

Reagent seems to be used not only for ingredients of a recipe but also for tools. Examples: the stepladder from Gather Plants.

QueuedContainer is the item being hauled to a barrel/bin, and Hauled is the target barrel/bin for Store Item in Barrel/Store Item in Bin. Not really much we can do at a structure level for this one, but I thought it was an interesting side effect of the implementation of the new version of Store Item in Barrel/Store Item in Bin.

missing job type

In 43.03 job type 40 (formerly "store item in chest") is now "Store Item in Location" and is used in connection with defined locations (such as a tavern) in a fort.

The job-type enum (job-types.xml) should be appropriately updated.

abstract_building: 64-bit pointer differences

As I test out my 0.43.05 build on Win64 just noting some research and likely unknowns that are pointers rather than integer unknowns based on data alignment.

The following was noted by failure to use the exportlegends script successfully on a world.
Buildings did not have appropriate siteid or position information as well as names so changed the following on abstract_building and now that works:

 df.world-site.xml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/df.world-site.xml b/df.world-site.xml
index 7ed2360..d234443 100644
--- a/df.world-site.xml
+++ b/df.world-site.xml
@@ -69,9 +69,9 @@
         <int32_t name='unk3'/>
         <stl-vector name='unk4' type-name='int32_t'/>
         <int32_t name='site_owner_id' ref-target='historical_entity'/>
-        <int32_t name='unk_v42_1' comment='v0.42.01'/>
-        <int32_t name='unk_v42_2' comment='v0.42.01'/>
-        <int32_t name='unk_v42_3' comment='v0.42.01'/>
+        <pointer name='unk_v42_1' comment='v0.42.01'/>
+        <pointer name='unk_v42_2' comment='v0.42.01'/>
+        <pointer name='unk_v42_3' comment='v0.42.01'/>
         <int32_t name='site_id' ref-target='world_site'
                  comment='not initialized/saved/loaded, assumed member of base class'/>
         <compound name='pos' type-name='coord2d' comment='v0.42.01'/>

Side-question: Is it possible to load worlds created on 32-bit worlds on the 64-bit equivalent environment? I suppose I can just try but would help isolate this kind of thing much faster if that worked.

linux 64-bit: extra bytes between building_def

On 64 bit linux df crashes when creating a custom workshop (soapmaker's) while dfhack's labormanager is on. Testing in VMs it works on 32 bit linux and 32 or 64 bit windows. The problem is between needs_magma and build_items in building_def (https://github.com/DFHack/df-structures/blob/master/df.building-raws.xml). Running debug prints on 64 bit linux I get

8 code: SOAP_MAKER
10 id: 0
18 name: Soap Maker's Workshop
20 building_type: ...
24 building_subtype: 17
28 name_color: ...
2e tile: ...
f32 tile_color: ...
3c3e tile_block: ...
4000 build_key: 96
4004 needs_magma: 0
4008 build_items: .size() = -147855838
4020 dim_x: b97f3120
4024 dim_y: 7fff
4028 workloc_x: 3
402c workloc_y: 3
4030 build_labors: .size() = -1368175537
4048 labor_description: �
4050 build_stages: b960a0c8
4004: 00000000
4008: 00000000
400c: 00000000
4010: b97f3110
4014: 00007fff
4018: b97f3120
401c: 00007fff
4020: b97f3120
4024: 00007fff
4028: 00000003
402c: 00000003
4030: 00000001
4034: 00000001
4038: b9cd3140
403c: 00007fff
4040: b9cd3144
4044: 00007fff
4048: b9cd3144
404c: 00007fff
[DFHack]# Segmentation fault (core dumped)

adding enough padding to bump build_items to its next alignment makes everything work:

8 code: SOAP_MAKER
10 id: 0
18 name: Soap Maker's Workshop
20 building_type: ...
24 building_subtype: 17
28 name_color: ...
2e tile: ...
f32 tile_color: ...
3c3e tile_block: ...
4000 build_key: 96
4004 needs_magma: 0
4005 mystery[0]: 0
4006 mystery[1]: 0
4007 mystery[2]: 0
4008 mystery[3]: 0
4009 mystery[4]: 0
400a mystery[5]: 0
400b mystery[6]: 0
400d mystery[8]: 0
400e mystery[9]: 0
400f mystery[10]: 0
4010 build_items: .size() = 2
4028 dim_x: 3
402c dim_y: 3
4030 workloc_x: 1
4034 workloc_y: 1
4038 build_labors: .size() = 1
4050 labor_description: Soap Making
4058 build_stages: 3
4004: 00000000
4008: 00000000
400c: 00000000
4010: b9cc3960
4014: 00007fff
4018: b9cc3970
401c: 00007fff
4020: b9cc3970
4024: 00007fff
4028: 00000003
402c: 00000003
4030: 00000001
4034: 00000001
4038: b9dae7d0
403c: 00007fff
4040: b9dae7d4
4044: 00007fff
4048: b9dae7d4
404c: 00007fff
4050: b960fe98
4054: 00007fff
[DFHack]# 

So on 64-bit linux build_items is 8 bytes off.

(EDIT) I can set [NEEDS_MAGMA] in the raws, and it results in:

8 code: SOAP_MAKER
10 id: 0
18 name: Soap Maker's Workshop
20 building_type: ...
24 building_subtype: 17
28 name_color: ...
2e tile: ...
f32 tile_color: ...
3c3e tile_block: ...
4000 build_key: 96
4004 needs_magma: 0
4005 mystery[0]: 0
4006 mystery[1]: 0
4007 mystery[2]: 0
4008 mystery[3]: 1
4009 mystery[4]: 0
400a mystery[5]: 0
400b mystery[6]: 0
400d mystery[8]: 0
400e mystery[9]: 0
400f mystery[10]: 0
4010 build_items: .size() = 2
4028 dim_x: 3
402c dim_y: 3
4030 workloc_x: 1
4034 workloc_y: 1
4038 build_labors: .size() = 1
4050 labor_description: Soap Making
4058 build_stages: 3
4004: 00000000
4008: 00000001
400c: 00000000
4010: b9cd85e0
4014: 00007fff
4018: b9cd85f0
401c: 00007fff
4020: b9cd85f0
4024: 00007fff
4028: 00000003
402c: 00000003
4030: 00000001
4034: 00000001
4038: b9cff3a0
403c: 00007fff
4040: b9cff3a4
4044: 00007fff
4048: b9cff3a4
404c: 00007fff
4050: b964a298
4054: 00007fff

so needs_magma is 4 bytes off. It seems the cause is that build_key is a long, which is 4 bytes on MS and 32 bit gcc but 8 bytes on 64 bit gcc. I can't work a debugger well enough to really confirm it though.

creature.flags unk_6e, unk_6f & unk_49

only humans have unk_6f.

the set of creatures that have either unk_6e or unk_49 is exactly the set of creatures armor can be made for via the blacksmith. notably this set of creatures does not include several species that can equip and learn/speak/utter, like ogres, trolls, gremlins, gnomes, foul blendecs, troglodytes etc.

only animal men and gorlaks have unk_6e, 187 species in total.
14 species have unk_49, among them dwarves, elves, humans, goblins and kobolds. the rest are animal men as well, some of which have unk_6e too, but not all.

specifically, bat men, olm men, cave fish men, cave swallow men have both flags.
amphib men, ant men, reptile men, rodent men and serpent men have unk_49, but not unk_6e.

presumably these species either have entities or are advmode controllable?

Enum df.world_data.world_region_type same as df.world.worldgen_region_type

The title refers to the .XML files the enums reside in. The enums have the "same" values in the same order. The mixed case enums in the former type have different names with broadly the same meaning in some cases ('Jungle' vs 'FOREST', 'Steppe' vs 'GRASSLAND'). Since the latter enum's values match what's used by DF itself through the world generation files, that is probably the type that should remain.

Attack action research

From angavrilov#3, reported by @Putnam3145

http://pastebin.com/a8n2W3tj

Posting in pastebin form just in case editing may be required.

action.data.attack.unk_0 --attacked unit id

action.data.attack.unk_4 --some structure which represents something

action.data.attack.unk_4.unk_8 --0 when item attacking

action.data.attack.unk_4.unk_14 --0 when item attacking, -1 otherwise

action.data.attack.unk_1c --attacking item ID, if applicable

action.data.attack.unk_20 --attacked BP ID

action.data.attack.unk_22 --attacking bp id, if applicable

action.data.attack.unk_24 --attack ID; separate for items and units, so 0 could either be sword slash or left punch, by appearances

action.data.attack.unk_28 --usually 3, not sure what it is

action.data.attack.unk_2c --usually 3, not sure what it is

action.data.attack.unk_30 --hell if I know, changes a lot, way smaller with quick attack

action.data.attack.unk_34 --mode

-- 1: ?

-- 2: haven't seen it unactivated

-- 3: BP attacks usually have this, item attacks don't

-- 4: ?

-- 5: ?

-- 6: quick attack

-- 7: heavy attack

-- 8: wild attack

-- 9: precise attack

-- 10: charge attack

-- 11: multi-attack? (kicks have this always, so might be attack_flag_bad_multiattack)

action.data.attack.unk_38 --almost always 103 exactly, except when biting, where it's 102, at least when latching; perhaps related to latching? probably another flags, though that would be a lot of activated flags

action.data.attack.unk_3c -- different most of the time, not sure exactly what is

action.data.attack.timer1 --probably prepare

action.data.attack.timer2 --probably recover

df.world-data.xml:world_underground_region unknown parameter proposal

All of the unk_* fields were 0 for the magma sea and hell, so those levels are ignored below.
unk_7a: probably "water".
unk_7c: No idea. No obvious relation to unk_7a
unk_7e: Probably "openness_min"
unk_80: Probably "openness_max"
unk_82: Probably "passage_density_min"
passage_density: Probably actually "passage_density_max"

This assumption is supported by not finding any value outside of the expected for a large region with the following parameter:
Openness Min/Max: 25-50
Density Min/Max: 1-24
Water Min/Max: 76-90
using the following Lua script:
`function x ()
for i, region in ipairs (df.global.world.world_data.underground_regions) do
if region.layer_depth < 3 then
if region.unk_7a < df.global.world.worldgen.worldgen_parms.cavern_layer_water_min or
region.unk_7a > df.global.world.worldgen.worldgen_parms.cavern_layer_water_max then
dfhack.println ("Water out of bounds")
end

  if region.unk_7e < df.global.world.worldgen.worldgen_parms.cavern_layer_openness_min or 
     region.unk_7e > df.global.world.worldgen.worldgen_parms.cavern_layer_openness_max then
    dfhack.println ("Openness min out of bounds")
  end

  if region.unk_80 < df.global.world.worldgen.worldgen_parms.cavern_layer_openness_min or 
     region.unk_80 > df.global.world.worldgen.worldgen_parms.cavern_layer_openness_max or
	 region.unk_7e > region.unk_80 then
    dfhack.println ("Openness max out of bounds")
  end
  
  if region.unk_82 < df.global.world.worldgen.worldgen_parms.cavern_layer_passage_density_min or
     region.unk_82 > df.global.world.worldgen.worldgen_parms.cavern_layer_passage_density_max then
	dfhack.println ("Density min out of bounds")
  end
  
  if region.passage_density < df.global.world.worldgen.worldgen_parms.cavern_layer_passage_density_min or
     region.passage_density > df.global.world.worldgen.worldgen_parms.cavern_layer_passage_density_max or
	 region.passage_density < region.unk_82 then
	dfhack.println ("Density max out of bounds")
  end
  
  dfhack.println (region.layer_depth, region.unk_7a, region.unk_7c, region.unk_7e, region.unk_80, region.unk_82, region.passage_density)
end

end
end

x ()`

Edit:
I believe unk_7a < 9 => Biome = Subterranean Chams, while >= 10 => Subterranean Water. I performed the following experiment:
Embark on a world tile and used "reveal all" to view the caverns.
cavern 1: unk_7a = 4; muddy
cavern 2: unk_7a = 0; muddy
cavern 3: unk_7a = 10: "normal"
Deleting the world and loading a copy, editing the unk_7a values, embarking at the same location, and revealing:
cavern 1: unk_7a = 10; generic grass (no plants were present in the biome's population)
cavern 2: unk_7a = 10; ditto
cavern 3: unk_7a = 9; Mud covered, but normal shrubs, saplings and trees, but no moss.

Edit 2:
Further experiments indicates the previous thought on unk_7a is incorrect, and it probably is better called "muddiness" (changed above). 0-9 generates muddy caverns, but so does 91-100. However, The high range muddy caverns have been seen "naturally" together with both lakes and cavern trees and bushes (but not "grass", i.e. moss). Also, I have been completely unable to get cavern lakes to form in my world generated with a 0-25 cavern water world gen parameter range. I've played with unk_7c together with unk_7a as well as observed both on "natural" worlds without getting any understanding of unk_7c.

Edit 3:
Ignore Edit 2. Those are the results you get if the region you're going to embark in is in focus when you change the parameter. When changing the parameter from 39/29/39 for the 3 caverns to 100/100/100 while the embark was not in focus caused the embark to change from a bit of water in the 3:rd cavern to all of them almost covered (the 2:nd one had a little higher, muddy, ground).

Edit 4:
It seems the amount of water is roughly controlled by world_data.region_details[0].features[x][y][l].unk_30, where x/y are region coordinates and l is the feature entry for the cavern. The first 4 bits of the unk_30 array seems to control about 25% of the cavern for that mid level tile, but water did only appear with a Water parameter value of 39, but not one of 29, so there's probably a minimum value required for water to appear. I failed to see a clear correspondence between the water location and the bit set.

Edit 5:
Gradually increasing the value of unk_7a indicates it is accompanied by a gradual increase of the number of world_data.region_details[0].features[x][y][l].unk_30 flags being set both counted as number of flags per tile and number of tiles with flags set. At 100 I found at least one flag being set on 98/93/97% of the tiles of the three caverns in my test region (counting only cavern tiles belonging to the world tile's underground regions, not those of "encroaching" neighbors). Interestingly, a value of 9 resulted in muddy caverns, but some tiles actually had flags set, and checking one such case showed that the cavern actually had water in it together with mud. A value of 5 saw 0 flags set.

Proposal to add new attribute to fields new added to df-structures

There're a lot of comments like this one sparced over all xml files
<int32_t** name='unk_v4201_1' init-value='-1' comment='v0.42.01'/>

I would be very interesting if a new attibute could be added to df-structures specifically for modifications/aditions:

<int32_t name='unk_v4201_1' init-value='-1' since='v0.42.01' comment='data related to the field'/>

This new attribute would allow to track when this field first appeared in df-structures and free the comment attribute for information related to the field function. Also, detailed logs of new fields added to DF Structures could then be easily generated by some automatic tool

TwbT structures research

Mifki has said that the only thing preventing TwbT being merged into DFHack is the additional structures research required. Instructions here; it would be good to merge this too.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.