Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions docs/modding/hitman/guides/suitmodding/newoutfit.md
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,7 @@ Open your outfit file in GlacierKit.
Copy the following textbox (it is an entity) and paste it into the root `OUTFIT_Agent47_Street_Smart_HeroA_V0` entity by selecting Clipboard and clicking Paste.

```json
{"rootEntity":"cafe1c73325d6168","data":{"cafe1c73325d6168":{"parent":"8d2dd8c9d88913be","name":"FX_Hitman_Wet_Logic_Character","factory":"[assembly:/_pro/effects/templates/water/fx_water_hitman_wet_logic.template?/fx_hitman_wet_logic_character.entitytemplate].pc_entitytype","blueprint":"[assembly:/_pro/effects/templates/water/fx_water_hitman_wet_logic.template?/fx_hitman_wet_logic_character.entitytemplate].pc_entityblueprint","properties":{"HeadMaterialToOverride":{"type":"ZRuntimeResourceID","value":{"resource":"[assembly:/_pro/characters/assets/_sourcefiles/male_reg_heads_unique/materials/male_reg_head_47_s3.mi].pc_mi","flag":"5F"}},"HeadMaterialOverride":{"type":"TArray<SEntityTemplateReference>","value":[],"postInit":true}},"events":{"HitmanWetness":{"T":["cafeb592e0ab9249","cafedc850188fd63","cafe57b613171dc2","cafee50db419698b"]}}},"cafe57b613171dc2":{"parent":"cafe1c73325d6168","name":"Lerp roughness fabric","factory":"[modules:/zmathlerp.class].pc_entitytype","blueprint":"[modules:/zmathlerp.class].pc_entityblueprint","properties":{"m_A":{"type":"float32","value":1.0},"m_fT":{"type":"float32","value":0.0},"m_B":{"type":"float32","value":2.0}},"events":{"Lerp":{"ConstantVector1D_14_Value":[]}}},"cafedc850188fd63":{"parent":"cafe1c73325d6168","name":"Lerp bumpmap","factory":"[modules:/zmathlerp.class].pc_entitytype","blueprint":"[modules:/zmathlerp.class].pc_entityblueprint","properties":{"m_fT":{"type":"float32","value":0.0},"m_B":{"type":"float32","value":0.30000001192092896}},"events":{"Lerp":{"ConstantVector1D_06_Value":[]}}},"cafee50db419698b":{"parent":"cafe1c73325d6168","name":"Lerp roughness other","factory":"[modules:/zmathlerp.class].pc_entitytype","blueprint":"[modules:/zmathlerp.class].pc_entityblueprint","properties":{"m_B":{"type":"float32","value":0.4000000059604645},"m_A":{"type":"float32","value":0.0},"m_fT":{"type":"float32","value":0.0}},"events":{"Lerp":{"ConstantVector1D_04_Value":[]}}},"cafeb592e0ab9249":{"parent":"cafe1c73325d6168","name":"Lerp albedo","factory":"[modules:/zmathlerp.class].pc_entitytype","blueprint":"[modules:/zmathlerp.class].pc_entityblueprint","properties":{"m_fT":{"type":"float32","value":0.0},"m_B":{"type":"float32","value":0.20000000298023224}},"events":{"Lerp":{"ConstantVector1D_01_Value":[]}}}}}
{"rootEntity":"cafe704aaa4b21c5","data":{"cafe704aaa4b21c5":{"parent":"22ea5f8267450642","name":"FX_Hitman_Wet_Logic_Character","factory":"[assembly:/_pro/effects/templates/water/fx_water_hitman_wet_logic.template?/fx_hitman_wet_logic_character.entitytemplate].pc_entitytype","blueprint":"[assembly:/_pro/effects/templates/water/fx_water_hitman_wet_logic.template?/fx_hitman_wet_logic_character.entitytemplate].pc_entityblueprint","properties":{"HeadMaterialToOverride":{"type":"ZRuntimeResourceID","value":{"resource":"[assembly:/_pro/characters/assets/_sourcefiles/male_reg_heads_unique/materials/male_reg_head_47_s3.mi].pc_mi","flag":"5F"}},"HeadMaterialOverride":{"type":"TArray<SEntityTemplateReference>","value":[],"postInit":true}},"events":{"HitmanWetness":{"T":["cafe7713b2d0cc7f","cafe12a9bd56da15","cafea848f0bc31e6","cafecc20e8c149df","cafe714de5ad0557"]}}},"cafecc20e8c149df":{"parent":"cafe704aaa4b21c5","name":"Lerp roughness fabric","factory":"[modules:/zmathlerp.class].pc_entitytype","blueprint":"[modules:/zmathlerp.class].pc_entityblueprint","properties":{"m_A":{"type":"float32","value":0.0},"m_fT":{"type":"float32","value":0.0},"m_B":{"type":"float32","value":0.4}},"events":{"Lerp":{"ConstantVector1D_14_Value":[]}}},"cafea848f0bc31e6":{"parent":"cafe704aaa4b21c5","name":"Lerp bumpmap","factory":"[modules:/zmathlerp.class].pc_entitytype","blueprint":"[modules:/zmathlerp.class].pc_entityblueprint","properties":{"m_A":{"type":"float32","value":0},"m_fT":{"type":"float32","value":0.0},"m_B":{"type":"float32","value":0.6}},"events":{"Lerp":{"ConstantVector1D_06_Value":[]}}},"cafe714de5ad0557":{"parent":"cafe704aaa4b21c5","name":"Lerp roughness other","factory":"[modules:/zmathlerp.class].pc_entitytype","blueprint":"[modules:/zmathlerp.class].pc_entityblueprint","properties":{"m_A":{"type":"float32","value":0.0},"m_fT":{"type":"float32","value":0.0},"m_B":{"type":"float32","value":0.4}},"events":{"Lerp":{"ConstantVector1D_04_Value":[]}}},"cafe7713b2d0cc7f":{"parent":"cafe704aaa4b21c5","name":"Lerp albedo","factory":"[modules:/zmathlerp.class].pc_entitytype","blueprint":"[modules:/zmathlerp.class].pc_entityblueprint","properties":{"m_A":{"type":"float32","value":0.5},"m_fT":{"type":"float32","value":0.0},"m_B":{"type":"float32","value":0.2}},"events":{"Lerp":{"ConstantVector1D_01_Value":[]}}},"cafe12a9bd56da15":{"parent":"cafe704aaa4b21c5","name":"Lerp jacket albedo","factory":"[modules:/zmathlerp.class].pc_entitytype","blueprint":"[modules:/zmathlerp.class].pc_entityblueprint","properties":{"m_A":{"type":"float32","value":2},"m_fT":{"type":"float32","value":0.0},"m_B":{"type":"float32","value":1}},"events":{"Lerp":{"ConstantVector1D_01_Value":[]}}}}}
```

You should now have an `FX_Hitman_Wet_Logic_Character` entity in the tree.
Expand All @@ -635,17 +635,19 @@ Now expand the `FX_Hitman_Wet_Logic_Character` entity and we will look at its ch

This will make the `ConstantVector1D_01_Value` go from A to B when it is triggered. `ConstantVector1D_01_Value` is a value that controls the brightness of the albedo (or diffuse) texture. It will, in effect, make a texture darker over time.

You might notice that it has an `m_B` (after) property, but not an `m_A` (before) property. If A is not specified it will use the referenced entity's standard `ConstantVector1D_01_Value` value as A.

Under the `events` and `Lerp` property we find an array called `ConstantVector1D_01_Value`. This is an array of entity IDs whose `ConstantVector1D_01_Value` that the `zmathlerp` entity should modify. Right now it is empty, so let's fill it up.

Like I mentioned only things made of fabric should be darker in the rain. So right click and copy the IDs of `hat_beanie_cuffed`, `Jacket_Bomber_Open`, `Pants_Jeans_Skinny`, and `TShirt_CrewNeck_Cut_Jacket`, and put them into this array, separated by commas.
Like I mentioned only things made of fabric should be darker in the rain. So right click and copy the IDs of `hat_beanie_cuffed`, `Pants_Jeans_Skinny`, and `TShirt_CrewNeck_Cut_Jacket`, and put them into this array, separated by commas.

It should look something like this when you are done.

![Supplying the Lerp albedo entity](/img/suitmodding/newoutfit/lerp_albedo.png)

With the `Lerp albedo` supplied let's continue with `Lerp bumpmap`. The property for this lerp is `ConstantVector1D_06_Value` which controls how strong the normal map is.
You will notice the jacket has its own albedo lerp. This is because its `ConstantVector1D_01_Value` starts at a much higher value (2, not 1). So if we step out of the rain the jacket's `ConstantVector1D_01_Value` will return to 1 and not 2, which is very dark. It's not uncommon to have to create multiple lerps, given that each value can be different for each body part.

Supply `Jacket_Bomber_Open`'s entity ID into `Lerp jacket albedo`s event.

With the `Lerp albedo`s supplied let's continue with `Lerp bumpmap`. The property for this lerp is `ConstantVector1D_06_Value` which controls how strong the normal map is.

We will be using the same entities as we specified in the albedo lerp for this one, so you can copy the array and paste it in for this. Just take care not to replace `ConstantVector1D_06_Value`.

Expand Down
2 changes: 2 additions & 0 deletions docs/modding/hitman/guides/suitmodding/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Let us take our [Street Smart](./newoutfit.md) outfit and introduce a pair of gl

First off you actually *cannot* use GlacierKit for this as it does not presently have the ability to patch custom entities, only stock game entities. You will need to download the legacy [QuickEntity Editor](https://github.com/atampy25/quickentity-editor-next/releases/latest/) to make options for your custom entities. So download it now and install it.

Due to a potential bug you may need to manually create the QuickEntity working directory. Hit Win + R, type `%APPDATA%` and hit Enter. In this folder create the folder `app.quickentity.editor`.

## Preparing

In your mod folder `MyName.StreetSmart`, create a new folder called `patches`. In that folder, make a folder called `gloves`. In that folder, make a folder called `leather`. In that folder, make a folder called `chunk0`.
Expand Down
173 changes: 173 additions & 0 deletions docs/modding/hitman/guides/suitmodding/propertyaliases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
---
sidebar_position: 8
description: Exploring templates, property aliases and input copying
---

# Property Aliases, Input Copying and Template Anatomy

The particularly eagle eyed out there may have noticed in the [Street Smart outfit we made](./newoutfit.md) that the bomber jacket and jeans don't actually change much in the rain. But how is that possible? We are changing the constant vectors with our lerp, so it should work?

This is because the `Jacket_Bomber_Open` and `Pants_Jeans_Skinny` templates we are using don't have an *input copying* set up for the constant vectors we are using. First though let's start with a related concept known as *property aliases*. Property aliases allow us to specify things like colors, or a template's mesh.

## Property aliases

Let's open our Street Smart outfit project. In the `outfit_street_smart.entity.json` file, click `Jacket_Bomber_Open` in the tree.

![Opening the bomber jacket template](/img/suitmodding/propertyaliases/open_factory.png)

Right click the factory path and click **Open factory in new tab.** This is the jacket's template. Some properties in the screenshot have been collapsed for brevity.

![The jacket template open](/img/suitmodding/propertyaliases/jacket_template.png)

The top layer entity is just a blank zentity. It's essentially a clean slate and needs to be configured. It needs to pass our constant vectors along to material entities down the tree. For this, property aliases are used.

For example, by *exposing* the `Mesh` entity's `m_pMeshResource` property through a property alias, we can easily change the `m_pMeshResource` directly through the template's properties as we need to, in an outfit for example.

The same is true for `Diffuse_Color_01_Value` and `ConstantVector1D_01_Value`. Consider the top-most property alias:

```json
"ConstantVector1D_01_Value": [
{
"originalProperty": "ConstantVector1D_01_Value",
"originalEntity": "4bcc2cbe47581fe1"
}
]
```

This simply means that any `ConstantVector1D_01_Value` supplied to the template will be *forwarded* to the sub-entity `4bcc2cbe47581fe1` with the property `ConstantVector1D_01_Value`.

The property alias itself can be named whatever we want, as long as the `originalProperty` is the correct property name. And we can supply multiple subentities for each property alias. As an example this is perfectly valid:

```json
"Shinyness": [
{
"originalProperty": "ConstantVector1D_14_Value",
"originalEntity": "cafefb0bd0b2a258"
},
{
"originalProperty": "ConstantVector1D_04_Value",
"originalEntity": "cafebe430153005e"
}
]
```

Then in an outfit where we implement the template, both of these constant vectors would be changed if we supply a property like this:

```json
"Shinyness": {
"type": "float32",
"value": 15.0
}
```

## Input copying

Input copying is a related concept to property aliases but you are forwarding events instead. The wet logic fires events at the clothing templates, but since there is no input copying to forward the event to the material entity inside, nothing happens.

The beanie and the t-shirt in the Street Smart outfit actually have this set up already. Let's look at the t-shirt for a reference.

![Opening the t-shirt's template.](/img/suitmodding/propertyaliases/open_tshirt.png)

Go back to the Street Smart outfit, find the t-shirt and open its factory.

![The T-shirt templates input copying forwarding events.](/img/suitmodding/propertyaliases/inputcopying.png)

The format is slightly different to the property aliases but you should be able to follow the flow. When the template receives a `ConstantVector1D_06_Value` (bump map strength) event from the wet logic, it forwards it to an array of entities, which right now is only the `base_male_shirt_regular` sub-entity.

Much like property aliases we can also name input copying whatever we want. As an example IOI have done this for 47's suit:

![47's suit having specifically named input copying.](/img/suitmodding/propertyaliases/47_suit_inputcopying.png)

But all we need to worry about is forwarding the constant vector events to the jacket's material entity, and the jeans' material entity. Let's go back to our jacket and do that.

## Creating our patches

### The jacket

With the jacket's template open, create a new object directly after `properties` named `inputCopying`. We will need 3 objects inside `inputCopying` for our 3 constant vectors that forward to the material entity named `base_male_jacket_bomber`. Feel free to copy them here and paste under `inputCopying`:

```json
"ConstantVector1D_06_Value": {
"ConstantVector1D_06_Value": [
"4bcc2cbe47581fe1"
]
},
"ConstantVector1D_14_Value": {
"ConstantVector1D_14_Value": [
"4bcc2cbe47581fe1"
]
},
"ConstantVector1D_01_Value": {
"ConstantVector1D_01_Value": [
"4bcc2cbe47581fe1"
]
}
```

It should look like this when set up:

![The jacket template with input copying hooked up.](/img/suitmodding/propertyaliases/corrected_jacket.png)

We will also need to make sure that these 3 constant vectors `_op` parameters in the material entity are set to `eReplace`. Go to the `base_male_jacket_bomber` material entity and check.

![The albedo value is set up properly.](/img/suitmodding/propertyaliases/albedo_value.png)

At least `ConstantVector1D_01_Value_op` is set to `eReplace`, but `06` and `14` aren't here. Feel free to copy them here and paste them into properties:

```json
"ConstantVector1D_06_Value_op": {
"type": "IRenderMaterialEntity.EModifierOperation",
"value": "eReplace"
},
"ConstantVector1D_14_Value_op": {
"type": "IRenderMaterialEntity.EModifierOperation",
"value": "eReplace"
},
```

Now save your changes. Save it under `content/chunk0` with the file name `jacket_bomber_open`.

### The jeans

Go back to the Street Smart outfit and open the factory for `Pants_Jeans_Skinny`. This template doesn't have any properties, so just make `inputCopying` after `blueprint`. Like before we forward our 3 constant vector events to the material entity, named `male_reg_pants_jeans`. Feel free to copy from here:

```json
"ConstantVector1D_06_Value": {
"ConstantVector1D_06_Value": [
"ecd31deec793f2a9"
]
},
"ConstantVector1D_14_Value": {
"ConstantVector1D_14_Value": [
"ecd31deec793f2a9"
]
},
"ConstantVector1D_01_Value": {
"ConstantVector1D_01_Value": [
"ecd31deec793f2a9"
]
}
```

It should look like this when set up:

![The jacket template with input copying hooked up.](/img/suitmodding/propertyaliases/corrected_jeans.png)

Like with the jacket check the material entity `male_reg_pants_jeans` for our 3 constant vector `_op` parameters. `01` and `14` are present but not `06`. Feel free to copy it here and paste under properties.

```json
"ConstantVector1D_06_Value_op": {
"type": "IRenderMaterialEntity.EModifierOperation",
"value": "eReplace"
},
```

Now save your changes. Save it under `content/chunk0` with the file name `pants_jeans_skinny`.

Deploy and see that you should now be properly soggy, with the pants and jacket wet!

![47 more wet than usual.](/img/suitmodding/propertyaliases/properly_soggy.jpg)

## Further reading

If you want to dive deeper into these entity concepts please see the [Hitman Resources](https://hitman-resources.netlify.app/documentation/entity-system/entity-templates/overview).
Binary file modified static/img/suitmodding/newoutfit/lerp_albedo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified static/img/suitmodding/newoutfit/wet_01.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified static/img/suitmodding/newoutfit/wet_02.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified static/img/suitmodding/newoutfit/wet_logic.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading