Gun fusion / breeding - Thought and notes


While working on porting the gun system to Godot, I took a peek at the code responsible to breed / fuse guns. It was very confusing and I simply had no idea how it worked and how its supposed to work. That was, like, 6 months ago.

For the next update, I decided to work on gun breeding / fusing, trying to replicate the original game's behavior.

On this post, I wanted to document and rant about how it work, how I managed to replicate the system and some weird quirks I found out.

Overview

Gun fusing is supposed to work like this.

Lets take 2 generic guns, found in the wild, Gun_A (Type Pistol, Material Steel) and Gun_B (Type Shotgun, Material Zinc), and fuse / breed them. After fusing, a Gun_C (Type Revolver, Material Fiberglass) is created. The type and material choices are not random and both have a login behind it.
Gun_C stats and affixes are also the mixed stats from both parents, but its not just a simple average.



Lets take a look at the process used to breed these guns.

  • Create a "blank" gun for the child
  • Using both parent's Gunmap positions, define a type for the child
  • Using both parent's material, define the child's material using the "Material periodic table".
  • Using both parent's stats, define the child stats using averages and noises.
  • Using both parent's affixes, define the child affix
  • Update the child's gun name.

Create a "blank" gun for the child

This is a very simple one. Just create a random gun to serve as a template. Also, create 2 "fake" parents for this gun. These parents are created semi-randomly. Store the parent data as a Dictionary.

NOTE: "fake" parents do not have parents.

NOTE2: "fake" parents aren't semi-random anymore. It tries to do a "backwards fusing" extrapolating data from the child gun. Type / Material / Affixes make sense now.

Using both parent's Gunmap positions, define a type for the child

Ah, the GunMap. For the longest time, I thought that this was just a silly map, that had no impact over anything.

The idea for the GunMap is very interesting. Each guntype live in a different section of the map (landmass). The a gun is created, a random spot on that gun type's section is claimed for that weapon.

When a Gun is fused, the type is decided based on the average position for both guns. 

T = Top Gun, B = Bottom Gun, X = Child Gun

Each parent can also have a bigger influence over the child's final position.

T = Top Gun, B = Bottom Gun, X = Child Gun


The map is created in a very interesting manner. The code from the original game was WAY too confusing and I decided to make my own implementation. Here is a great article that I used as a reference: https://christianjmills.com/posts/procedural-map-generation-techniques-notes/

For the map, I used Diffusion-Limited Aggregation (DLA) and Drunkard’s Walk (I think). Here is how it works:

  • Create a 80 x 80 Dictionary filled with the material "None"
  • Randomly, set 6 "Gun Group Regions". The game can group similar weapons to groups. This way, similar gun types are set near each other.
  • Randomly, set 27 "seeds" for each gun type. 
  • Initially for each "seed" spot, grow 13 tiles outward. This ensures that no gun type can be overwhelmed by other gun type.
  • Depending on the type rarity and permutations set, grow each region one pixel at time until most of the map is filled.
  • Create a image using the data from the dictionary.

Turns out that the original game uses a very similar method, but the code itself is very confusing.

It works very well and haven't had any issues with so far.

Using both parent's material, define the child's material using the "Material periodic table".

Material fusing is actually very simple, but the code is very, VERY messy. I'm sure that they had some kind of documentation on hand while developing this method, but since I don't have it, I was lost for the longest time.

First, check this periodic table shared by Frankie here.



And here is my in-game periodic table:


The material choice itself has a bunch of exceptions and special behaviors depending on the material, but basically you take the average atomic weight of both materials and round down to the nearest material.
The original game's code made this much more confusing than needed. The periodic table data was stored on a CSV file and the programmers had to jump through many hoops to index that data correctly. I just parsed all that data and threw them on a JSON file.
Man, working with Godot is so much simpler than GML.

Using both parent's stats, define the child stats using averages and noises.

This one was pretty funny. Check the original code here.

Basically, its juts a bunch of calculations of averages between both parents + some random noise, storing them inside array.

I just copy-pasted all that code,  adjusted how arrays are handled (due to the differences between GML and GDScript) and adjusted how the data is delivered to the child gun.

It works, but the base stats generation is still broken, so this calculations may result in some overwhelming stats.

Using both parent's affixes, define the child affix

The code for this was, surprise surprise, a bit weird and confusing.

I think i got the gist of what it was trying to do and coded my own interpretation.

Gun can have 3 affixes; Prefix1, Prefix2 and Suffix. Each affix will apply some effect / bullet behavior, but that isn't coded yet.

We just take the affix list for both guns, apply an OR operation to it and add them to the child gun. if both guns doesn't have Prefix1, for example, the child gun has a small chance to get a random prefix.

Update the child's gun name.

Just re-run the "Get gun name" function once again. Pretty simple.

Conclusion

So far, this is it.

I'm still working on the next update that will probably just contain this "Gun fusing and stats" change, along with the diving minigame.
Iḿ only doing the diving minigame because it seems fun to work on.

Get Barkley 2 - Godot Port

Download NowName your own price

Leave a comment

Log in with itch.io to leave a comment.