Jump to content

khzmusik

Members
  • Posts

    1,247
  • Joined

  • Last visited

  • Days Won

    7

Posts posted by khzmusik

  1. 2 hours ago, RAGE PVE said:

    Hey guys anyone verify if this mod works well for the current release and if its worth having?  Looks good thanks

     

    In A20 I put it into my Quality of Life modlet. Here's the A20 thread:

     

  2. Just added another modlet: Human Faction Reputation and Quests.

     

    This adds a "reputation" system to the game, where the player can gain or lose reputation with the human NPC factions. The two ways a player can change their reputation is by killing NPCs, or by doing faction-specific quests that you get from the traders.

     

    There are quests that require human POIs, but those aren't added to the trader quest list yet. There aren't enough POIs to support them. I'm hoping that will change in the near future.

     

    @bdubyah I know you were curious about doing something like this. Feel free to use this modlet, it should hopefully save you a lot of work. (You might even have enough human POIs to support the POI quests.)

     

    Details about all of this are in the first post, or for technical details, here is link to the README:

    https://gitlab.com/karlgiesing/7d2d-a20-modlets/-/blob/main/1-khzmusik_Human_Factions_Reputation_Quests/README.md

  3. I have not tried anything like this myself, but from what little I know, electricity is tricky to work with. The block needs to be a tile entity and that tile entity needs to be one that can accept electrical power. The tile entity class needs to be defined as a new C# class.

     

    ...and that's about where my knowledge ends.

     

    The SCore modlet (by @sphereii) has a "powered workstations" feature which takes a different approach. It uses a Harmony patch to the vanilla code, so that if you set a "RequirePower" property (to "true") in the workstation's XML, it will scan the surrounding chunks for active power sources, and set the workstation's "burn time" if it finds any.

     

    Here's the SCore repo if you want to take a look:

    https://github.com/SphereII/SphereII.Mods/tree/master/0-SCore

    That's the entire repo, here's the Harmony patch to workstations:
    https://github.com/SphereII/SphereII.Mods/blob/master/0-SCore/Harmony/TileEntities/PoweredWorkstations.cs

     

    But, that might not work the way you want. I think it only checks if there is an active power source in the area, and not whether that power source has actually been hooked up to the workstation (with the wire tool). I could easily be wrong though.

  4. Hey, all. I was wondering if this was possible to do in XML only. (I don't want to write custom C# code for this.)

     

    Let's say you have a cvar that represents a number that can be expressed by a tier. Example:

     

    • if myVar < 1, tier = "Low"
    • if myVar < 2, tier = "Medium"
    • ...etc.

     

    Is there any way to display the "Low", "Medium", etc. string instead of the cvar's numeric value?

     

    I'm especially looking for some way to do this with buffs, as a replacement for the "display_value" property - unless there's a way to get that property to display strings instead of numbers. (EDIT: I'm also aware that "display_value_key" can make it display non-numeric characters, but it can only accept standard C# string formatting.)

     

    Ideally I would also like some way to display this in the character stats window as well. Right now I am using "{cvar(myVar:0)}" but that displays the numeric value.

     

    Any ideas?

  5. 5 hours ago, Jeco said:

    I don't think I did this right.  I still get vultures.  Lots of vultures.  Oh well.  I have to investigate further.

     

    If you post what you did I can probably help.

     

    Probably the simplest solution is to put this in your Mods/entitygroups.xml:

     

    <config>
        <set xpath="//entity[@name='animalZombieVulture']/@name">none</set>
    </config>

     

    The two slashes mean "any descendant XML node" (in this case of the whole XML document). It matches any "entity" tag, with an attribute ("@") called "name", whose value is "animalZombieVulture"; and sets its "name" attribute to "none".


    This way you don't have to worry about targeting the different entity groups or whatever - it matches all entity tags in the document. It removes them from biome spawns, wandering hordes, blood moon hordes, even from the group used to spawn them in POIs.
     

    You could also replace the "name" attribute with the name of some other animal or zombie, like other people suggested above.

     

    You probably need to do the same thing for radiated vultures, unless you want those to still spawn in. (I'm pretty sure they only spawn in blood moon hordes.)

  6. I think  you need to make sure you distinguish between these behaviors:

     

    1. Spider zombies leaping at you
    2. All zombies jumping to climb up or down to get up or over a block
    3. All zombies climbing ladders

    I'm not an expert in all these areas, but here's what I know:

    1. Leaping is captured in the AITask value of "Leap" in the entity class. In spider zombies it's "AITask-1". I think you can get rid of that but then move each task "up" one number (so after you delete "AITask-1" then "AITask-2" becomes "AITask-1" and so on). FWIW, mountain lions also use this task.
    2. As Xyth said, this is hard-coded and can't be removed. It's part of the AI, including pathing calculations. You could switch the jumping animation if you create a custom Unity controller that has a different animation, but that's incredibly complicated.
    3. Whether an entity can climb ladders or not is determined by the "CanClimbLadders" property in the entity class. In zombies it's set in the "zombieTemplateMale" class and inherited by other entity classes. Setting this to "false" will stop zombies from being able to climb ladders.

    Hope that helps.

  7. On 6/24/2022 at 8:55 AM, Aesirkin said:

     

    Thanks khzmusik!  I'm closer to vanilla, so I'm going to give the A19 version a try.  I appreciate you looking at it and, of course, you creating it!  :)

     

    You're very welcome.

     

    I just uploaded the A20 version. This version will work with modlets (like NPC core) that change the dialog windows. Unfortunately, in this case, you'll get warnings in the console about XPath not applying, but those can be ignored (it's intentional behavior).

     

    I also just uploaded another modlet, that changes the behavior of NPCs spawned into sleeper volumes in POIs. The NPC Core defaults have them waking up immediately when they're spawned in, which can make it difficult if you're designing a "dungeon crawl" style POI with NPCs in it. The modlet uses SCore feature flags to make NPCs behave a bit more like zombies. It's mainly for POI designers, but you might find it useful if you're playing a mod with NPCs in it.

     

    I also figured out how to get links to automatically-generated .zip files on GitLab, so I added those links to all the modlets. It should make life easier. But make sure you put the directory inside the top-level directory in your Mods folder.

     

    I'm still working on other things (POIs, more NPCs) so stay tuned.

  8. On 6/21/2022 at 2:28 PM, zztong said:

     

    Is it, or is it left over from when somebody copied XML from another POI that had a quest?

     

     

    Wouldn't you want this to be set to True?

     

     

    So is the TraderAreaProtect value a location in the world? I was thinking it was a bounding box indicating how much area to protect.

     

    <property value="20,0,20" name="TraderAreaProtect"/>

     

    So is that "protect a 20x20 area" or protect an area centered at location 20,20 in the world?

     

    Sorry, I meant to reply earlier.

     

    I didn't realize that the "lobby" and trader POIs were different. I'm still not sure what the "lobby" is supposed to be. But for the trader POI, you do want "TraderProtection" set to "true". That should enable the ability to size the trader protection area in the POI editor, though you might have to also copy in an existing trader area and adjust it later. (I can't remember what I originally did with my A19 trader POI.)

     

    The "QuestTags" values are what quests the POI accepts when it is used as a quest destination. If your POI is a trader, it shouldn't even have that property - you don't want anyone to be sent to a trader POI for a clear quest. The quests that can possibly be given by a trader have nothing to do with the prefab XML, they're defined in quests.xml.

     

    As far as the trader protection area goes, I'm sure that "TraderAreaProtect" values are relative to the POI's origin. They're defined in the POI XML, and at that point the POI hasn't been placed into the world yet.

     

    That's different than the trader area value that is used to keep track of used POIs. When representing what quest POIs have already been given by that trader, the trader area is represented as a 2D vector, and I'm pretty sure it represents the center of the trader protection bounds as they exist in the world.

  9. Have you tried using a nav_object? It won't apply the radiated effect but it will make arrows easier to find. That's what the spear uses.

     

    You would add something like this to arrows:

    <property name="NavObject" value="arrow"/>

     

    Then create an "arrow" nav_object_class:

     

    <nav_object_class name="arrow">
        <property name="requirement_type" value="Tracking" />
    
        <map_settings>
            <property name="sprite_name" value="ui_game_symbol_map_player_arrow"/>
            <property name="min_distance" value="0"/>
            <property name="max_distance" value="-1"/>
            <property name="color" value="255,255,0,255"/>
            <property name="has_pulse" value="true"/>
        </map_settings>
    
        <compass_settings>
            <property name="sprite_name" value="ui_game_symbol_map_player_arrow"/>
            <property name="min_distance" value="0"/>
            <property name="max_distance" value="1024"/>
            <property name="color" value="255,255,0,255"/>
            <property name="has_pulse" value="true"/>
            <property name="icon_clamped" value="false" />
        </compass_settings>
    
        <onscreen_settings>
            <property name="sprite_name" value="ui_game_symbol_map_player_arrow"/>
            <property name="min_distance" value="0"/>
            <property name="max_distance" value="50"/>
            <property name="color" value="255,255,0,255"/>
            <property name="has_pulse" value="true"/>
            <property name="text_type" value="Distance"/>
        </onscreen_settings>
    </nav_object_class>

     

    I haven't tried it myself, but in theory it should work.

     

    I know it isn't exactly what you're looking for, but it's all I could think of.

     

    EDIT: It looks like @omegaflames had the same idea and couldn't get it to work. (He posted something that I didn't see before replying.) So maybe that's a dead end.

  10. As the title says. I remember back in A19, along with other improvements to modding, there was a rumor that there would be a way to do this.

     

    Here's why I ask. I am porting over an A19 modlet with more trader dialog. In order to show longer statement text, I have to add some space to the "windowStatement" window, and move the "windowRespondentName" window up a bit.

     

    But, I only have to do this with the vanilla window values. In particular, the NPCCore mod changes this window, and the longer statement text already works with those changes. Furthermore, if I use the same XML values as vanilla, the windows actually won't show at all because they're now in a different place on the screen.

     

    Targeting only vanilla is pretty easy - I only target those XML window tags whose attributes (like "pos") have vanilla values. If they don't match, as in SCore, then the changes aren't applied - which is what I want to happen.

     

    The problem is that if the XPath changes aren't applied, yellow warning messages show up in the console. It doesn't make any difference in a functional sense, everything still works as designed, but users looking in the console will see this and think something is wrong.

     

    So I'd like to suppress these warnings if possible, and ideally only for those XPath changes (and not for warnings that were logged for other mods/modlets).

     

    Does anyone know if this is possible? I know it's a long shot.

  11. Quick update: I am in the process of updating the "Trader Lore" modlet for A20.

     

    The A19 version works fine if it's installed into a vanilla game, but not if it's installed into a game with SCore/NPCCore installed. Those modlets (forget which) modify the trader dialog window, and if you install the Trader Lore modlet, the responses don't show up for some reason.

     

    As soon as I figure that out, and fix it, I will release it here.

  12. 15 hours ago, Aesirkin said:

     

    Thanks!  I was looking for something completely different when this mod came up in my search, and I knew my one friend would absolutely love it on our server.  :)

     

    Well, I have some good news and some bad news.

     

    The good news is that I just installed it into an A20 vanilla game, and it works fine. So if you're modding vanilla (or close to it) then you can just use the A19 modlet.

     

    The bad news is that it's not compatible with the new dialog window in SCore and NPCCore. The traders' responses don't show up.

     

    I will have to figure out why, and how to fix it, before I release the A20 modlet. So that will take a bit of time. It should be coming eventually though.

     

    EDIT: Also because I am a dope, I didn't realize this was the A19 thread. Let's move this to the A20 thread, here:

     

  13. 12 hours ago, Aesirkin said:

    Do you happen to know if the trader lore modlet is compatible with A20?  I didn't see it listed in the A20 thread, unless I just missed it.  Thanks!

     

    I have not ported it to A20, but it should work as is. I was going to make it part of a larger mod, but I can port it over as soon as I am off work tomorrow.

  14. 15 hours ago, BFT2020 said:

    Never tried this myself, but you may be able to add another property to the fetch / clear quests:

     

    From a T1 fetch quest:

     

            <objective type="RandomPOIGoto">
                <property name="phase" value="1"/>
                <property name="biome_filter_type" value="SameBiome" />
                <property name="biome_filter" value="burnt_forest" />
                <property name="nav_object" value="quest" />
            </objective>

     

    From a T1 buried supplies quest:

     

            <objective type="RandomGotoNPC" phase="1">
                <property name="completion_distance" value="20"/>
                <property name="distance" value="350-600"/>
                <property name="nav_object" value="quest" />
            </objective>

     

    Again, haven't tried this myself, but if you add the property distance line in the fetch / clear quests, it might limit it to only quest enabled POIs at a specific distance from the traders.

     

    At the very least, something to try until someone with a better understanding the quest system comes along

     

    This won't work for the "RandomPOIGoto" objective - it doesn't support the "distance" property.

     

    However, if you don't mind using a C# mod (so required by both server and client), then I recently made a new quest objective type in SCore. It's called "RandomTaggedPOIGotoSDX". As the name implies, it was originally used for going to POIs with a specific tag (in the "Tags" property of its XML). But I also added support for the "distance" property. It can take either the max distance as a single number, or the min and max distances separated by dashes. (The "dash" format is the same format buried supply quests use, as in the XML above.)

     

    One other thing to keep in mind. The game does keep track of which POIs you've gone to, and which you haven't - but that list is per trader protection area, not per trader. If you have several traders in a protected area, they will share that same list. That's probably what you want, but I felt I should mention it.

     

    It also means that if you don't have a trader protection area, the game won't allow your trader to give quests to POIs. You'll get nothing but buried supply quests.

     

    (I know this because that new quest objective I wrote also doesn't require the trader protection area. A trader without one will still send you to POIs for quests, and not just give you buried treasure quests. In this situation there's no way to keep track of which POIs you've gone to already, but I figured it was better than nothing.)

  15. On 6/13/2022 at 5:42 AM, RipClaw said:

    The Behemoth, on the other side, was originally planned to be 5 blocks high. As far as I know there were problems with the pathing at this size.

     

     

    There are mods that try to revive the Behemoth, and they reveal some of the problems with it. Pathing is only part of the problem.

     

    The main issue is that the zombie AI is designed to target only two block heights for destruction: the one at "eye" level, and the one at ground level (so, two blocks high).

     

    If any zombie is taller than two blocks high, they can be trivially blocked by placing a weak block three blocks above ground level. No matter how weak, it will block movement, because the zombie will never target it for destruction. You could make a three-block-high wall of wood frames and be totally safe.

     

    So either the Behemoth needs to adjust its collision mesh so it clips through blocks higher than the second block (which looks ridiculous), or it will need to be shrunk so it fits within two-block openings (which makes it not so much a "behemoth" as a new zombie skin). The mods that try to bring it back have tried both approaches, and neither really makes for a compelling gameplay experience.

     

    It would be cool if TFP made the AI changes necessary for enemies to destroy blocks relative to the entity's size. (I for one would like a 7D2D version of the Stranger Things mindlfayer.) But this is quite a bit of work, and I don't think they will push other things aside just for this.

  16. 11 hours ago, arramus said:

    Correct. A trader requires a point of origin to measure distance to POIs and offer quests.

     

    Just as an FYI, I recently provided code to SCore that gets around this.

     

    Normally when a quest giver gives a quest that goes to a POI, that quest giver needs to have an associated trader protected area (it presumes the quest giver is a vanilla trader).

     

    If you substitute "RandomTaggedPOIGotoSDX, SCore" for the vanilla "RandomPOIGoto" objective, then it should get around this. If there is no trader protected area around the quest giver, then it should just choose a random POI, without considering the used POIs around that specific trader (it can't do that without a trader protected area). There is always the danger of repeated POIs, but it should at least work without throwing errors.

     

    To use it, you would need to use the "RandomTaggedPOIGotoSDX" objective instead of the vanilla "RandomPOIGoto" objective.

     

  17. 9 hours ago, smokedpone said:

    Been playing this game for years but only recently got into modding it, and I just wanted to say that the work you guys have done with this mod is incredible! ❤️

    I was wondering if there is perhaps a way to set it up so that NPCs can spawn with their faction randomly chosen between a selection of values (without having to make new entities)? I've been using khzmusik's lovely Civilians add-on, and I thought it'd make for interesting situations if the player couldn't immediately tell whether they will be friendly or hostile on approach.

    I tried <property name="Faction" value="whiteriver,bandits" /> , thinking that would work (still very new to all this XML/XPath stuff), but it just made them not spawn and give a null reference error in the console instead. 

     

    Each entity can have only one faction, that property does not accept a list.

     

    What you want can be done, but it's not easy. It would involve creating new entity classes for every single NPC you want duplicated (including weapon variations), and then adding those NPCs to spawn in the game.

     

    Let's say you wanted to make unfriendly versions of my "Male Cowboy" civilian NPC. I am going to assume you want them to be of the "bandits" faction (not one of the other unfriendly factions like "whisperers").

     

    The first thing to do is to make bandit versions of the character and weapon type. Example:

    <entity_class name="npcBanditMaleCowboyKhzClub" extends="npcMaleCowboyKhzClub">
      <property name="Tags" value="entity,male,npc,melee,bandit" />
      <property name="Faction" value="bandits" />
    </entity_class>
    <entity_class name="npcBanditMaleCowboyKhzKnife" extends="npcMaleCowboyKhzKnife">
      <property name="Tags" value="entity,male,npc,melee,bandit" />
      <property name="Faction" value="bandits" />
    </entity_class>
    <!-- ...etc. for all weapon types -->

     

    The "Tags" property doesn't extend so you need to specify it, and you need to change the "Faction" property value to whatever faction you want the NPCs to be. I'm pretty sure that's all you need to change to get things working.

     

    The next step is to get them to spawn into the world. In general there are two ways NPCs can spawn:

    1. In the world, outside of POIs. This is controlled by the biome spawn groups.
    2. In NPC specific POIs. This isn't widely used yet but will be in the near future when people start making POIs that are dedicated to NPCs.

    In both cases, spawning is controlled in the "entitygroups.xml" file.

     

    For biome spawning, I suggest just copying-and-pasting the XPath that puts the NPCs into the "ZombiesAll", "ZombiesNight", and "SnowZombies" entity groups. You can mess around with other groups later once everything is working, if you want.

     

    For POI spawning, I suggest copying the XPath that puts the NPCs into the various "npcWhiteriver" and "npcFreindly" groups, except that you should instead put them into the equivalent "npcBandits" and "npcEnemy" groups.

     

    There is a catch: the Civilian NPCs (and in general other folks' friendly NPCs) can be interacted with and hired, and that means they can't be spawned into horde groups (wandering hordes or blood moon hordes). It's possible to modify them so they can be spawned into these groups without throwing errors, but that's more complicated. I can tell you how to do that if you want.

     

    Hope that helps.

     

    FWIW, I do plan to make a "Rogues" pack that has more "normal looking" unfriendly NPCs. They will still be distinct, but perhaps not so obviously "bad" as other NPC bandit packs. (There will also be others that are more obviously "bad" though.) I still have a lot more to do before I get to that - mainly making NPC POIs - but it's on the roadmap.

  18. First, make a new item display info tag in ui_display.xml:

    <item_display_info display_type="modArmorCritResist" display_group="modAttire">
        <display_entry name="PhysicalDamageResist" display_type="Decimal1" title_key="statPhysicalDamageResist" display_leading_plus="true" />
        <display_entry name="ElementalDamageResist" display_type="Decimal1" title_key="statExplosionResistance" display_leading_plus="true" tags="heat,electrical" />
        <display_entry name="BuffResistance" title_key="statBuffResistance" display_type="Percent" tags="critResistDisplay" show_inverted="false" />
    </item_display_info>

     

    (You can name it whatever you want, I chose "modArmorCritResist" because that made sense to me.)

     

    Next, update your custom item to use that display type:

    <property name="DisplayType" value="modArmorCritResist" />

     

    That should do it.

     

    (That is the XML, I didn't include the XPath commands to insert it.)

  19. 2 hours ago, Laz Man said:

     

     

    This looks cool. But, does it only turn off the flames? I could definitely see uses for being able to turn them on, like if you have a "defend this POI" quest you could use them to trap the areas where the pipes are broken.

  20. I think you're talking about a character from the 1-VaultDwellerzPack modlet. Either that or you're playing the Wasteland mod, since I believe it uses that modlet. So the appropriate place to ask is in either the NPC Core thread or the Wasteland thread.

     

    However - I'm pretty sure I know the cause. If the entity has a "LootListAlive" property, then it will show the "Press <E>..." prompt when it's dead. You could remove that property, but that would disable the character's inventory if it's a hired NPC. The NPC Core folks get around this by having hirable NPCs despawn almost immediately after they die, so most players can't get the prompt.

     

    So either you have power armor NPCs that can't be interacted with or hired, or you live with that bug. Personally I think that bug is a small price to pay.

  21. Hey, all. I'm hoping someone with a lot of C# skills can help me with this.

     

    In C#, I'm creating a custom quest objective to go to a POI. It is designed to be a drop-in replacement for ObjectiveRandomPOIGoto, except that it accepts additional properties: included POI tags, excluded POI tags, and a distance (range or max distance) from the quest giver.

     

    This is all working in single-player, but now I want it to work in multi-player. And, in multi-player, this is my understanding of how it should work.

     

    1. The method to find a POI is called on a client. Don't do it, and instead send a NetPackage to the server for it to find the POI.

    2. The server receives the NetPackage, and the NetPackage itself does the job of finding the POI. It should use the same logic as the Objective would in single-player.

    3. Once the POI is found, the server sends another NetPackage back to the clients with the POI information.

    4. The clients receive the NetPackage, and "finalize" the objective (set the POI position and size).

     

    I am pretty sure that's accurate, but I want to get another set of eyes on it.

     

    One question is about step 3. I assume that, as long as the client is sent the POI position and size, that it doesn't need to be the same (custom) NetPackage type that the client sent to the server; that instead a vanilla NetPackageQuestGotoPoint type would do (this is what the vanilla ObjectiveRandomPOIGoto uses).

     

    Also: All the vanilla NetPackage classes have a GetLength method, and I can't tell what that is supposed to represent. Some return 8, others return 32, still others return a different length depending upon the count of some internal list or other.

     

    If  you're reading this and can't answer, then would it be possible to help me test? I don't have any way to test a multiplayer game by myself.

  22. On 5/19/2022 at 5:59 PM, Aesirkin said:

    I love the concept presented by this mod: https://7daystodiemods.com/crop-growth-by-weather/.  However, that one was made using DMT.  Though when I look at the forum page for DMT it says DMT is being sunset because A20 XML modding can do the things DMT used to be needed for.  So I'm hoping I can recreate some of the functionality presented there in an XML-only modlet.

     

    I'm the one who wrote that modlet, so I can tell you the technical details.

     

    DMT is being sunsetted, but not because XML modding can do the things DMT could do. DMT used to be used for C# patching using Harmony, and that is now supported natively by the game. But it's still C# code, so requires both client and server installation.

     

    The main reason I haven't updated that modlet to A20 is not because of DMT, it's because weather itself was totally revamped in A20, and none of the A19 code can be used. Another reason is that A20 severely nerfed farming, so making crops be able to die - thus making farming even more difficult - is something I thought was unnecessary, and not something I thought anyone else would be interested in.

     

    The placeholder block idea from Telric is probably your best bet if you want an XPath-only modlet.

  23. 2 hours ago, theoilver said:

    Hi, sorry I feel lost.

     

    Do I need to also have "0-XNPCCore" in my Mods folder if I want to try the mod below?

    2-XNPCCore_khzmusik_Progression

     

    What other mods do I need to have in my Mods folder if I want to try "2-RaiderzPack_khzmusik_Progression"?

     

     

    Those "progression" modlets are designed to work with the various NPC packs. Since there's no way for me to know which packs a user has installed, I had to make one modlet per NPC pack.

     

    They're named after the pack that they work with, except they start with a higher number, and have a "_khzmusik_Progression" suffix. So, "2-XNPCCore_khzmusik_Progression" is designed to work with "0-XNPCCore", and "2-RaiderzPack_khzmusik_Progression" is designed to work with "1-RaiderzPack", and so forth.

     

    That's the recommended way to name modlets that are designed to work with other modlets. (For example, the "2-NPCXSpiderPack-ColonyExpansion" by Arramus is designed to work with/extend "1-NPCXSpiderPack".) I thought this was either obvious or common knowledge, so I didn't explain it in the post itself. Obviously I was wrong, so I'll update the post.

     

    EDIT: The list also says which modlet it was designed to work with. So the link to "2-RaiderzPack_khzmusik_Progression" says explicitly that it is "for 1-RaiderzPack".

     

    EDIT 2: Maybe the installation procedure, as opposed to the modlet relationship, isn't clear? In general, if a modlet is designed to work with another modlet, it doesn't include that other modlet. They need to be downloaded and installed separately. That's true of all modlets in general. And, yes, they should all be installed into the "Mods" folder.

  24. 22 hours ago, xyth said:

    Very nice writeup! 

     

    Additionaly, the NPCCore by default has this line added:  <set xpath="/blocks/block[@name='ConfigFeatureBlock']/property[@class='AdvancedNPCFeatures']/property[@name='AllEntitiesUseFactionTargeting']/@value">true</set>    which forces faction based targeting on for all entities, including animals.  

     

    I forgot that was still in NPC Core. I thought we changed that when it moved to using tags. I guess that means the animal factions are actually live, I didn't think they were.

     

    I just updated my post with this information. Thanks!

  25. On 5/15/2022 at 6:15 PM, RogueSpirit said:

    Is there a guide anywhere that might help learning what to edit to change the npc's behavior. For example to change a faction or the hostility of NPC's? I know that it can be done by editing the .xml files but I am not clear on which files and if there is an existing list of factions that have to be used or can I create my own.

     

    I wrote a good chunk of the faction-related code that is in SCore, so I can give you the details. I expect a lot of people will have questions about NPCs and factions, so I'll try to answer them here.

     

    This is meant to be kind of a "user's manual" so it's long and detailed. Skip it if you're not interested in modding the factions or NPCs.

     

    1. How are factions and relationships defined in XML?

     

    Each faction, and its relationships with other factions, is defined in npc.xml. There are factions that are defined in vanilla XML, and factions defined by NPC Core XML.

     

    Here is the vanilla XML that defines the "duke" faction:

     

    <faction name="duke">
        <relationship name="*" value="neutral"/>
        <relationship name="whiteriver" value="dislike"/>
        <relationship name="undead" value="hate"/>
        <relationship name="bandits" value="dislike"/>
    </faction>

     

    Between vanilla and NPC Core, there are a whole lot of factions. But if you want to define your own, that is the XML you would need to write.

     

    2. What factions are already defined?

     

    Vanilla defines these factions:

    • "none": for non-player entities that don't specify which faction they belong to (see below)
    • "animals":  vanilla animals - can't be used for faction targeting
    • "undead":  zombies
    • "bandits":  human enemies; "bad guys"
    • "whiteriver":  Noah's clan (apparently based on the real Whiteriver, AZ); "good guys"
    • "duke":  the Duke's clan
    • "trader":  traders

    NPC Core defines these additional factions:

    • "whisperers": TWD-style whisperers (I just released a pack for these guys, see my thread if you want it)
    • "vault": Fallout-style vault dwellers
    • "military": military
    • "redteam": sample military faction, currently unused
    • "blueteam": sample military faction, currently unused
    • "blueteam": sample military faction, currently unused
    • "mechs": enemy mechs, robots, cyborgs, etc.
    • "allymechs": currently unused

    NPC Core also created these animal factions, and it sets the factions of vanilla animals to use them:

    • "companionanimals": used by the NPC Core fox
    • "zombieanimals": bears, vultures, dogs
    • "passiveanimalssmall": rabbit, chicken
    • "passiveanimalsmedium": stag, doe, boar
    • "passiveanimalslarge": not currently used
    • "aggressiveanimals": not currently used
    • "aggressiveanimalssmall": snake, coyote
    • "aggressiveanimalsmedium": wolf, dire wolf, mountain lion
    • "aggressiveanimalslarge": bear, Grace

     

    3. What do the relationship values mean?

     

    In the XML, the "relationship" tag defines a relationship between the faction and another faction. The "name" property specifies the other faction.

     

    The special value "*" means "any other faction that isn't defined here." That includes all player characters. (It does not include members of the same faction.)

     

    In 7D2D, the relationships between factions are stored as numbers between 0 and 1000 (inclusive). The values in XML specify the tier of the relationship.

     

    Here are the values for each tier:

    • "hate": 0
    • "dislike": 200
    • "neutral": 400
    • "like": 600
    • "love": 800

     

    The relationship between members of the same faction is always "love". (TFP hard-coded this.)

     

    A relationship of "hate" means that the NPC will attack the member of the other faction (or player) on sight. Otherwise, the NPC will not attack the other NPC/player, unless that other NPC/player damages them first.

     

    The faction relationship also determines "friendly fire" rules. If a the relationship with the other entity is high enough, the NPC can't damage that other entity. Note that the "other entity" could be any entity, including the player.

     

    • If the NPC descends from the C# EntityNPC class, the relationship needs to be "neutral" or higher to be damage immune.
    • If the NPC descends from any other C# class, the relationship needs to be "love" or higher to be damage immune.
    • Regardless of C# class, if the other entity is a player, the relationship needs to be "hate" for the player to be damaged.

     

    However, if an NPC is damaged by another entity, that other entity becomes their "revenge target" (this is actually what TFP calls it). Regardless of the above rules, an NPC can damage its revenge target. (An NPC can only have one revenge target.)

     

    The "friendly fire" relationship level can be changed by setting the "DamageRelationship" cvar on the entity class. For instance, to make the player able to damage any NPC, set a cvar when the player spawns in:

     

    <effect_group name="Damage All NPCs">
        <triggered_effect trigger="onSelfFirstSpawn" action="ModifyCVar" cvar="DamageRelationship" operation="set" value="1001" />
        <triggered_effect trigger="onSelfEnteredGame" action="ModifyCVar" cvar="DamageRelationship" operation="set" value="1001" />
        <triggered_effect trigger="onSelfRespawn" action="ModifyCVar" cvar="DamageRelationship" operation="set" value="1001" />
    </effect_group>

     

    (This XML is in the NPC Core entityclasses.xml file but is commented out.)

     

    If you want this to apply to NPCs, then you would have to set that cvar on the XML entity class that defines those NPCs. All characters that use NPC Core descend from the "npcMeleeTemplate" entity class, so if you want it to be set on all NPCs (human or otherwise), you could use that.

     

    The exception to all of the above is the vanilla "animals" faction. SCore is hard-coded such that enemy entities which are part of that faction, totally ignore all faction-based rules. (This was done to fix a bug where the mere presence of SCore, with or without NPC Core, would make all animals immune from damage. It's probably not necessary now that we use tags - see below - but it's still in the code AFAIK.)

     

    3. Which entities use factions? How can you change that?

     

    Please note something important: The entity does not have to use Utility AI (UAI, used by human NPCs in Core) in order to use faction targeting/friendly fire rules.

     

    An entity's faction is defined by the "Faction" property in its entity class XML (in the entityclasses.xml file). That property is inherited. All vanilla and NPC Core entities have their factions set already.


    That doesn't apply to players. Each player is assigned its own unique faction. (So, NPCs have unique relationships with each player in a multi-player game.) Player faction relationships can't be specified in XML, and I'm pretty sure the game would ignore the "Faction" property if you tried to set it on a player's entity class.

     

    However, the mere presence of the "Faction" property doesn't necessarily mean the faction is actually used by the entity.

     

    SCore has a "config feature block" which is used to configure various things, including NPC behavior.  If you want all entities in the game to use faction targeting/damage rules, you can set the "AllEntitiesUseFactionTargeting" property value to "true". It is set to "true" in NPC core, so this is the default.

     

    If you only want certain entities to use factions, then you should set that value to "false":

    <set xpath="/blocks/block[@name='ConfigFeatureBlock']/property[@class='AdvancedNPCFeatures']/property[@name='AllEntitiesUseFactionTargeting']/@value">false</set>

    You can then specify which entities use factions, according to the tags on the entity (in its "Tags" property in the entity class XML). Note that tags are not inherited.

     

    In the SCore config feature block, the "UseFactionsTags" property defines which entity tags use faction targeting. To change it, you could edit that by hand, or you could use XPath in your own modlet.

     

    For example, this is what I did in my Whisperers pack, so that zombies don't attack whisperers, and vice versa:

     

    <append xpath="//block[@name='ConfigFeatureBlock']/property[@class='AdvancedNPCFeatures']/property[@name='UseFactionsTags']/@value">,zombie</append>

     

    Another approach is to add one of the existing SCore tags to whichever entity you want to obey faction rules.

     

    These are the entity tags that SCore currently uses to determine whether the entity uses factions:

    • human
    • bandit
    • survivor
    • npc
    • trader

     

    4. What about follower (hired) NPCs?

     

    Followers (like hired NPCs) always use the faction rules of their leader (like the player that employs them) for targeting and damage.

     

    The exception is when they are hired by one player, and are targeting another. In this case, they use the same "friendly fire" rules as the players themselves. So, if two players cannot damage each other, then one player's hires can't damage the other player, and one player's hires can't damage the other player's hires.

     

    In either case, the follower's faction is no longer relevant. All of this is hard-coded in SCore and can't be changed.

     

    5. Are faction changes save-game safe?

     

    Absolutely not. You must start a new game if you ever add factions to, or remove factions from, the game.

     

    Here's why. 7D2D saves the factions in an array (with a numeric index), not by name. Let's say you add a new faction. In the game save, the faction at index 10 might have previously belonged to a player, but now belongs to the new faction you just added. It will be a mess - and is hard to debug, because it might not even result in a red error in the console. So, just don't do it.

     

    Hope that helps!

×
×
  • Create New...