headless zombie spawning in place of a molerat I released the Spawn Replacements holotape feature for my Zombie Walkers mod and an issue...

Curse of the Headless Zombies

headless zombie spawning in place of a molerat
I released the Spawn Replacements holotape feature for my Zombie Walkers mod and an issue appeared almost immediately. Some of the zombies replacing other creature types were spawning naked and the head is invisible! If you look closely at the picture above, you'll notice that the strands of hair do render. Also, the zombies seem to behave normally and can even be shot in their invisible heads.

The Issue

I spent a lot of time looking into this and it appears to only be happening for certain ambush type leveled list spawns. I've confirmed this for molerats and radroaches so far but I suspect others like radscorpions are probably also impacted.

Leveled actors are special in that they spawn different actor base types based on character level. For example, an instance of LvlMolerat in the world is templated from LCharMolerat which is a leveled list where one of EncMolerat01Template, EncMolerate02, etc. are chosen depending on character level. In this case there are no custom scripts attached and the replacement works fine in game. These represent molerats already spawned above ground.

The molerats that pop out of the ground (most) use a different actor called LvlMoleratAmbush. This actor works the same as the LvlMolerat except that it has a MasterAmbushActorScript attached to it. I've looked at this script and it does things like activate the actor and calls EvalutePackage. According to the Creation Kit wiki, the EvaluatePackage function "Forces this actor's AI to re-evaluate its package stack". Not 100% sure what that means, but I think we can safely assume more scripts will run. Maybe it runs the scripts attached to LvlMoleratAmbush on the Feral Ghoul?

In addition to the above, the ambushes are attached to "furniture". In the case of molerats we use the term furniture loosely as it is really a hole they dig in the ground that magically appears.

There are two types of furniture used for molerats called AmbushMolerate01Long and AmbushMolerate02Short. Each type of furniture that is linked to the ambush spawn has an animation associated with it and it intended for use with a specific actor type.


Based on the above, there are at least a couple different factors at play that may be causing problems where the game expects a molerat skeleton for animations and various scripts.

How to fix it?

Using scripting alone, I'm not sure there is a fix.

I did some research on other modders posting about a similar problem. One such case suggested doing a search and replace inside the world view window (click to select and Ctrl-F). I'm currently testing this solution but it seems sound in theory.

The problem though, is that doing this type of replacement is NOT configurable. I'm beginning to understand why other mods offer creature replacements in a separate optional mod now. I'm still wrestling with where I want to go from here before I deploy a "fix":

  1. separate optional replacement mod (at least for ambush replacements)
  2. bake ambush replacements into the mod (no option for users to disable)
  3. continue to dig into the scripting to try to resolve the problem (which may have no solution)

Update: 8/28/16

I have tested an confirmed the search & replace option works well (even at scripted ambushes like Red Rocket). I currently have the ambush replacements in a separate mod.

One interesting thing I noticed when starting a brand new game you run into a zombie in Vault 111 before you get the 10mm pistol. Fortunately, you can maneuver around until he electrocutes himself. In all, there were around 6 or 7 zombies told in the vault and 3 live radroaches (non-ambush spawns). Upon activating the pipboy, you can enable Spawn Replacements which will then replace most non-ambush spawns as well and you may never see a radroach again.

Update: 8/30/16

Zombie Walkers - Ambush Replacements mod has been published for XB1 and PS4.

0 comments:

First, I don't recommend it. But if you have a cheap PC (or Mac on bootcamp) with integrated graphics like my Intel HD 4000 graphics chi...

Modding on integrated intel graphics

First, I don't recommend it. But if you have a cheap PC (or Mac on bootcamp) with integrated graphics like my Intel HD 4000 graphics chip, you can run fallout though it isn't pretty.

Using dxcpl to configure direct x compatability

This article was very helpful in getting past startup crashes. Basically you can set your direct x compatibility using a program called dxcpl:

https://www.reddit.com/r/lowendgaming/comments/3sf7ea/i_did_it_how_to_run_fallout_4_on_intel_hd/

"Force WARP" will cause the game to always load but run at very low FPS (1-5). If I leave this setting off it will crash during startup most of the time but eventually work (After 5-10 tries). I find that using Task Manager to set the priority of the fallout4.exe process to "above normal" or "high" and clicking on the window helps (I run it on lowest res in windowed borderless mode).

After tweaking graphics settings to low it will actually run quite well though there are still some crazy artifacts that appear. With vsync off the frame rates are 15-30.

Speed up dev/test cycle

To get around having to re-start the entire game to test a single small change, I figured out you can actually keep the game running and reload the mod. This is especially important if you game crashes a lot during startup like it does for me (see above).

Basically, remove the mod from the load order and let the game reload (not restart the app itself). Then you can save your mod using the Creation Kit since the mod files will no longer be locked. Once saved, re-add the mod to the load order and then test your changes.

Summary

I play Fallout 4 primarily on my xbox and only bought a PC copy of the game for modding. The above allows me to do basic testing on my PC which speeds up dev time. 

0 comments:

When you enter a zombie apocalypse themed world, you expect to see lots of zombies. To that end, I wanted to provide the option to replace s...

Configurable Spawn Replacements

When you enter a zombie apocalypse themed world, you expect to see lots of zombies. To that end, I wanted to provide the option to replace several of the built-in creature types in Fallout 4 with zombies.

Leveled Lists

Fallout 4 uses leveled lists for several things including creature spawns. Not all actors in the game world are spawned this way, but most of them are which make them an excellent way to put more zombies in the world.
Bloodbug Leveled Character List

Basically, leveled lists give the game a way to "spawn a bloodbug appropriate for the player's current level". The bloodbugs with higher number in the example above are stronger and higher in level. Once the player hits level 10, the second variation of bloodbug (EncBloodbug02) will start to spawn.

These leveled lists can be changed by mods and completely different creatures can be added to them. So when the game says "spawn a bloodbug appropriate for the player's current level", a Zombie or Alien or Gorilla etc. might appear instead. 

Option 1: modifying leveled lists directly (bad)

These leveled lists can be directly modified by drag & drop. You can both drag existing entries out of the leveled list (removing them) or drag new actor types into the leveled list (adding them). You can also adjust the levels associated with the entries in the list. Doing this allows you to completely replace 100% of leveled list spawns with another creature type if you want to.

Doing this will mark the file as included by your mod but there's a big problem with this. If any other mods modify the same leveled list file, then your mod will conflict. In scenarios where two or more mods modify the same file, the load order comes into play. The last mod loaded wins. You can think of it as each mod effectively overwriting the file changes of previous mods.

For most mods, you can't avoid all possible conflicts as you have to edit some files. That is sort of the point of a mod. But in cases of leveled lists (for spawns, weapon drops, etc.) it is best to avoid modifying them as they tend to be touched a lot by mods. As such, there's no sense in adding possible conflicts when there's another option available...

Option 2: modifying leveled list with a separate mod (a pain)

Other mod authors have created separate mods just for spawn replacements. These mods serve as sort of plugins to the main mod and only focus on replacing a single type. This has the advantage of allowing them to replace 100% of leveled list spawns and only be applied if a user chooses to download and enable that extra mod.

However, the big disadvantage is that mod authors have to maintain multiple mods and end users have to download and enable multiple mods. Keeping everything in one mod is cleaner and simpler. It also makes it a lot easier to enable/disable zombie mode when switching between characters as there is only one mod to toggle. This approach still has the disadvantage of possibly conflicting with other mods as well.

Option 3: modifying leveled lists through scripting

Fortunately there are functions available to modify the various leveled lists in Fallout 4. For spawns there is a LeveledActor script with the following methods:
  • Function AddForm(Form apForm, int auiLevel)
    • Adds the given form to the leveled list under the given level.
  • Function Revert()
    • Removes all script added forms from the leveled list.
This gives you the ability to add and remove all, but I really wish there was a RemoveForm method to remove specific entries. Why? Well, a couple reasons. First, I have no way to remove the existing entries in a leveled list so I can add a bunch of zombies to the list but they'll never spawn 100% of the time. Second, the Revert method can potentially remove entries added by other mods.

Since this is all I have to work with, I tried to make the best of it and provided the following options:
  • Disable (calls Revert and effectively removes any Zombies that may have previously been added)
  • 50% (calls AddForm once per entry in the list)
  • 75% (calls AddForm three times per entry in the list)
  • 90% (calls AddForm nine times per entry in the list)
An important thing to understand is that when there is more than one entry in a leveled list for a given player level, the game will randomly select one of them. So for each level I have accomplished a % chance that a zombie will spawn instead of the default type by adding the appropriate number of zombies for each level in the list. 
  • 1 bloodbug, 1 zombie = 50% a zombie is selected
  • 1 bloodbug, 3 zombies = 75% a zombie is selected
  • 1 bloodbug, 9 zombies = 90% a zombie is selected

Leveled list properties

Leveled lists have a couple properties that can help in figuring out how to approach 100% replacement:
  • Calculate from all levels <= PC's level - if checked, when randomly choosing an actor to spawn all actors in the leveled list less than or equal to the players level are available. This means leveled list entries marked at level 1 are always possible to spawn regardless of player level. If not checked, then only actors at the highest level less than or equal to the players level are available.
  • Calculate for each item in count - if checked, the choice of which actor to spawn is made ONCE and all actors that spawn will be that same actor type/level. If not checked, then actors are randomly selected each time so groups that spawn may be of mixed type/level.
Bloatfly leveled list with both properties not checked.
Consider the bloatfly leveled list example above. The "Calculate from all levels <= PC's level" property is not checked. If we add 9 zombies at level 1, then when the player is level 1 there is a 90% chance for a zombie to spawn. If we add a single zombie at level 2, then when the player is level 2 there is a 100% chance a zombie will spawn. This 100% chance will remain true as the player levels until they hit level 9.

Level 1, 9, 17, 27 = 90% zombie spawn (assuming 9 zombies added for each of these levels)
Level 2-8, 10-16, 18-26, 28+ = 100% zombie spawn (assuming 1 zombie added at levels 2,10,18,28)

If you do the math for bloatflies up to player level 30, then you are looking at an overall replacement rate of around 98.7%.

Implementation with global functions and properties

In implementing the holotape I realized I'd be modifying a lot of leveled lists in a similar way. I wanted to create some helper functions to make my life easier. After some research, I realized I could add a general script to each holotape menu that had global functions defined in it. Inside the Papyrus Fragment for each holotape menu item I can reference those global functions. This basically limited the amount of code I had to write for each replacement to one line per list per fragment.

Replace Bugs terminal config showing global property script and fragment using it.
Using the global function everywhere made my Papyrus Fragments basically simple scripts with a whole lot of properties. I configure properties for each leveled list to be modified and properties specifying the lists of zombies to add to each of those lists. Since the LeveledActor script does not have any "Get" methods, I have no way of knowing by scripting what levels are mapped. Therefore, I created additional properties for each leveled list to specify an array of levels so I know at what levels to add the zombies at. 

Replace Bugs Papyrus Fragment Properties

Bug: headless zombies?

For each leveled list I am updating I tried to add the appropriate matching zombies types. Normal zombies for normal lists, legendary zombies for legendary lists, etc. However, I ran into a bug with the ambush list types.

I went to Red Rocket, greeted Dogmeat, and then waited for the inevitable molerat ambush. Once the enemies spawned, the zombies had invisible heads. They still moved and attacked as normal and I could shoot them where there head should be but the heads were simply missing.

As a result I decided to replace the ambush lists with normal zombies instead until I can figure out what is going on. You'll notice the properties screenshot above has both ZombieList and ZombieAmbushList mapped to the same FormList (ZombieList).

Edit: this is still a bug with the normal ZombieList that I may blog about in a separate post.

Summary of advantages/disadvantages

Using scripting allowed me to make the replacements configurable via holotape and greatly reduce the chances of other mod conflicts. It also keeps everything contained in a single mod which is easier to use and maintain. 

However, due to the lack of a RemoveForm function I was not able to offer a 100% replacement option and my mod still runs the risk of removing other mod added spawn options if users choose to disable replacements after adding them.

Update 11/24/2016

This approach is no longer recommended and I have moved away from it. Please see New Replacement Approach for details.

0 comments:

Finally, time for some scripting In my last post I left off with adding a custom Magic Effect called ZombieInfectionEffect to unarmed fer...

Zombie Walkers - Part 3

Finally, time for some scripting

In my last post I left off with adding a custom Magic Effect called ZombieInfectionEffect to unarmed feral ghoul attacks. Magic effects have a whole lot of properties (too many to describe here). In my case my magic effect exists to add the Infection disease built into Fallout 4's survival difficulty. This requires scripting which is part of the reason I chose to add it to my first release. As a programmer, I was anxious to get into some coding after all these GUI changes.

When you open a Magic Effect and look in the lower right corner of the window you'll see a section for scripts with a label of Script Name. From here you can click the Add button to create a new one, Remove to delete a script, or Properties to set properties of the selected script which we'll come back to later.



Creating a new script will add the new script and bring you straight to the Properties view. Now this confused me at first. I thought maybe scripting was GUI-driven at first when I saw this (it's not). For me this is backwards and I'd rather start working on the flow of the script first which will flush out the properties I need. I close this window and then right click on the new script and select Edit Source.



Scriptname ZombieInfectionScript extends activemagiceffect
Hurray! Source code. Well, one line anyway. Unfortunately, this is point where you start to wonder how you even get started. 

OnEffectStart and Logging

I'll skip ahead a bit and say that I looked at existing magic effects in the CK to get some samples and at least get to a point where I realized the function you need to use to get code to run "on effect start" and how to log data.


Scriptname ZombieInfectionScript extends activemagiceffect
; Called when an Actor is hit by a zombie attack
Event OnEffectStart(Actor akTarget, Actor akCaster)
    ; log function called
    Debug.OpenUserLog("joefor")
    Debug.TraceUser("joefor", "[ZombieInfectionScript] called!" )
EndEvent
In addition to using the special Debug class to open and trace to a user log, you must enable logging in your Fallout4.ini file (C:\Users\{username}\Documents\My Games\Fallout4\Fallout4.ini on Windows 10). Search for the bEnableLogging and bEnableTrace properties and set each to 1.

Save the script with Ctrl-S and verify the script compilation at the bottom of the script window.


Now you can test the function logs by doing the following:

  1. File -> Save to save the mod (.esp file)
  2. File -> Create Archive to generate the archive that contains the script (.ba2 files)
  3. Run the game
  4. Open the console and spawn a zombie using "player.placeatme 000758AD"
  5. Let the zombie hit you
  6. Pause the game and look for a log file (C:\Users\{username}\Documents\My Games\Fallout4\Logs\Script\User\joefor.0 on Windows 10)
  7. Verify the log statement appears in the file once for each time the Zombie hit you

Now for the fun stuff

Now we get to actually write the logic to give the player an Infection. But... how do we do that?

It was at this point that took me a lot of research and trial and error. In the end I looked at existing game files for an example. The breakthrough came when I stumbled upon a Quest called HC_Manager. This quest has a script associated with it called Hardcore:HC_ManagerScript with all kinds of juicy code to implement the new survival mode released after game launch. From this over 3k line script I learned a few things:
  • there is no search function using the built-in script editor! (copy/paste to Notepad++ or something)
  • diseases are Potions that apply MagicEffects
  • to display a message to the player you need to use a predefined Message object
  • you can get a reference to the player with Game.GetPlayer()
  • you can get the current difficulty level with Game.GetDifficulty()
This basically gave me all the pieces I needed to flush out the script logic.


Scriptname ZombieInfectionScript extends activemagiceffect
; Define properties
Potion Property effectToAdd Auto Const Mandatory
MagicEffect Property magicEffectToApply Auto Const Mandatory
Message Property messageToDisplay Auto Const Mandatory
; Called when an Actor is hit by a zombie "bite" attack
Event OnEffectStart(Actor akTarget, Actor akCaster)
; Get Player Actor
Actor player = Game.GetPlayer()
; Check if target is player
if( akTarget  == player )
; Only proceed if difficulty set to survival
if ( Game.GetDifficulty() == 6 )
; Display message only if you don't already have the disease
if( !player.HasMagicEffect(magicEffectToApply) )
messageToDisplay.show()
endif
; Add infection to player (equip potion - force it down their throat!)
player.equipitem(effectToAdd, false, true)
endif
endif
EndEvent
Basically the above is doing a couple checks to only proceed if the target of the effect is the Player and the Difficulty is Survival (6 ... hard-coded this way in the HC_Manager script so I went with it).

The HasMagicEffect function is useful in that it gives you a way to see if the Player already has an Infection (or other effect). This allowed me to avoid spamming the user with popup messages every time they were hit by a Zombie.

The EquipItem function forces the player to activate the special Potion item immediately as if they clicked on it in their inventory.

I said I'd get back to Properties. Well, when you save the script and click on the Properties button you can now see the properties and assign them values. In this case I basically assigned properties for the Infection Potion, Infection Magic Effect, and the Message to display ("you feel ill") from the values bound in the HC_Manager script.


From here you can repeat the test from above while playing at Survival difficulty and verify that you receive the Infection disease when a Zombie hits you. 

Special Bug Note: my initial release did not have the difficulty check. You can apply Infection to players on non-survival difficulties so be careful. Apparently doctors can still cure Infection on those difficulties though (I didn't test this myself but it was mentioned in the mod comments).

Wrap up

This concludes at least most of the changes that went into releasing the initial version of my Zombie Walkers mod. The mod is far from complete and I've already released additional features like NPC Resurrection and Radstag replacement via a new Holotape. I'll continue blogging on specific items and already have some rants in store for NPC Resurrection so stay tuned.

Back to Part 2

0 comments:

Some of the changes below are linked at the Actor level. Most Feral Ghouls extend a single base template (with a few exceptions). This makes...

Zombie Walkers - Part 2

Some of the changes below are linked at the Actor level. Most Feral Ghouls extend a single base template (with a few exceptions). This makes it easier to make changes and have all Ferals inherit them.
Actor -> Actor -> FeralGhoulRace -> Male -> encFeralGhoul01Template

Stop dodging like a monkey

Feral Ghouls have the ability to bob and weave to dodge bullets like agile monkeys. This of course needs to stop. Evade chances are controlled by Combat Style which is linked to Actors on the AI Data tab.
Miscellaneous -> CombatStyle -> csFeralGhoul
On the General tab of the csFeralGhoul combat style there's sliders for Avoid Threats. I set all of them to 0 and so far in my testing have not seen them dodge much of anything.

Make them tougher as you level

Changing Feral Ghouls to level with the player is trivial. Doing so makes them tougher to kill as their hit points will increase. The Stats tab on an Actor has a checkbox called PC Level Mult. Simply check this and the Actor will level with the player.

Don't let them hit you

I wanted to create Zombies that were slow but made you pay if you let them hit you. This means more damage and adverse effects were needed outside of how Feral Ghouls work in the game by default.

Feral Ghouls don't use weapons in Fallout 4. They attack with their hands (and bite). These attacks use a hidden Unarmed Weapon that is linked to the Race on the Combat Data tab.
Weapon -> Default -> UnarmedFeralGhoul
Weapons have a lot of fields that I haven't explored yet. The only field I modified for this mod as of the time of this writing is base damage by changing it from 15 to 30 (Damage -> Base).

Some weapons, including this one, have magical enchantments associated with them that is specified using the Enchanting dropdown. Seeing the term "Enchanting" is one of many hints that the Creation Kit originated with the Elder Scrolls games (eg. Skyrim) and it is a little humorous to see it retrofitted for Fallout 4 but it works.
Miscellaneous ->dtRadiationEnchFeralGhoul
Feral Ghouls had a little bit of bleed damage (which I may add back at some point) and radiation damage that varied dependent on level. I changed this to include two effects for the first release:
  1. The Stagger effect used by the Yao Guai. Ideally I'd like to have the Zombies grab their enemies and then bite, but that may not be doable. I figured a stagger is the closest I could come in that if they hit their prey, the prey would stagger allowing them to close in for the kill. It makes the Zombies very dangerous, especially in groups.
  2. My own custom magic effect called ZombieInfectionEffect which I'll blog about in the next post.

0 comments:

Pages (8)1234567 »