Look into a system for unifying different attribute bonuses / abilities.
SigmundGranaas opened this issue ยท 3 comments
Every tool part, material and gem has attributes hard-coded, and each attribute needs to be handled specifically. This leads to a lot of verbose code and a very rigid system. I need to look into system, like EntityAttributes which can be recongnised at different parts in the game.
TLDR; the current system is very rigid, making changing things up really hard.
I have made a lot of progress regarding a new Attribute system. A basic version is implemented in #72. The main issue with the system is balancing the properties and figuring out which materials should boost which stats. This still needs some work. The system currently only supports attributes, as I have to figure out how to implement specific buffs later.
TODO:
Here are some fields I need to work on before merging the new property system.
Attributes:
- Create rules/calculations for how MINING_LEVEL attributes should be handled by tools
- Scrub conditions when properties regarding tool parts and their placements are gathered from tool part state. This is important to allow tool parts specific buffs to be applied when you no longer know where they came from.
- Add properties to gems and let them be recognised when fetching attributes.
- Rework the target interface. The interface needs to be much better encapsulated, it is quite stupid right now.
- Add rarity to properties.
- Remove traces of the old attributes
- Add edge case handling in case
- Figure out how Attack speed works and how to work with it. why is it negative
- Decide on a way to handle negative attributes. Make sure properties does not end up negative and that negative scaling does not multiply with another negative, which ends up being positive.
- Allow gem levels to affects properties
General:
- List all properties associated with tools, gems and tool parts when viewing their descriptions.
- Add baseline damage and attack speed to weapon heads, to make constructing Tool Items easier to initialize. Currently they need an extra float when being constructed because I was lazy when coding it.
Documentation:
- Document the Attribute API and how it is used, all interfaces should be properly documented.
- Document an example on the WIKI for how Materials and gems are described with JSON and what the properties mean.
Tests:
- Create a baseline for how weapons should behave compared to vanilla behaviour
- Create tests for making sure that some combination of tools won't be to powerful
- Create tests for what happens when you approach edge cases
- Verify conditions for properties with TOOL_PART_PLACEMENTS conditions.
- Create a baseline test for what a diamond tool head should be able to achieve with a variety of upgrades. Secondary upgrades, gems, handles and bindings.
- Create a baseline test for what a netherite tool should be able to achieve with a variety of upgrades. Secondary upgrades, gems, handles and bindings.
- Create a baseline test for what a wooden tool should be able to achieve with a variety of upgrades. Secondary upgrades, gems, handles and bindings.
- Create a baseline test for what a iron tool should be able to achieve with a variety of upgrades. Secondary upgrades, gems, handles and bindings.
Idea
Handle all properties of tool parts with the same type of attributes. This means treating all properties of all tool parts as a "pool" of properties, which will be gathered, sorted and computed whenever the tool is used.
I see no reason for restricting which properties can be applied to any tool part/gem in code. There are of curse a lot of properties which don't belong on certain materials or gems, but that decision should be handled when creating the resources.
I need to create some core types of attributes which can be filtered when calculating properties. If I can efficiently stream attributes i can create a sort of DSL to gather the right properties.
Categories
- Mining speed
- Mining level
- Durability
- Attack speed
- Attack damage
- Passive attributes
- Use attributes
Examples
{
"properties": {
"attributes": [
{
"attack_damage": {
"order": "END",
"type": "MULT",
"value": 1.2,
"condition": {
"target": "ENTITY",
"tag": "LIVING"
}
}
},
{
"attack_speed": {
"order": "BASE",
"type": "ADD",
"value": 3.0
}
},
{
"attack_speed": {
"order": "BASE",
"type": "ADD",
"value": 3.0,
"condition": {
"target": "ENVIRONMENT",
"tag": "DAY"
}
}
},
{
"attack_damage": {
"order": "BASE",
"type": "ADD",
"value": 3.0
}
}
],
"passive": [
{
"type": "EMISSIVE",
"value": 3.0
},
{ "type": "GOLDEN" }
],
"active": []
}
}
A system like EntityAttributes can be gathered from all tool parts using streams.
I want to be able to support three things:
Custom behaviour
I want to support dynamically adding custom behaviour to tool based on properties of the toolparts, materials and gems.
Examples of this is:
Adding gold to equipment should make piglins friendly
Wooden equipment taking damage when you are on fire
Equipment working better at certain parts of day/weather
Interacting with environment, really expensive equipment can affect how things react to you.
Lighting up the environment if you are carrying luminous equipment.
Custom base attributes
I want to support setting custom attributes, this is the base stats provided by materials and gems.
Adaptive attributes
I want to support adding attributes for tools which change based on the situation. This can be tools that work better on certain types of blocks, like materials that work better when used on "harder" rocks. Some swords/weapons should also work a lot better against different types of enemies. Hammers should be better against skeletons.
Supporting all of this requires the tool to have a very dynamic strategy for calculating stats, and it needs to be able to gather all potential properties and export them to the game world. Hardcoding stats and strategies is not good enough.
Gems
Gems is currently designed quite bad. I have duplicate code and a mess of inheritance across interfaces. the behaviour is hard-coded, and quite bad.
A new approach could be to define only the interface for where gems can be placed, like Head gems, Handle gems and binding gems. I would define standard default methods for all methods, which enables me to expand the interface and what each gems can be able to do. new Gems can either be added with new classes, or I can create Anonymous classes to deal with the methods. I can also change the flow, so the are registered as Functional interfaces.
TODO: I need to research how to create a very dynamic flow for calculating properties of tools. This needs to support reordering operations and targets.