feat(ALP)
This commit is contained in:
parent
ff3ab9a974
commit
6aac2af208
26 changed files with 63289 additions and 0 deletions
29
user/mods/AlgorithmicLevelProgression/.github/workflows/action.yml
vendored
Normal file
29
user/mods/AlgorithmicLevelProgression/.github/workflows/action.yml
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
name: "tagged-release"
|
||||
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
tagged-release:
|
||||
name: "Tagged Release"
|
||||
runs-on: "ubuntu-latest"
|
||||
permissions:
|
||||
contents: write
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 2
|
||||
- name: Print package.json version (before)
|
||||
id: versionstep
|
||||
run: |
|
||||
echo "version=$(jq -r .version package.json)" >> $GITHUB_OUTPUT
|
||||
working-directory: ${{ github.workspace }}
|
||||
- uses: "marvinpinto/action-automatic-releases@latest"
|
||||
with:
|
||||
repo_token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
automatic_release_tag: ${{ steps.versionstep.outputs.version }}
|
||||
title: "ALP ${{ steps.versionstep.outputs.version }}"
|
||||
prerelease: false
|
||||
files: |
|
||||
./dist/*.zip
|
||||
15
user/mods/AlgorithmicLevelProgression/.releaserc
Normal file
15
user/mods/AlgorithmicLevelProgression/.releaserc
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
branches:
|
||||
- main
|
||||
- name: staging
|
||||
prerelease: true
|
||||
debug: true
|
||||
ci: true
|
||||
dryRun: false
|
||||
plugins:
|
||||
- "@semantic-release/commit-analyzer"
|
||||
- "@semantic-release/release-notes-generator"
|
||||
- "@semantic-release/github"
|
||||
- "@semantic-release/npm"
|
||||
- - "@semantic-release/git"
|
||||
- assets: ["package.json"]
|
||||
message: "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
|
||||
21
user/mods/AlgorithmicLevelProgression/LICENSE.md
Normal file
21
user/mods/AlgorithmicLevelProgression/LICENSE.md
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2023 DewardianDev
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
650
user/mods/AlgorithmicLevelProgression/config/advancedConfig.json
Normal file
650
user/mods/AlgorithmicLevelProgression/config/advancedConfig.json
Normal file
|
|
@ -0,0 +1,650 @@
|
|||
{
|
||||
"DO NOT CHANGE ANYTHING HERE": "DON't ASK FOR HELP IF YOU DO!",
|
||||
"forceStock": true,
|
||||
"daytimeSilencerCutoff": -22,
|
||||
"forbiddenBullets": {
|
||||
"3": [],
|
||||
"4": [
|
||||
"5d6e68a8a4b9360b6c0d54e2",
|
||||
"5efb0da7a29a85116f6ea05f",
|
||||
"5efb0cabfb3e451d70735af5",
|
||||
"5a26ac0ec4a28200741e1e18",
|
||||
"5cc80f38e4a949001152b560",
|
||||
"5ba26835d4351e0035628ff5",
|
||||
"61962d879bb3d20b0946d385",
|
||||
"5c0d688c86f77413ae3407b2",
|
||||
"61962b617c6c7b169525f168",
|
||||
"56dff026d2720bb8668b4567",
|
||||
"5c0d5e4486f77478390952fe",
|
||||
"59e690b686f7746c9f75e848",
|
||||
"601949593ae8f707c4608daa",
|
||||
"59e0d99486f7744a32234762",
|
||||
"601aa3d2b2bcb34913271e6d",
|
||||
"5fd20ff893a8961fc660a954",
|
||||
"5a6086ea4f39f99cd479502f",
|
||||
"5efb0c1bd79ff02a1f5e68d9",
|
||||
"560d61e84bdc2da74d8b4571",
|
||||
"5e023d48186a883be655e551",
|
||||
"5cadf6eeae921500134b2799",
|
||||
"5fc382a9d724d907e2077dab"
|
||||
],
|
||||
"5": []
|
||||
},
|
||||
"locations": {
|
||||
"bigmap": {
|
||||
"sightConfiguration": {
|
||||
"SniperRifle": ["OpticScope", "AssaultScope"],
|
||||
"MarksmanRifle": ["OpticScope", "AssaultScope", "Collimator"],
|
||||
"AssaultCarbine": ["AssaultScope", "Collimator", "CompactCollimator"],
|
||||
"AssaultRifle": ["AssaultScope", "Collimator", "CompactCollimator"],
|
||||
"MachineGun": ["Collimator", "CompactCollimator"],
|
||||
"Smg": ["Collimator", "CompactCollimator"],
|
||||
"SpecialWeapon": ["Collimator", "CompactCollimator"],
|
||||
"Shotgun": ["Collimator", "CompactCollimator"],
|
||||
"Pistol": ["Collimator", "CompactCollimator"],
|
||||
"Revolver": ["Collimator", "CompactCollimator"],
|
||||
"GrenadeLauncher": ["Collimator", "CompactCollimator"]
|
||||
},
|
||||
"weightingAdjustments": {
|
||||
"FirstPrimaryWeapon": {
|
||||
"AssaultCarbine": 1.2,
|
||||
"AssaultRifle": 1.3,
|
||||
"GrenadeLauncher": 1,
|
||||
"MachineGun": 1.2,
|
||||
"MarksmanRifle": 0.7,
|
||||
"Revolver": 1.2,
|
||||
"Shotgun": 1.2,
|
||||
"Smg": 1.3,
|
||||
"SniperRifle": 0.7
|
||||
}
|
||||
}
|
||||
},
|
||||
"factory4_day": {
|
||||
"sightConfiguration": {
|
||||
"SniperRifle": ["Collimator", "CompactCollimator"],
|
||||
"MarksmanRifle": ["Collimator", "CompactCollimator"],
|
||||
"AssaultCarbine": ["Collimator", "CompactCollimator"],
|
||||
"AssaultRifle": ["Collimator", "CompactCollimator"],
|
||||
"MachineGun": ["Collimator", "CompactCollimator"],
|
||||
"Smg": ["Collimator", "CompactCollimator"],
|
||||
"SpecialWeapon": ["Collimator", "CompactCollimator"],
|
||||
"Shotgun": ["Collimator", "CompactCollimator"],
|
||||
"Pistol": ["Collimator", "CompactCollimator"],
|
||||
"Revolver": ["Collimator", "CompactCollimator"],
|
||||
"GrenadeLauncher": ["Collimator", "CompactCollimator"]
|
||||
},
|
||||
"weightingAdjustments": {
|
||||
"FirstPrimaryWeapon": {
|
||||
"AssaultCarbine": 0.8,
|
||||
"AssaultRifle": 1.2,
|
||||
"GrenadeLauncher": 1.5,
|
||||
"MachineGun": 1.2,
|
||||
"MarksmanRifle": 0.3,
|
||||
"Revolver": 1.5,
|
||||
"Shotgun": 1.2,
|
||||
"Smg": 1.5,
|
||||
"SniperRifle": 0.3
|
||||
}
|
||||
}
|
||||
},
|
||||
"factory4_night": {
|
||||
"sightConfiguration": {
|
||||
"SniperRifle": ["Collimator", "CompactCollimator"],
|
||||
"MarksmanRifle": ["Collimator", "CompactCollimator"],
|
||||
"AssaultCarbine": ["Collimator", "CompactCollimator"],
|
||||
"AssaultRifle": ["Collimator", "CompactCollimator"],
|
||||
"MachineGun": ["Collimator", "CompactCollimator"],
|
||||
"Smg": ["Collimator", "CompactCollimator"],
|
||||
"SpecialWeapon": ["Collimator", "CompactCollimator"],
|
||||
"Shotgun": ["Collimator", "CompactCollimator"],
|
||||
"Pistol": ["Collimator", "CompactCollimator"],
|
||||
"Revolver": ["Collimator", "CompactCollimator"],
|
||||
"GrenadeLauncher": ["Collimator", "CompactCollimator"]
|
||||
},
|
||||
"weightingAdjustments": {
|
||||
"FirstPrimaryWeapon": {
|
||||
"AssaultCarbine": 0.8,
|
||||
"AssaultRifle": 1.2,
|
||||
"GrenadeLauncher": 1.5,
|
||||
"MachineGun": 1.2,
|
||||
"MarksmanRifle": 0.3,
|
||||
"Revolver": 1.5,
|
||||
"Shotgun": 1.2,
|
||||
"Smg": 1.5,
|
||||
"SniperRifle": 0.3
|
||||
}
|
||||
}
|
||||
},
|
||||
"interchange": {
|
||||
"sightConfiguration": {
|
||||
"SniperRifle": ["OpticScope", "AssaultScope"],
|
||||
"MarksmanRifle": ["OpticScope", "AssaultScope", "Collimator"],
|
||||
"AssaultCarbine": ["AssaultScope", "Collimator"],
|
||||
"AssaultRifle": ["AssaultScope", "Collimator", "CompactCollimator"],
|
||||
"MachineGun": ["Collimator", "CompactCollimator"],
|
||||
"Smg": ["Collimator", "CompactCollimator"],
|
||||
"SpecialWeapon": ["Collimator", "CompactCollimator"],
|
||||
"Shotgun": ["Collimator", "CompactCollimator"],
|
||||
"Pistol": ["Collimator", "CompactCollimator"],
|
||||
"Revolver": ["Collimator", "CompactCollimator"],
|
||||
"GrenadeLauncher": ["Collimator", "CompactCollimator"]
|
||||
},
|
||||
"weightingAdjustments": {
|
||||
"FirstPrimaryWeapon": {
|
||||
"AssaultCarbine": 1.1,
|
||||
"AssaultRifle": 1.2,
|
||||
"GrenadeLauncher": 1,
|
||||
"MachineGun": 1,
|
||||
"MarksmanRifle": 1.2,
|
||||
"Revolver": 0.6,
|
||||
"Shotgun": 0.6,
|
||||
"Smg": 0.6,
|
||||
"SniperRifle": 1.1
|
||||
}
|
||||
}
|
||||
},
|
||||
"laboratory": {
|
||||
"sightConfiguration": {
|
||||
"SniperRifle": [
|
||||
"AssaultScope",
|
||||
"Collimator",
|
||||
"CompactCollimator",
|
||||
"ThermalVision"
|
||||
],
|
||||
"MarksmanRifle": [
|
||||
"AssaultScope",
|
||||
"Collimator",
|
||||
"CompactCollimator",
|
||||
"ThermalVision"
|
||||
],
|
||||
"AssaultCarbine": [
|
||||
"AssaultScope",
|
||||
"Collimator",
|
||||
"CompactCollimator",
|
||||
"ThermalVision"
|
||||
],
|
||||
"AssaultRifle": [
|
||||
"AssaultScope",
|
||||
"Collimator",
|
||||
"CompactCollimator",
|
||||
"ThermalVision"
|
||||
],
|
||||
"MachineGun": ["Collimator", "CompactCollimator", "ThermalVision"],
|
||||
"Smg": ["Collimator", "CompactCollimator"],
|
||||
"SpecialWeapon": ["Collimator", "CompactCollimator"],
|
||||
"Shotgun": ["Collimator", "CompactCollimator"],
|
||||
"Pistol": ["Collimator", "CompactCollimator"],
|
||||
"Revolver": ["Collimator", "CompactCollimator"],
|
||||
"GrenadeLauncher": ["Collimator", "CompactCollimator"]
|
||||
},
|
||||
"weightingAdjustments": {
|
||||
"FirstPrimaryWeapon": {
|
||||
"AssaultCarbine": 0.8,
|
||||
"AssaultRifle": 1.3,
|
||||
"GrenadeLauncher": 1.3,
|
||||
"MachineGun": 1.2,
|
||||
"MarksmanRifle": 0.3,
|
||||
"Revolver": 1.2,
|
||||
"Shotgun": 1.2,
|
||||
"Smg": 1.3,
|
||||
"SniperRifle": 0.3
|
||||
}
|
||||
}
|
||||
},
|
||||
"lighthouse": {
|
||||
"sightConfiguration": {
|
||||
"SniperRifle": ["OpticScope", "AssaultScope"],
|
||||
"MarksmanRifle": ["OpticScope", "AssaultScope"],
|
||||
"AssaultCarbine": ["AssaultScope"],
|
||||
"AssaultRifle": ["AssaultScope", "Collimator"],
|
||||
"MachineGun": ["Collimator", "CompactCollimator"],
|
||||
"Smg": ["Collimator", "CompactCollimator"],
|
||||
"SpecialWeapon": ["Collimator", "CompactCollimator"],
|
||||
"Shotgun": ["Collimator", "CompactCollimator"],
|
||||
"Pistol": ["Collimator", "CompactCollimator"],
|
||||
"Revolver": ["Collimator", "CompactCollimator"],
|
||||
"GrenadeLauncher": ["Collimator", "CompactCollimator"]
|
||||
},
|
||||
"weightingAdjustments": {
|
||||
"FirstPrimaryWeapon": {
|
||||
"AssaultCarbine": 1.5,
|
||||
"AssaultRifle": 1,
|
||||
"GrenadeLauncher": 0.8,
|
||||
"MachineGun": 0.7,
|
||||
"MarksmanRifle": 2,
|
||||
"Revolver": 0.2,
|
||||
"Shotgun": 0.2,
|
||||
"Smg": 0.2,
|
||||
"SniperRifle": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"rezervbase": {
|
||||
"sightConfiguration": {
|
||||
"SniperRifle": ["OpticScope", "AssaultScope"],
|
||||
"MarksmanRifle": ["OpticScope", "AssaultScope"],
|
||||
"AssaultCarbine": ["AssaultScope", "Collimator", "CompactCollimator"],
|
||||
"AssaultRifle": ["AssaultScope", "Collimator", "CompactCollimator"],
|
||||
"MachineGun": ["Collimator", "CompactCollimator"],
|
||||
"Smg": ["Collimator", "CompactCollimator"],
|
||||
"SpecialWeapon": ["Collimator", "CompactCollimator"],
|
||||
"Shotgun": ["Collimator", "CompactCollimator"],
|
||||
"Pistol": ["Collimator", "CompactCollimator"],
|
||||
"Revolver": ["Collimator", "CompactCollimator"],
|
||||
"GrenadeLauncher": ["Collimator", "CompactCollimator"]
|
||||
},
|
||||
"weightingAdjustments": {
|
||||
"FirstPrimaryWeapon": {
|
||||
"AssaultCarbine": 1.3,
|
||||
"AssaultRifle": 1,
|
||||
"GrenadeLauncher": 0.8,
|
||||
"MachineGun": 0.8,
|
||||
"MarksmanRifle": 1.6,
|
||||
"Revolver": 0.3,
|
||||
"Shotgun": 0.3,
|
||||
"Smg": 0.5,
|
||||
"SniperRifle": 1.6
|
||||
}
|
||||
}
|
||||
},
|
||||
"shoreline": {
|
||||
"sightConfiguration": {
|
||||
"SniperRifle": ["OpticScope", "AssaultScope"],
|
||||
"MarksmanRifle": ["OpticScope", "AssaultScope"],
|
||||
"AssaultCarbine": ["AssaultScope"],
|
||||
"AssaultRifle": ["AssaultScope", "Collimator"],
|
||||
"MachineGun": ["Collimator", "CompactCollimator"],
|
||||
"Smg": ["Collimator", "CompactCollimator"],
|
||||
"SpecialWeapon": ["Collimator", "CompactCollimator"],
|
||||
"Shotgun": ["Collimator", "CompactCollimator"],
|
||||
"Pistol": ["Collimator", "CompactCollimator"],
|
||||
"Revolver": ["Collimator", "CompactCollimator"],
|
||||
"GrenadeLauncher": ["Collimator", "CompactCollimator"]
|
||||
},
|
||||
"weightingAdjustments": {
|
||||
"FirstPrimaryWeapon": {
|
||||
"AssaultCarbine": 1.5,
|
||||
"AssaultRifle": 1,
|
||||
"GrenadeLauncher": 0.8,
|
||||
"MachineGun": 0.7,
|
||||
"MarksmanRifle": 2,
|
||||
"Revolver": 0.2,
|
||||
"Shotgun": 0.2,
|
||||
"Smg": 0.2,
|
||||
"SniperRifle": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"tarkovstreets": {
|
||||
"sightConfiguration": {
|
||||
"SniperRifle": ["OpticScope", "AssaultScope"],
|
||||
"MarksmanRifle": ["OpticScope", "AssaultScope"],
|
||||
"AssaultCarbine": ["AssaultScope", "Collimator", "CompactCollimator"],
|
||||
"AssaultRifle": ["AssaultScope", "Collimator", "CompactCollimator"],
|
||||
"MachineGun": ["Collimator", "CompactCollimator"],
|
||||
"Smg": ["Collimator", "CompactCollimator"],
|
||||
"SpecialWeapon": ["Collimator", "CompactCollimator"],
|
||||
"Shotgun": ["Collimator", "CompactCollimator"],
|
||||
"Pistol": ["Collimator", "CompactCollimator"],
|
||||
"Revolver": ["Collimator", "CompactCollimator"],
|
||||
"GrenadeLauncher": ["Collimator", "CompactCollimator"]
|
||||
},
|
||||
"weightingAdjustments": {
|
||||
"FirstPrimaryWeapon": {
|
||||
"AssaultCarbine": 1.2,
|
||||
"AssaultRifle": 1.2,
|
||||
"GrenadeLauncher": 1,
|
||||
"MachineGun": 1,
|
||||
"MarksmanRifle": 1,
|
||||
"Revolver": 1,
|
||||
"Shotgun": 1,
|
||||
"Smg": 1.3,
|
||||
"SniperRifle": 0.8
|
||||
}
|
||||
}
|
||||
},
|
||||
"sandbox_high": {
|
||||
"sightConfiguration": {
|
||||
"SniperRifle": ["OpticScope", "AssaultScope"],
|
||||
"MarksmanRifle": ["OpticScope", "AssaultScope"],
|
||||
"AssaultCarbine": ["AssaultScope", "Collimator", "CompactCollimator"],
|
||||
"AssaultRifle": ["AssaultScope", "Collimator", "CompactCollimator"],
|
||||
"MachineGun": ["Collimator", "CompactCollimator"],
|
||||
"Smg": ["Collimator", "CompactCollimator"],
|
||||
"SpecialWeapon": ["Collimator", "CompactCollimator"],
|
||||
"Shotgun": ["Collimator", "CompactCollimator"],
|
||||
"Pistol": ["Collimator", "CompactCollimator"],
|
||||
"Revolver": ["Collimator", "CompactCollimator"],
|
||||
"GrenadeLauncher": ["Collimator", "CompactCollimator"]
|
||||
},
|
||||
"weightingAdjustments": {
|
||||
"FirstPrimaryWeapon": {
|
||||
"AssaultCarbine": 1.2,
|
||||
"AssaultRifle": 1.2,
|
||||
"GrenadeLauncher": 1,
|
||||
"MachineGun": 1,
|
||||
"MarksmanRifle": 1,
|
||||
"Revolver": 1,
|
||||
"Shotgun": 1,
|
||||
"Smg": 1.3,
|
||||
"SniperRifle": 0.8
|
||||
}
|
||||
}
|
||||
},
|
||||
"sandbox": {
|
||||
"sightConfiguration": {
|
||||
"SniperRifle": ["OpticScope", "AssaultScope"],
|
||||
"MarksmanRifle": ["OpticScope", "AssaultScope"],
|
||||
"AssaultCarbine": ["AssaultScope", "Collimator", "CompactCollimator"],
|
||||
"AssaultRifle": ["AssaultScope", "Collimator", "CompactCollimator"],
|
||||
"MachineGun": ["Collimator", "CompactCollimator"],
|
||||
"Smg": ["Collimator", "CompactCollimator"],
|
||||
"SpecialWeapon": ["Collimator", "CompactCollimator"],
|
||||
"Shotgun": ["Collimator", "CompactCollimator"],
|
||||
"Pistol": ["Collimator", "CompactCollimator"],
|
||||
"Revolver": ["Collimator", "CompactCollimator"],
|
||||
"GrenadeLauncher": ["Collimator", "CompactCollimator"]
|
||||
},
|
||||
"weightingAdjustments": {
|
||||
"FirstPrimaryWeapon": {
|
||||
"AssaultCarbine": 1.2,
|
||||
"AssaultRifle": 1.2,
|
||||
"GrenadeLauncher": 1,
|
||||
"MachineGun": 1,
|
||||
"MarksmanRifle": 1,
|
||||
"Revolver": 1,
|
||||
"Shotgun": 1,
|
||||
"Smg": 1.3,
|
||||
"SniperRifle": 0.8
|
||||
}
|
||||
}
|
||||
},
|
||||
"woods": {
|
||||
"sightConfiguration": {
|
||||
"SniperRifle": ["OpticScope", "AssaultScope"],
|
||||
"MarksmanRifle": ["OpticScope", "AssaultScope"],
|
||||
"AssaultCarbine": ["OpticScope", "AssaultScope"],
|
||||
"AssaultRifle": ["AssaultScope", "Collimator"],
|
||||
"MachineGun": ["Collimator", "CompactCollimator"],
|
||||
"Smg": ["Collimator", "CompactCollimator"],
|
||||
"SpecialWeapon": ["Collimator", "CompactCollimator"],
|
||||
"Shotgun": ["Collimator", "CompactCollimator"],
|
||||
"Pistol": ["Collimator", "CompactCollimator"],
|
||||
"Revolver": ["Collimator", "CompactCollimator"],
|
||||
"GrenadeLauncher": ["Collimator", "CompactCollimator"]
|
||||
},
|
||||
"weightingAdjustments": {
|
||||
"FirstPrimaryWeapon": {
|
||||
"AssaultCarbine": 1.5,
|
||||
"AssaultRifle": 1,
|
||||
"GrenadeLauncher": 0.8,
|
||||
"MachineGun": 0.7,
|
||||
"MarksmanRifle": 2,
|
||||
"Revolver": 0.2,
|
||||
"Shotgun": 0.2,
|
||||
"Smg": 0.2,
|
||||
"SniperRifle": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"otherBotTypes": {
|
||||
"assault": {
|
||||
"weaponSlotIdsToMakeRequired": [],
|
||||
"randomisation": [
|
||||
{
|
||||
"levelRange": {
|
||||
"min": 1,
|
||||
"max": 79
|
||||
},
|
||||
"generation": {
|
||||
"specialItems": {
|
||||
"weights": {
|
||||
"0": 1
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"healing": {
|
||||
"weights": {
|
||||
"0": 5,
|
||||
"1": 2,
|
||||
"2": 1
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"drugs": {
|
||||
"weights": {
|
||||
"0": 5,
|
||||
"1": 2
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"stims": {
|
||||
"weights": {
|
||||
"0": 20,
|
||||
"1": 1
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"backpackLoot": {
|
||||
"weights": {
|
||||
"0": 4,
|
||||
"1": 5,
|
||||
"2": 5,
|
||||
"3": 4,
|
||||
"4": 4,
|
||||
"5": 2,
|
||||
"6": 2,
|
||||
"8": 1
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"pocketLoot": {
|
||||
"weights": {
|
||||
"0": 1,
|
||||
"1": 3,
|
||||
"2": 1
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"vestLoot": {
|
||||
"weights": {
|
||||
"0": 1,
|
||||
"1": 3,
|
||||
"2": 2,
|
||||
"3": 1,
|
||||
"6": 1
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"magazines": {
|
||||
"weights": {
|
||||
"0": 1,
|
||||
"1": 5,
|
||||
"2": 5,
|
||||
"3": 1
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"grenades": {
|
||||
"weights": {
|
||||
"0": 3,
|
||||
"1": 1
|
||||
},
|
||||
"whitelist": {
|
||||
"5710c24ad2720bc3458b45a3": 1,
|
||||
"5a0c27731526d80618476ac4": 1,
|
||||
"619256e5f8af2c1a4e1f5d92": 1,
|
||||
"5e32f56fcb6d5863cc5e5ee4": 1,
|
||||
"5e340dcdcb6d5863cc5e5efb": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"equipment": {
|
||||
"ArmBand": 0,
|
||||
"ArmorVest": 50,
|
||||
"Backpack": 44,
|
||||
"Earpiece": 0,
|
||||
"Eyewear": 26,
|
||||
"FaceCover": 47,
|
||||
"FirstPrimaryWeapon": 92,
|
||||
"Headwear": 74,
|
||||
"Holster": 7,
|
||||
"Pockets": 100,
|
||||
"Scabbard": 80,
|
||||
"SecondPrimaryWeapon": 0,
|
||||
"SecuredContainer": 100,
|
||||
"TacticalVest": 100
|
||||
},
|
||||
"equipmentMods": {
|
||||
"front_plate": 60,
|
||||
"back_plate": 60,
|
||||
"left_side_plate": 15,
|
||||
"right_side_plate": 15,
|
||||
"mod_equipment": 10,
|
||||
"mod_equipment_000": 0,
|
||||
"mod_equipment_001": 0,
|
||||
"mod_equipment_002": 0,
|
||||
"mod_mount": 0,
|
||||
"mod_nvg": 0
|
||||
},
|
||||
"weaponMods": {
|
||||
"mod_reciever": 99,
|
||||
"mod_stock_akms": 90,
|
||||
"mod_stock": 90,
|
||||
"mod_sight_front": 50,
|
||||
"mod_sight_rear": 50,
|
||||
"mod_flashlight": 50,
|
||||
"mod_muzzle": 5,
|
||||
"mod_tactical": 10,
|
||||
"mod_handguard": 0,
|
||||
"mod_charge": 0,
|
||||
"mod_equipment": 0,
|
||||
"mod_equipment_000": 0,
|
||||
"mod_equipment_001": 0,
|
||||
"mod_equipment_002": 0,
|
||||
"mod_foregrip": 0,
|
||||
"mod_launcher": 0,
|
||||
"mod_magazine": 0,
|
||||
"mod_mount": 0,
|
||||
"mod_mount_000": 0,
|
||||
"mod_mount_001": 0,
|
||||
"mod_nvg": 0,
|
||||
"mod_pistol_grip": 0,
|
||||
"mod_scope": 0,
|
||||
"mod_scope_000": 0,
|
||||
"mod_scope_001": 0,
|
||||
"mod_scope_002": 0,
|
||||
"mod_scope_003": 0,
|
||||
"mod_tactical_000": 0,
|
||||
"mod_tactical_001": 0,
|
||||
"mod_tactical_002": 0,
|
||||
"mod_tactical_003": 0,
|
||||
"mod_stock_000": 0,
|
||||
"mod_stock_001": 0,
|
||||
"mod_barrel": 0,
|
||||
"mod_bipod": 0,
|
||||
"mod_mount_002": 0,
|
||||
"mod_mount_003": 0,
|
||||
"mod_mount_004": 0,
|
||||
"mod_mount_005": 0,
|
||||
"mod_mount_006": 0,
|
||||
"mod_muzzle_000": 5,
|
||||
"mod_muzzle_001": 1,
|
||||
"mod_pistol_grip_akms": 0,
|
||||
"mod_tactical001": 0,
|
||||
"mod_tactical002": 0,
|
||||
"mod_tactical_2": 0,
|
||||
"mod_gas_block": 0,
|
||||
"mod_pistolgrip": 0,
|
||||
"mod_trigger": 0,
|
||||
"mod_hammer": 0,
|
||||
"mod_catch": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"armorPlateWeighting": [
|
||||
{
|
||||
"levelRange": {
|
||||
"min": 1,
|
||||
"max": 99
|
||||
},
|
||||
"front_plate": {
|
||||
"2": 25,
|
||||
"3": 5,
|
||||
"4": 1,
|
||||
"5": 1,
|
||||
"6": 1
|
||||
},
|
||||
"back_plate": {
|
||||
"2": 25,
|
||||
"3": 5,
|
||||
"4": 1,
|
||||
"5": 1,
|
||||
"6": 1
|
||||
},
|
||||
"side_plate": {
|
||||
"2": 25,
|
||||
"3": 5,
|
||||
"4": 1,
|
||||
"5": 1,
|
||||
"6": 1
|
||||
},
|
||||
"left_side_plate": {
|
||||
"2": 25,
|
||||
"3": 5,
|
||||
"4": 1,
|
||||
"5": 1,
|
||||
"6": 1
|
||||
},
|
||||
"right_side_plate": {
|
||||
"2": 25,
|
||||
"3": 5,
|
||||
"4": 1,
|
||||
"5": 1,
|
||||
"6": 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"blacklist": [
|
||||
{
|
||||
"levelRange": {
|
||||
"min": 1,
|
||||
"max": 99
|
||||
},
|
||||
"equipment": {
|
||||
"mod_magazine": [
|
||||
"5b1fb3e15acfc4001637f068",
|
||||
"59e5f5a486f7746c530b3ce2"
|
||||
],
|
||||
"mod_stock_akms": ["5a0c59791526d8dba737bba7"],
|
||||
"mod_stock": [
|
||||
"5a0c59791526d8dba737bba7",
|
||||
"59ecc28286f7746d7a68aa8c",
|
||||
"5b222d335acfc4771e1be099",
|
||||
"5ac78eaf5acfc4001926317a",
|
||||
"626a8ae89e664a2e2a75f409",
|
||||
"5649b2314bdc2d79388b4576"
|
||||
],
|
||||
"mod_handguard": [
|
||||
"5648ae314bdc2d3d1c8b457f",
|
||||
"5827272a24597748c74bdeea",
|
||||
"5648b4534bdc2d3d1c8b4580"
|
||||
]
|
||||
},
|
||||
"cartridge": {}
|
||||
}
|
||||
],
|
||||
"whitelist": [
|
||||
{
|
||||
"levelRange": {
|
||||
"min": 1,
|
||||
"max": 99
|
||||
},
|
||||
"equipment": {},
|
||||
"cartridge": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
63
user/mods/AlgorithmicLevelProgression/config/config.json
Normal file
63
user/mods/AlgorithmicLevelProgression/config/config.json
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
{
|
||||
"enableProgressionChanges": true,
|
||||
"enableLevelChanges": true,
|
||||
"leveledClothing": true,
|
||||
"enableNonPMCBotChanges": true,
|
||||
"enableLootChanges": true,
|
||||
"questUnlockedItemsShifted": true,
|
||||
"tradedItemsShifted": true,
|
||||
"addCustomTraderItems": false,
|
||||
"customTradersToExclude": [
|
||||
"insertTheTraderNameToIgnoreTheirItems",
|
||||
"CustomTradersNamesWillPrintToConsoleIfFoundAndaddCustomTraderItemsIsSetToTrue"
|
||||
],
|
||||
"customBlacklist": [
|
||||
"get id's from here https://db.sp-tarkov.com/search/",
|
||||
"5example3208of34not8f83real8a1id"
|
||||
],
|
||||
"levelRange": {
|
||||
"1": {
|
||||
"min": 1,
|
||||
"max": 14
|
||||
},
|
||||
"2": {
|
||||
"min": 15,
|
||||
"max": 28
|
||||
},
|
||||
"3": {
|
||||
"min": 29,
|
||||
"max": 39
|
||||
},
|
||||
"4": {
|
||||
"min": 40,
|
||||
"max": 55
|
||||
},
|
||||
"5": {
|
||||
"min": 56,
|
||||
"max": 100
|
||||
}
|
||||
},
|
||||
"botRangeAtLevel": {
|
||||
"1": [12, 5, 1, 1, 0],
|
||||
"2": [8, 10, 5, 2, 1],
|
||||
"3": [6, 8, 10, 5, 2],
|
||||
"4": [4, 6, 8, 7, 3],
|
||||
"5": [2, 4, 6, 9, 4]
|
||||
},
|
||||
"strictEquipmentTiering": true,
|
||||
"higherTierAmmoChance": 0.3,
|
||||
"randomness": {
|
||||
"Ammo": 0.3,
|
||||
"Holster": 0.2,
|
||||
"Headwear": 0.3,
|
||||
"FirstPrimaryWeapon": 0.3,
|
||||
"Earpiece": 0.2,
|
||||
"Backpack": 0.2,
|
||||
"Eyewear": 0.5,
|
||||
"TacticalVest": 0.1,
|
||||
"ArmorVest": 0.1,
|
||||
"FaceCover": 0.3
|
||||
},
|
||||
"forceCached": false,
|
||||
"debug": false
|
||||
}
|
||||
|
|
@ -0,0 +1,596 @@
|
|||
{
|
||||
"addRandomizedKeysToScavs": true,
|
||||
"lootDisparityMultiplier": 1,
|
||||
"percentageOfKeysInSpawnPool": 0.3,
|
||||
"scavLootBlacklist": [],
|
||||
"additionalScavLoot": ["5c94bbff86f7747ee735c08f"],
|
||||
"botAmmoRandomness": 0.1,
|
||||
"botEquipmentRandomness": 0.3,
|
||||
"ignoreList": ["add names of bot types here you DONT want alp to touch"],
|
||||
"Example_______IgnoreList": [
|
||||
"bosspartisan",
|
||||
"bossbully",
|
||||
"bosstagilla",
|
||||
"bossgluhar",
|
||||
"bosskilla",
|
||||
"bosskojaniy",
|
||||
"bosssanitar",
|
||||
"bosskolontay",
|
||||
"bossknight"
|
||||
],
|
||||
"nonPmcBots": {
|
||||
"bossboar": {
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"HasModdedWeapons": true,
|
||||
"AllowSniperRifles": false,
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Holster": [0, 0.5],
|
||||
"FirstPrimaryWeapon": [0.5, 0.9],
|
||||
"Backpack": [0, 0],
|
||||
"Ammo": [0.1, 0.5],
|
||||
"ArmorVest": [0, 0.5],
|
||||
"TacticalVest": [0, 0.4],
|
||||
"Headwear": [0, 0.6],
|
||||
"FaceCover": [0.1, 0.4],
|
||||
"Eyewear": [0, 0.3],
|
||||
"BasePlateChance": 40,
|
||||
"SidePlateChance": 20
|
||||
},
|
||||
"bosspartisan": {
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"HasModdedWeapons": true,
|
||||
"AllowSniperRifles": false,
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Holster": [0, 0.5],
|
||||
"FirstPrimaryWeapon": [0, 0.5],
|
||||
"Backpack": [0, 0],
|
||||
"Ammo": [0.1, 0.5],
|
||||
"ArmorVest": [0.3, 0.7],
|
||||
"TacticalVest": [0.2, 0.6],
|
||||
"Headwear": [0, 0.6],
|
||||
"FaceCover": [0.1, 0.4],
|
||||
"Eyewear": [0, 0.3],
|
||||
"BasePlateChance": 40,
|
||||
"SidePlateChance": 20
|
||||
},
|
||||
"bossbully": {
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"HasModdedWeapons": true,
|
||||
"AllowSniperRifles": false,
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Holster": [0, 0],
|
||||
"FirstPrimaryWeapon": [0.3, 0.7],
|
||||
"Backpack": [0, 0],
|
||||
"Ammo": [0.5, 1],
|
||||
"ArmorVest": [0.2, 0.5],
|
||||
"TacticalVest": [0.1, 0.4],
|
||||
"Headwear": [0.3, 1],
|
||||
"FaceCover": [0.5, 1],
|
||||
"Eyewear": [0, 0],
|
||||
"BasePlateChance": 50,
|
||||
"SidePlateChance": 30
|
||||
},
|
||||
"bosstagilla": {
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"HasModdedWeapons": true,
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Holster": [0, 0],
|
||||
"FirstPrimaryWeapon": [0.4, 0.7],
|
||||
"Backpack": [0, 0],
|
||||
"Ammo": [0.5, 1],
|
||||
"ArmorVest": [0.3, 0.7],
|
||||
"TacticalVest": [0.3, 0.7],
|
||||
"Headwear": [0.5, 1],
|
||||
"FaceCover": [0.5, 1],
|
||||
"Eyewear": [0, 0],
|
||||
"BasePlateChance": 90,
|
||||
"SidePlateChance": 60
|
||||
},
|
||||
"bossgluhar": {
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"HasModdedWeapons": true,
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Holster": [0, 0],
|
||||
"FirstPrimaryWeapon": [0.4, 0.7],
|
||||
"Backpack": [0, 0],
|
||||
"Ammo": [0.5, 1],
|
||||
"ArmorVest": [0.3, 0.7],
|
||||
"TacticalVest": [0.3, 0.7],
|
||||
"Headwear": [0.5, 1],
|
||||
"FaceCover": [0.5, 1],
|
||||
"Eyewear": [0, 0],
|
||||
"BasePlateChance": 90,
|
||||
"SidePlateChance": 60
|
||||
},
|
||||
"bosskilla": {
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"HasModdedWeapons": true,
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Holster": [0, 0],
|
||||
"FirstPrimaryWeapon": [0.4, 0.7],
|
||||
"Backpack": [0, 0],
|
||||
"Ammo": [0.5, 1],
|
||||
"ArmorVest": [0.3, 0.7],
|
||||
"TacticalVest": [0.3, 0.7],
|
||||
"Headwear": [0.5, 1],
|
||||
"FaceCover": [0.5, 1],
|
||||
"Eyewear": [0, 0],
|
||||
"BasePlateChance": 90,
|
||||
"SidePlateChance": 60
|
||||
},
|
||||
"bosskojaniy": {
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"HasModdedWeapons": true,
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Holster": [0, 0],
|
||||
"FirstPrimaryWeapon": [0.4, 0.7],
|
||||
"Backpack": [0, 0],
|
||||
"Ammo": [0.5, 1],
|
||||
"ArmorVest": [0.3, 0.7],
|
||||
"TacticalVest": [0.3, 0.7],
|
||||
"Headwear": [0.5, 1],
|
||||
"FaceCover": [0.5, 1],
|
||||
"Eyewear": [0, 0],
|
||||
"BasePlateChance": 90,
|
||||
"SidePlateChance": 60
|
||||
},
|
||||
"bosssanitar": {
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"HasModdedWeapons": true,
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Holster": [0, 0],
|
||||
"FirstPrimaryWeapon": [0.4, 0.7],
|
||||
"Backpack": [0, 0],
|
||||
"Ammo": [0.5, 1],
|
||||
"ArmorVest": [0.3, 0.7],
|
||||
"TacticalVest": [0.3, 0.7],
|
||||
"Headwear": [0.5, 1],
|
||||
"FaceCover": [0.5, 1],
|
||||
"Eyewear": [0, 0],
|
||||
"BasePlateChance": 90,
|
||||
"SidePlateChance": 60
|
||||
},
|
||||
"bosskolontay": {
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"HasModdedWeapons": true,
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Holster": [0, 0],
|
||||
"FirstPrimaryWeapon": [0.4, 0.7],
|
||||
"Backpack": [0, 0],
|
||||
"Ammo": [0.5, 1],
|
||||
"ArmorVest": [0.3, 0.7],
|
||||
"TacticalVest": [0.3, 0.7],
|
||||
"Headwear": [0.5, 1],
|
||||
"FaceCover": [0.5, 1],
|
||||
"Eyewear": [0, 0],
|
||||
"BasePlateChance": 90,
|
||||
"SidePlateChance": 60
|
||||
},
|
||||
"bossknight": {
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"HasModdedWeapons": true,
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Holster": [0, 0],
|
||||
"FirstPrimaryWeapon": [0.4, 0.7],
|
||||
"Backpack": [0, 0],
|
||||
"Ammo": [0.5, 1],
|
||||
"ArmorVest": [0, 0],
|
||||
"TacticalVest": [0, 0],
|
||||
"Headwear": [0, 0],
|
||||
"FaceCover": [0, 0],
|
||||
"Eyewear": [0, 0],
|
||||
"BasePlateChance": 90,
|
||||
"SidePlateChance": 60
|
||||
},
|
||||
"followersanitar": {
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"HasModdedWeapons": true,
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Earpiece": [0, 0.3],
|
||||
"Backpack": [0, 0.4],
|
||||
"Ammo": [0.4, 0.8],
|
||||
"ArmorVest": [0.3, 0.6],
|
||||
"TacticalVest": [0.3, 0.7],
|
||||
"Headwear": [0, 0.6],
|
||||
"FaceCover": [0, 0.3],
|
||||
"Eyewear": [0.2, 0.6],
|
||||
"BasePlateChance": 70,
|
||||
"SidePlateChance": 50
|
||||
},
|
||||
"followerkolontayassault": {
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"HasModdedWeapons": true,
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Earpiece": [0, 0.3],
|
||||
"Backpack": [0, 0.4],
|
||||
"Ammo": [0.4, 0.8],
|
||||
"ArmorVest": [0.3, 0.6],
|
||||
"TacticalVest": [0.3, 0.7],
|
||||
"Headwear": [0, 0.6],
|
||||
"FaceCover": [0, 0.3],
|
||||
"Eyewear": [0.2, 0.6],
|
||||
"BasePlateChance": 70,
|
||||
"SidePlateChance": 50
|
||||
},
|
||||
"followerkolontaysecurity": {
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"HasModdedWeapons": true,
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Earpiece": [0, 0.3],
|
||||
"Backpack": [0, 0.4],
|
||||
"Ammo": [0.4, 0.8],
|
||||
"ArmorVest": [0.3, 0.6],
|
||||
"TacticalVest": [0.3, 0.7],
|
||||
"Headwear": [0, 0.6],
|
||||
"FaceCover": [0, 0.3],
|
||||
"Eyewear": [0.2, 0.6],
|
||||
"BasePlateChance": 70,
|
||||
"SidePlateChance": 50
|
||||
},
|
||||
"followerboarclose1": {
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"HasModdedWeapons": true,
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Earpiece": [0, 0.3],
|
||||
"Backpack": [0, 0.4],
|
||||
"Ammo": [0.4, 0.8],
|
||||
"ArmorVest": [0.3, 0.6],
|
||||
"TacticalVest": [0.3, 0.7],
|
||||
"Headwear": [0, 0.6],
|
||||
"FaceCover": [0, 0.3],
|
||||
"Eyewear": [0.2, 0.6],
|
||||
"BasePlateChance": 70,
|
||||
"SidePlateChance": 50
|
||||
},
|
||||
"followerboarclose2": {
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"HasModdedWeapons": true,
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Earpiece": [0, 0.3],
|
||||
"Backpack": [0, 0.4],
|
||||
"Ammo": [0.4, 0.8],
|
||||
"ArmorVest": [0.3, 0.6],
|
||||
"TacticalVest": [0.3, 0.7],
|
||||
"Headwear": [0, 0.6],
|
||||
"FaceCover": [0, 0.3],
|
||||
"Eyewear": [0.2, 0.6],
|
||||
"BasePlateChance": 70,
|
||||
"SidePlateChance": 50
|
||||
},
|
||||
"followerbully": {
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"HasModdedWeapons": true,
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Earpiece": [0, 0.3],
|
||||
"Backpack": [0, 0.4],
|
||||
"Ammo": [0.4, 0.8],
|
||||
"ArmorVest": [0.3, 0.6],
|
||||
"TacticalVest": [0.3, 0.7],
|
||||
"Headwear": [0, 0.6],
|
||||
"FaceCover": [0, 0.3],
|
||||
"Eyewear": [0.2, 0.6],
|
||||
"BasePlateChance": 70,
|
||||
"SidePlateChance": 50
|
||||
},
|
||||
"followergluharscout": {
|
||||
"AllowSniperRifles": true,
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"HasModdedWeapons": true,
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Earpiece": [0, 0.3],
|
||||
"Backpack": [0, 0.4],
|
||||
"Ammo": [0.4, 0.8],
|
||||
"ArmorVest": [0.3, 0.6],
|
||||
"TacticalVest": [0.3, 0.7],
|
||||
"Headwear": [0, 0.6],
|
||||
"FaceCover": [0, 0.3],
|
||||
"Eyewear": [0.2, 0.6],
|
||||
"BasePlateChance": 70,
|
||||
"SidePlateChance": 50
|
||||
},
|
||||
"followerbigpipe": {
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"HasModdedWeapons": true,
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"AllowSniperRifles": false,
|
||||
"Holster": [0, 0],
|
||||
"FirstPrimaryWeapon": [0.6, 0.9],
|
||||
"Backpack": [0, 0],
|
||||
"Ammo": [0.5, 1],
|
||||
"ArmorVest": [0, 0],
|
||||
"TacticalVest": [0, 0],
|
||||
"Headwear": [0, 0],
|
||||
"FaceCover": [0, 0],
|
||||
"Eyewear": [0, 0],
|
||||
"BasePlateChance": 90,
|
||||
"SidePlateChance": 60
|
||||
},
|
||||
"followerbirdeye": {
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"HasModdedWeapons": true,
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"AllowSniperRifles": true,
|
||||
"Holster": [0, 0],
|
||||
"FirstPrimaryWeapon": [0.6, 0.9],
|
||||
"Backpack": [0, 0],
|
||||
"Ammo": [0.5, 1],
|
||||
"ArmorVest": [0, 0],
|
||||
"TacticalVest": [0, 0],
|
||||
"Headwear": [0, 0],
|
||||
"FaceCover": [0, 0],
|
||||
"Eyewear": [0, 0],
|
||||
"BasePlateChance": 90,
|
||||
"SidePlateChance": 60
|
||||
},
|
||||
"followergluharassault": {
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"HasModdedWeapons": true,
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Earpiece": [0, 0.3],
|
||||
"Backpack": [0, 0.4],
|
||||
"Ammo": [0.4, 0.8],
|
||||
"ArmorVest": [0.3, 0.6],
|
||||
"TacticalVest": [0.3, 0.7],
|
||||
"Headwear": [0, 0.6],
|
||||
"FaceCover": [0, 0.3],
|
||||
"Eyewear": [0.2, 0.6],
|
||||
"BasePlateChance": 70,
|
||||
"SidePlateChance": 50
|
||||
},
|
||||
"followergluharsecurity": {
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"HasModdedWeapons": true,
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Earpiece": [0, 0.3],
|
||||
"Backpack": [0, 0.4],
|
||||
"Ammo": [0.4, 0.8],
|
||||
"ArmorVest": [0.3, 0.6],
|
||||
"TacticalVest": [0.3, 0.7],
|
||||
"Headwear": [0, 0.6],
|
||||
"FaceCover": [0, 0.3],
|
||||
"Eyewear": [0.2, 0.6],
|
||||
"BasePlateChance": 70,
|
||||
"SidePlateChance": 50
|
||||
},
|
||||
"followerboar": {
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"HasModdedWeapons": true,
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Earpiece": [0, 0.3],
|
||||
"Backpack": [0, 0.4],
|
||||
"Ammo": [0.4, 0.8],
|
||||
"ArmorVest": [0.3, 0.6],
|
||||
"TacticalVest": [0.3, 0.7],
|
||||
"Headwear": [0, 0.6],
|
||||
"FaceCover": [0, 0.3],
|
||||
"Eyewear": [0.2, 0.6],
|
||||
"BasePlateChance": 70,
|
||||
"SidePlateChance": 50
|
||||
},
|
||||
"followerkojaniy": {
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"HasModdedWeapons": true,
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Earpiece": [0, 0.3],
|
||||
"Backpack": [0, 0.4],
|
||||
"Ammo": [0.4, 0.8],
|
||||
"ArmorVest": [0.3, 0.6],
|
||||
"TacticalVest": [0.3, 0.7],
|
||||
"Headwear": [0, 0.6],
|
||||
"FaceCover": [0, 0.3],
|
||||
"Eyewear": [0.2, 0.6],
|
||||
"BasePlateChance": 70,
|
||||
"SidePlateChance": 50
|
||||
},
|
||||
"infectedpmc": {
|
||||
"tiers": [
|
||||
[1, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Earpiece": [0, 0.4],
|
||||
"Headwear": [0.3, 0.9],
|
||||
"FaceCover": [0, 0.9],
|
||||
"Eyewear": [0, 0.9],
|
||||
"BasePlateChance": 60,
|
||||
"SidePlateChance": 20
|
||||
},
|
||||
"infectedassault": {
|
||||
"tiers": [
|
||||
[1, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Earpiece": [0, 0.2],
|
||||
"Headwear": [0.3, 0.9],
|
||||
"FaceCover": [0, 0.9],
|
||||
"Eyewear": [0, 0.9],
|
||||
"BasePlateChance": 60,
|
||||
"SidePlateChance": 20
|
||||
},
|
||||
"infectedcivil": {
|
||||
"tiers": [
|
||||
[1, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Headwear": [0, 0.3],
|
||||
"FaceCover": [0, 0.9],
|
||||
"Eyewear": [0, 0.4],
|
||||
"BasePlateChance": 60,
|
||||
"SidePlateChance": 20
|
||||
},
|
||||
"infectedlaborant": {
|
||||
"tiers": [
|
||||
[1, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"Headwear": [0, 0.3],
|
||||
"FaceCover": [0, 0],
|
||||
"Eyewear": [0.3, 0.9],
|
||||
"BasePlateChance": 60,
|
||||
"SidePlateChance": 20
|
||||
},
|
||||
"assault": {
|
||||
"tiers": [
|
||||
[1, 9],
|
||||
[12, 15],
|
||||
[16, 29],
|
||||
[30, 100]
|
||||
],
|
||||
"Ammo": [0, 0.4],
|
||||
"Holster": [0, 0.6],
|
||||
"FirstPrimaryWeapon": [0, 0.6],
|
||||
"Backpack": [0, 0.3],
|
||||
"ArmorVest": [0, 0.4],
|
||||
"TacticalVest": [0, 0.3],
|
||||
"Headwear": [0, 0.4],
|
||||
"FaceCover": [0, 0.5],
|
||||
"Eyewear": [0, 0.5],
|
||||
"BasePlateChance": 60,
|
||||
"SidePlateChance": 10
|
||||
},
|
||||
"marksman": {
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"AllowSniperRifles": true,
|
||||
"HasModdedWeapons": false,
|
||||
"FirstPrimaryWeapon": [0, 0.8],
|
||||
"Backpack": [0, 0.3],
|
||||
"Ammo": [0.3, 0.8],
|
||||
"ArmorVest": [0.3, 0.6],
|
||||
"TacticalVest": [0.3, 0.6],
|
||||
"Headwear": [0.3, 0.6],
|
||||
"FaceCover": [0, 0.5],
|
||||
"BasePlateChance": 60,
|
||||
"SidePlateChance": 10
|
||||
},
|
||||
"pmcbot": {
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"HasModdedWeapons": true,
|
||||
"Ammo": [0.4, 0.6],
|
||||
"ArmorVest": [0.3, 0.6],
|
||||
"TacticalVest": [0.2, 0.6],
|
||||
"Headwear": [0.1, 0.5],
|
||||
"FaceCover": [0.2, 0.6],
|
||||
"Eyewear": [0, 0.5],
|
||||
"BasePlateChance": 90
|
||||
},
|
||||
"exusec": {
|
||||
"tiers": [
|
||||
[1, 14],
|
||||
[15, 24],
|
||||
[25, 100]
|
||||
],
|
||||
"forceOnlyArmoredRigWhenNoArmor": true,
|
||||
"Earpiece": [0, 0.4],
|
||||
"HasModdedWeapons": true,
|
||||
"Ammo": [0.6, 0.8],
|
||||
"ArmorVest": [0.4, 0.7],
|
||||
"TacticalVest": [0.4, 0.7],
|
||||
"Headwear": [0.5, 0.8],
|
||||
"FaceCover": [0.2, 0.6],
|
||||
"Eyewear": [0, 0.5],
|
||||
"BasePlateChance": 90
|
||||
}
|
||||
},
|
||||
"arenafighterevent": "because no",
|
||||
"arenafighter": "because no"
|
||||
}
|
||||
28
user/mods/AlgorithmicLevelProgression/package.json
Normal file
28
user/mods/AlgorithmicLevelProgression/package.json
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"name": "AlgorithmicLevelProgression",
|
||||
"version": "5.5.0-RC1",
|
||||
"main": "src/mod.js",
|
||||
"license": "MIT",
|
||||
"author": "DewardianDev",
|
||||
"sptVersion": "^3.11.x",
|
||||
"scripts": {
|
||||
"build": "node ./packageBuild.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "20.11",
|
||||
"@semantic-release/git": "^10.0.1",
|
||||
"semantic-release": "^24.2.0",
|
||||
"@typescript-eslint/eslint-plugin": "7.2",
|
||||
"@typescript-eslint/parser": "7.2",
|
||||
"archiver": "^6.0",
|
||||
"bestzip": "2.2.1",
|
||||
"eslint": "8.57",
|
||||
"fs-extra": "11.2",
|
||||
"glob": "8.0.3",
|
||||
"ignore": "^5.2",
|
||||
"os": "^0.1",
|
||||
"tsyringe": "4.8.0",
|
||||
"typescript": "5.4",
|
||||
"winston": "3.12"
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
40238
user/mods/AlgorithmicLevelProgression/src/Cache/tablesbotstypesusec.json
Normal file
40238
user/mods/AlgorithmicLevelProgression/src/Cache/tablesbotstypesusec.json
Normal file
File diff suppressed because it is too large
Load diff
208
user/mods/AlgorithmicLevelProgression/src/Constants/Tier5.ts
Normal file
208
user/mods/AlgorithmicLevelProgression/src/Constants/Tier5.ts
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
export default {
|
||||
Scabbard: [
|
||||
"54491bb74bdc2d09088b4567",
|
||||
"57cd379a24597778e7682ecf",
|
||||
"57e26ea924597715ca604a09",
|
||||
"57e26fc7245977162a14b800",
|
||||
"5bc9c1e2d4351e00367fbcf0",
|
||||
"5c010e350db83400232feec7",
|
||||
"5c07df7f0db834001b73588a",
|
||||
"5fc64ea372b0dd78d51159dc",
|
||||
"601948682627df266209af05",
|
||||
"63495c500c297e20065a08b1",
|
||||
],
|
||||
Backpack: [
|
||||
"56e335e4d2720b6c058b456d",
|
||||
"56e33634d2720bd8058b456b",
|
||||
"59e763f286f7742ee57895da",
|
||||
"5e997f0b86f7741ac73993e2",
|
||||
"5f5e45cc5021ce62144be7aa",
|
||||
"6034d103ca006d2dca39b3f0",
|
||||
"61b9e1aaef9a1b5d6a79899a",
|
||||
"628bc7fb408e2b2e9c0801b1",
|
||||
"628e1ffc83ec92260c0f437f",
|
||||
],
|
||||
Headwear: [
|
||||
"572b7d8524597762b472f9d1",
|
||||
"572b7fa124597762b472f9d2",
|
||||
"59e7708286f7742cbd762753",
|
||||
"59e770f986f7742cbe3164ef",
|
||||
"59ef13ca86f77445fd0e2483",
|
||||
"5a43943586f77416ad2f06e2",
|
||||
"5a43957686f7742a2c2f11b0",
|
||||
"5aa2b89be5b5b0001569311f",
|
||||
"5aa2b8d7e5b5b00014028f4a",
|
||||
"5aa7e276e5b5b000171d0647",
|
||||
"5ab8f20c86f7745cdb629fb2",
|
||||
"5b4329075acfc400153b78ff",
|
||||
"5bd073c986f7747f627e796c",
|
||||
"5c08f87c0db8340019124324",
|
||||
"5c0d2727d174af02a012cf58",
|
||||
"5c0e874186f7745dc7616606",
|
||||
"5ca20ee186f774799474abc2",
|
||||
"5d96141523f0ea1b7f2aacab",
|
||||
"5df8a58286f77412631087ed",
|
||||
"5e4bfc1586f774264f7582d3",
|
||||
"5ea05cf85ad9772e6624305d",
|
||||
"5ea17ca01412a1425304d1c0",
|
||||
"5f60b34a41e30a4ab12a6947",
|
||||
"5f60c74e3b85f6263c145586",
|
||||
"5f99418230835532b445e954",
|
||||
"5f994730c91ed922dd355de3",
|
||||
"603618feffd42c541047f771",
|
||||
"603619720ca681766b6a0fc4",
|
||||
"60361a7497633951dc245eb4",
|
||||
"60361b0b5a45383c122086a1",
|
||||
"60361b5a9a15b10d96792291",
|
||||
"6040de02647ad86262233012",
|
||||
"60a7acf20c5cb24b01346648",
|
||||
"60bf74184a63fc79b60c57f6",
|
||||
"618aef6d0a5a59657e5f55ee",
|
||||
"61bca7cda0eae612383adf57",
|
||||
"61c18db6dfd64163ea78fbb4",
|
||||
"628e4dd1f477aa12234918aa",
|
||||
"636270263f2495c26f00b007",
|
||||
],
|
||||
FaceCover: [
|
||||
"572b7fa524597762b747ce82",
|
||||
"59e7715586f7742ee5789605",
|
||||
"5b4326435acfc433000ed01d",
|
||||
"5b432c305acfc40019478128",
|
||||
"5bd06f5d86f77427101ad47c",
|
||||
"5bd0716d86f774171822ef4b",
|
||||
"5bd071d786f7747e707b93a3",
|
||||
"5bd073a586f7747e6f135799",
|
||||
"5c1a1e3f2e221602b66cc4c2",
|
||||
"5e54f76986f7740366043752",
|
||||
"5e54f79686f7744022011103",
|
||||
"5e71f6be86f77429f2683c44",
|
||||
"5e71fad086f77422443d4604",
|
||||
"5fd8d28367cb5e077335170f",
|
||||
"60363c0c92ec1c31037959f5",
|
||||
"607f201b3c672b3b3a24a800",
|
||||
"60a7ad2a2198820d95707a2e",
|
||||
"60a7ad3a0c5cb24b0134664a",
|
||||
"6176a40f0b8c0312ac75a3d3",
|
||||
"6176a48d732a664031271438",
|
||||
"62963c18dbc8ab5f0d382d0b",
|
||||
"62a09dd4621468534a797ac7",
|
||||
"62a09e08de7ac81993580532",
|
||||
"62a5c2c98ec41a51b34739c0",
|
||||
"62a5c333ec21e50cad3b5dc6",
|
||||
"62a5c41e8ec41a51b34739c3",
|
||||
"62a61bbf8ec41a51b34758d2",
|
||||
"635267ab3c89e2112001f826",
|
||||
"63626d904aa74b8fe30ab426",
|
||||
],
|
||||
Eyewear: [
|
||||
"59e770b986f7742cbd762754",
|
||||
"5aa2b923e5b5b000137b7589",
|
||||
"5aa2b9aee5b5b00015693121",
|
||||
"5e71f70186f77429ee09f183",
|
||||
"61c18d83b00456371a66814b",
|
||||
"62a09e410b9d3c46de5b6e78",
|
||||
],
|
||||
Holster: ["5b3b713c5acfc4330140bd8d"],
|
||||
ArmorVest: [
|
||||
"5b44cf1486f77431723e3d05",
|
||||
"5c0e541586f7747fa54205c9",
|
||||
"5c0e625a86f7742d77340f62",
|
||||
"5c0e655586f774045612eeb2",
|
||||
"5fd4c474dd870108a754b241",
|
||||
"6038b4b292ec1c3103795a0b",
|
||||
"6038b4ca92ec1c3103795a0d",
|
||||
"607f20859ee58b18e41ecd90",
|
||||
"62a09d79de7ac81993580530",
|
||||
],
|
||||
FirstPrimaryWeapon: [
|
||||
"6275303a9f372d6ea97f9ec7",
|
||||
"5bf3e0490db83400196199af",
|
||||
"5de7bd7bfd6b4e6e2276dc25",
|
||||
"639af924d0446708ee62294e",
|
||||
"639c3fbbd0446708ee622ee9",
|
||||
"64637076203536ad5600c990",
|
||||
"64ca3d3954fc657e230529cc",
|
||||
],
|
||||
ammo: [
|
||||
"5c0d56a986f774449d5de529",
|
||||
"5c0d591486f7744c505b416f",
|
||||
"5c0d5ae286f7741e46554302",
|
||||
"5d70e500a4b9364de70d38ce",
|
||||
"5ede4739e0350d05467f73e8",
|
||||
"5ede47405b097655935d7d16",
|
||||
"5ede474b0c226a66f5402622",
|
||||
"5ede475339ee016e8c534742",
|
||||
"5f0c892565703e5c461894e9",
|
||||
"64b8ee384b75259c590fa89b",
|
||||
"5d6e68a8a4b9360b6c0d54e2",
|
||||
"5efb0cabfb3e451d70735af5",
|
||||
"5a26ac0ec4a28200741e1e18",
|
||||
"5cc80f38e4a949001152b560",
|
||||
"61962d879bb3d20b0946d385",
|
||||
"5c0d688c86f77413ae3407b2",
|
||||
"56dff026d2720bb8668b4567",
|
||||
"5c0d5e4486f77478390952fe",
|
||||
"59e690b686f7746c9f75e848",
|
||||
"5fd20ff893a8961fc660a954",
|
||||
"5a6086ea4f39f99cd479502f",
|
||||
"560d61e84bdc2da74d8b4571",
|
||||
"5cadf6eeae921500134b2799",
|
||||
"5fc382a9d724d907e2077dab",
|
||||
],
|
||||
TacticalVest: [
|
||||
"5c0e9f2c86f77432297fe0a3",
|
||||
"5f5f41f56760b4138443b352",
|
||||
"5fd4c4fa16cac650092f6771",
|
||||
"5fd4c5477a8d854fa0105061",
|
||||
"6040dd4ddcf9592f401632d2",
|
||||
"609e860ebd219504d8507525",
|
||||
"628b9784bcf6e2659e09b8a2",
|
||||
"628b9c7d45122232a872358f",
|
||||
"628baf0b967de16aab5a4f36",
|
||||
"63611865ba5b90db0c0399d1",
|
||||
"64a536392d2c4e6e970f4121",
|
||||
"64a5366719bab53bd203bf33",
|
||||
],
|
||||
Earpiece: [
|
||||
"5e4d34ca86f774264f758330",
|
||||
"5f60cd6cf2bcbb675b00dac6",
|
||||
"628e4e576d783146b124c64d",
|
||||
],
|
||||
ArmBand: [
|
||||
"5f9949d869e2777a0e779ba5",
|
||||
"60b0f988c4449e4cb624c1da",
|
||||
"619bc61e86e01e16f839a999",
|
||||
"619bdd8886e01e16f839a99c",
|
||||
"619bddc6c9546643a67df6ee",
|
||||
"619bddffc9546643a67df6f0",
|
||||
"619bde3dc9546643a67df6f2",
|
||||
"619bde7fc9546643a67df6f4",
|
||||
"619bdeb986e01e16f839a99e",
|
||||
"619bdef8c9546643a67df6f6",
|
||||
"619bdf9cc9546643a67df6f8",
|
||||
"619bdfd4c9546643a67df6fa",
|
||||
],
|
||||
StimsMeds: [
|
||||
"5751a89d24597722aa0e8db0",
|
||||
"5755383e24597772cb798966",
|
||||
"5ed515c8d380ab312177c0fa",
|
||||
"5ed515e03a40a50460332579",
|
||||
"5ed515ece452db0eb56fc028",
|
||||
"5ed515f6915ec335206e4152",
|
||||
"5ed5160a87bb8443d10680b5",
|
||||
"5ed51652f6c34d2cc26336a1",
|
||||
"5ed5166ad380ab312177c100",
|
||||
"5fca138c2a7b221b2852a5c6",
|
||||
"5fca13ca637ee0341a484f46",
|
||||
"637b60c3b7afa97bfc3d7001",
|
||||
"637b612fb7afa97bfc3d7005",
|
||||
"637b6179104668754b72f8f5",
|
||||
"637b620db7afa97bfc3d7009",
|
||||
"637b6251104668754b72f8f9",
|
||||
],
|
||||
Grenades: [
|
||||
"5e340dcdcb6d5863cc5e5efb",
|
||||
"617fd91e5539a84ec44ce155",
|
||||
"618a431df1eb8e24b8741deb",
|
||||
],
|
||||
};
|
||||
File diff suppressed because it is too large
Load diff
3041
user/mods/AlgorithmicLevelProgression/src/Constants/tieredItems.json
Normal file
3041
user/mods/AlgorithmicLevelProgression/src/Constants/tieredItems.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,78 @@
|
|||
import { IBotBase } from "../../types/models/eft/common/tables/IBotBase";
|
||||
import { IBotGenerationDetails } from "../../types/models/spt/bots/BotGenerationDetails";
|
||||
import { IRandomisedBotLevelResult } from "../../types/models/eft/bot/IRandomisedBotLevelResult";
|
||||
import { MinMax } from "../../types/models/common/MinMax";
|
||||
import { DependencyContainer } from "tsyringe";
|
||||
import { botRangeAtLevel, levelRange } from "../../config/config.json";
|
||||
import { getCurrentLevelRange } from "../LoadoutChanges/utils";
|
||||
import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
|
||||
import { ConfigServer } from "@spt/servers/ConfigServer";
|
||||
import { BotLevelGenerator } from "@spt/generators/BotLevelGenerator";
|
||||
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
|
||||
import config from "../../config/config.json";
|
||||
import { IPmcConfig } from "@spt/models/spt/config/IPmcConfig";
|
||||
|
||||
export default function BotLevelChanges(
|
||||
container: DependencyContainer
|
||||
): undefined {
|
||||
const profileHelper = container.resolve<ProfileHelper>("ProfileHelper");
|
||||
const botLevelGenerator =
|
||||
container.resolve<BotLevelGenerator>("BotLevelGenerator");
|
||||
const configServer = container.resolve<ConfigServer>("ConfigServer");
|
||||
const pmcConfig = configServer.getConfig<IPmcConfig>(ConfigTypes.PMC);
|
||||
|
||||
pmcConfig.botRelativeLevelDeltaMax = 1;
|
||||
|
||||
container.afterResolution(
|
||||
"BotLevelGenerator",
|
||||
(_t, result: BotLevelGenerator) => {
|
||||
result.generateBotLevel = (
|
||||
levelDetails: MinMax,
|
||||
botGenerationDetails: IBotGenerationDetails,
|
||||
bot: IBotBase
|
||||
): IRandomisedBotLevelResult => {
|
||||
if (!botGenerationDetails.isPmc)
|
||||
return botLevelGenerator.generateBotLevel(
|
||||
levelDetails,
|
||||
botGenerationDetails,
|
||||
bot
|
||||
);
|
||||
|
||||
const { playerLevel } = botGenerationDetails;
|
||||
|
||||
const currentLevelRange = getCurrentLevelRange(playerLevel);
|
||||
const currentRangeArray = botRangeAtLevel[currentLevelRange];
|
||||
const test = currentRangeArray.map((val, k) => ({
|
||||
levelRange: k + 1,
|
||||
val: Math.random() * val,
|
||||
}));
|
||||
|
||||
const randomizedRange = test.sort((a, b) => b.val - a.val)[0]
|
||||
.levelRange;
|
||||
const range = { ...levelRange[randomizedRange] } as MinMax;
|
||||
if (range.max > 79) {
|
||||
range.max = 79;
|
||||
}
|
||||
if (range.min > 70) {
|
||||
range.min = 50;
|
||||
}
|
||||
|
||||
const level =
|
||||
Math.round((range.max - range.min) * Math.random()) + range.min;
|
||||
|
||||
const final = {
|
||||
level,
|
||||
exp: profileHelper.getExperience(level),
|
||||
};
|
||||
|
||||
// debug && console.log(final)
|
||||
|
||||
return final;
|
||||
};
|
||||
},
|
||||
{ frequency: "Always" }
|
||||
);
|
||||
|
||||
config.debug &&
|
||||
console.log("Algorthimic Progression: BotLevelGenerator registered");
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
import { DependencyContainer } from "tsyringe";
|
||||
import { buildClothingWeighting, cloneDeep } from "./utils";
|
||||
import { DatabaseServer } from "@spt/servers/DatabaseServer";
|
||||
import { ConfigServer } from "@spt/servers/ConfigServer";
|
||||
import { IBotConfig } from "@spt/models/spt/config/IBotConfig";
|
||||
import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
|
||||
import { globalValues } from "./GlobalValues";
|
||||
|
||||
export default function ClothingChanges(
|
||||
container: DependencyContainer
|
||||
): undefined {
|
||||
const databaseServer = container.resolve<DatabaseServer>("DatabaseServer");
|
||||
const tables = databaseServer.getTables();
|
||||
|
||||
const configServer = container.resolve<ConfigServer>("ConfigServer");
|
||||
const botConfig = configServer.getConfig<IBotConfig>(ConfigTypes.BOT);
|
||||
|
||||
const usecAppearance = tables.bots.types.usec.appearance;
|
||||
const bearAppearance = tables.bots.types.bear.appearance;
|
||||
const traders = tables.traders;
|
||||
const customization = tables.templates.customization;
|
||||
|
||||
let allTradersSuits = Object.values(traders)
|
||||
.filter(({ suits }) => !!suits?.length)
|
||||
.map(({ suits }) => suits)
|
||||
.flat(1);
|
||||
|
||||
buildClothingWeighting(
|
||||
allTradersSuits,
|
||||
customization,
|
||||
botConfig,
|
||||
usecAppearance,
|
||||
bearAppearance
|
||||
);
|
||||
globalValues.originalBotTypes = cloneDeep(tables.bots.types);
|
||||
globalValues.originalWeighting = cloneDeep(botConfig.equipment.pmc);
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import { IInventory } from "@spt/models/eft/common/tables/IBotType";
|
||||
|
||||
export const fixSpecificItemIssues = (inventory: IInventory) => {
|
||||
const removeAccentScopeList = new Set([
|
||||
"6171407e50224f204c1da3c5", // Recknagel Era-Tac 30mm ring scope mount
|
||||
"61713cc4d8e3106d9806c109", // Recknagel Era-Tac 34mm ring scope mount
|
||||
"5b2389515acfc4771e1be0c0", // Burris AR-P.E.P.R. 30mm ring scope mount
|
||||
"5addc00b5acfc4001669f144", // M14 Vltor CASV-14 rail system
|
||||
"5a37ca54c4a282000d72296a", // JP Enterprises Flat-Top 30mm ring scope mount
|
||||
"5aa66c72e5b5b00016327c93", // Nightforce Magmount 34mm ring scope mount with Ruggedized Accessory Platform
|
||||
]);
|
||||
|
||||
removeAccentScopeList.forEach((id) => {
|
||||
if (inventory.mods?.[id]?.mod_scope_001) {
|
||||
inventory.mods[id].mod_scope_001 = [];
|
||||
}
|
||||
if (inventory.mods?.[id]?.mod_scope_002) {
|
||||
inventory.mods[id].mod_scope_002 = [];
|
||||
}
|
||||
if (inventory.mods?.[id]?.mod_scope_003) {
|
||||
inventory.mods[id].mod_scope_003 = [];
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
@ -0,0 +1,241 @@
|
|||
import { cloneDeep, mergeDeep, saveToFile } from "./utils";
|
||||
import { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { IDatabaseTables } from "@spt/models/spt/server/IDatabaseTables";
|
||||
import config from "../../config/config.json";
|
||||
import advancedConfig from "../../config/advancedConfig.json";
|
||||
import {
|
||||
EquipmentFilters,
|
||||
IBotConfig,
|
||||
} from "@spt/models/spt/config/IBotConfig";
|
||||
import { ConfigServer } from "@spt/servers/ConfigServer";
|
||||
import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
|
||||
import { IBotType } from "@spt/models/eft/common/tables/IBotType";
|
||||
import {
|
||||
cullModItems,
|
||||
makeMapSpecificWeaponWeightings,
|
||||
makeRandomisationAdjustments,
|
||||
updateScopes,
|
||||
} from "./OnGameStartUtils";
|
||||
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
|
||||
import {
|
||||
StoredWeightingAdjustmentDetails,
|
||||
buffScavGearAsLevel,
|
||||
setPlateWeightings,
|
||||
} from "../NonPmcBotChanges/NonPmcUtils";
|
||||
|
||||
export class globalValues {
|
||||
public static Logger: ILogger;
|
||||
public static profileHelper: ProfileHelper;
|
||||
public static storedEquipmentValues: Record<
|
||||
string,
|
||||
StoredWeightingAdjustmentDetails[]
|
||||
> = {};
|
||||
public static tables: IDatabaseTables;
|
||||
public static originalBotTypes: Record<string, IBotType>;
|
||||
public static config = config;
|
||||
public static advancedConfig = advancedConfig;
|
||||
public static originalWeighting: EquipmentFilters;
|
||||
public static configServer: ConfigServer;
|
||||
|
||||
public static updateInventory(
|
||||
currentLevel: number,
|
||||
location: keyof typeof advancedConfig.locations
|
||||
) {
|
||||
const items = this.tables.templates.items;
|
||||
const nameList = Object.keys(this.storedEquipmentValues);
|
||||
if (!nameList.length || !currentLevel) return;
|
||||
const botConfig = this.configServer.getConfig<IBotConfig>(ConfigTypes.BOT);
|
||||
const firstPrimaryWeaponMultiplier =
|
||||
advancedConfig.locations[location].weightingAdjustments
|
||||
.FirstPrimaryWeapon;
|
||||
|
||||
nameList.forEach((botName) => {
|
||||
const copiedInventory = cloneDeep(
|
||||
this.originalBotTypes[botName].inventory
|
||||
);
|
||||
|
||||
const currentLevelIndex = this.storedEquipmentValues[botName].findIndex(
|
||||
({ levelRange: { min, max } }) =>
|
||||
currentLevel <= max && currentLevel >= min
|
||||
);
|
||||
|
||||
const weightingToUpdate =
|
||||
this.storedEquipmentValues[botName][currentLevelIndex];
|
||||
|
||||
if (!weightingToUpdate) return;
|
||||
if (weightingToUpdate?.ammo) {
|
||||
for (const caliber in weightingToUpdate.ammo) {
|
||||
copiedInventory.Ammo[caliber] = {
|
||||
...copiedInventory.Ammo[caliber],
|
||||
...weightingToUpdate.ammo[caliber],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (weightingToUpdate?.equipment) {
|
||||
for (const equipmentType in weightingToUpdate.equipment) {
|
||||
copiedInventory.equipment[equipmentType] = {
|
||||
...copiedInventory.equipment[equipmentType],
|
||||
...weightingToUpdate.equipment[equipmentType],
|
||||
};
|
||||
try {
|
||||
//update weapon type weightings per map here
|
||||
if (
|
||||
equipmentType === "FirstPrimaryWeapon" &&
|
||||
botName !== "marksman"
|
||||
) {
|
||||
// console.log("Updating", botName, " weapons for map", location);
|
||||
const firstPrimary: Record<string, number> = cloneDeep(
|
||||
copiedInventory.equipment[equipmentType]
|
||||
);
|
||||
|
||||
const firstPrimaryKeys = Object.keys(firstPrimary);
|
||||
firstPrimaryKeys?.forEach((weaponId) => {
|
||||
const parentId = items[weaponId]?._parent;
|
||||
const parent = items?.[parentId]?._name;
|
||||
if (parent && firstPrimaryWeaponMultiplier[parent]) {
|
||||
const multiplier =
|
||||
(firstPrimaryWeaponMultiplier[parent] - 1) / 2 + 1;
|
||||
|
||||
copiedInventory.equipment[equipmentType][weaponId] =
|
||||
Math.round(multiplier * firstPrimary[weaponId]);
|
||||
|
||||
// if (botName === "assault") {
|
||||
// console.log(
|
||||
// multiplier,
|
||||
// location,
|
||||
// botName,
|
||||
// firstPrimary[weaponId],
|
||||
// " to ",
|
||||
// copiedInventory.equipment[equipmentType][weaponId],
|
||||
// parent,
|
||||
// items[weaponId]._name
|
||||
// );
|
||||
// }
|
||||
} else {
|
||||
console.log(
|
||||
`[AlgorithmicLevelProgression]: Unable to set map settings for bot ${botName}'s item ${items[weaponId]._name} - ${weaponId} `
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
`[AlgorithmicLevelProgression]: Failed to update bot ${botName}'s ${equipmentType}`;
|
||||
}
|
||||
}
|
||||
|
||||
if (botName === "assault") {
|
||||
//adjust randomization
|
||||
buffScavGearAsLevel(botConfig.equipment[botName], currentLevelIndex);
|
||||
}
|
||||
|
||||
setPlateWeightings(
|
||||
botName,
|
||||
botConfig.equipment[botName],
|
||||
currentLevelIndex
|
||||
);
|
||||
|
||||
// if (botName === "assault") {
|
||||
// saveToFile(this.tables.bots.types[botName], `refDBS/assault.json`);
|
||||
// }
|
||||
}
|
||||
|
||||
this.tables.bots.types[botName].inventory = copiedInventory;
|
||||
});
|
||||
}
|
||||
|
||||
public static setValuesForLocation(
|
||||
location: keyof typeof advancedConfig.locations,
|
||||
hours: number
|
||||
) {
|
||||
if (location === "factory4_day") hours = 12;
|
||||
if (location === "factory4_night") hours = 1;
|
||||
if (location === "laboratory") hours = 12;
|
||||
|
||||
this.config.debug &&
|
||||
this.Logger.info(
|
||||
`Algorthimic LevelProgression: Setting up values for map ${location}`
|
||||
);
|
||||
const botConfig = this.configServer.getConfig<IBotConfig>(ConfigTypes.BOT);
|
||||
|
||||
const mapWeightings =
|
||||
advancedConfig.locations?.[location]?.weightingAdjustments;
|
||||
|
||||
const items = this.tables.templates.items;
|
||||
|
||||
if (!mapWeightings) {
|
||||
return this.Logger.warning(
|
||||
`Algorthimic LevelProgression: did not recognize 'location': ${location}, using defaults`
|
||||
);
|
||||
}
|
||||
|
||||
if (!this.originalWeighting) {
|
||||
return this.Logger.error(
|
||||
`Algorthimic LevelProgression: 'originalWeighting' was not set correctly`
|
||||
);
|
||||
}
|
||||
|
||||
if (!items) {
|
||||
return this.Logger.error(
|
||||
`Algorthimic LevelProgression: 'items' was not set correctly`
|
||||
);
|
||||
}
|
||||
|
||||
const finalEquipment: EquipmentFilters = cloneDeep(this.originalWeighting);
|
||||
|
||||
const isNight = hours < 7 || hours >= 19;
|
||||
|
||||
config.debug &&
|
||||
console.log(
|
||||
"The server thinks it is ",
|
||||
isNight ? "NIGHT" : "DAY",
|
||||
hours,
|
||||
" do appropriate things."
|
||||
);
|
||||
|
||||
const randomisation = finalEquipment.randomisation;
|
||||
|
||||
makeRandomisationAdjustments(
|
||||
isNight,
|
||||
this.originalWeighting,
|
||||
randomisation,
|
||||
location
|
||||
);
|
||||
|
||||
const originalBotTypesCopy: Record<string, IBotType> = cloneDeep(
|
||||
this.originalBotTypes
|
||||
);
|
||||
|
||||
cullModItems(
|
||||
originalBotTypesCopy.usec.inventory.mods,
|
||||
isNight,
|
||||
items,
|
||||
location
|
||||
);
|
||||
|
||||
updateScopes(
|
||||
originalBotTypesCopy.usec.inventory.mods,
|
||||
isNight,
|
||||
items,
|
||||
location
|
||||
);
|
||||
|
||||
originalBotTypesCopy.bear.inventory.mods =
|
||||
originalBotTypesCopy.usec.inventory.mods;
|
||||
|
||||
const pmcWeighting = finalEquipment.weightingAdjustmentsByBotLevel;
|
||||
makeMapSpecificWeaponWeightings(
|
||||
location,
|
||||
items,
|
||||
this.originalWeighting,
|
||||
pmcWeighting
|
||||
);
|
||||
|
||||
// saveToFile(originalBotTypesCopy.usec.inventory.mods, "updated.json")
|
||||
// saveToFile(originalBotTypesCopy.usec.inventory, "refDBS/usecInventoryRef.json")
|
||||
// saveToFile(finalEquipment, "finalEquipment.json");
|
||||
// saveToFile(this.originalWeighting, "originalWeighting.json")
|
||||
botConfig.equipment.pmc = finalEquipment;
|
||||
this.tables.bots.types = originalBotTypesCopy;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,271 @@
|
|||
export default [
|
||||
"544a3f024bdc2d1d388b4568", //ELCAN Specter OS4x assault scope
|
||||
///
|
||||
"5af99e9186f7747c447120b8", // Bad pockets
|
||||
"60c7272c204bc17802313365",
|
||||
"627a4e6b255f7527fb05a0f6",
|
||||
"64cbd95a29b9b4283e216ff5",
|
||||
///
|
||||
"622b4f54dc8dcc0ba8742f85", //HK G36 Hensoldt HKV ZF 1.5x carry handle
|
||||
"622b4d7df9cfc87d675d2ded", //HK G36 Hensoldt HKV 3x carry handle
|
||||
// armasight vulcan universal base
|
||||
// Geissele Super Precision 30mm
|
||||
"5aa66a9be5b5b0214e506e89", // Nightforce Magmount 34mm ring scope mount > stupid long scope mount
|
||||
"5a1ead28fcdbcb001912fa9f", // Reap-ir Mount
|
||||
"5c86592b2e2216000e69e77c", // IEA Mil-Optics KH/F 34mm one-piece magmount <Stupid Long distance scopes>
|
||||
"5c11046cd174af02a012e42b", // Wilcox Interface for PVS-7 > Thermal night vision connector
|
||||
"5ea058e01dbce517f324b3e2", // Tac-Kek Heavy Trooper mask for Ops-Core-type helmets
|
||||
"5c0558060db834001b735271", // GPNVG-18 Night Vision goggles
|
||||
"5648b62b4bdc2d9d488b4585", // gp-34
|
||||
"5e99711486f7744bfc4af328", // Sanitarsmedkit
|
||||
"5d52cc5ba4b9367408500062",
|
||||
"6087e570b998180e9f76dc24",
|
||||
"58ac60eb86f77401897560ff", // golden balaclava!
|
||||
"6241c316234b593b5676b637", // bb ammo
|
||||
"5cdeb229d7f00c000e7ce174", // stationary gun
|
||||
"5943d9c186f7745a13413ac9", // shrapnel bullets?
|
||||
"5996f6cb86f774678763a6ca", // shrapnel bullets?
|
||||
"5996f6fc86f7745e585b4de3", // shrapnel bullets?
|
||||
"63b35f281745dd52341e5da7", // shrapnel bullets?
|
||||
"5d2f2ab648f03550091993ca", // shrapnel bullets?
|
||||
"5cde8864d7f00c0010373be1",
|
||||
"64b9cf0ac12b9c38db26923a", // << no idea
|
||||
"627a137bf21bc425b06ab944",
|
||||
"610720f290b75a49ff2e5e25",
|
||||
"5996f6d686f77467977ba6cc", // shrapnel bullets?
|
||||
"5ae083b25acfc4001a5fc702", // Master hand ?
|
||||
"544a3d0a4bdc2d1b388b4567",
|
||||
"5a16bb52fcdbcb001a3b00dc", // skull lock
|
||||
"5a1eaa87fcdbcb001865f75e", // reap-ir
|
||||
"5d1b5e94d7ad1a2b865a96b0", // flir
|
||||
"5c066ef40db834001966a595", // helmet_armasight_nvg_googles_mask
|
||||
"5a0c59791526d8dba737bba7", // butt pad
|
||||
"57371aab2459775a77142f22",
|
||||
//small mags
|
||||
"57838f0b2459774a256959b2",
|
||||
"5aaa5e60e5b5b000140293d6",
|
||||
"5b1fd4e35acfc40018633c39",
|
||||
"59e5d83b86f7745aed03d262",
|
||||
"5b7bef1e5acfc43d82528402",
|
||||
"617130016c780c1e710c9a24",
|
||||
"55d4837c4bdc2d1d4e8b456c",
|
||||
"5c503ac82e221602b21d6e9a",
|
||||
"6241c2c2117ad530666a5108",
|
||||
//large mags
|
||||
// "55d485804bdc2d8c2f8b456b", shotgun 153/155 extended /7/8
|
||||
// "56deeefcd2720bc8328b4568", shotgun 153/155 extended /7/8
|
||||
// "5882163224597757561aa920", shotgun 153/155 extended /7/8
|
||||
"5a78832ec5856700155a6ca3",
|
||||
"5a966f51a2750c00156aacf6",
|
||||
"5cf8f3b0d7f00c00217872ef",
|
||||
"625ff2eb9f5537057932257d",
|
||||
"625ff3046d721f05d93bf2ee",
|
||||
"625ff31daaaa8c1130599f64",
|
||||
"627bce33f21bc425b06ab967",
|
||||
"564ca9df4bdc2d35148b4569",
|
||||
// '55d481904bdc2d8c2f8b456a', //45 round ak
|
||||
"55d482194bdc2d1d4e8b456b",
|
||||
"5bed625c0db834001c062946",
|
||||
"55d485be4bdc2d962f8b456f",
|
||||
"5cbdc23eae9215001136a407",
|
||||
"5c6175362e221600133e3b94",
|
||||
"5cfe8010d7ad1a59283b14c6",
|
||||
"61695095d92c473c7702147a",
|
||||
"61695095d92c473c7702147a",
|
||||
"59c1383d86f774290a37e0ca",
|
||||
"5c6592372e221600133e47d7",
|
||||
"544a37c44bdc2d25388b4567",
|
||||
"5a718f958dc32e00094b97e7",
|
||||
"5c5db6742e2216000f1b2852",
|
||||
"5a351711c4a282000b1521a4",
|
||||
"5addccf45acfc400185c2989",
|
||||
"5b7bef9c5acfc43d102852ec",
|
||||
// "5b1fb3e15acfc4001637f068", 40 round ak
|
||||
// "59e5f5a486f7746c530b3ce2", 40 round
|
||||
// "544a378f4bdc2d30388b4567", 40 round
|
||||
// "5d1340bdd7ad1a0e8d245aab", 40-round 556 45
|
||||
// "630e295c984633f1fb0e7c30",
|
||||
// "5ba26586d4351e44f824b340", MP7 40
|
||||
"5c5db6652e221600113fba51",
|
||||
"5cffa483d7ad1a049e54ef1c",
|
||||
"5d52d479a4b936793d58c76b",
|
||||
// stm-9
|
||||
// stocks
|
||||
"5c0faeddd174af02a962601f",
|
||||
"5d120a10d7ad1a4e1026ba85",
|
||||
"5b0800175acfc400153aebd4",
|
||||
"5947e98b86f774778f1448bc",
|
||||
"5947eab886f77475961d96c5",
|
||||
// "602e3f1254072b51b239f713",
|
||||
"5c793fb92e221644f31bfb64",
|
||||
"5c793fc42e221600114ca25d",
|
||||
"591aef7986f774139d495f03",
|
||||
"591af10186f774139d495f0e",
|
||||
"627254cc9c563e6e442c398f",
|
||||
"638de3603a1a4031d8260b8c",
|
||||
"5a33ca0fc4a282000d72292f",
|
||||
// Saiga-9 9x19 carbine
|
||||
// stocks
|
||||
"5cf50fc5d7f00c056c53f83c", //AK-74M CAA AKTS AK74 buffer tube > 25
|
||||
"5ac78eaf5acfc4001926317a", //AK-74M/AK-100 Zenit PT Lock >2
|
||||
//Full Size AK mods
|
||||
// stocks
|
||||
// "628a6678ccaab13006640e49", //AKM/AK-74 RD AK to M4 buffer tube adapter > 17
|
||||
"5b222d335acfc4771e1be099", //AKM/AK-74 Zenit PT Lock > 1
|
||||
"59ecc28286f7746d7a68aa8c", // AK-74U Zenit PT Lock > 1
|
||||
"5839a40f24597726f856b511", // bufferTubes > 21
|
||||
"5cf518cfd7f00c065b422214",
|
||||
"5649b2314bdc2d79388b4576",
|
||||
"5b04473a5acfc40018632f70", //beefy Stock
|
||||
"5e217ba4c1434648c13568cd", //Red funky stock
|
||||
"5b0e794b5acfc47a877359b2", // Zhokov black
|
||||
"6087e2a5232e5a31c233d552", //Archangel
|
||||
//DustCovers
|
||||
"59d6507c86f7741b846413a2", // AKM dust cover (6P1 0-1) allowing one
|
||||
"59e6449086f7746c9f75e822",
|
||||
"628a665a86cbd9750d2ff5e5",
|
||||
"5649af094bdc2df8348b4586",
|
||||
"5ac50da15acfc4001718d287",
|
||||
//bullets that think they are guns
|
||||
"624c0b3340357b5f566e8766",
|
||||
"624c0b3340357b5f566e8766",
|
||||
"6217726288ed9f0845317459",
|
||||
"62178be9d0050232da3485d9",
|
||||
//Mosin shorty,
|
||||
"5bfd36ad0db834001c38ef66",
|
||||
"5bfd36290db834001966869a",
|
||||
"5a16b9fffcdbcb0176308b34",
|
||||
"5c07c9660db834001a66b588",
|
||||
"5d2f25bc48f03502573e5d85",
|
||||
"5a7c74b3e899ef0014332c29",
|
||||
//Waffle 545
|
||||
"615d8f8567085e45ef1409ca",
|
||||
//Mosin stocks
|
||||
"5bbdb870d4351e00367fb67d",
|
||||
"5bae13bad4351e00320204af",
|
||||
//IR lasers
|
||||
"57fd23e32459772d0805bcf1",
|
||||
"544909bb4bdc2d6f028b4577",
|
||||
"5d10b49bd7ad1a1a560708b0",
|
||||
"5c06595c0db834001a66af6c",
|
||||
"5c5952732e2216398b5abda2",
|
||||
"5a5f1ce64f39f90b401987bc",
|
||||
"61605d88ffa6e502ac5e7eeb",
|
||||
//pistolGrips
|
||||
"5b07db875acfc40dc528a5f6",
|
||||
"615d8faecabb9b7ad90f4d5d",
|
||||
"59db3acc86f7742a2c4ab912",
|
||||
"59db3b0886f77429d72fb895",
|
||||
"59db3a1d86f77429e05b4e92",
|
||||
"5d025cc1d7ad1a53845279ef",
|
||||
"5f6341043ada5942720e2dc5",
|
||||
"6087e663132d4d12c81fd96b",
|
||||
"5e2192a498a36665e8337386",
|
||||
"5cf54404d7f00c108840b2ef",
|
||||
"5b30ac585acfc433000eb79c",
|
||||
"628a664bccaab13006640e47",
|
||||
"628c9ab845c59e5b80768a81",
|
||||
"5c6bf4aa2e2216001219b0ae",
|
||||
"5649ae4a4bdc2d1b2b8b4588",
|
||||
"6113c3586c780c1e710c90bc",
|
||||
"6113cce3d92c473c770200c7",
|
||||
"6113cc78d3a39d50044c065a",
|
||||
"5b7d679f5acfc4001a5c4024",
|
||||
//Handguards
|
||||
"595cfa8b86f77427437e845b",
|
||||
"595cf16b86f77427440c32e2",
|
||||
"55f84c3c4bdc2d5f408b4576",
|
||||
"619b5db699fb192e7430664f",
|
||||
"5b2cfa535acfc432ff4db7a0",
|
||||
"5c9a25172e2216000f20314e",
|
||||
"55f84c3c4bdc2d5f408b4576",
|
||||
"588b56d02459771481110ae2",
|
||||
"5c9a26332e2216001219ea70",
|
||||
"5ea16ada09aa976f2e7a51be",
|
||||
"5ea16acdfadf1d18c87b0784",
|
||||
"5d4405f0a4b9361e6a4e6bd9",
|
||||
"5c78f2492e221600114c9f04",
|
||||
"5c78f2612e221600114c9f0d",
|
||||
"6034e3e20ddce744014cb878",
|
||||
"6034e3d953a60014f970617b",
|
||||
"6034e3cb0ddce744014cb870",
|
||||
"5c6d5d8b2e221644fc630b39",
|
||||
"5d00e0cbd7ad1a6c6566a42d",
|
||||
"5d00f63bd7ad1a59283b1c1e",
|
||||
"6087e0336d0bd7580617bb7a",
|
||||
"63888bbd28e5cc32cc09d2b6",
|
||||
//Foregrips
|
||||
"5fc0f9b5d724d907e2077d82",
|
||||
"5cda9bcfd7f00c0c0b53e900",
|
||||
"59f8a37386f7747af3328f06",
|
||||
"5a7dbfc1159bd40016548fde",
|
||||
"619386379fb0c665d5490dbe",
|
||||
"5de8fbad2fbe23140d3ee9c4",
|
||||
"5b057b4f5acfc4771e1bd3e9",
|
||||
"5c791e872e2216001219c40a",
|
||||
"5f6340d3ca442212f4047eb2",
|
||||
"591af28e86f77414a27a9e1d",
|
||||
"5c1bc5612e221602b5429350",
|
||||
"5c1cd46f2e22164bef5cfedb",
|
||||
"5c1bc5af2e221602b412949b",
|
||||
"648c1a965043c4052a4f8505", // Ebudal (bad stim)
|
||||
"5d02778e86f774203e7dedbe", // CMS surgical kit
|
||||
"5d02797c86f774203f38e30a", // Surv kit
|
||||
"590c657e86f77412b013051d", //grizzly
|
||||
"5d1c702ad7ad1a632267f429", //long handgun stock
|
||||
"620109578d82e67e7911abf2", // signal pistol
|
||||
"62178c4d4ecf221597654e3d",
|
||||
"624c0570c9b794431568f5d5",
|
||||
"624c09da2cec124eb67c1046",
|
||||
"624c09e49b98e019a3315b66",
|
||||
"624c09cfbc2e27219346d955",
|
||||
"62389aaba63f32501b1b444f", // signal ammo
|
||||
"62389ba9a63f32501b1b4451",
|
||||
"62389bc9423ed1685422dc57",
|
||||
"62389be94d5d474bf712e709",
|
||||
"635267f063651329f75a4ee8",
|
||||
"633a98eab8b0506e48497c1a", // sr-2m 20 round mag
|
||||
"5caf1041ae92157c28402e3f", // ash12 10 round
|
||||
"5d0a29fed7ad1a002769ad08",
|
||||
"62811f461d5df4475f46a332",
|
||||
"6275303a9f372d6ea97f9ec7", //revolver grenadeLauncher
|
||||
"6422e1ea3c0f06190302161a", //SVT-40 7.62x54R 10-round magazine
|
||||
"5c471c442e221602b542a6f8", //SVD 7.62x54R 10-round magazine
|
||||
"57d14e1724597714010c3f4b", //PP-91 "Kedr" 9x18PM 20-round magazine
|
||||
"5d2f213448f0355009199284", //HK MP5 9x19 20-round magazine
|
||||
"5a43957686f7742a2c2f11b0", //Santahat
|
||||
"639af924d0446708ee62294e", // FN40GL Mk2
|
||||
"639c3fbbd0446708ee622ee9", // FN40GL Mk25e81ebcd8e146c7080625e15
|
||||
"5e81ebcd8e146c7080625e15", // FN40GL Mk2 40mm grenade launcher
|
||||
"59f32c3b86f77472a31742f0", // dogtags
|
||||
"59f32bb586f774757e1e8442", // dogtags
|
||||
"6662e9f37fa79a6d83730fa0", // dogtags
|
||||
"6662ea05f6259762c56f3189", // dogtags
|
||||
"6662e9aca7e0b43baa3d5f74", // dogtags
|
||||
"6662e9cda7e0b43baa3d5f76", // dogtags
|
||||
"5b9b9020e7ef6f5716480215", // dogtags
|
||||
"65392f611406374f82152ba5", // mount_all_gbrs_hydra_micro_kit
|
||||
"653931da5db71d30ab1d6296", // GBRS Aimpoint Hydra Mount Kit (FDE)
|
||||
"618b9682a3884f56c957ca78", //Reptilia ROF-90 RMR mount for Geissele scope mounts
|
||||
"618ba92152ecee1505530bd3", //Reptilia ROF-90 RMR mount for Geissele scope mounts ddc
|
||||
"6601546f86889319850bd566",
|
||||
"66015072e9f84d5680039678",
|
||||
"66015dc4aaad2f54cb04c56a",
|
||||
"5d70e500a4b9364de70d38ce",
|
||||
|
||||
"670e8eab8c1bb0e5a7075acf", //mag_pm_izhmeh_9x18pm_999_infectedMagazin
|
||||
"671d85439ae8365d69117ba6", //mag_tt_toz_std_762x25tt_999_infectedMagazin
|
||||
"671d8617a3e45c1f5908278c", //mag_mp443_izhmeh_std_9x19_999_infectedMagazin
|
||||
"671d8ac8a3e45c1f59082799", //mag_glock_glock_w_pad_9x19_999_fde_Infected
|
||||
"671d8b38b769f0d88c0950f8", //mag_m1911_colt_m45a1_std_1143x23_999_infected
|
||||
"671d8b8c0959c721a50ca838", //mag_usp_hk_usp_tactical_1143x23_999_infected
|
||||
"628120f210e26c1f344e6558", // mxc broken mod
|
||||
"66d98233302686954b0c6f81", // RSP-30 reactive signal cartridge (Blue)
|
||||
];
|
||||
|
||||
//5d0a29fed7ad1a002769ad08
|
||||
//62811f461d5df4475f46a332
|
||||
|
||||
//56ea70acd2720b844b8b4594 optic
|
||||
|
||||
// 6275303a9f372d6ea97f9ec7
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
import { StaticRouterModService } from "@spt/services/mod/staticRouter/StaticRouterModService";
|
||||
import { DependencyContainer } from "tsyringe";
|
||||
import { globalValues } from "./GlobalValues";
|
||||
import { WeatherController } from "@spt/controllers/WeatherController";
|
||||
import { saveToFile } from "./utils";
|
||||
import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
|
||||
import { IBotConfig } from "@spt/models/spt/config/IBotConfig";
|
||||
import { enableNonPMCBotChanges } from "../../config/config.json";
|
||||
|
||||
export const LocationUpdater = (container: DependencyContainer): undefined => {
|
||||
const staticRouterModService = container.resolve<StaticRouterModService>(
|
||||
"StaticRouterModService"
|
||||
);
|
||||
|
||||
const weatherController =
|
||||
container.resolve<WeatherController>("WeatherController");
|
||||
|
||||
staticRouterModService.registerStaticRouter(
|
||||
`AlgorithmicLevelProgressionMapUpdater`,
|
||||
[
|
||||
{
|
||||
url: "/client/match/local/start",
|
||||
action: async (_url, info, sessionId, output) => {
|
||||
const time = weatherController.generate().time;
|
||||
|
||||
const hours = getTime(time, info.timeVariant === "PAST" ? 12 : 0);
|
||||
// console.log("hours", hours);
|
||||
try {
|
||||
globalValues.setValuesForLocation(
|
||||
info.location.toLowerCase(),
|
||||
hours
|
||||
);
|
||||
if (enableNonPMCBotChanges) {
|
||||
const pmcData =
|
||||
globalValues.profileHelper.getPmcProfile(sessionId);
|
||||
globalValues.updateInventory(
|
||||
pmcData?.Info?.Level || 1,
|
||||
info.location.toLowerCase()
|
||||
);
|
||||
}
|
||||
console.log("Algorthimic LevelProgression: Loaded");
|
||||
} catch (error) {
|
||||
console.log(
|
||||
`"Algorthimic LevelProgression: failed to make equipment changes.
|
||||
` + error?.message
|
||||
);
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
},
|
||||
],
|
||||
"aki"
|
||||
);
|
||||
|
||||
globalValues.config.debug &&
|
||||
console.log(
|
||||
"Algorthimic LevelProgression: Custom router AlgorithmicLevelProgressionMapUpdater Registered"
|
||||
);
|
||||
};
|
||||
|
||||
function getTime(time: string, hourDiff: number): number {
|
||||
let [hours, minutes] = time.split(":");
|
||||
|
||||
if (hourDiff == 12 && parseInt(hours) >= 12) {
|
||||
return Math.abs(parseInt(hours) - hourDiff);
|
||||
}
|
||||
return Math.abs(parseInt(hours) + hourDiff);
|
||||
}
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
import { IBotType } from "@spt/models/eft/common/tables/IBotType";
|
||||
import { IHandbookBase } from "@spt/models/eft/common/tables/IHandbookBase";
|
||||
import { IBotConfig } from "@spt/models/spt/config/IBotConfig";
|
||||
import {
|
||||
blacklistedItems,
|
||||
checkParentRecursive,
|
||||
keyMechanical,
|
||||
saveToFile,
|
||||
} from "./utils";
|
||||
import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem";
|
||||
import { IPmcConfig } from "@spt/models/spt/config/IPmcConfig";
|
||||
import nonPmcBotConfig from "../../config/nonPmcBotConfig.json";
|
||||
import { BaseClasses } from "@spt/models/enums/BaseClasses";
|
||||
|
||||
export const buildLootChanges = (
|
||||
items: Record<string, ITemplateItem>,
|
||||
handbook: IHandbookBase,
|
||||
prices: Record<string, number>,
|
||||
_: IPmcConfig,
|
||||
botConfig: IBotConfig,
|
||||
types: Record<string, IBotType>
|
||||
) => {
|
||||
const assaultInventory = types.assault.inventory;
|
||||
const handbookMapper = {} as Record<string, number>;
|
||||
|
||||
// Zero out all current items
|
||||
for (const key in assaultInventory.items.Backpack) {
|
||||
assaultInventory.items.Backpack[key] = 1;
|
||||
}
|
||||
for (const key in assaultInventory.items.Pockets) {
|
||||
assaultInventory.items.Pockets[key] = 1;
|
||||
}
|
||||
for (const key in assaultInventory.items.TacticalVest) {
|
||||
assaultInventory.items.TacticalVest[key] = 1;
|
||||
}
|
||||
|
||||
handbook.Items.forEach(({ Id, Price }) => {
|
||||
handbookMapper[Id] = Price;
|
||||
});
|
||||
|
||||
const getFleaPrice = (itemID: string): number => {
|
||||
if (typeof prices[itemID] != "undefined") {
|
||||
return prices[itemID];
|
||||
} else {
|
||||
return handbookMapper[itemID];
|
||||
}
|
||||
};
|
||||
|
||||
const newToAdd = {
|
||||
[BaseClasses.BARTER_ITEM]: 50,
|
||||
[BaseClasses.HOUSEHOLD_GOODS]: 50,
|
||||
[BaseClasses.FOOD_DRINK]: 50,
|
||||
[BaseClasses.ELECTRONICS]: 1,
|
||||
[BaseClasses.JEWELRY]: 2,
|
||||
[BaseClasses.OTHER]: 1,
|
||||
[BaseClasses.TOOL]: 5,
|
||||
[BaseClasses.REPAIR_KITS]: 1,
|
||||
[BaseClasses.MONEY]: 1,
|
||||
"60b0f6c058e0b0481a09ad11": 1, //gingy
|
||||
"62a09d3bcf4a99369e262447": 1, //wallet
|
||||
"5783c43d2459774bbe137486": 1, //walletz
|
||||
};
|
||||
|
||||
if (nonPmcBotConfig.addRandomizedKeysToScavs) {
|
||||
newToAdd[BaseClasses.KEY_MECHANICAL] = 1;
|
||||
}
|
||||
|
||||
const itemsToRemove = new Set([
|
||||
BaseClasses.AMMO_BOX,
|
||||
BaseClasses.GEAR_MOD,
|
||||
BaseClasses.SILENCER,
|
||||
BaseClasses.KNIFE,
|
||||
BaseClasses.ASSAULT_SCOPE,
|
||||
BaseClasses.COLLIMATOR,
|
||||
BaseClasses.SPECIAL_SCOPE,
|
||||
BaseClasses.OPTIC_SCOPE,
|
||||
BaseClasses.FOREGRIP,
|
||||
BaseClasses.ARMOR,
|
||||
BaseClasses.VEST,
|
||||
BaseClasses.TACTICAL_COMBO,
|
||||
]);
|
||||
|
||||
const addList = Object.keys(newToAdd);
|
||||
const removeList = [...itemsToRemove];
|
||||
|
||||
//limit keys on scavs
|
||||
botConfig.itemSpawnLimits.assault[BaseClasses.KEY_MECHANICAL] = 1;
|
||||
|
||||
const randomlyAllowKey = (id) => {
|
||||
if (
|
||||
checkParentRecursive(id, items, [BaseClasses.KEY_MECHANICAL]) &&
|
||||
Math.random() > nonPmcBotConfig.percentageOfKeysInSpawnPool
|
||||
) {
|
||||
// console.log(items[id]._name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const scavLootBlacklist = new Set(nonPmcBotConfig.scavLootBlacklist);
|
||||
|
||||
const loot = Object.keys(items).filter(
|
||||
(id) =>
|
||||
!scavLootBlacklist.has(id) &&
|
||||
!blacklistedItems.has(id) &&
|
||||
randomlyAllowKey(id) &&
|
||||
checkParentRecursive(id, items, addList) &&
|
||||
!checkParentRecursive(id, items, [BaseClasses.MONEY, ...removeList]) &&
|
||||
!items[id]?._props?.QuestItem &&
|
||||
!!getFleaPrice(id)
|
||||
);
|
||||
|
||||
const importedCustomLoot = nonPmcBotConfig?.additionalScavLoot.filter(
|
||||
(id) => !!items[id] && !!getFleaPrice(id)
|
||||
);
|
||||
|
||||
const configmultiplier = 100 / nonPmcBotConfig.lootDisparityMultiplier;
|
||||
|
||||
const allLoot = [...loot, ...importedCustomLoot]
|
||||
.map((id) => ({
|
||||
id,
|
||||
value: Math.round(getFleaPrice(id) / configmultiplier) || 1,
|
||||
name: items[id]._name,
|
||||
}))
|
||||
.sort(({ value: b }, { value: a }) => b - a);
|
||||
|
||||
const reverseLoot = [...allLoot].reverse().map(({ value }) => value);
|
||||
|
||||
const top = reverseLoot[Math.round(reverseLoot.length * 0.15)];
|
||||
const bottom = reverseLoot[Math.round(allLoot.length * 0.7)];
|
||||
|
||||
const finalValues: Record<string, number> = {};
|
||||
|
||||
allLoot.forEach(({ value, id, name }, index) => {
|
||||
let rarity = reverseLoot[index];
|
||||
switch (true) {
|
||||
case reverseLoot[index] > top:
|
||||
rarity = top;
|
||||
break;
|
||||
case reverseLoot[index] < bottom:
|
||||
rarity = Math.round(
|
||||
rarity * (0.3 / nonPmcBotConfig.lootDisparityMultiplier)
|
||||
);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
if (checkParentRecursive(id, items, [keyMechanical])) {
|
||||
rarity = Math.round(rarity * (Math.random() * Math.random())) || 1;
|
||||
}
|
||||
|
||||
finalValues[id] = rarity;
|
||||
});
|
||||
|
||||
// saveToFile(finalValues, "refDBS/allLoot.json");
|
||||
|
||||
assaultInventory.items.Backpack = finalValues;
|
||||
assaultInventory.items.Pockets = finalValues;
|
||||
assaultInventory.items.TacticalVest = finalValues;
|
||||
|
||||
// botConfig.walletLoot.chancePercent = 35;
|
||||
// botConfig.walletLoot.walletTplPool = [];
|
||||
|
||||
itemsToRemove.forEach((id) => {
|
||||
if (botConfig.itemSpawnLimits.assault[id])
|
||||
delete botConfig.itemSpawnLimits.assault[id];
|
||||
if (assaultInventory.items.Backpack[id])
|
||||
delete assaultInventory.items.Backpack[id];
|
||||
if (assaultInventory.items.TacticalVest[id])
|
||||
delete assaultInventory.items.TacticalVest[id];
|
||||
if (assaultInventory.items.Pockets[id])
|
||||
delete assaultInventory.items.Pockets[id];
|
||||
});
|
||||
|
||||
Object.keys(newToAdd).forEach((id) => {
|
||||
botConfig.itemSpawnLimits.assault[id] = newToAdd[id];
|
||||
botConfig.itemSpawnLimits.assaultgroup[id] = newToAdd[id];
|
||||
});
|
||||
|
||||
return finalValues;
|
||||
};
|
||||
|
|
@ -0,0 +1,373 @@
|
|||
import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem";
|
||||
import {
|
||||
EquipmentFilters,
|
||||
IRandomisationDetails,
|
||||
IWeightingAdjustmentDetails,
|
||||
} from "@spt/models/spt/config/IBotConfig";
|
||||
import advancedConfig from "../../config/advancedConfig.json";
|
||||
import { IBotType, IMods } from "@spt/models/eft/common/tables/IBotType";
|
||||
import {
|
||||
SightType,
|
||||
checkParentRecursive,
|
||||
cloneDeep,
|
||||
mountParent,
|
||||
muzzleParent,
|
||||
sightParent,
|
||||
weaponParent,
|
||||
weaponTypeNameToId,
|
||||
} from "./utils";
|
||||
import InternalBlacklist from "./InternalBlacklist";
|
||||
import { globalValues } from "./GlobalValues";
|
||||
|
||||
export const makeRandomisationAdjustments = (
|
||||
isNight: boolean,
|
||||
originalWeight: EquipmentFilters,
|
||||
randomisation: IRandomisationDetails[],
|
||||
location: keyof typeof advancedConfig.locations
|
||||
) => {
|
||||
const noNvgNeeded = ["factory4_day", "factory4_night", "laboratory"].includes(
|
||||
location
|
||||
);
|
||||
|
||||
// levelRange: MinMax;
|
||||
// generation?: Record<string, GenerationData>;
|
||||
// /** Mod slots that should be fully randomised -ignores mods from bottype.json and instaed creates a pool using items.json */
|
||||
// randomisedWeaponModSlots?: string[];
|
||||
// /** Armor slots that should be randomised e.g. 'Headwear, Armband' */
|
||||
// randomisedArmorSlots?: string[];
|
||||
// /** Equipment chances */
|
||||
// equipment?: Record<string, number>;
|
||||
// /** Weapon mod chances */
|
||||
// weaponMods?: Record<string, number>;
|
||||
// /** Equipment mod chances */
|
||||
// equipmentMods?: Record<string, number>;
|
||||
|
||||
originalWeight.randomisation.forEach((_, index) => {
|
||||
// NVG's
|
||||
if (
|
||||
!noNvgNeeded &&
|
||||
randomisation?.[index]?.equipmentMods?.mod_nvg !== undefined
|
||||
) {
|
||||
randomisation[index].equipmentMods.mod_nvg = isNight
|
||||
? (index + 1) * 18
|
||||
: 0;
|
||||
if (randomisation[index].equipmentMods.mod_nvg > 100)
|
||||
randomisation[index].equipmentMods.mod_nvg = 100;
|
||||
}
|
||||
// Silencers??
|
||||
if (randomisation?.[index]?.weaponMods?.mod_muzzle !== undefined) {
|
||||
randomisation[index].weaponMods.mod_muzzle += isNight ? 18 : 0;
|
||||
if (randomisation[index].weaponMods.mod_muzzle > 100)
|
||||
randomisation[index].weaponMods.mod_muzzle = 100;
|
||||
}
|
||||
// Flashlights
|
||||
if (
|
||||
location === "laboratory" ||
|
||||
randomisation?.[index]?.weaponMods?.mod_flashlight !== undefined
|
||||
) {
|
||||
randomisation[index].weaponMods.mod_flashlight += isNight ? 45 : 0;
|
||||
if (randomisation[index].weaponMods.mod_flashlight > 100)
|
||||
randomisation[index].weaponMods.mod_flashlight = 100;
|
||||
}
|
||||
|
||||
if (location === "laboratory") {
|
||||
[
|
||||
"mod_equipment",
|
||||
"mod_equipment_000",
|
||||
"mod_equipment_001",
|
||||
"mod_equipment_002", //TODO: check if this is still needed
|
||||
"mod_pistol_grip_akms",
|
||||
"mod_tactical",
|
||||
"mod_tactical_2",
|
||||
"mod_tactical001",
|
||||
"mod_tactical002",
|
||||
"mod_tactical_000",
|
||||
"mod_tactical_001",
|
||||
"mod_tactical_002",
|
||||
"mod_tactical_003",
|
||||
].forEach((modName) => {
|
||||
if (randomisation?.[index]?.weaponMods?.[modName] !== undefined) {
|
||||
randomisation[index].weaponMods[modName] += 30;
|
||||
if (randomisation[index].weaponMods[modName] > 100)
|
||||
randomisation[index].weaponMods[modName] = 100;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const makeMapSpecificWeaponWeightings = (
|
||||
location: keyof typeof advancedConfig.locations,
|
||||
items: Record<string, ITemplateItem>,
|
||||
originalWeight: EquipmentFilters,
|
||||
pmcWeighting: IWeightingAdjustmentDetails[]
|
||||
) => {
|
||||
const firstPrimaryWeaponTypes =
|
||||
advancedConfig.locations[location].weightingAdjustments.FirstPrimaryWeapon;
|
||||
originalWeight.weightingAdjustmentsByBotLevel.forEach((weightTier, index) => {
|
||||
const firstPrimary = weightTier.equipment.edit.FirstPrimaryWeapon;
|
||||
const firstPrimaryKeys = Object.keys(firstPrimary);
|
||||
firstPrimaryKeys?.forEach((weaponId) => {
|
||||
const parentId = items[weaponId]?._parent;
|
||||
const parent = items?.[parentId]?._name;
|
||||
if (parent && firstPrimaryWeaponTypes[parent]) {
|
||||
const multiplier = firstPrimaryWeaponTypes[parent];
|
||||
pmcWeighting[index].equipment.edit.FirstPrimaryWeapon[weaponId] =
|
||||
Math.round(multiplier * firstPrimary[weaponId]);
|
||||
// console.log(firstPrimary[weaponId], " to ", pmcWeighting[index].equipment.edit.FirstPrimaryWeapon[weaponId], parent, items[weaponId]._name)
|
||||
} else {
|
||||
console.log(
|
||||
`Algorthimic LevelProgression: Unable to set map settings for ${items[weaponId]._name} - ${weaponId} `
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const cullModItems = (
|
||||
mods: IMods,
|
||||
isNight: boolean,
|
||||
items: Record<string, ITemplateItem>,
|
||||
location: keyof typeof advancedConfig.locations
|
||||
) => {
|
||||
const cullList: Set<string> = new Set([
|
||||
...(isNight ? nightTimeCullList : dayTimeCullList),
|
||||
...InternalBlacklist,
|
||||
]);
|
||||
|
||||
if (location === "laboratory") {
|
||||
cullList.delete("5a1ead28fcdbcb001912fa9f");
|
||||
cullList.delete("5c11046cd174af02a012e42b");
|
||||
cullList.delete("5a1eaa87fcdbcb001865f75e");
|
||||
cullList.delete("5d1b5e94d7ad1a2b865a96b0");
|
||||
cullList.delete("5ea058e01dbce517f324b3e2");
|
||||
}
|
||||
|
||||
for (let key in mods) {
|
||||
if (
|
||||
cullList.has(key) ||
|
||||
!checkDaytimeSilencer(key, isNight, items, cullList)
|
||||
) {
|
||||
delete mods[key];
|
||||
} else {
|
||||
for (const modType in mods[key]) {
|
||||
if (mods?.[key]?.[modType].length) {
|
||||
mods[key][modType] = mods[key][modType].filter(
|
||||
(id) =>
|
||||
!cullList.has(id) &&
|
||||
checkDaytimeSilencer(id, isNight, items, cullList)
|
||||
);
|
||||
if (
|
||||
mods[key][modType].length === 0 &&
|
||||
Object.keys(mods[key]).length === 1
|
||||
) {
|
||||
delete mods[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const checkDaytimeSilencer = (
|
||||
id: string,
|
||||
isNight: boolean,
|
||||
items: Record<string, ITemplateItem>,
|
||||
cullList: Set<string>
|
||||
) => {
|
||||
const item = items[id];
|
||||
if (!item?._props) return false;
|
||||
switch (true) {
|
||||
case !isNight &&
|
||||
checkParentRecursive(id, items, [muzzleParent]) &&
|
||||
item._props.Loudness < globalValues.advancedConfig.daytimeSilencerCutoff:
|
||||
// console.log(item._name);
|
||||
cullList.add(id);
|
||||
return false;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const nightTimeCullList = [
|
||||
"5cc9c20cd7f00c001336c65d", // tactical_all_ncstar_tactical_blue_laser
|
||||
"560d657b4bdc2da74d8b4572", // tactical_all_zenit_2p_kleh_vis_laser
|
||||
];
|
||||
const dayTimeCullList = [
|
||||
"5b3b6dc75acfc47a8773fb1e",
|
||||
"644a3df63b0b6f03e101e065", // tactical_all_bemeyers_mawl_c1_plus
|
||||
"5b3a337e5acfc4704b4a19a0", // tactical_all_zenit_2u_kleh
|
||||
"626becf9582c3e319310b837", // tactical_all_insight_wmx200
|
||||
"57fd23e32459772d0805bcf1", // tactical_all_holosun_ls321
|
||||
"544909bb4bdc2d6f028b4577", // tactical_all_insight_anpeq15
|
||||
];
|
||||
|
||||
const smgUpperRails = new Set([
|
||||
"5926dad986f7741f82604363",
|
||||
"5a966ec8a2750c00171b3f36",
|
||||
"602e63fb6335467b0c5ac94d",
|
||||
"5894a5b586f77426d2590767",
|
||||
"5de8e67c4a9f347bc92edbd7",
|
||||
]);
|
||||
|
||||
const marksmanUpperRails = new Set([
|
||||
"5df8e4080b92095fd441e594",
|
||||
"5dfcd0e547101c39625f66f9",
|
||||
]);
|
||||
|
||||
export const updateScopes = (
|
||||
mods: IMods,
|
||||
isNight: boolean,
|
||||
items: Record<string, ITemplateItem>,
|
||||
location: keyof typeof advancedConfig.locations
|
||||
) => {
|
||||
const weaponTypeMapper = buildOutWeaponTypeMapper(location, isNight);
|
||||
for (let key in mods) {
|
||||
if (
|
||||
smgUpperRails.has(key) ||
|
||||
marksmanUpperRails.has(key) ||
|
||||
checkParentRecursive(key, items, [weaponParent])
|
||||
) {
|
||||
const parent = items[key]._parent;
|
||||
let scopeTypes = weaponTypeMapper[parent];
|
||||
|
||||
if (smgUpperRails.has(key)) {
|
||||
scopeTypes = weaponTypeMapper[weaponTypeNameToId.Smg];
|
||||
}
|
||||
|
||||
if (marksmanUpperRails.has(key)) {
|
||||
scopeTypes = weaponTypeMapper[weaponTypeNameToId.MarksmanRifle];
|
||||
}
|
||||
|
||||
if (!scopeTypes) {
|
||||
// console.log("UNABLE TO FIND PARENT FOR", key, items[key]._name)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!!mods[key]?.mod_scope?.length) {
|
||||
const result = mods[key].mod_scope.filter(
|
||||
(id) =>
|
||||
scopeTypes.has(items[id]?._parent) ||
|
||||
checkIfChildHasScopes(id, items, scopeTypes, mods)
|
||||
);
|
||||
if (result.length) mods[key].mod_scope = result;
|
||||
}
|
||||
|
||||
if (!!mods[key]?.mod_mount) {
|
||||
const mountResult = mods[key].mod_mount.filter(
|
||||
(id) =>
|
||||
scopeTypes.has(items[id]?._parent) ||
|
||||
checkIfChildHasScopes(id, items, scopeTypes, mods, true)
|
||||
);
|
||||
// console.log(key, items[key]._name, mods[key].mod_mount.length, mountResult.length)
|
||||
if (mountResult.length) mods[key].mod_mount = mountResult;
|
||||
mods[key]?.mod_mount;
|
||||
}
|
||||
|
||||
[
|
||||
"mod_mount_001",
|
||||
"mod_mount_002",
|
||||
"mod_mount_003",
|
||||
"mod_mount_004",
|
||||
].forEach((mountType) => {
|
||||
if (!!mods[key]?.[mountType]) {
|
||||
const mountResult = mods[key][mountType].filter(
|
||||
(id) =>
|
||||
!checkParentRecursive(id, items, [mountParent, sightParent]) ||
|
||||
(items[id]?._parent === mountParent && !mods[id]?.mod_scope) ||
|
||||
scopeTypes.has(items[id]?._parent) ||
|
||||
checkIfChildHasScopes(id, items, scopeTypes, mods, true)
|
||||
);
|
||||
// console.log(mountType, key, items[key]._name, mods[key][mountType].length, mountResult.length)
|
||||
if (mountResult.length) mods[key][mountType] = mountResult;
|
||||
mods[key]?.[mountType];
|
||||
}
|
||||
});
|
||||
|
||||
if (!!mods[key]?.mod_reciever) {
|
||||
const receiverScopetypes = checkAssaultScopeTypes(
|
||||
items,
|
||||
key,
|
||||
scopeTypes,
|
||||
weaponTypeMapper
|
||||
);
|
||||
const receiverResult = mods[key].mod_reciever.filter(
|
||||
(id) =>
|
||||
scopeTypes.has(items[id]?._parent) ||
|
||||
checkIfChildHasScopes(id, items, receiverScopetypes, mods, true)
|
||||
);
|
||||
// console.log(key, items[key]._name, mods[key].mod_reciever.length, receiverResult.length)
|
||||
if (receiverResult?.length) mods[key].mod_reciever = receiverResult;
|
||||
mods[key]?.mod_reciever;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const akType = "reciever_ak";
|
||||
const checkAssaultScopeTypes = (
|
||||
items: Record<string, ITemplateItem>,
|
||||
id: string,
|
||||
originalScopeType: Set<string>,
|
||||
weaponTypeMapper: Record<string, Set<string>>
|
||||
) => {
|
||||
if (items[id]?._name?.includes(akType))
|
||||
return weaponTypeMapper["5447b5f14bdc2d61278b4567"]; //assault rifle type
|
||||
return originalScopeType;
|
||||
};
|
||||
|
||||
const checkIfChildHasScopes = (
|
||||
id: string,
|
||||
items: Record<string, ITemplateItem>,
|
||||
scopeTypes: Set<string>,
|
||||
mods: IMods,
|
||||
clean?: boolean
|
||||
) => {
|
||||
const result = !!mods[id]?.mod_scope?.find((scopeId) =>
|
||||
scopeTypes.has(items[scopeId]?._parent)
|
||||
);
|
||||
if (result && clean) {
|
||||
const filtered = mods[id]?.mod_scope.filter(
|
||||
(id) =>
|
||||
scopeTypes.has(items[id]?._parent) ||
|
||||
checkIfChildHasScopes(id, items, scopeTypes, mods)
|
||||
);
|
||||
if (filtered?.length) mods[id].mod_scope = filtered;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
const buildOutWeaponTypeMapper = (
|
||||
location: keyof typeof advancedConfig.locations,
|
||||
isNight: boolean
|
||||
) => {
|
||||
const mapper: Record<string, Set<string>> = {};
|
||||
const sightConfiguration = cloneDeep(
|
||||
advancedConfig.locations[location].sightConfiguration
|
||||
);
|
||||
|
||||
if (isNight) {
|
||||
["SniperRifle", "MarksmanRifle", "AssaultCarbine", "AssaultRifle"].forEach(
|
||||
(type) => {
|
||||
sightConfiguration[type].push("NightVision");
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
for (const weaponType in sightConfiguration) {
|
||||
const weaponTypeUUID = weaponTypeNameToId[weaponType];
|
||||
mapper[weaponTypeUUID] = new Set(
|
||||
sightConfiguration[weaponType].map((name) => SightType[name])
|
||||
);
|
||||
}
|
||||
|
||||
return mapper;
|
||||
};
|
||||
|
||||
// check if item is scope, if so ignore (allow for child scopes)
|
||||
// check if item is weapon, if so, filter mod_scope
|
||||
|
||||
// if scope, check
|
||||
// if "55818b224bdc2dde698b456f" Mount, check if any mod_scope within contain correct scopes, if not remove
|
||||
|
|
@ -0,0 +1,655 @@
|
|||
import { IPmcConfig } from "./../../types/models/spt/config/IPmcConfig.d";
|
||||
import { DependencyContainer } from "tsyringe";
|
||||
|
||||
import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
|
||||
import { ConfigServer } from "@spt/servers/ConfigServer";
|
||||
import { DatabaseServer } from "@spt/servers/DatabaseServer";
|
||||
|
||||
import advancedConfig from "../../config/advancedConfig.json";
|
||||
import config from "../../config/config.json";
|
||||
import { IBotConfig } from "../../types/models/spt/config/IBotConfig.d";
|
||||
import {
|
||||
addBossSecuredContainer,
|
||||
addToModsObject,
|
||||
AmmoParent,
|
||||
armorPlateParent,
|
||||
blacklistedItems,
|
||||
buildEmptyWeightAdjustments,
|
||||
buildInitialRandomization,
|
||||
buildOutModsObject,
|
||||
buildWeaponSightWhitelist,
|
||||
checkParentRecursive,
|
||||
cloneDeep,
|
||||
combineWhitelist,
|
||||
deleteBlacklistedItemsFromInventory,
|
||||
ensureAllAmmoInSecuredContainer,
|
||||
fixEmptyChancePlates,
|
||||
getEquipmentType,
|
||||
magParent,
|
||||
moneyParent,
|
||||
numList,
|
||||
reduceAmmoChancesTo1,
|
||||
reduceEquipmentChancesTo1,
|
||||
saveToFile,
|
||||
setupBaseWhiteList,
|
||||
setupMods,
|
||||
setWeightingAdjustments,
|
||||
setWhitelists,
|
||||
TradersMasterList,
|
||||
} from "./utils";
|
||||
import Tier5 from "../Constants/Tier5";
|
||||
|
||||
import botConfigequipmentpmc from "../Cache/botConfigequipmentpmc.json";
|
||||
import tablesbotstypesusec from "../Cache/tablesbotstypesusec.json";
|
||||
import { buildLootChanges } from "./LootChanges";
|
||||
import { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { fixSpecificItemIssues } from "./FixSpecificScopeIssues";
|
||||
|
||||
export default function ProgressionChanges(
|
||||
container: DependencyContainer
|
||||
): undefined {
|
||||
const databaseServer = container.resolve<DatabaseServer>("DatabaseServer");
|
||||
const tables = databaseServer.getTables();
|
||||
const configServer = container.resolve<ConfigServer>("ConfigServer");
|
||||
|
||||
// const presets = tables.globals.ItemPresets;
|
||||
|
||||
// let mappedPresets = {};
|
||||
|
||||
// Object.values(presets).forEach((preset) => {
|
||||
// if (preset._encyclopedia) {
|
||||
// const newPreset = {};
|
||||
|
||||
// let mainId = "";
|
||||
// const otherPresets = {};
|
||||
// const mapper = {};
|
||||
// preset._items.forEach((item) => {
|
||||
// if (item._tpl === preset._encyclopedia) {
|
||||
// mainId = item._id;
|
||||
// }
|
||||
|
||||
// if (item.parentId && item.slotId) {
|
||||
// mapper[item._id] = item._tpl;
|
||||
// if (item.parentId === mainId) {
|
||||
// if (!newPreset[item.slotId]) newPreset[item.slotId] = [];
|
||||
// newPreset[item.slotId].push(item._tpl);
|
||||
// } else {
|
||||
// if (!otherPresets[mapper[item.parentId]])
|
||||
// otherPresets[mapper[item.parentId]] = {};
|
||||
// if (!otherPresets[mapper[item.parentId]][item.slotId]) {
|
||||
// otherPresets[mapper[item.parentId]][item.slotId] = [item._tpl];
|
||||
// } else {
|
||||
// otherPresets[mapper[item.parentId]][item.slotId].push(item._tpl);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
||||
// mappedPresets[preset._encyclopedia] = newPreset;
|
||||
// if (Object.keys(otherPresets))
|
||||
// mappedPresets = { ...mappedPresets, ...otherPresets };
|
||||
// }
|
||||
// });
|
||||
|
||||
// saveToFile(mappedPresets, "Constants/mappedPresets.json");
|
||||
|
||||
const botConfig = configServer.getConfig<IBotConfig>(ConfigTypes.BOT);
|
||||
const pmcConfig = configServer.getConfig<IPmcConfig>(ConfigTypes.PMC);
|
||||
const Logger = container.resolve<ILogger>("WinstonLogger");
|
||||
|
||||
const items = tables.templates.items;
|
||||
|
||||
const traders = tables.traders;
|
||||
|
||||
const usecInventory = tables.bots.types.usec.inventory;
|
||||
const bearInventory = tables.bots.types.bear.inventory;
|
||||
const prices = tables.templates.prices;
|
||||
const handbook = tables.templates.handbook;
|
||||
|
||||
let loot: Record<string, number> = {};
|
||||
|
||||
if (config.enableLootChanges && !config.forceCached) {
|
||||
try {
|
||||
loot = buildLootChanges(
|
||||
items,
|
||||
handbook,
|
||||
prices,
|
||||
pmcConfig,
|
||||
botConfig,
|
||||
tables.bots.types
|
||||
);
|
||||
} catch (error) {
|
||||
Logger.error(
|
||||
"Algorthimic Progression: buildLootChanges failed, maybe try turning off 'enableLootChanges', \nError: " +
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (botConfig.secureContainerAmmoStackCount < 80)
|
||||
botConfig.secureContainerAmmoStackCount = 80;
|
||||
if (!pmcConfig.forceHealingItemsIntoSecure)
|
||||
pmcConfig.forceHealingItemsIntoSecure = true;
|
||||
|
||||
pmcConfig.looseWeaponInBackpackChancePercent = 2;
|
||||
pmcConfig.looseWeaponInBackpackLootMinMax = { min: 0, max: 1 };
|
||||
|
||||
if (config?.forceCached !== true) {
|
||||
try {
|
||||
const tradersToInclude = [
|
||||
"Prapor",
|
||||
"Therapist",
|
||||
"Skier",
|
||||
"Peacekeeper",
|
||||
"Mechanic",
|
||||
"Ragman",
|
||||
"Jaeger",
|
||||
"Arena",
|
||||
];
|
||||
|
||||
const tradersToExclude = [
|
||||
"Unknown",
|
||||
"caretaker",
|
||||
"Fence",
|
||||
"БТР",
|
||||
...config.customTradersToExclude,
|
||||
];
|
||||
|
||||
const traderList = Object.values(traders).filter(({ base }) => {
|
||||
if (config.addCustomTraderItems) {
|
||||
return !tradersToExclude.includes(base.nickname);
|
||||
}
|
||||
return tradersToInclude.includes(base.nickname);
|
||||
});
|
||||
|
||||
botConfig.equipment.pmc.nvgIsActiveChanceNightPercent = 85;
|
||||
botConfig.equipment.pmc.lightIsActiveNightChancePercent = 45;
|
||||
botConfig.equipment.pmc.lightIsActiveDayChancePercent = 25;
|
||||
botConfig.equipment.pmc.laserIsActiveChancePercent = 90;
|
||||
|
||||
botConfig.equipment.pmc.armorPlateWeighting = [
|
||||
{
|
||||
levelRange: {
|
||||
min: 1,
|
||||
max: 99,
|
||||
},
|
||||
front_plate: {
|
||||
"1": 1,
|
||||
"2": 3,
|
||||
"3": 15,
|
||||
"4": 35,
|
||||
"5": 15,
|
||||
"6": 5,
|
||||
},
|
||||
back_plate: {
|
||||
"1": 1,
|
||||
"2": 3,
|
||||
"3": 15,
|
||||
"4": 35,
|
||||
"5": 15,
|
||||
"6": 5,
|
||||
},
|
||||
side_plate: {
|
||||
"1": 1,
|
||||
"2": 3,
|
||||
"3": 15,
|
||||
"4": 35,
|
||||
"5": 15,
|
||||
"6": 5,
|
||||
},
|
||||
left_side_plate: {
|
||||
"1": 1,
|
||||
"2": 3,
|
||||
"3": 15,
|
||||
"4": 35,
|
||||
"5": 15,
|
||||
"6": 5,
|
||||
},
|
||||
right_side_plate: {
|
||||
"1": 1,
|
||||
"2": 3,
|
||||
"3": 15,
|
||||
"4": 35,
|
||||
"5": 15,
|
||||
"6": 5,
|
||||
},
|
||||
},
|
||||
];
|
||||
// botConfig.equipment.pmc.forceOnlyArmoredRigWhenNoArmor = false;
|
||||
botConfig.equipment.pmc.faceShieldIsActiveChancePercent = 100;
|
||||
botConfig.equipment.pmc.weightingAdjustmentsByBotLevel =
|
||||
buildEmptyWeightAdjustments();
|
||||
|
||||
// >>>>>>>>>>>>>>> Working tradersMasterList <<<<<<<<<<<<<<<<<<
|
||||
const tradersMasterList: TradersMasterList = {
|
||||
1: new Set(["572b7adb24597762ae139821", "5fd4c4fa16cac650092f6771"]),
|
||||
2: new Set(),
|
||||
3: new Set(),
|
||||
4: new Set(),
|
||||
5: new Set(Object.values(Tier5).flat(1)),
|
||||
};
|
||||
|
||||
const mods = { "1": {}, "2": {}, "3": {}, "4": {}, "5": {} };
|
||||
|
||||
// SetBaseWhitelist
|
||||
botConfig.equipment.pmc.whitelist = setupBaseWhiteList();
|
||||
|
||||
traderList.forEach(
|
||||
(
|
||||
{
|
||||
base: { nickname },
|
||||
questassort,
|
||||
assort: {
|
||||
items: tradeItems,
|
||||
loyal_level_items,
|
||||
barter_scheme,
|
||||
} = {},
|
||||
},
|
||||
index
|
||||
) => {
|
||||
if (!tradeItems || !nickname) return;
|
||||
|
||||
if (
|
||||
config.addCustomTraderItems &&
|
||||
![...tradersToExclude, ...tradersToInclude].includes(nickname)
|
||||
) {
|
||||
console.log(
|
||||
`[AlgorithmicLevelProgression]: Attempting to add items for custom trader > ${nickname}!`
|
||||
);
|
||||
}
|
||||
|
||||
tradeItems.forEach(({ _tpl, _id, parentId, slotId }) => {
|
||||
if (
|
||||
blacklistedItems.has(_tpl) ||
|
||||
checkParentRecursive(_tpl, items, [armorPlateParent])
|
||||
)
|
||||
return; //Remove blacklisted items and bullets
|
||||
|
||||
const item = items[_tpl];
|
||||
if (!item)
|
||||
return console.log(
|
||||
"[AlgorithmicLevelProgression]: Skipping custom item: ",
|
||||
_tpl,
|
||||
" for trader: ",
|
||||
nickname
|
||||
);
|
||||
|
||||
const parent = item._parent;
|
||||
if (!parent || !items[parent])
|
||||
return console.log(
|
||||
"[AlgorithmicLevelProgression]: Skipping custom item: ",
|
||||
_tpl,
|
||||
" for trader: ",
|
||||
nickname
|
||||
);
|
||||
|
||||
const equipmentType = getEquipmentType(parent, items);
|
||||
|
||||
switch (true) {
|
||||
//Add Ammo
|
||||
case checkParentRecursive(parent, items, [AmmoParent]):
|
||||
const calibre = item._props.Caliber || item._props.ammoCaliber;
|
||||
if (calibre) {
|
||||
usecInventory.Ammo[calibre] = {
|
||||
...(usecInventory.Ammo[calibre] || {}),
|
||||
[_tpl]: 1,
|
||||
};
|
||||
bearInventory.Ammo[calibre] = {
|
||||
...(bearInventory.Ammo[calibre] || {}),
|
||||
[_tpl]: 1,
|
||||
};
|
||||
|
||||
// usecInventory.items.SecuredContainer[_tpl] = 1;
|
||||
// bearInventory.items.SecuredContainer[_tpl] = 1;
|
||||
} else {
|
||||
console.log(
|
||||
item._name,
|
||||
" likely has the incorrect calibre: ",
|
||||
calibre
|
||||
);
|
||||
}
|
||||
break;
|
||||
case checkParentRecursive(parent, items, [magParent]):
|
||||
// usecInventory.items.SecuredContainer[_tpl] = 1;
|
||||
// bearInventory.items.SecuredContainer[_tpl] = 1;
|
||||
break;
|
||||
// case equipmentType === "mod_scope":
|
||||
// break;
|
||||
// Check if revolver shotgun
|
||||
case _tpl === "60db29ce99594040e04c4a27":
|
||||
if (!usecInventory.equipment["FirstPrimaryWeapon"])
|
||||
usecInventory.equipment["FirstPrimaryWeapon"] = {};
|
||||
if (!bearInventory.equipment["FirstPrimaryWeapon"])
|
||||
bearInventory.equipment["FirstPrimaryWeapon"] = {};
|
||||
usecInventory.equipment["FirstPrimaryWeapon"][_tpl] = 1;
|
||||
bearInventory.equipment["FirstPrimaryWeapon"][_tpl] = 1;
|
||||
break;
|
||||
// Check if sawed-off shotgun
|
||||
case _tpl === "64748cb8de82c85eaf0a273a":
|
||||
if (!usecInventory.equipment["Holster"])
|
||||
usecInventory.equipment["Holster"] = {};
|
||||
if (!bearInventory.equipment["Holster"])
|
||||
bearInventory.equipment["Holster"] = {};
|
||||
usecInventory.equipment["Holster"][_tpl] = 1;
|
||||
bearInventory.equipment["Holster"][_tpl] = 1;
|
||||
break;
|
||||
// Add matching equipment
|
||||
case !!equipmentType:
|
||||
if (!usecInventory.equipment[equipmentType])
|
||||
usecInventory.equipment[equipmentType] = {};
|
||||
if (!bearInventory.equipment[equipmentType])
|
||||
bearInventory.equipment[equipmentType] = {};
|
||||
usecInventory.equipment[equipmentType][_tpl] = 1;
|
||||
bearInventory.equipment[equipmentType][_tpl] = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const loyaltyLevel =
|
||||
loyal_level_items[_id] || loyal_level_items[parentId];
|
||||
|
||||
//Set trader list for levels
|
||||
if (loyaltyLevel) {
|
||||
const barterSchemeRef =
|
||||
barter_scheme[_id] || barter_scheme[parentId];
|
||||
|
||||
switch (true) {
|
||||
// If large magazine
|
||||
case checkParentRecursive(_tpl, items, [magParent]) &&
|
||||
item?._props?.Cartridges?.[0]?._max_count > 39:
|
||||
// if (item?._props?.Cartridges?.[0]?._max_count > 39) {
|
||||
// tradersMasterList[5].add(_tpl)
|
||||
// return
|
||||
// }
|
||||
// tradersMasterList[loyaltyLevel].add(_tpl)
|
||||
|
||||
// addToModsObject(mods, _tpl, items, loyaltyLevel, slotId)
|
||||
break;
|
||||
// Check if its a quest unlocked trade
|
||||
case !!questassort.success[_id]:
|
||||
if (!config?.questUnlockedItemsShifted) {
|
||||
tradersMasterList[loyaltyLevel].add(_tpl);
|
||||
|
||||
addToModsObject(mods, _tpl, items, loyaltyLevel, slotId);
|
||||
} else {
|
||||
if (loyaltyLevel === 4) {
|
||||
tradersMasterList[4].add(_tpl);
|
||||
|
||||
addToModsObject(mods, _tpl, items, 4, slotId);
|
||||
} else {
|
||||
tradersMasterList[loyaltyLevel + 1].add(_tpl);
|
||||
|
||||
addToModsObject(
|
||||
mods,
|
||||
_tpl,
|
||||
items,
|
||||
loyaltyLevel + 1,
|
||||
slotId
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
// Only add the item if it's a cash trade or if tradeItems are not shifted
|
||||
case items[barterSchemeRef?.[0]?.[0]?._tpl]?._parent ===
|
||||
moneyParent || !config?.tradedItemsShifted:
|
||||
tradersMasterList[loyaltyLevel].add(_tpl);
|
||||
|
||||
addToModsObject(mods, _tpl, items, loyaltyLevel, slotId);
|
||||
break;
|
||||
// Then it's a tradeItem
|
||||
default:
|
||||
if (loyaltyLevel + 2 > 4) {
|
||||
tradersMasterList[4].add(_tpl);
|
||||
|
||||
addToModsObject(mods, _tpl, items, 4, slotId);
|
||||
} else {
|
||||
tradersMasterList[loyaltyLevel + 2].add(_tpl);
|
||||
|
||||
addToModsObject(
|
||||
mods,
|
||||
_tpl,
|
||||
items,
|
||||
loyaltyLevel + 2,
|
||||
slotId
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
//Setup beast mod level 5
|
||||
tradersMasterList[5].forEach((id) => {
|
||||
if (blacklistedItems.has(id)) {
|
||||
tradersMasterList[5].delete(id);
|
||||
} else {
|
||||
const item = items[id];
|
||||
const parent = items[id]?._parent;
|
||||
if (!item || !parent) return;
|
||||
const equipmentType = getEquipmentType(parent, items);
|
||||
|
||||
switch (true) {
|
||||
case checkParentRecursive(parent, items, [AmmoParent]):
|
||||
const calibre = item._props.Caliber || item._props.ammoCaliber;
|
||||
if (calibre) {
|
||||
usecInventory.Ammo[calibre] = {
|
||||
...(usecInventory.Ammo[calibre] || {}),
|
||||
[id]: 1,
|
||||
};
|
||||
bearInventory.Ammo[calibre] = {
|
||||
...(bearInventory.Ammo[calibre] || {}),
|
||||
[id]: 1,
|
||||
};
|
||||
}
|
||||
break;
|
||||
case !!equipmentType:
|
||||
if (!usecInventory.equipment[equipmentType])
|
||||
usecInventory.equipment[equipmentType] = {};
|
||||
if (!bearInventory.equipment[equipmentType])
|
||||
bearInventory.equipment[equipmentType] = {};
|
||||
usecInventory.equipment[equipmentType][id] = 1;
|
||||
bearInventory.equipment[equipmentType][id] = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const combinedNumList = new Set([
|
||||
...tradersMasterList[1],
|
||||
...tradersMasterList[2],
|
||||
...tradersMasterList[3],
|
||||
...tradersMasterList[4],
|
||||
]);
|
||||
//TODO: keep an eye on this.. this might be a bad idea.
|
||||
const combinedNumWith5List = new Set([
|
||||
...combinedNumList,
|
||||
...tradersMasterList[5],
|
||||
]);
|
||||
|
||||
buildWeaponSightWhitelist(items, botConfig, tradersMasterList);
|
||||
buildOutModsObject(combinedNumWith5List, items, usecInventory, botConfig);
|
||||
bearInventory.mods = cloneDeep(usecInventory.mods);
|
||||
|
||||
setupMods(mods);
|
||||
|
||||
// lets disable this for now
|
||||
// addKeysToPockets(combinedNumList, items, tables.bots.types.assault.inventory);
|
||||
|
||||
//Make everything level 1 in equipment
|
||||
reduceEquipmentChancesTo1(usecInventory);
|
||||
reduceEquipmentChancesTo1(bearInventory);
|
||||
reduceAmmoChancesTo1(usecInventory);
|
||||
reduceAmmoChancesTo1(bearInventory);
|
||||
|
||||
// Eliminates duplicate id's in later levels
|
||||
numList.forEach((num) => {
|
||||
tradersMasterList[num].forEach((id) => {
|
||||
numList.slice(num, 5).forEach((numListNum) => {
|
||||
tradersMasterList[numListNum].delete(id);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
if (botConfig.equipment.pmc.blacklist?.[0]?.equipment) {
|
||||
if (
|
||||
!botConfig.equipment.pmc.blacklist?.[0]?.equipment?.FirstPrimaryWeapon
|
||||
)
|
||||
botConfig.equipment.pmc.blacklist[0].equipment.FirstPrimaryWeapon =
|
||||
[];
|
||||
if (!botConfig.equipment.pmc.blacklist?.[0]?.equipment?.mod_scope)
|
||||
botConfig.equipment.pmc.blacklist[0].equipment.mod_scope = [];
|
||||
if (!botConfig.equipment.pmc.blacklist?.[0]?.equipment?.mod_handguard)
|
||||
botConfig.equipment.pmc.blacklist[0].equipment.mod_handguard = [];
|
||||
if (!botConfig.equipment.pmc.blacklist?.[0]?.equipment?.Headwear)
|
||||
botConfig.equipment.pmc.blacklist[0].equipment.Headwear = [];
|
||||
botConfig.equipment.pmc.blacklist[0].equipment.FirstPrimaryWeapon.push(
|
||||
"624c0b3340357b5f566e8766",
|
||||
"624c0b3340357b5f566e8766",
|
||||
"6217726288ed9f0845317459",
|
||||
"62389be94d5d474bf712e709"
|
||||
);
|
||||
botConfig.equipment.pmc.blacklist[0].equipment.mod_scope.push(
|
||||
"544a3d0a4bdc2d1b388b4567"
|
||||
);
|
||||
botConfig.equipment.pmc.blacklist[0].equipment.mod_stock.push(
|
||||
"5a0c59791526d8dba737bba7"
|
||||
);
|
||||
botConfig.equipment.pmc.blacklist[0].equipment.Headwear.push(
|
||||
"5c066ef40db834001966a595"
|
||||
);
|
||||
}
|
||||
|
||||
setWhitelists(items, botConfig, tradersMasterList, mods);
|
||||
setWeightingAdjustments(items, botConfig, tradersMasterList, mods);
|
||||
|
||||
let lootingBotsDetected = false;
|
||||
|
||||
if (
|
||||
tables?.bots?.types?.bear?.generation?.items?.backpackLoot?.weights &&
|
||||
new Set(
|
||||
Object.values(
|
||||
tables?.bots?.types?.bear?.generation?.items?.backpackLoot.weights
|
||||
)
|
||||
).size === 1
|
||||
) {
|
||||
console.log(
|
||||
"[AlgorithmicLevelProgression] Looting bots detected, removing pmc loot"
|
||||
);
|
||||
lootingBotsDetected = true;
|
||||
}
|
||||
|
||||
buildInitialRandomization(
|
||||
items,
|
||||
botConfig,
|
||||
tradersMasterList,
|
||||
lootingBotsDetected
|
||||
);
|
||||
|
||||
deleteBlacklistedItemsFromInventory(usecInventory, blacklistedItems);
|
||||
deleteBlacklistedItemsFromInventory(bearInventory, blacklistedItems);
|
||||
|
||||
// add ai2 and surv to bot containerq
|
||||
|
||||
// cms
|
||||
usecInventory.items.SecuredContainer["5d02778e86f774203e7dedbe"] = 1;
|
||||
bearInventory.items.SecuredContainer["5d02778e86f774203e7dedbe"] = 1;
|
||||
// ai2
|
||||
usecInventory.items.SecuredContainer["5755356824597772cb798962"] = 1;
|
||||
bearInventory.items.SecuredContainer["5755356824597772cb798962"] = 1;
|
||||
// Splint
|
||||
usecInventory.items.SecuredContainer["5af0454c86f7746bf20992e8"] = 1;
|
||||
bearInventory.items.SecuredContainer["5af0454c86f7746bf20992e8"] = 1;
|
||||
// Esmarch5e831507ea0a7c419c2f9bd9
|
||||
usecInventory.items.SecuredContainer["5e831507ea0a7c419c2f9bd9"] = 1;
|
||||
bearInventory.items.SecuredContainer["5e831507ea0a7c419c2f9bd9"] = 1;
|
||||
|
||||
// ensureAllAmmoInSecuredContainer(usecInventory);
|
||||
// ensureAllAmmoInSecuredContainer(bearInventory);
|
||||
|
||||
addBossSecuredContainer(usecInventory);
|
||||
addBossSecuredContainer(bearInventory);
|
||||
|
||||
// addAllMedsToInventory(combinedNumWith5List, usecInventory, items);
|
||||
|
||||
fixEmptyChancePlates(botConfig);
|
||||
|
||||
fixSpecificItemIssues(usecInventory);
|
||||
fixSpecificItemIssues(bearInventory);
|
||||
|
||||
tables.bots.types.usec.inventory = usecInventory;
|
||||
tables.bots.types.bear.inventory = bearInventory;
|
||||
tables.bots.types.bear.inventory = tables.bots.types.usec.inventory; // TESTING << REMOVE IF SLOWER
|
||||
} catch (error) {
|
||||
config.forceCached = true;
|
||||
throw Error(
|
||||
"Failed to dynamically update items, likely a mod conflict, turning on forceCached and will try again! \nError: " +
|
||||
error
|
||||
);
|
||||
}
|
||||
} else {
|
||||
botConfig.equipment.pmc = botConfigequipmentpmc as any;
|
||||
tables.bots.types.usec = tablesbotstypesusec as any;
|
||||
tables.bots.types.bear = tablesbotstypesusec as any;
|
||||
}
|
||||
|
||||
if (config.strictEquipmentTiering === false) {
|
||||
combineWhitelist(botConfig.equipment.pmc);
|
||||
}
|
||||
|
||||
Object.keys(advancedConfig.otherBotTypes).forEach((botType) => {
|
||||
botConfig.equipment[botType] = {
|
||||
...botConfig.equipment[botType],
|
||||
...advancedConfig.otherBotTypes[botType],
|
||||
};
|
||||
});
|
||||
|
||||
if (
|
||||
tables?.bots?.types?.assault?.generation?.items?.backpackLoot?.weights &&
|
||||
new Set(
|
||||
Object.values(
|
||||
tables.bots.types.assault.generation.items.backpackLoot.weights
|
||||
)
|
||||
).size === 1
|
||||
) {
|
||||
console.log(
|
||||
"[AlgorithmicLevelProgression] Looting bots detected, removing scav loot"
|
||||
);
|
||||
const generation = (botConfig.equipment.assault.randomisation[0] as any)
|
||||
.generation;
|
||||
generation.backpackLoot = {
|
||||
...(generation.looseLoot || {}),
|
||||
weights: { "0": 1 },
|
||||
whitelist: {},
|
||||
};
|
||||
generation.pocketLoot = {
|
||||
...(generation.looseLoot || {}),
|
||||
weights: { "0": 1 },
|
||||
whitelist: {},
|
||||
};
|
||||
generation.vestLoot = {
|
||||
...(generation.looseLoot || {}),
|
||||
weights: { "0": 1 },
|
||||
whitelist: {},
|
||||
};
|
||||
}
|
||||
|
||||
// saveToFile(botConfig, "botConfig.json");
|
||||
// saveToFile(pmcConfig, "pmcConfig.json");
|
||||
|
||||
// tables.bots.types.usec
|
||||
// botConfig.equipment.pmc
|
||||
// saveToFile(tables.bots.types.usec, `Cache/tablesbotstypesusec.json`);
|
||||
// saveToFile(botConfig.equipment.pmc, `Cache/botConfigequipmentpmc.json`);
|
||||
|
||||
config.debug ||
|
||||
(config.forceCached &&
|
||||
console.log("Algorthimic Progression: Progression Changes completed"));
|
||||
}
|
||||
|
||||
//59ef13ca86f77445fd0e2483
|
||||
//5b4329f05acfc47a86086aa1
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import { DependencyContainer } from "tsyringe";
|
||||
import { globalValues } from "./GlobalValues";
|
||||
import { ConfigServer } from "@spt/servers/ConfigServer";
|
||||
import { cloneDeep } from "./utils";
|
||||
import { IBotConfig } from "@spt/models/spt/config/IBotConfig";
|
||||
import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
|
||||
import { DatabaseServer } from "@spt/servers/DatabaseServer";
|
||||
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
|
||||
|
||||
export const SetupLocationGlobals = (
|
||||
container: DependencyContainer
|
||||
): undefined => {
|
||||
const configServer = container.resolve<ConfigServer>("ConfigServer");
|
||||
const botConfig = configServer.getConfig<IBotConfig>(ConfigTypes.BOT);
|
||||
const databaseServer = container.resolve<DatabaseServer>("DatabaseServer");
|
||||
const profileHelper = container.resolve<ProfileHelper>("ProfileHelper");
|
||||
const tables = databaseServer.getTables();
|
||||
globalValues.Logger = container.resolve("WinstonLogger");
|
||||
globalValues.tables = tables;
|
||||
globalValues.profileHelper = profileHelper;
|
||||
globalValues.originalBotTypes = cloneDeep(tables.bots.types);
|
||||
globalValues.configServer = configServer;
|
||||
globalValues.originalWeighting = cloneDeep(botConfig.equipment.pmc);
|
||||
// globalValues.setValuesForLocation("woods", 1);
|
||||
};
|
||||
1996
user/mods/AlgorithmicLevelProgression/src/LoadoutChanges/utils.ts
Normal file
1996
user/mods/AlgorithmicLevelProgression/src/LoadoutChanges/utils.ts
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,750 @@
|
|||
import {
|
||||
IEquipment,
|
||||
IInventory,
|
||||
IMods,
|
||||
} from "@spt/models/eft/common/tables/IBotType";
|
||||
import { EquipmentFilters } from "@spt/models/spt/config/IBotConfig";
|
||||
import {
|
||||
armorParent,
|
||||
blacklistedItems,
|
||||
checkParentRecursive,
|
||||
cloneDeep,
|
||||
deleteBlacklistedItemsFromInventory,
|
||||
getAmmoWeighting,
|
||||
getArmorRating,
|
||||
getBackPackInternalGridValue,
|
||||
getTacticalVestValue,
|
||||
getWeaponWeighting,
|
||||
headwearParent,
|
||||
rigParent,
|
||||
saveToFile,
|
||||
weaponTypeNameToId,
|
||||
} from "../LoadoutChanges/utils";
|
||||
import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem";
|
||||
import advancedConfig from "../../config/advancedConfig.json";
|
||||
import nonPmcBotConfig from "../../config/nonPmcBotConfig.json";
|
||||
import { MinMax } from "@spt/models/common/MinMax";
|
||||
import { inventory as cachedInventory } from "../Cache/tablesbotstypesusec.json";
|
||||
import { weightingAdjustmentsByBotLevel as botWeights } from "../Cache/botConfigequipmentpmc.json";
|
||||
import tieredItems from "../Constants/tieredItems.json";
|
||||
import mappedPresets from "../Constants/mappedPresets.json";
|
||||
import { IPreset } from "@spt/models/eft/common/IGlobals";
|
||||
|
||||
const objectToOrderedList = (
|
||||
equipment: Record<string, number>,
|
||||
items: Record<string, ITemplateItem>
|
||||
) =>
|
||||
Object.keys(equipment)
|
||||
.sort((a, b) => equipment[a] - equipment[b])
|
||||
.map((id) => ({ id, value: equipment[id], name: items[id]._name }));
|
||||
|
||||
const blackList = new Set<string>([
|
||||
"5e4abc6786f77406812bd572",
|
||||
"628bc7fb408e2b2e9c0801b1",
|
||||
"5b3b713c5acfc4330140bd8d",
|
||||
"5e997f0b86f7741ac73993e2",
|
||||
"5c0126f40db834002a125382",
|
||||
"601948682627df266209af05",
|
||||
"63495c500c297e20065a08b1",
|
||||
"59ef13ca86f77445fd0e2483",
|
||||
"670e8eab8c1bb0e5a7075acf", //mag_pm_izhmeh_9x18pm_999_infectedMagazin
|
||||
"671d85439ae8365d69117ba6", //mag_tt_toz_std_762x25tt_999_infectedMagazin
|
||||
"671d8617a3e45c1f5908278c", //mag_mp443_izhmeh_std_9x19_999_infectedMagazin
|
||||
"671d8ac8a3e45c1f59082799", //mag_glock_glock_w_pad_9x19_999_fde_Infected
|
||||
"671d8b38b769f0d88c0950f8", //mag_m1911_colt_m45a1_std_1143x23_999_infected
|
||||
"671d8b8c0959c721a50ca838", //mag_usp_hk_usp_tactical_1143x23_999_infected
|
||||
"628120f210e26c1f344e6558", // mxc broken mag
|
||||
]);
|
||||
|
||||
const makeRare = new Set<string>([
|
||||
"6038b4ca92ec1c3103795a0d",
|
||||
"6038b4b292ec1c3103795a0b",
|
||||
"5fd4c474dd870108a754b241",
|
||||
"628b9c7d45122232a872358f",
|
||||
"628baf0b967de16aab5a4f36",
|
||||
"628b9784bcf6e2659e09b8a2",
|
||||
"628baf0b967de16aab5a4f36",
|
||||
"5c0e541586f7747fa54205c9",
|
||||
"5bffdd7e0db834001b734a1a",
|
||||
]);
|
||||
|
||||
export const buldTieredItemTypes = (items: Record<string, ITemplateItem>) => {
|
||||
const result = {};
|
||||
|
||||
botWeights.forEach((weight, index) => {
|
||||
if (index < 4)
|
||||
// Prevents boss related gear appearing on normal bots
|
||||
for (const key in weight.equipment.edit) {
|
||||
Object.keys(weight.equipment.edit[key]).forEach((id) => {
|
||||
if (blackList.has(id)) return;
|
||||
if (!result[key]) result[key] = {};
|
||||
|
||||
result[key][id] = Math.max(
|
||||
result[key][id] || 1,
|
||||
weight.equipment.edit[key][id]
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
for (const key in result) {
|
||||
for (const id in result[key]) {
|
||||
if (makeRare.has(id)) {
|
||||
result[key][id] = result[key][id] * 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const key in result) {
|
||||
const equipmentSet = result[key] as Record<string, number>;
|
||||
result[key] = objectToOrderedList(equipmentSet, items);
|
||||
}
|
||||
|
||||
// AMMO
|
||||
const ammo = {};
|
||||
|
||||
for (const caliber in cachedInventory.Ammo) {
|
||||
for (const ammoId in cachedInventory.Ammo[caliber]) {
|
||||
if (items[ammoId]) {
|
||||
ammo[ammoId] = getAmmoWeighting(items[ammoId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result["Ammo"] = objectToOrderedList(ammo, items);
|
||||
|
||||
const map = {};
|
||||
|
||||
for (const key in result) {
|
||||
result[key].forEach(({ id, value }) => {
|
||||
map[id] = value;
|
||||
});
|
||||
}
|
||||
|
||||
result["mapper"] = map;
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
export interface BotUpdateInterface {
|
||||
tiers: Array<number[]>;
|
||||
HasModdedWeapons?: boolean;
|
||||
AllowSniperRifles?: boolean;
|
||||
Ammo: number[];
|
||||
TacticalVest?: number[];
|
||||
ArmorVest?: number[];
|
||||
Backpack?: number[];
|
||||
Earpiece?: number[];
|
||||
Eyewear?: number[];
|
||||
Headwear?: number[];
|
||||
FaceCover?: number[];
|
||||
// Scabbard?: number[];
|
||||
FirstPrimary?: number[];
|
||||
Holster?: number[];
|
||||
BasePlateChance: number;
|
||||
SidePlateChance?: number;
|
||||
}
|
||||
|
||||
const equipmentTypesTochange = new Set([
|
||||
"TacticalVest",
|
||||
"ArmorVest",
|
||||
"Backpack",
|
||||
"Earpiece",
|
||||
"Eyewear",
|
||||
"Headwear",
|
||||
"FaceCover",
|
||||
// "Scabbard",
|
||||
"FirstPrimaryWeapon",
|
||||
"Holster",
|
||||
]);
|
||||
|
||||
const getRating = (id: string, dflt = 10) => tieredItems.mapper[id] || dflt;
|
||||
|
||||
export const normalizeMedianInventoryValues = (inventory: IInventory) => {
|
||||
for (const caliber in inventory.Ammo) {
|
||||
let highest = 0;
|
||||
|
||||
Object.values(inventory.Ammo[caliber]).forEach((value) => {
|
||||
if (value > highest) highest = value;
|
||||
});
|
||||
|
||||
const multiplier = 100 / highest;
|
||||
Object.keys(inventory.Ammo[caliber]).forEach((id) => {
|
||||
inventory.Ammo[caliber][id] =
|
||||
Math.round(inventory.Ammo[caliber][id] * multiplier) || 10;
|
||||
});
|
||||
}
|
||||
|
||||
for (const equipmentType in inventory.equipment) {
|
||||
if (equipmentTypesTochange.has(equipmentType)) {
|
||||
let highest = 0;
|
||||
|
||||
Object.values(inventory.equipment[equipmentType]).forEach(
|
||||
(value: number) => {
|
||||
if (value > highest) highest = value;
|
||||
}
|
||||
);
|
||||
|
||||
const multiplier = 200 / highest;
|
||||
Object.keys(inventory.equipment[equipmentType]).forEach((id) => {
|
||||
inventory.equipment[equipmentType][id] =
|
||||
Math.round(inventory.equipment[equipmentType][id] * multiplier) || 10;
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const addItemsToBotInventory = (
|
||||
inventory: IInventory,
|
||||
botToUpdate: BotUpdateInterface,
|
||||
items: Record<string, ITemplateItem>,
|
||||
isMarksman = false
|
||||
) => {
|
||||
const { Ammo: botToUpdateAmmo, BasePlateChance, ...equipment } = botToUpdate;
|
||||
|
||||
const ammoToAdd = new Set<string>([]);
|
||||
|
||||
Object.keys(tieredItems).forEach((key) => {
|
||||
if (equipment[key]) {
|
||||
const equipmentStart = equipment[key][0];
|
||||
const equipmentEnd = equipment[key][1];
|
||||
|
||||
if (equipmentStart || equipmentEnd) {
|
||||
const startIndex = Math.floor(tieredItems[key].length * equipmentStart);
|
||||
const endIndex = Math.floor(tieredItems[key].length * equipmentEnd);
|
||||
|
||||
tieredItems[key]
|
||||
.slice(startIndex, endIndex)
|
||||
.forEach(({ id, value }) => {
|
||||
if (
|
||||
(!botToUpdate.AllowSniperRifles &&
|
||||
checkParentRecursive(id, items, [
|
||||
weaponTypeNameToId.SniperRifle,
|
||||
weaponTypeNameToId.MarksmanRifle,
|
||||
])) ||
|
||||
(isMarksman &&
|
||||
key === "FirstPrimaryWeapon" &&
|
||||
!checkParentRecursive(id, items, [
|
||||
weaponTypeNameToId.SniperRifle,
|
||||
weaponTypeNameToId.MarksmanRifle,
|
||||
weaponTypeNameToId.AssaultCarbine,
|
||||
]))
|
||||
) {
|
||||
// if (isMarksman && key === "FirstPrimaryWeapon")
|
||||
// console.log(items[id]._name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (blacklistedItems.has(id) || blackList.has(id)) return;
|
||||
if (!inventory.equipment[key][id]) {
|
||||
inventory.equipment[key][id] = value;
|
||||
}
|
||||
const item = items[id];
|
||||
if (inventory.mods[id]) return;
|
||||
switch (key) {
|
||||
case "Headwear":
|
||||
case "ArmorVest":
|
||||
case "TacticalVest":
|
||||
if (!inventory.mods[id]) {
|
||||
const newModObject = {};
|
||||
item._props.Slots.forEach((mod) => {
|
||||
if (mod._props.filters[0].Plate) {
|
||||
newModObject[mod._name] = newModObject[mod._name] = [
|
||||
mod._props.filters[0].Plate,
|
||||
];
|
||||
}
|
||||
});
|
||||
inventory.mods[id] = newModObject;
|
||||
}
|
||||
break;
|
||||
case "FirstPrimaryWeapon":
|
||||
case "Holster":
|
||||
if (!cachedInventory.mods[id] || !mappedPresets[id]) {
|
||||
break;
|
||||
}
|
||||
inventory.mods[id] = mappedPresets[id];
|
||||
// if (isMarksman) console.log(items[id]._name);
|
||||
if (cachedInventory.mods[id]["patron_in_weapon"]) {
|
||||
mappedPresets[id]["patron_in_weapon"] =
|
||||
cachedInventory.mods[id]["patron_in_weapon"];
|
||||
}
|
||||
if (cachedInventory.mods[id]["patron_in_weapon_000"]) {
|
||||
mappedPresets[id]["patron_in_weapon_000"] =
|
||||
cachedInventory.mods[id]["patron_in_weapon_000"];
|
||||
}
|
||||
|
||||
if (cachedInventory.mods[id]["patron_in_weapon_001"]) {
|
||||
mappedPresets[id]["patron_in_weapon_001"] =
|
||||
cachedInventory.mods[id]["patron_in_weapon_001"];
|
||||
}
|
||||
|
||||
const ammo = [
|
||||
...(cachedInventory.mods[id]["patron_in_weapon"]
|
||||
? cachedInventory.mods[id]["patron_in_weapon"]
|
||||
: []),
|
||||
...(cachedInventory.mods[id]["patron_in_weapon_000"]
|
||||
? cachedInventory.mods[id]["patron_in_weapon_000"]
|
||||
: []),
|
||||
...(cachedInventory.mods[id]["patron_in_weapon_001"]
|
||||
? cachedInventory.mods[id]["patron_in_weapon_001"]
|
||||
: []),
|
||||
];
|
||||
ammo.forEach((id) => {
|
||||
ammoToAdd.add(id);
|
||||
});
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (botToUpdate?.Ammo?.[1] > 0) {
|
||||
const Ammo = tieredItems.Ammo;
|
||||
|
||||
const ammoStart = botToUpdateAmmo[0];
|
||||
const ammoEnd = botToUpdateAmmo[1];
|
||||
if (ammoStart || ammoEnd) {
|
||||
const startIndex = Math.floor(Ammo.length * ammoStart);
|
||||
const endIndex = Math.floor(Ammo.length * ammoEnd);
|
||||
|
||||
const toAddAmmo = [...ammoToAdd]
|
||||
.map((id) => ({
|
||||
id,
|
||||
value: tieredItems.mapper[id],
|
||||
}))
|
||||
.sort((a, b) => a.value - b.value);
|
||||
const toAddAmmoStartIndex = Math.floor(toAddAmmo.length * ammoStart);
|
||||
const toAddAmmoEndIndex = Math.floor(toAddAmmo.length * ammoEnd);
|
||||
|
||||
[
|
||||
...toAddAmmo.slice(toAddAmmoStartIndex, toAddAmmoEndIndex),
|
||||
...Ammo.slice(startIndex, endIndex),
|
||||
].forEach(({ id, value }) => {
|
||||
const calibre =
|
||||
items[id]?._props?.Caliber || items[id]?._props?.ammoCaliber;
|
||||
|
||||
if (
|
||||
calibre &&
|
||||
inventory.Ammo[calibre] &&
|
||||
!inventory.Ammo?.[calibre]?.[id]
|
||||
) {
|
||||
inventory.Ammo[calibre][id] = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Add all plates to all equipment for all bots <<PLATE VARIETY>>
|
||||
Object.keys(inventory.mods).forEach((id) => {
|
||||
if (
|
||||
!checkParentRecursive(id, items, [headwearParent]) &&
|
||||
checkParentRecursive(id, items, [armorParent, rigParent])
|
||||
) {
|
||||
const item = items[id];
|
||||
if (item?._props?.Slots?.length > 0) {
|
||||
// if (!inventory.mods[id]) {
|
||||
const newModObject = {};
|
||||
item._props.Slots.forEach((mod) => {
|
||||
if (mod._props.filters[0].Plate) {
|
||||
newModObject[mod._name] = mod._props.filters[0].Filter;
|
||||
}
|
||||
});
|
||||
if (Object.keys(newModObject).length) inventory.mods[id] = newModObject;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const itemsToAdd = new Set<string>([]);
|
||||
|
||||
Object.keys(inventory.mods).forEach((id) => {
|
||||
Object.values(inventory.mods[id])
|
||||
.flat(1)
|
||||
.forEach((item) => {
|
||||
if (!inventory.mods[item]) itemsToAdd.add(item);
|
||||
});
|
||||
});
|
||||
|
||||
while (itemsToAdd.size) {
|
||||
const [id] = itemsToAdd;
|
||||
if (!inventory.mods[id]) {
|
||||
if (mappedPresets[id]) {
|
||||
inventory.mods[id] = mappedPresets[id];
|
||||
} else if (cachedInventory.mods[id]) {
|
||||
inventory.mods[id] = cachedInventory.mods[id];
|
||||
}
|
||||
}
|
||||
itemsToAdd.delete(id);
|
||||
}
|
||||
|
||||
deleteBlacklistedItemsFromInventory(inventory, blackList);
|
||||
};
|
||||
|
||||
const defaultRandomisation = [
|
||||
{
|
||||
levelRange: {
|
||||
min: 1,
|
||||
max: 100,
|
||||
},
|
||||
equipmentMods: { mod_nvg: 0 },
|
||||
},
|
||||
];
|
||||
|
||||
export const setPlateWeightings = (
|
||||
name: string,
|
||||
equipmentFilters: EquipmentFilters,
|
||||
index: number
|
||||
) => {
|
||||
equipmentFilters.armorPlateWeighting = [
|
||||
{
|
||||
levelRange: {
|
||||
min: 1,
|
||||
max: 100,
|
||||
},
|
||||
front_plate: {
|
||||
"1": 1,
|
||||
"2": 3,
|
||||
"3": 20,
|
||||
"4": 20,
|
||||
"5": 4,
|
||||
"6": 1,
|
||||
},
|
||||
back_plate: {
|
||||
"1": 1,
|
||||
"2": 3,
|
||||
"3": 20,
|
||||
"4": 20,
|
||||
"5": 4,
|
||||
"6": 1,
|
||||
},
|
||||
side_plate: {
|
||||
"1": 1,
|
||||
"2": 3,
|
||||
"3": 20,
|
||||
"4": 20,
|
||||
"5": 4,
|
||||
"6": 1,
|
||||
},
|
||||
left_side_plate: {
|
||||
"1": 1,
|
||||
"2": 3,
|
||||
"3": 20,
|
||||
"4": 20,
|
||||
"5": 4,
|
||||
"6": 1,
|
||||
},
|
||||
right_side_plate: {
|
||||
"1": 1,
|
||||
"2": 3,
|
||||
"3": 20,
|
||||
"4": 20,
|
||||
"5": 4,
|
||||
"6": 1,
|
||||
},
|
||||
},
|
||||
] as any;
|
||||
|
||||
if (!nonPmcBotConfig.nonPmcBots?.[name]?.BasePlateChance) {
|
||||
return;
|
||||
}
|
||||
//=========================================
|
||||
// UPDATE PLATE SPAWN CHANCE
|
||||
|
||||
if (!equipmentFilters?.randomisation) {
|
||||
equipmentFilters.randomisation = defaultRandomisation;
|
||||
}
|
||||
|
||||
const randomizationToUpdate = cloneDeep(equipmentFilters.randomisation[0]);
|
||||
|
||||
if (nonPmcBotConfig.nonPmcBots[name].BasePlateChance < 101) {
|
||||
let front = nonPmcBotConfig.nonPmcBots[name].BasePlateChance + index * 15;
|
||||
if (front > 100) front = 100;
|
||||
randomizationToUpdate.equipmentMods["front_plate"] = front;
|
||||
|
||||
let back =
|
||||
nonPmcBotConfig.nonPmcBots[name].BasePlateChance - 20 + index * 15;
|
||||
if (back > 100) back = 100;
|
||||
randomizationToUpdate.equipmentMods["back_plate"] = back;
|
||||
}
|
||||
|
||||
if (nonPmcBotConfig.nonPmcBots?.[name]?.SidePlateChance) {
|
||||
["left_side_plate", "right_side_plate"].forEach((key) => {
|
||||
let value = nonPmcBotConfig.nonPmcBots[name].SidePlateChance + index * 10;
|
||||
if (value > 100) value = 100;
|
||||
if (value < 0) value = 0;
|
||||
randomizationToUpdate.equipmentMods[key] = value;
|
||||
});
|
||||
} else {
|
||||
["left_side_plate", "right_side_plate"].forEach((key) => {
|
||||
let value =
|
||||
nonPmcBotConfig.nonPmcBots[name].BasePlateChance - 30 + index * 10;
|
||||
if (value > 100) value = 100;
|
||||
if (value < 0) value = 0;
|
||||
randomizationToUpdate.equipmentMods[key] = value;
|
||||
});
|
||||
}
|
||||
// console.log(name, randomizationToUpdate.equipmentMods);
|
||||
equipmentFilters.randomisation[0] = randomizationToUpdate;
|
||||
//=========================================
|
||||
};
|
||||
|
||||
export const buffScavGearAsLevel = (
|
||||
equipmentFilters: EquipmentFilters,
|
||||
index: number
|
||||
) => {
|
||||
equipmentFilters.weightingAdjustmentsByPlayerLevel = [
|
||||
{
|
||||
levelRange: {
|
||||
min: 1,
|
||||
max: 99,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
if (!index) return;
|
||||
|
||||
const randomizationToUpdate = cloneDeep(
|
||||
advancedConfig.otherBotTypes.assault.randomisation[0]
|
||||
);
|
||||
|
||||
[
|
||||
"Headwear",
|
||||
"Earpiece",
|
||||
"ArmorVest",
|
||||
"FaceCover",
|
||||
// "Scabbard",
|
||||
"Eyewear",
|
||||
"Backpack",
|
||||
].forEach((key) => {
|
||||
randomizationToUpdate.equipment[key] += index * 15;
|
||||
if (randomizationToUpdate.equipment[key] > 99)
|
||||
randomizationToUpdate.equipment[key] = 99;
|
||||
});
|
||||
|
||||
equipmentFilters.randomisation[0] = randomizationToUpdate;
|
||||
equipmentFilters.blacklist = advancedConfig.otherBotTypes.assault.blacklist;
|
||||
equipmentFilters.whitelist = advancedConfig.otherBotTypes.assault.whitelist;
|
||||
};
|
||||
|
||||
export interface StoredWeightingAdjustmentDetails {
|
||||
levelRange: MinMax;
|
||||
ammo: Record<string, Record<string, number>>;
|
||||
equipment: Record<string, Record<string, number>>;
|
||||
}
|
||||
|
||||
export const buildEmptyWeightAdjustmentsByDevision = (
|
||||
botToUpdate: BotUpdateInterface
|
||||
): StoredWeightingAdjustmentDetails[] => {
|
||||
const { tiers } = botToUpdate;
|
||||
const result = [];
|
||||
|
||||
tiers.forEach((tier) => {
|
||||
result.push({
|
||||
levelRange: {
|
||||
min: tier[0],
|
||||
max: tier[1],
|
||||
},
|
||||
ammo: {},
|
||||
equipment: {},
|
||||
});
|
||||
});
|
||||
|
||||
return result as StoredWeightingAdjustmentDetails[];
|
||||
};
|
||||
|
||||
export const applyValuesToStoredEquipment = (
|
||||
inventory: IInventory,
|
||||
items: Record<string, ITemplateItem>,
|
||||
storedWeightingAdjustmentDetails: StoredWeightingAdjustmentDetails[]
|
||||
) => {
|
||||
const ammoList = {};
|
||||
Object.keys(inventory.Ammo).forEach((key) => {
|
||||
ammoList[key] = [];
|
||||
Object.keys(inventory.Ammo[key]).forEach((id) => {
|
||||
//Zero out ammo
|
||||
ammoList[key].push({
|
||||
id,
|
||||
rating: getAmmoWeighting(items[id]), // + inventory.Ammo[key][id],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Object.keys(ammoList).forEach((key) => {
|
||||
ammoList[key] = ammoList[key].sort((a, b) => a.rating - b.rating);
|
||||
});
|
||||
|
||||
const equipmentList = {};
|
||||
|
||||
Object.keys(inventory.equipment).forEach((key: keyof IEquipment) => {
|
||||
if (equipmentTypesTochange.has(key)) {
|
||||
equipmentList[key] = [];
|
||||
Object.keys(inventory.equipment[key]).forEach((id) => {
|
||||
//Zero out equipment
|
||||
if (key === "FirstPrimaryWeapon" || key === "Holster") {
|
||||
const defAmmoWeight = getAmmoWeighting(
|
||||
items[items[id]._props.defAmmo]
|
||||
);
|
||||
equipmentList[key].push({
|
||||
id,
|
||||
rating: getRating(id),
|
||||
// + inventory.equipment[key][id],
|
||||
});
|
||||
} else {
|
||||
equipmentList[key].push({
|
||||
id,
|
||||
rating: getRating(id), //+ inventory.equipment[key][id],
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys(equipmentList).forEach((key) => {
|
||||
equipmentList[key] = equipmentList[key].sort((a, b) => a.rating - b.rating);
|
||||
});
|
||||
|
||||
const division = storedWeightingAdjustmentDetails.length;
|
||||
|
||||
for (let index = 0; index < division; index++) {
|
||||
const currentLevelRange = storedWeightingAdjustmentDetails[index];
|
||||
Object.keys(ammoList).forEach((key) => {
|
||||
const listPortion = ammoList[key];
|
||||
const quantityPerLevel = Math.round(listPortion.length / division);
|
||||
const resultingList = (listPortion as Array<{ id; rating }>).slice(
|
||||
0,
|
||||
index === division - 1
|
||||
? listPortion.length
|
||||
: index * quantityPerLevel + quantityPerLevel
|
||||
);
|
||||
|
||||
resultingList.forEach(({ id, rating }) => {
|
||||
if (!currentLevelRange.ammo[key]) currentLevelRange.ammo[key] = {};
|
||||
currentLevelRange.ammo[key][id] =
|
||||
Math.round(rating + rating * (index * 0.4)) + inventory.Ammo[key][id];
|
||||
});
|
||||
});
|
||||
|
||||
Object.keys(equipmentList).forEach((key: keyof IEquipment) => {
|
||||
const listPortion = equipmentList[key];
|
||||
const quantityPerLevel = Math.round(listPortion.length / division);
|
||||
const resultingList = (listPortion as Array<{ id; rating }>).slice(
|
||||
0,
|
||||
index === division - 1
|
||||
? listPortion.length
|
||||
: index * quantityPerLevel + quantityPerLevel
|
||||
);
|
||||
resultingList.forEach(({ id, rating }) => {
|
||||
if (!currentLevelRange.equipment[key])
|
||||
currentLevelRange.equipment[key] = {};
|
||||
currentLevelRange.equipment[key][id] =
|
||||
Math.round(rating + rating * (index * 0.4)) +
|
||||
inventory.equipment[key][id];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
storedWeightingAdjustmentDetails.forEach((_, index) => {
|
||||
const weight = storedWeightingAdjustmentDetails[index];
|
||||
Object.keys(weight.ammo).forEach((caliber) => {
|
||||
const caliberList = Object.keys(weight.ammo[caliber]).sort(
|
||||
(a, b) => weight.ammo[caliber][b] - weight.ammo[caliber][a]
|
||||
);
|
||||
caliberList.forEach((id, rank) => {
|
||||
if (caliberList.length > 1 && rank > 0) {
|
||||
if (rank > 3) {
|
||||
weight.ammo[caliber][id] = Math.round(
|
||||
weight.ammo[caliber][id] * 0.5
|
||||
);
|
||||
} else {
|
||||
const modifier = (caliberList.length - rank) / caliberList.length;
|
||||
weight.ammo[caliber][id] =
|
||||
Math.round(weight.ammo[caliber][id] * modifier) || 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Apply randomness
|
||||
for (const category in weight.ammo) {
|
||||
const randomnessMultiplier = nonPmcBotConfig.botAmmoRandomness;
|
||||
if (!randomnessMultiplier) return;
|
||||
const list = weight.ammo[category];
|
||||
const keys = Object.keys(list);
|
||||
const sortedValues = Object.values(list).sort((a, b) => a - b);
|
||||
const middleIndex = 0 + Math.round((sortedValues.length - 1) / 2);
|
||||
const medianValue = sortedValues[middleIndex];
|
||||
const highestValue = sortedValues[sortedValues.length - 1];
|
||||
const lowestValue = sortedValues[0];
|
||||
const betterValue = Math.round(
|
||||
(medianValue + highestValue + lowestValue) / 3
|
||||
);
|
||||
|
||||
if (betterValue > 1) {
|
||||
keys.forEach((key) => {
|
||||
const valToAdjust = list[key];
|
||||
if (valToAdjust > 5) {
|
||||
const adjustedAmountMax = betterValue - valToAdjust;
|
||||
const amountAfterAdjustment = Math.round(
|
||||
valToAdjust + adjustedAmountMax * randomnessMultiplier
|
||||
);
|
||||
if (weight.ammo[category][key]) {
|
||||
weight.ammo[category][key] = Math.abs(amountAfterAdjustment);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Fix weapon weightings
|
||||
Object.keys(weight.equipment?.FirstPrimaryWeapon || []).forEach((id) => {
|
||||
const calibre =
|
||||
items[id]?._props?.Caliber || items[id]?._props?.ammoCaliber;
|
||||
if (calibre && weight.ammo[calibre]) {
|
||||
let highestRating = 0;
|
||||
Object.keys(weight.ammo[calibre]).forEach((key) => {
|
||||
if (weight.ammo[calibre][key] > highestRating) {
|
||||
highestRating = weight.ammo[calibre][key];
|
||||
}
|
||||
});
|
||||
if (highestRating) {
|
||||
weight.equipment.FirstPrimaryWeapon[id] = getWeaponWeighting(
|
||||
items[id],
|
||||
highestRating
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
for (const category in weight.equipment) {
|
||||
const randomnessMultiplier = nonPmcBotConfig.botEquipmentRandomness;
|
||||
if (!randomnessMultiplier) return;
|
||||
const list = weight.equipment[category];
|
||||
const keys = Object.keys(list);
|
||||
const sortedValues = Object.values(list).sort((a, b) => a - b);
|
||||
const middleIndex = 0 + Math.round((sortedValues.length - 1) / 2);
|
||||
const medianValue = sortedValues[middleIndex];
|
||||
const highestValue = sortedValues[sortedValues.length - 1];
|
||||
const lowestValue = sortedValues[0];
|
||||
const betterValue = Math.round(
|
||||
(medianValue + highestValue + lowestValue) / 3
|
||||
);
|
||||
if (betterValue > 1) {
|
||||
keys.forEach((key) => {
|
||||
const valToAdjust = list[key];
|
||||
if (valToAdjust > 5) {
|
||||
const adjustedAmountMax = betterValue - valToAdjust;
|
||||
const amountAfterAdjustment = Math.round(
|
||||
valToAdjust + adjustedAmountMax * randomnessMultiplier
|
||||
);
|
||||
if (weight.equipment[category][key]) {
|
||||
weight.equipment[category][key] = Math.abs(amountAfterAdjustment);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
import { DependencyContainer } from "tsyringe";
|
||||
|
||||
import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
|
||||
import { DatabaseServer } from "@spt/servers/DatabaseServer";
|
||||
import config from "../../config/config.json";
|
||||
import nonPmcBotConfig from "../../config/nonPmcBotConfig.json";
|
||||
import { IBotConfig } from "../../types/models/spt/config/IBotConfig";
|
||||
|
||||
import {
|
||||
addItemsToBotInventory,
|
||||
applyValuesToStoredEquipment,
|
||||
buildEmptyWeightAdjustmentsByDevision,
|
||||
buldTieredItemTypes,
|
||||
normalizeMedianInventoryValues,
|
||||
} from "./NonPmcUtils";
|
||||
import { saveToFile } from "../LoadoutChanges/utils";
|
||||
import { globalValues } from "../LoadoutChanges/GlobalValues";
|
||||
import { ConfigServer } from "@spt/servers/ConfigServer";
|
||||
|
||||
export default function SetupNonPMCBotChanges(
|
||||
container: DependencyContainer
|
||||
): undefined {
|
||||
const databaseServer = container.resolve<DatabaseServer>("DatabaseServer");
|
||||
const tables = databaseServer.getTables();
|
||||
const items = tables.templates.items;
|
||||
const botsForUpdate = nonPmcBotConfig?.nonPmcBots;
|
||||
const configServer = container.resolve<ConfigServer>("ConfigServer");
|
||||
// const tieredItemTypes = buldTieredItemTypes(items);
|
||||
// saveToFile(tieredItemTypes, "Constants/tieredItems.json");
|
||||
|
||||
const botConfig = configServer.getConfig<IBotConfig>(ConfigTypes.BOT);
|
||||
|
||||
Object.keys(botsForUpdate).forEach((name) => {
|
||||
if (nonPmcBotConfig.ignoreList.includes(name)) return;
|
||||
|
||||
if (botConfig.equipment?.[name]?.weightingAdjustmentsByPlayerLevel) {
|
||||
botConfig.equipment[name].weightingAdjustmentsByPlayerLevel = [];
|
||||
}
|
||||
|
||||
if (
|
||||
botConfig.equipment[name] &&
|
||||
!botConfig.equipment[name]?.forceOnlyArmoredRigWhenNoArmor &&
|
||||
nonPmcBotConfig.nonPmcBots[name].forceOnlyArmoredRigWhenNoArmor
|
||||
) {
|
||||
botConfig.equipment[name]["forceOnlyArmoredRigWhenNoArmor"] = true;
|
||||
}
|
||||
|
||||
if (!tables.bots.types[name]?.inventory?.Ammo) return;
|
||||
const inventory = tables.bots.types[name].inventory;
|
||||
const chances = tables.bots.types[name].chances;
|
||||
|
||||
if (name !== "assault") {
|
||||
Object.keys(nonPmcBotConfig.nonPmcBots[name]).forEach((key) => {
|
||||
if (
|
||||
chances.equipment[key] !== undefined &&
|
||||
chances.equipment[key] < 30 &&
|
||||
nonPmcBotConfig.nonPmcBots[name][key][1] > 0
|
||||
) {
|
||||
switch (key) {
|
||||
case "Scabbard":
|
||||
break;
|
||||
case "Backpack":
|
||||
case "Holster":
|
||||
case "Eyewear":
|
||||
case "FaceCover":
|
||||
case "Earpiece":
|
||||
chances.equipment[key] = 30;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (name.includes("infected")) {
|
||||
chances.equipment[key] = 50;
|
||||
break;
|
||||
}
|
||||
chances.equipment[key] = 70;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (chances.equipment.SecondPrimaryWeapon) {
|
||||
chances.equipment.SecondPrimaryWeapon = 10;
|
||||
} else {
|
||||
chances.equipment.SecondPrimaryWeapon = 0;
|
||||
}
|
||||
// console.log("\n");
|
||||
}
|
||||
|
||||
// if (name === "marksman") {
|
||||
// saveToFile(tables.bots.types[name].inventory, `refDBS/marksman.json`);
|
||||
// }
|
||||
// console.log("\n", name);
|
||||
|
||||
addItemsToBotInventory(
|
||||
inventory,
|
||||
nonPmcBotConfig.nonPmcBots[name],
|
||||
items,
|
||||
name === "marksman"
|
||||
);
|
||||
|
||||
if (nonPmcBotConfig.nonPmcBots[name].HasModdedWeapons) {
|
||||
inventory.mods = tables.bots.types.usec.inventory.mods;
|
||||
}
|
||||
|
||||
normalizeMedianInventoryValues(inventory);
|
||||
|
||||
const storedEquipmentValues = buildEmptyWeightAdjustmentsByDevision(
|
||||
nonPmcBotConfig.nonPmcBots[name]
|
||||
);
|
||||
|
||||
applyValuesToStoredEquipment(inventory, items, storedEquipmentValues);
|
||||
|
||||
// if (name === "marksman") {
|
||||
// saveToFile(tables.bots.types[name].inventory, `refDBS/marksman2.json`);
|
||||
// }
|
||||
|
||||
globalValues.storedEquipmentValues[name] = storedEquipmentValues;
|
||||
});
|
||||
// console.log(bots);
|
||||
|
||||
// saveToFile(
|
||||
// globalValues.storedEquipmentValues,
|
||||
// `refDBS/storedEquipmentValues.json`
|
||||
// );
|
||||
|
||||
// saveToFile(botConfig.equipment.assault, "refDBS/equipmentAssault.json");
|
||||
// saveToFile(
|
||||
// globalValues.tables.bots.types["assault"]?.inventory,
|
||||
// `NonPmcBotChanges/botsRef/storedAssault.json`
|
||||
// );
|
||||
|
||||
config.debug &&
|
||||
console.log("Algorthimic Progression: nonPmcBots equipment stored!");
|
||||
}
|
||||
83
user/mods/AlgorithmicLevelProgression/src/mod.ts
Normal file
83
user/mods/AlgorithmicLevelProgression/src/mod.ts
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
import { IPreSptLoadMod } from "@spt/models/external/IPreSptLoadMod";
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import { DependencyContainer } from "tsyringe";
|
||||
import { IPostSptLoadMod } from "@spt/models/external/IPostSptLoadMod";
|
||||
import { IPostDBLoadMod } from "@spt/models/external/IPostDBLoadMod";
|
||||
import BotLevelChanges from "./LevelChanges/BotLevelChanges";
|
||||
import {
|
||||
enableProgressionChanges,
|
||||
enableLevelChanges,
|
||||
enableNonPMCBotChanges,
|
||||
leveledClothing,
|
||||
} from "../config/config.json";
|
||||
import ProgressionChanges from "./LoadoutChanges/ProgressionChanges";
|
||||
import { SetupLocationGlobals } from "./LoadoutChanges/SetupLocationGlobals";
|
||||
import { LocationUpdater } from "./LoadoutChanges/LocationUpdater";
|
||||
import SetupNonPMCBotChanges from "./NonPmcBotChanges/SetupNonPMCBotChanges";
|
||||
import ClothingChanges from "./LoadoutChanges/ClothingChanges";
|
||||
import { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { globalValues } from "./LoadoutChanges/GlobalValues";
|
||||
import { cloneDeep } from "./LoadoutChanges/utils";
|
||||
import { DatabaseServer } from "@spt/servers/DatabaseServer";
|
||||
import { ConfigServer } from "@spt/servers/ConfigServer";
|
||||
import { IBotConfig } from "@spt/models/spt/config/IBotConfig";
|
||||
import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
|
||||
|
||||
class AlgorithmicLevelProgression
|
||||
implements IPreSptLoadMod, IPostDBLoadMod, IPostSptLoadMod
|
||||
{
|
||||
preSptLoad(container: DependencyContainer): void {
|
||||
enableLevelChanges && BotLevelChanges(container);
|
||||
enableProgressionChanges && LocationUpdater(container);
|
||||
}
|
||||
|
||||
postDBLoad(container: DependencyContainer): void {
|
||||
if (enableProgressionChanges) {
|
||||
try {
|
||||
ProgressionChanges(container);
|
||||
} catch (error) {
|
||||
const Logger = container.resolve<ILogger>("WinstonLogger");
|
||||
const hasForceCachedChanged = !!error?.message?.includes("forceCached");
|
||||
if (hasForceCachedChanged) {
|
||||
Logger.error(
|
||||
`Algorithmic Level Progression failed to make progression changes.
|
||||
Trying again using "forceCached" enabled.
|
||||
Try changing your mod loader so ALP is earlier than mods that add custom items to avoid this message in the future.
|
||||
Error: ` + error?.message
|
||||
);
|
||||
ProgressionChanges(container);
|
||||
} else {
|
||||
Logger.error(
|
||||
`Algorithmic Level Progression failed to make progression changes.
|
||||
Try changing your mod loader so ALP is earlier than mods that add custom items
|
||||
Error: ` + error?.message
|
||||
);
|
||||
}
|
||||
}
|
||||
SetupLocationGlobals(container);
|
||||
}
|
||||
enableNonPMCBotChanges && SetupNonPMCBotChanges(container);
|
||||
const databaseServer = container.resolve<DatabaseServer>("DatabaseServer");
|
||||
const tables = databaseServer.getTables();
|
||||
const configServer = container.resolve<ConfigServer>("ConfigServer");
|
||||
const botConfig = configServer.getConfig<IBotConfig>(ConfigTypes.BOT);
|
||||
globalValues.originalBotTypes = cloneDeep(tables.bots.types);
|
||||
globalValues.originalWeighting = cloneDeep(botConfig.equipment.pmc);
|
||||
// globalValues.updateInventory(1, "woods"); // REMOVE
|
||||
}
|
||||
|
||||
postSptLoad(container: DependencyContainer): void {
|
||||
try {
|
||||
leveledClothing && ClothingChanges(container);
|
||||
} catch (error) {
|
||||
const Logger = container.resolve<ILogger>("WinstonLogger");
|
||||
Logger.error(
|
||||
`Algorithmic Level Progression failed to makeclothing changes.
|
||||
Try turning off custom clothing in the config!
|
||||
Error: ` + error?.message
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { mod: new AlgorithmicLevelProgression() };
|
||||
Loading…
Add table
Add a link
Reference in a new issue