8 Commits
Author SHA1 Message Date
Rage 1d21d74bb9 Some Optimizations to the Modpack
Disabled a lot of client-side related mods, removed Performance Improvements and disabled some potentially bad mods.

Reinstalled a default version of MOAR with just the source code preset selection set to custom.
2025-01-16 01:26:40 -05:00
Rage 3ebaed3777 Removed Potential Mod Corrupting Game 2025-01-15 21:33:26 -05:00
Rage 5d24318a39 Added A Mod; Fixed One Mod Installation
Added
- Black Clothing Pack

Fixed
- Make Val/VSS Great Again
2025-01-15 20:59:57 -05:00
Rage a161750966 Added Mods
- New Trader Mod; Painter
  - Along with a new weapon attachment mod; Black Core
- Make Val/VSS Great Again
2025-01-15 20:53:42 -05:00
Rage c3fcfb84f8 Reduced Quantity Multipliers 2025-01-15 20:16:52 -05:00
Rage 35e1404f43 Reduced MOAR Bot Spawn Counts 2025-01-15 19:38:36 -05:00
Rage f004d53072 Fixed Version Number 2025-01-15 18:47:35 -05:00
Rage 4a1cdbcd20 Tweaked MOAR Map-Specific Spawns and Config 2025-01-15 18:47:15 -05:00
530 changed files with 9010 additions and 45031 deletions
@@ -1,11 +1,11 @@
[General]
gameName=spt
modid=0
version=d2025.1.1.0
version=d2025.1.15.0
newestVersion=
category="1,2"
category="1,"
nexusFileStatus=1
installationFile=Default Epic.zip
installationFile=MoxoPixel-BlackCore.zip
repository=Nexus
ignoredVersion=
comments=
@@ -15,7 +15,7 @@ url=
hasCustomURL=true
lastNexusQuery=
lastNexusUpdate=
nexusLastModified=2025-01-01T06:47:45Z
nexusLastModified=2025-01-16T01:49:42Z
nexusCategory=0
converted=false
validated=false
@@ -0,0 +1,556 @@
{
"manifest": [
{
"key":"tactical_all_insight_wmx200_retex.bundle",
"dependencyKeys":[]
},
{
"key":"mag_stanag_hk_polymer_mag_556x45_30_retex.bundle",
"dependencyKeys":[]
},
{
"key":"handguard_ar15_dd_ris_ii_fsp_9,5_retex.bundle",
"dependencyKeys":[]
},
{
"key":"scope_all_eotech_exps3_retex.bundle",
"dependencyKeys":[
"scope_all_eotech_exps3_gloss_nrm_retex.bundle",
"scope_all_eotech_exps3_mesh_retex.bundle",
"scope_all_eotech_exps3_tan_textures_retex.bundle",
"scope_all_eotech_xps3_textures_retex.bundle"
]
},
{
"key":"scope_all_eotech_exps3_gloss_nrm_retex.bundle",
"dependencyKeys":[]
},
{
"key":"scope_all_eotech_exps3_tan_textures_retex.bundle",
"dependencyKeys":[]
},
{
"key":"scope_all_eotech_xps3_textures_retex.bundle",
"dependencyKeys":[]
},
{
"key":"scope_all_eotech_exps3_mesh_retex.bundle",
"dependencyKeys":[
"scope_all_eotech_exps3_gloss_nrm_retex.bundle",
"scope_all_eotech_exps3_tan_textures_retex.bundle",
"scope_all_eotech_xps3_textures_retex.bundle"
]
},
{
"key":"tactical_all_holosun_ls321_retex.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/textures/holemanager/glow_particle_bright.bundle",
"assets/standard assets/effects/lightcookies/textures/flashlightcookie.bundle",
"assets/systems/effects/collimator.bundle",
"assets/systems/effects/laserbeam/laser.bundle",
"assets/systems/effects/multiflare/multiflare.bundle",
"assets/systems/effects/nightvision.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"m4a1_black_lines/textures/client_assets.bundle",
"dependencyKeys":[
]
},
{
"key":"m4a1_black_lines/client_assets.bundle",
"dependencyKeys":[
"m4a1_black_lines/textures/client_assets.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"m4a1_black_lines/weapon_colt_m4a1_556x45_container.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/audio/banks/m4a1.bundle",
"assets/content/audio/blendoptions/assets.bundle",
"assets/content/audio/weapons/ak74.bundle",
"assets/content/audio/weapons/generic",
"assets/content/audio/weapons/m4a1.bundle",
"assets/content/weapons/additional_hands/client_assets.bundle",
"assets/content/weapons/animations/simple_animations.bundle",
"assets/content/weapons/animations/spirit_animations.bundle",
"m4a1_black_lines/client_assets.bundle",
"m4a1_black_lines/textures/client_assets.bundle",
"assets/content/weapons/tx15/client_assets.bundle",
"assets/content/weapons/tx15/textures/client_assets.bundle",
"assets/content/weapons/tx15/weapon_lone_star_tx15_designated_marksman_556x45_container.bundle",
"assets/content/weapons/weapon_root_anim_fix.bundle",
"assets/content/weapons/wip/kibas tuning prefabs/muzzlejets_templates/default_assets.bundle",
"assets/systems/effects/heathaze/defaultheathaze.bundle",
"assets/systems/effects/muzzleflash/muzzleflash.bundle",
"assets/systems/effects/smoke.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"ak103_black_lines/textures/client_assets.bundle",
"dependencyKeys":[
]
},
{
"key":"ak103_black_lines/client_assets.bundle",
"dependencyKeys":[
"ak103_black_lines/textures/client_assets.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"ak103_black_lines/weapon_izhmash_ak103_762x39_container.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/audio/banks/ak74.bundle",
"assets/content/audio/banks/akm.bundle",
"assets/content/audio/blendoptions/assets.bundle",
"assets/content/audio/weapons/ak74.bundle",
"assets/content/audio/weapons/akm.bundle",
"assets/content/audio/weapons/generic",
"assets/content/audio/weapons/saiga12.bundle",
"assets/content/items/mods/handguards/handguard_pp-19-01_izhmash_vityaz_std_plastic_textures.bundle",
"assets/content/weapons/additional_hands/client_assets.bundle",
"ak103_black_lines/client_assets.bundle",
"ak103_black_lines/textures/client_assets.bundle",
"assets/content/weapons/ak100/weapon_izhmash_ak104_762x39_container.bundle",
"assets/content/weapons/ak100/weapon_izhmash_ak105_545x39_container.bundle",
"assets/content/weapons/ak74m/textures/client_assets.bundle",
"assets/content/weapons/animations/simple_animations.bundle",
"assets/content/weapons/animations/spirit_animations.bundle",
"assets/content/weapons/pp-19-01/textures/client_assets.bundle",
"assets/content/weapons/weapon_root_anim_fix.bundle",
"assets/content/weapons/wip/kibas tuning prefabs/muzzlejets_templates/default_assets.bundle",
"assets/systems/effects/heathaze/defaultheathaze.bundle",
"assets/systems/effects/muzzleflash/muzzleflash.bundle",
"assets/systems/effects/smoke.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"reciever_ak_akademia_bastion_retex.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"rsass_black/weapon_remington_r11_rsass_762x51_container.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/audio/banks/rsass.bundle",
"assets/content/audio/blendoptions/assets.bundle",
"assets/content/audio/weapons/ak74.bundle",
"assets/content/audio/weapons/generic",
"assets/content/audio/weapons/mpx.bundle",
"assets/content/weapons/additional_hands/client_assets.bundle",
"assets/content/weapons/animations/simple_animations.bundle",
"assets/content/weapons/animations/spirit_animations.bundle",
"rsass_black/client_assets.bundle",
"rsass_black/textures/client_assets.bundle",
"assets/content/weapons/weapon_root_anim_fix.bundle",
"assets/content/weapons/wip/kibas tuning prefabs/muzzlejets_templates/default_assets.bundle",
"assets/systems/effects/heathaze/defaultheathaze.bundle",
"assets/systems/effects/muzzleflash/muzzleflash.bundle",
"assets/systems/effects/smoke.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"rsass_black/client_assets.bundle",
"dependencyKeys":[
"rsass_black/textures/client_assets.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"rsass_black/textures/client_assets.bundle",
"dependencyKeys":[
]
},
{
"key":"mk47_black_lines/textures/client_assets.bundle",
"dependencyKeys":[
]
},
{
"key":"mk47_black_lines/client_assets.bundle",
"dependencyKeys":[
"mk47_black_lines/textures/client_assets.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"mk47_black_lines/weapon_cmmg_mk47_762x39_container.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/audio/banks/mp5.bundle",
"assets/content/audio/blendoptions/assets.bundle",
"assets/content/audio/weapons/ak74.bundle",
"assets/content/audio/weapons/akm/instrumental.bundle",
"assets/content/audio/weapons/generic",
"assets/content/audio/weapons/mp5.bundle",
"assets/content/audio/weapons/mpx.bundle",
"assets/content/weapons/additional_hands/client_assets.bundle",
"assets/content/weapons/animations/simple_animations.bundle",
"assets/content/weapons/animations/spirit_animations.bundle",
"assets/content/weapons/m4a1/client_assets.bundle",
"assets/content/weapons/m4a1/textures/client_assets.bundle",
"mk47_black_lines/client_assets.bundle",
"mk47_black_lines/textures/client_assets.bundle",
"assets/content/weapons/weapon_root_anim_fix.bundle",
"assets/content/weapons/wip/kibas tuning prefabs/muzzlejets_templates/default_assets.bundle",
"assets/systems/effects/heathaze/defaultheathaze.bundle",
"assets/systems/effects/muzzleflash/muzzleflash.bundle",
"assets/systems/effects/smoke.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"reciever_mk47_cmmg_mk47_std_retex.bundle",
"dependencyKeys":[
]
},
{
"key":"tactical_all_wilcox_raptar_es_retex.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/textures/holemanager/glow_particle_bright.bundle",
"assets/standard assets/effects/lightcookies/textures/flashlightcookie.bundle",
"assets/systems/effects/collimator.bundle",
"assets/systems/effects/laserbeam/laser.bundle",
"assets/systems/effects/multiflare/multiflare.bundle",
"assets/systems/effects/nightvision.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"scope_30mm_razor_hd_gen_2_1_6x24_retex.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/textures/holemanager/round_spec_mask.bundle",
"assets/systems/effects/opticsight/opticsightsmasks.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"reciever_ar15_noveske_gen3_retex.bundle",
"dependencyKeys":[
]
},
{
"key":"stock_vepr_molot_vpo-101_std_wood_retex.bundle",
"dependencyKeys":[
]
},
{
"key":"stock_m14_troy_sass_chassis_retex.bundle",
"dependencyKeys":[
]
},
{
"key":"silencer_mount_silencerco_hybrid_46_multi_retex.bundle",
"dependencyKeys":[]
},
{
"key":"mag_aug_steyr_std_556x45_30_retex.bundle",
"dependencyKeys":[]
},
{
"key":"stock_ak_zenit_pt_1_retex.bundle",
"dependencyKeys":[]
},
{
"key":"pistolgrip_ak_magpul_moe_ak_retex.bundle",
"dependencyKeys":[]
},
{
"key":"gas_block_akp_slr_ak_railed_gas_tube_retex.bundle",
"dependencyKeys":[]
},
{
"key":"reciever_ak_texas_weapon_systems_dog_leg_rail_gen_3_retex.bundle",
"dependencyKeys":[]
},
{
"key":"handguard_ar15_precision_reflex_carbon_fiber_delta_gen_3_retex.bundle",
"dependencyKeys":[]
},
{
"key":"helmet_armor_slaap.bundle",
"dependencyKeys":[]
},
{
"key":"reciever_glock_glock_17_std_retex.bundle",
"dependencyKeys":[]
},
{
"key":"reciever_glock_gspc_viper_slide_cut_retex.bundle",
"dependencyKeys":[]
},
{
"key":"m4a1_flame/textures/client_assets.bundle",
"dependencyKeys":[
]
},
{
"key":"m4a1_flame/client_assets.bundle",
"dependencyKeys":[
"m4a1_flame/textures/client_assets.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"m4a1_flame/weapon_colt_m4a1_556x45_container.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/audio/banks/m4a1.bundle",
"assets/content/audio/blendoptions/assets.bundle",
"assets/content/audio/weapons/ak74.bundle",
"assets/content/audio/weapons/generic",
"assets/content/audio/weapons/m4a1.bundle",
"assets/content/weapons/additional_hands/client_assets.bundle",
"assets/content/weapons/animations/simple_animations.bundle",
"assets/content/weapons/animations/spirit_animations.bundle",
"m4a1_flame/client_assets.bundle",
"m4a1_flame/textures/client_assets.bundle",
"assets/content/weapons/tx15/client_assets.bundle",
"assets/content/weapons/tx15/textures/client_assets.bundle",
"assets/content/weapons/tx15/weapon_lone_star_tx15_designated_marksman_556x45_container.bundle",
"assets/content/weapons/weapon_root_anim_fix.bundle",
"assets/content/weapons/wip/kibas tuning prefabs/muzzlejets_templates/default_assets.bundle",
"assets/systems/effects/heathaze/defaultheathaze.bundle",
"assets/systems/effects/muzzleflash/muzzleflash.bundle",
"assets/systems/effects/smoke.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"foregrip_all_bcm_mod_3_new.bundle",
"dependencyKeys":[]
},
{
"key":"mag_ak74_izhmash_6l23_545x39_30_retex.bundle",
"dependencyKeys":[]
},
{
"key":"m4a1_new/textures/client_assets.bundle",
"dependencyKeys":[
]
},
{
"key":"m4a1_new/client_assets.bundle",
"dependencyKeys":[
"m4a1_new/textures/client_assets.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"m4a1_new/weapon_colt_m4a1_556x45_container.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/audio/banks/m4a1.bundle",
"assets/content/audio/blendoptions/assets.bundle",
"assets/content/audio/weapons/ak74.bundle",
"assets/content/audio/weapons/generic",
"assets/content/audio/weapons/m4a1.bundle",
"assets/content/weapons/additional_hands/client_assets.bundle",
"assets/content/weapons/animations/simple_animations.bundle",
"assets/content/weapons/animations/spirit_animations.bundle",
"m4a1_new/client_assets.bundle",
"m4a1_new/textures/client_assets.bundle",
"assets/content/weapons/tx15/client_assets.bundle",
"assets/content/weapons/tx15/textures/client_assets.bundle",
"assets/content/weapons/tx15/weapon_lone_star_tx15_designated_marksman_556x45_container.bundle",
"assets/content/weapons/weapon_root_anim_fix.bundle",
"assets/content/weapons/wip/kibas tuning prefabs/muzzlejets_templates/default_assets.bundle",
"assets/systems/effects/heathaze/defaultheathaze.bundle",
"assets/systems/effects/muzzleflash/muzzleflash.bundle",
"assets/systems/effects/smoke.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"reciever_ar15_vltor_mur-1s_retex.bundle",
"dependencyKeys":[
]
},
{
"key":"mag_ar10_lancer_l7_awm_762x51_20.bundle",
"dependencyKeys":[
]
},
{
"key":"mag_ar10_lancer_l7_awm_762x51_25.bundle",
"dependencyKeys":[
]
},
{
"key":"spear_black/textures/client_assets.bundle",
"dependencyKeys":[
]
},
{
"key":"spear_black/client_assets.bundle",
"dependencyKeys":[
"spear_black/textures/client_assets.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"spear_black/weapon_sig_mcx_spear_68x51_container.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/audio/blendoptions/assets.bundle",
"assets/content/audio/weapons/ak74.bundle",
"assets/content/audio/weapons/generic",
"assets/content/weapons/additional_hands/client_assets.bundle",
"assets/content/weapons/animations/simple_animations.bundle",
"assets/content/weapons/animations/spirit_animations.bundle",
"spear_black/client_assets.bundle",
"spear_black/textures/client_assets.bundle",
"assets/content/weapons/weapon_root_anim_fix.bundle",
"assets/content/weapons/wip/kibas tuning prefabs/muzzlejets_templates/default_assets.bundle",
"assets/systems/effects/heathaze/defaultheathaze.bundle",
"assets/systems/effects/muzzleflash/muzzleflash.bundle",
"assets/systems/effects/smoke.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"spear_black/reciever_mcx_sig_spear_upper.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"spear_black/client_assets.bundle",
"spear_black/textures/client_assets.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"pistolgrip_ar15_sig_reduced_angle_pistol_grip_ct_retex.bundle",
"dependencyKeys":[
]
},
{
"key":"handguard_mcx_sig_spear_m_lok_retex.bundle",
"dependencyKeys":[]
},
{
"key":"silencer_clutchlok_sig_slx68_mg_qd_suppressor_68x51_retex.bundle",
"dependencyKeys":[]
},
{
"key":"charge_spear_sig_spear_std_retex.bundle",
"dependencyKeys":[]
},
{
"key":"stock_ar15_magpul_moe_sl_k_carbine_ct_retex.bundle",
"dependencyKeys":[]
},
{
"key":"stock_base_sig_low_profile_tube_ct_retex.bundle",
"dependencyKeys":[]
},
{
"key":"balaclava/item_equipment_facecover_balaclava_black.bundle",
"dependencyKeys":[
"balaclava/wildman01head_textures_black.bundle"
]
},
{
"key":"balaclava/wildman01head_textures_black.bundle",
"dependencyKeys":[]
},
{
"key":"glasses/item_equipment_glasses_npp_retex.bundle",
"dependencyKeys":[]
},
{
"key":"rigs/cr_arscpc_retex.bundle",
"dependencyKeys":[]
},
{
"key":"rigs/item_equipment_rig_carriertactec_retex.bundle",
"dependencyKeys":[]
},
{
"key":"rigs/item_equipment_rig_tv110_retex.bundle",
"dependencyKeys":[]
},
{
"key":"rigs/item_equipment_rig_cryeavs_retex.bundle",
"dependencyKeys":[]
},
{
"key":"scope_all_vortex_razor_amg_uh-1_retex.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/textures/holemanager/eotech_spec_mask.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"tactical_all_insight_anpeq15_retex.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/textures/holemanager/glow_particle_bright.bundle",
"assets/standard assets/effects/lightcookies/textures/flashlightcookie.bundle",
"assets/systems/effects/collimator.bundle",
"assets/systems/effects/laserbeam/laser.bundle",
"assets/systems/effects/multiflare/multiflare.bundle",
"assets/systems/effects/nightvision.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"stock_ar15_fab_defense_gl_core_retex.bundle",
"dependencyKeys":[
]
},
{
"key":"scope_30mm_sig_tango6t_1_6x24_retex.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/textures/holemanager/round_spec_mask.bundle",
"assets/systems/effects/opticsight/opticsightsmasks.bundle",
"cubemaps",
"shaders"
]
},
{
"key":"nvg_l3_gpnvg-18_anvis_retex.bundle",
"dependencyKeys":[
"assets/commonassets/physics/physicsmaterials.bundle",
"assets/content/items/equipment/glasses_6b34/glasses_6b34_glass_textures",
"cubemaps",
"shaders"
]
}
]
}
@@ -0,0 +1,603 @@
{
"ItemPresets": {
"6783f24f861dfacffe36b138": {
"_changeWeaponName": false,
"_encyclopedia": "672e37d19f1683101780773b",
"_id": "6783f24f861dfacffe36b138",
"_items": [
{
"_id": "6783f25b69d649d493cda1fd",
"_tpl": "672e37d19f1683101780773b",
"upd": {
"Repairable": {
"Durability": 100,
"MaxDurability": 100
}
}
},
{
"_id": "6783f26abcf5805ba9248ad7",
"_tpl": "55d4b9964bdc2d1d4e8b456e",
"parentId": "6783f25b69d649d493cda1fd",
"slotId": "mod_pistol_grip"
},
{
"_id": "6783f26d3b2ca6db3f36b858",
"_tpl": "55d4887d4bdc2d962f8b4570",
"parentId": "6783f25b69d649d493cda1fd",
"slotId": "mod_magazine"
},
{
"_id": "6783f2723a07e8c6a8006e9f",
"_tpl": "672e37d1249244ae3a50bb2f",
"parentId": "6783f25b69d649d493cda1fd",
"slotId": "mod_reciever"
},
{
"_id": "6783f29a304ff60a67653ddb",
"_tpl": "55d3632e4bdc2d972f8b4569",
"parentId": "6783f2723a07e8c6a8006e9f",
"slotId": "mod_barrel"
},
{
"_id": "6783f29f017667af4aeda8df",
"_tpl": "544a38634bdc2d58388b4568",
"parentId": "6783f29a304ff60a67653ddb",
"slotId": "mod_muzzle"
},
{
"_id": "6783f2a148624b6f5fe0a317",
"_tpl": "5ae30e795acfc408fb139a0b",
"parentId": "6783f29a304ff60a67653ddb",
"slotId": "mod_gas_block"
},
{
"_id": "6783f2a88b7b6cd3c9225511",
"_tpl": "5ae30db85acfc408fb139a05",
"parentId": "6783f2723a07e8c6a8006e9f",
"slotId": "mod_handguard"
},
{
"_id": "6783f2ad374903cfc652f22f",
"_tpl": "637f57a68d137b27f70c4968",
"parentId": "6783f2a88b7b6cd3c9225511",
"slotId": "mod_handguard"
},
{
"_id": "6783f2aeb598721f40ef1263",
"_tpl": "5ae30bad5acfc400185c2dc4",
"parentId": "6783f2723a07e8c6a8006e9f",
"slotId": "mod_sight_rear"
},
{
"_id": "6783f2af7cf3b743d3d8c1e2",
"_tpl": "5649be884bdc2d79388b4577",
"parentId": "6783f25b69d649d493cda1fd",
"slotId": "mod_stock"
},
{
"_id": "6783f2b54115cf68d3ffa632",
"_tpl": "55d4ae6c4bdc2d8b2f8b456e",
"parentId": "6783f2af7cf3b743d3d8c1e2",
"slotId": "mod_stock_000"
},
{
"_id": "6783f2b66dc7254a0401b1ca",
"_tpl": "55d44fd14bdc2d962f8b456e",
"parentId": "6783f25b69d649d493cda1fd",
"slotId": "mod_charge"
}
],
"_name": "M4A1 Std Painter Edition",
"_parent": "6783f25b69d649d493cda1fd",
"_type": "Preset"
},
"6783f192c8a5270c18aad6b6": {
"_changeWeaponName": false,
"_encyclopedia": "672e37d1ddaf7c656e3a634c",
"_id": "6783f192c8a5270c18aad6b6",
"_items": [
{
"_id": "6783f1a47ef435b43580168c",
"_tpl": "672e37d1ddaf7c656e3a634c",
"upd": {
"Repairable": {
"Durability": 100,
"MaxDurability": 100
}
}
},
{
"_id": "6783f1b85be1b42bf29e4a61",
"_tpl": "55d4b9964bdc2d1d4e8b456e",
"parentId": "6783f1a47ef435b43580168c",
"slotId": "mod_pistol_grip"
},
{
"_id": "6783f1bb8ce2bb9545fae1d8",
"_tpl": "55d4887d4bdc2d962f8b4570",
"parentId": "6783f1a47ef435b43580168c",
"slotId": "mod_magazine"
},
{
"_id": "6783f1c160f9c16d7f779a4d",
"_tpl": "55d355e64bdc2d962f8b4569",
"parentId": "6783f1a47ef435b43580168c",
"slotId": "mod_reciever"
},
{
"_id": "6783f1d493fa264e4493ac2e",
"_tpl": "55d3632e4bdc2d972f8b4569",
"parentId": "6783f1c160f9c16d7f779a4d",
"slotId": "mod_barrel"
},
{
"_id": "6783f1d9be58dbc9b2a069ba",
"_tpl": "544a38634bdc2d58388b4568",
"parentId": "6783f1d493fa264e4493ac2e",
"slotId": "mod_muzzle"
},
{
"_id": "6783f1daae07965124acac83",
"_tpl": "5ae30e795acfc408fb139a0b",
"parentId": "6783f1d493fa264e4493ac2e",
"slotId": "mod_gas_block"
},
{
"_id": "6783f1ddde94724c8bd6ca16",
"_tpl": "5ae30db85acfc408fb139a05",
"parentId": "6783f1c160f9c16d7f779a4d",
"slotId": "mod_handguard"
},
{
"_id": "6783f1e275d0b1ed88572ad0",
"_tpl": "637f57a68d137b27f70c4968",
"parentId": "6783f1ddde94724c8bd6ca16",
"slotId": "mod_handguard"
},
{
"_id": "6783f1e3fbc6c6dbf0aadc86",
"_tpl": "5ae30bad5acfc400185c2dc4",
"parentId": "6783f1c160f9c16d7f779a4d",
"slotId": "mod_sight_rear"
},
{
"_id": "6783f1ec39e6076911b5df9c",
"_tpl": "5649be884bdc2d79388b4577",
"parentId": "6783f1a47ef435b43580168c",
"slotId": "mod_stock"
},
{
"_id": "6783f1f09bad1af82a378d05",
"_tpl": "55d4ae6c4bdc2d8b2f8b456e",
"parentId": "6783f1ec39e6076911b5df9c",
"slotId": "mod_stock_000"
},
{
"_id": "6783f1f235ede9255929f2d4",
"_tpl": "55d44fd14bdc2d962f8b456e",
"parentId": "6783f1a47ef435b43580168c",
"slotId": "mod_charge"
}
],
"_name": "M4A1 Std Flames",
"_parent": "6783f1a47ef435b43580168c",
"_type": "Preset"
},
"6783f0fbb5c5bfbb971871e1": {
"_changeWeaponName": false,
"_encyclopedia": "672e37d1179b7b969b7577cb",
"_id": "6783f0fbb5c5bfbb971871e1",
"_items": [
{
"_id": "6783f10174bf20e471c5c055",
"_tpl": "672e37d1179b7b969b7577cb",
"upd": {
"Repairable": {
"Durability": 100,
"MaxDurability": 100
}
}
},
{
"_id": "6783f11512857c267b254af7",
"_tpl": "55d4b9964bdc2d1d4e8b456e",
"parentId": "6783f10174bf20e471c5c055",
"slotId": "mod_pistol_grip"
},
{
"_id": "6783f11aec8108543017f1e3",
"_tpl": "55d4887d4bdc2d962f8b4570",
"parentId": "6783f10174bf20e471c5c055",
"slotId": "mod_magazine"
},
{
"_id": "6783f1205747a3ea48865e73",
"_tpl": "55d355e64bdc2d962f8b4569",
"parentId": "6783f10174bf20e471c5c055",
"slotId": "mod_reciever"
},
{
"_id": "6783f1350fbe98026207e7ea",
"_tpl": "55d3632e4bdc2d972f8b4569",
"parentId": "6783f1205747a3ea48865e73",
"slotId": "mod_barrel"
},
{
"_id": "6783f13b8484c0c25a66be35",
"_tpl": "544a38634bdc2d58388b4568",
"parentId": "6783f1350fbe98026207e7ea",
"slotId": "mod_muzzle"
},
{
"_id": "6783f13dc1acd3ecae24270f",
"_tpl": "5ae30e795acfc408fb139a0b",
"parentId": "6783f1350fbe98026207e7ea",
"slotId": "mod_gas_block"
},
{
"_id": "6783f1488a3d2dc4157c8758",
"_tpl": "5ae30db85acfc408fb139a05",
"parentId": "6783f1205747a3ea48865e73",
"slotId": "mod_handguard"
},
{
"_id": "6783f151960a80ad5f9745ae",
"_tpl": "637f57a68d137b27f70c4968",
"parentId": "6783f1488a3d2dc4157c8758",
"slotId": "mod_handguard"
},
{
"_id": "6783f154906b450be0b3182f",
"_tpl": "5ae30bad5acfc400185c2dc4",
"parentId": "6783f1205747a3ea48865e73",
"slotId": "mod_sight_rear"
},
{
"_id": "6783f15600d12159f91920f6",
"_tpl": "5649be884bdc2d79388b4577",
"parentId": "6783f10174bf20e471c5c055",
"slotId": "mod_stock"
},
{
"_id": "6783f15bc0fe63d6d241fb9b",
"_tpl": "55d4ae6c4bdc2d8b2f8b456e",
"parentId": "6783f15600d12159f91920f6",
"slotId": "mod_stock_000"
},
{
"_id": "6783f1f861bc1198d4d14f7c",
"_tpl": "55d44fd14bdc2d962f8b456e",
"parentId": "6783f10174bf20e471c5c055",
"slotId": "mod_charge"
}
],
"_name": "M4A1 Std Topo",
"_parent": "6783f10174bf20e471c5c055",
"_type": "Preset"
},
"6783f026a570e11e98538c25": {
"_changeWeaponName": false,
"_encyclopedia": "672e37d1e35a6ec6e6997492",
"_id": "6783f026a570e11e98538c25",
"_items": [
{
"_id": "6783f04c9ff3e61038c7a73b",
"_tpl": "672e37d1e35a6ec6e6997492"
},
{
"_id": "6783f05f37f27dd00e59aa24",
"_tpl": "59c6633186f7740cf0493bb9",
"parentId": "6783f04c9ff3e61038c7a73b",
"slotId": "mod_gas_block"
},
{
"_id": "6783f07124277c3fd1890147",
"_tpl": "5648b1504bdc2d9d488b4584",
"parentId": "6783f05f37f27dd00e59aa24",
"slotId": "mod_handguard"
},
{
"_id": "6783f0741ec1081b46650491",
"_tpl": "5ac72e7d5acfc40016339a02",
"parentId": "6783f04c9ff3e61038c7a73b",
"slotId": "mod_muzzle"
},
{
"_id": "6783f0764bac8452114f4a95",
"_tpl": "5649ade84bdc2d1b2b8b4587",
"parentId": "6783f04c9ff3e61038c7a73b",
"slotId": "mod_pistol_grip"
},
{
"_id": "6783f0770459d79d0f33b9da",
"_tpl": "672e37d10c5f88d8ed0d056a",
"parentId": "6783f04c9ff3e61038c7a73b",
"slotId": "mod_reciever"
},
{
"_id": "6783f07a137b256bffe1cfb1",
"_tpl": "5ac50c185acfc400163398d4",
"parentId": "6783f04c9ff3e61038c7a73b",
"slotId": "mod_stock"
},
{
"_id": "6783f07c8853c5e4efc96806",
"_tpl": "5ac66bea5acfc43b321d4aec",
"parentId": "6783f04c9ff3e61038c7a73b",
"slotId": "mod_magazine"
}
],
"_name": "AK-103 Default Topo",
"_parent": "6783f04c9ff3e61038c7a73b",
"_type": "Preset"
},
"6783ec2851c792b686291cb9": {
"_changeWeaponName": false,
"_encyclopedia": "672e37d17f433cdb29072bc8",
"_id": "6783ec2851c792b686291cb9",
"_items": [
{
"_id": "6783ec33c8d50fdb6b63d3e9",
"_tpl": "672e37d17f433cdb29072bc8",
"upd": {
"FireMode": {
"FireMode": "single"
},
"Repairable": {
"Durability": 100,
"MaxDurability": 100
}
}
},
{
"_id": "657eb3773271d8578610fe2a",
"_tpl": "672e37d1861c12c7e1d94089",
"parentId": "6783ec33c8d50fdb6b63d3e9",
"slotId": "mod_pistol_grip"
},
{
"_id": "657eb3773271d8578610fe2b",
"_tpl": "672e37d19811257c1de39e6d",
"parentId": "6783ec33c8d50fdb6b63d3e9",
"slotId": "mod_magazine"
},
{
"_id": "6783ec4cf0b00cd50d9c2a87",
"_tpl": "672e37d133cc1fb4424ddb4c",
"parentId": "6783ec33c8d50fdb6b63d3e9",
"slotId": "mod_reciever"
},
{
"_id": "6783ec6e1a49dfd7571ae44e",
"_tpl": "5b2389515acfc4771e1be0c0",
"parentId": "6783ec4cf0b00cd50d9c2a87",
"slotId": "mod_scope"
},
{
"_id": "6783ec7588341583da153886",
"_tpl": "67617ec9ea1e82ea5e103054",
"parentId": "6783ec6e1a49dfd7571ae44e",
"slotId": "mod_scope_000"
},
{
"_id": "6783ec85d0fd3275f2ab164a",
"_tpl": "652910565ae2ae97b80fdf35",
"parentId": "6783ec4cf0b00cd50d9c2a87",
"slotId": "mod_barrel"
},
{
"_id": "6783ec955c4560dd83a3c26f",
"_tpl": "6529113b5ae2ae97b80fdf39",
"parentId": "6783ec85d0fd3275f2ab164a",
"slotId": "mod_muzzle"
},
{
"_id": "6783ec9892098902e42933bd",
"_tpl": "672e37d143ba463a1cdcbd7b",
"parentId": "6783ec955c4560dd83a3c26f",
"slotId": "mod_muzzle"
},
{
"_id": "6783ec9ddf30430fd30d48ef",
"_tpl": "652910bc24cbe3c74a05e5b9",
"parentId": "6783ec85d0fd3275f2ab164a",
"slotId": "mod_gas_block"
},
{
"_id": "6783ec9fb358c9d737de5800",
"_tpl": "672e37d1984bc9a10241a9c7",
"parentId": "6783ec4cf0b00cd50d9c2a87",
"slotId": "mod_handguard"
},
{
"_id": "6783eea29163d870c845e6b9",
"_tpl": "6529348224cbe3c74a05e5c4",
"parentId": "6783ec33c8d50fdb6b63d3e9",
"slotId": "mod_stock_000"
},
{
"_id": "6783eea6b0158f1b5bf6ba4e",
"_tpl": "672e37d151b832f3fb8ccbb0",
"parentId": "6783eea29163d870c845e6b9",
"slotId": "mod_stock"
},
{
"_id": "6783eeaa698962dfeeda79a3",
"_tpl": "672e37d1d9a55146e49287d6",
"parentId": "6783eea6b0158f1b5bf6ba4e",
"slotId": "mod_stock_000"
},
{
"_id": "6783eca92713d47b3f369d0b",
"_tpl": "672e37d1906226680c4e28d5",
"parentId": "6783ec33c8d50fdb6b63d3e9",
"slotId": "mod_charge"
}
],
"_name": "SIG SPEAR default black",
"_parent": "6783ec33c8d50fdb6b63d3e9",
"_type": "Preset"
},
"6783e5da52977a05d959ac2f": {
"_changeWeaponName": false,
"_encyclopedia": "672e37d1dd890afba20c10e7",
"_id": "6783e5da52977a05d959ac2f",
"_items": [
{
"_id": "6783e5f4c23d0a4830e3d069",
"_tpl": "672e37d1dd890afba20c10e7",
"upd": {
"Repairable": {
"Durability": 100,
"MaxDurability": 100
}
}
},
{
"_id": "6783e603e6cebbfe9babfb73",
"_tpl": "5cc9bcaed7f00c011c04e179",
"parentId": "6783e5f4c23d0a4830e3d069",
"slotId": "mod_pistol_grip"
},
{
"_id": "6783e60517f08a8301bbd2c5",
"_tpl": "5a3501acc4a282000d72293a",
"parentId": "6783e5f4c23d0a4830e3d069",
"slotId": "mod_magazine"
},
{
"_id": "6783e607810d48f18bc7e606",
"_tpl": "5a33ca0fc4a282000d72292f",
"parentId": "6783e5f4c23d0a4830e3d069",
"slotId": "mod_stock"
},
{
"_id": "6783e60ba048490f25da323e",
"_tpl": "5d44069ca4b9361ebd26fc37",
"parentId": "6783e607810d48f18bc7e606",
"slotId": "mod_stock"
},
{
"_id": "6783e60d0f11531e764dd864",
"_tpl": "5d00ef6dd7ad1a0940739b16",
"parentId": "6783e5f4c23d0a4830e3d069",
"slotId": "mod_handguard"
},
{
"_id": "6783e61457c31046a3d9466b",
"_tpl": "5a34fae7c4a2826c6e06d760",
"parentId": "6783e5f4c23d0a4830e3d069",
"slotId": "mod_barrel"
},
{
"_id": "6783e618cc78902eec1f2c0b",
"_tpl": "5a34fd2bc4a282329a73b4c5",
"parentId": "6783e61457c31046a3d9466b",
"slotId": "mod_muzzle"
},
{
"_id": "6783e61a7bfb5f73bdcef867",
"_tpl": "5a34fbadc4a28200741e230a",
"parentId": "6783e61457c31046a3d9466b",
"slotId": "mod_gas_block"
}
],
"_name": "RSASS Black",
"_parent": "6783e5f4c23d0a4830e3d069",
"_type": "Preset"
},
"6783eb2892780aded22f44d6": {
"_changeWeaponName": false,
"_encyclopedia": "672e37d10b7a12e6a7a50b77",
"_id": "6783eb2892780aded22f44d6",
"_items": [
{
"_id": "6783eb3a05c979d9171196e2",
"_tpl": "672e37d10b7a12e6a7a50b77",
"upd": {
"FireMode": {
"FireMode": "single"
}
}
},
{
"_id": "6783eb482a3ac74d07710776",
"_tpl": "55802f5d4bdc2dac148b458f",
"parentId": "6783eb3a05c979d9171196e2",
"slotId": "mod_pistol_grip"
},
{
"_id": "6783eb4de2e02a031c2d2eb9",
"_tpl": "59d6272486f77466146386ff",
"parentId": "6783eb3a05c979d9171196e2",
"slotId": "mod_magazine"
},
{
"_id": "6783eb54e77a16ac4853c726",
"_tpl": "672e37d1a98e0628807ba29a",
"parentId": "6783eb3a05c979d9171196e2",
"slotId": "mod_reciever"
},
{
"_id": "6783eb6f7e0a5b57278b5d8f",
"_tpl": "60658776f2cb2e02a42ace2b",
"parentId": "6783eb54e77a16ac4853c726",
"slotId": "mod_barrel"
},
{
"_id": "6783eb76f0ceaeb9063cdbf2",
"_tpl": "6065c6e7132d4d12c81fd8e1",
"parentId": "6783eb6f7e0a5b57278b5d8f",
"slotId": "mod_muzzle"
},
{
"_id": "6783eb7901da578da4b2230c",
"_tpl": "6065dc8a132d4d12c81fd8e3",
"parentId": "6783eb6f7e0a5b57278b5d8f",
"slotId": "mod_gas_block"
},
{
"_id": "6783eb7b04cdf6ff2fb14809",
"_tpl": "6065880c132d4d12c81fd8da",
"parentId": "6783eb54e77a16ac4853c726",
"slotId": "mod_handguard"
},
{
"_id": "6783eb7e73028d0ad6ba25a7",
"_tpl": "5bc09a30d4351e00367fb7c8",
"parentId": "6783eb7b04cdf6ff2fb14809",
"slotId": "mod_sight_front"
},
{
"_id": "6783eb801f0133eec60418fd",
"_tpl": "5bc09a18d4351e003562b68e",
"parentId": "6783eb54e77a16ac4853c726",
"slotId": "mod_sight_rear"
},
{
"_id": "6783eb82d4bfe4734f1968e8",
"_tpl": "606587e18900dc2d9a55b65f",
"parentId": "6783eb3a05c979d9171196e2",
"slotId": "mod_stock_001"
},
{
"_id": "6783eb85ede00f4e10fe95fa",
"_tpl": "606587d11246154cad35d635",
"parentId": "6783eb82d4bfe4734f1968e8",
"slotId": "mod_stock_000"
},
{
"_id": "6783eb8781c4dad6d094d7d5",
"_tpl": "606587bd6d0bd7580617bacc",
"parentId": "6783eb3a05c979d9171196e2",
"slotId": "mod_charge"
}
],
"_name": "CMMG MK47 short default black",
"_parent": "6783eb3a05c979d9171196e2",
"_type": "Preset"
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,26 @@
{
"name": "Black Core",
"version": "1.1.6",
"main": "src/mod.js",
"license": "University of Illinois/NCSA Open Source License",
"author": "MoxoPixel",
"sptVersion": "3.10.X",
"isBundleMod": true,
"scripts": {
"setup": "npm i",
"build": "node ./build.mjs",
"buildinfo": "node ./build.mjs --verbose"
},
"devDependencies": {
"@types/node": "20.11",
"@typescript-eslint/eslint-plugin": "7.2",
"@typescript-eslint/parser": "7.2",
"archiver": "^6.0",
"eslint": "8.57",
"fs-extra": "11.2",
"ignore": "^5.2",
"tsyringe": "4.8.0",
"typescript": "5.4",
"winston": "3.12"
}
}
@@ -0,0 +1,236 @@
import { DependencyContainer } from "tsyringe";
import { IPostDBLoadMod } from "@spt/models/external/IPostDBLoadMod";
import { DatabaseServer } from "@spt/servers/DatabaseServer";
import { ImporterUtil } from "@spt/utils/ImporterUtil";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { PreSptModLoader } from "@spt/loaders/PreSptModLoader";
import { IDatabaseTables } from "@spt/models/spt/server/IDatabaseTables";
import { JsonUtil } from "@spt/utils/JsonUtil"
interface IHandbookEntry {
Id: string;
ParentId: string;
Price: number;
}
class BlackCore implements IPostDBLoadMod {
private db: IDatabaseTables;
private mydb: any;
private logger: ILogger;
private jsonUtil: JsonUtil;
public postDBLoad(container: DependencyContainer): void {
try {
this.logger = container.resolve<ILogger>("WinstonLogger");
this.jsonUtil = container.resolve<JsonUtil>("JsonUtil");
const databaseServer = container.resolve<DatabaseServer>("DatabaseServer");
const databaseImporter = container.resolve<ImporterUtil>("ImporterUtil");
const modLoader = container.resolve<PreSptModLoader>("PreSptModLoader");
this.db = databaseServer.getTables();
this.mydb = databaseImporter.loadRecursive(`${modLoader.getModPath("MoxoPixel-BlackCore")}database/`);
if (!this.db || !this.mydb) {
throw new Error("Failed to load required databases");
}
const modFolderName = "MoxoPixel-BlackCore";
const traders = {
"painter": "668aaff35fd574b6dcc4a686"
};
for (const newItem in this.mydb.items) {
this.cloneItem(this.mydb.items[newItem].clone, newItem);
this.addCompatibilitiesAndConflicts(this.mydb.items[newItem].clone, newItem);
const newItemLocales = this.mydb.items[newItem].locales;
for (const lang in this.db.locales.global) {
this.db.locales.global[lang][`${newItem} Name`] = newItemLocales.Name;
this.db.locales.global[lang][`${newItem} ShortName`] = newItemLocales.Shortname;
this.db.locales.global[lang][`${newItem} Description`] = newItemLocales.Description;
}
}
for (const trader in traders) this.addTraderAssort(traders[trader]);
for (const preset in this.mydb.globals.ItemPresets) {
this.db.globals.ItemPresets[preset] = this.mydb.globals.ItemPresets[preset];
}
const dbMastering = this.db.globals.config.Mastering;
for (const weapon in dbMastering) {
if (dbMastering[weapon].Name == "M4") dbMastering[weapon].Templates.push("672e37d1179b7b969b7577cb", "672e37d1ddaf7c656e3a634c", "672e37d19f1683101780773b");
if (dbMastering[weapon].Name == "AK74") dbMastering[weapon].Templates.push("672e37d1e35a6ec6e6997492");
if (dbMastering[weapon].Name == "R11SRASS") dbMastering[weapon].Templates.push("672e37d1dd890afba20c10e7");
if (dbMastering[weapon].Name == "MK47") dbMastering[weapon].Templates.push("672e37d10b7a12e6a7a50b77");
if (dbMastering[weapon].Name == "SPEAR") dbMastering[weapon].Templates.push("672e37d17f433cdb29072bc8");
}
const dbQuests = this.db.templates.quests;
for (const M4Quest in dbQuests) {
if (
dbQuests[M4Quest]._id === "5a27bb8386f7741c770d2d0a" ||
dbQuests[M4Quest]._id === "5c0d4c12d09282029f539173" ||
dbQuests[M4Quest]._id === "63a9b229813bba58a50c9ee5" ||
dbQuests[M4Quest]._id === "64e7b9bffd30422ed03dad38" ||
dbQuests[M4Quest]._id === "666314b4d7f171c4c20226c3"
) {
const availableForFinish = dbQuests[M4Quest].conditions.AvailableForFinish;
for (const condition of availableForFinish) {
if (condition.counter && condition.counter.conditions) {
for (const counterCondition of condition.counter.conditions) {
if (counterCondition.weapon) {
counterCondition.weapon.push(
"672e37d1179b7b969b7577cb",
"672e37d1ddaf7c656e3a634c",
"672e37d19f1683101780773b"
);
}
}
}
}
}
}
for (const AKQuest in dbQuests) {
if (
dbQuests[AKQuest]._id === "59c50a9e86f7745fef66f4ff" ||
dbQuests[AKQuest]._id === "61e6e60223374d168a4576a6" ||
dbQuests[AKQuest]._id === "64e7b9bffd30422ed03dad38"
) {
const availableForFinish = dbQuests[AKQuest].conditions.AvailableForFinish;
for (const condition of availableForFinish) {
if (condition.counter && condition.counter.conditions) {
for (const counterCondition of condition.counter.conditions) {
if (counterCondition.weapon) {
counterCondition.weapon.push(
"672e37d1e35a6ec6e6997492"
);
}
}
}
}
}
}
for (const MK47Quest in dbQuests) {
if (
dbQuests[MK47Quest]._id === "64e7b9bffd30422ed03dad38"
) {
const availableForFinish = dbQuests[MK47Quest].conditions.AvailableForFinish;
for (const condition of availableForFinish) {
if (condition.counter && condition.counter.conditions) {
for (const counterCondition of condition.counter.conditions) {
if (counterCondition.weapon) {
counterCondition.weapon.push(
"672e37d10b7a12e6a7a50b77",
"672e37d17f433cdb29072bc8"
);
}
}
}
}
}
}
this.logger.info("------------------------");
this.logger.info("Black Core Loaded");
} catch (error) {
this.logger.error(`Error loading BlackCore mod: ${error.message}`);
}
}
private cloneItem(itemToClone: string, blackCoreID: string): void {
if (!itemToClone || !blackCoreID) {
this.logger.error("Invalid parameters passed to cloneItem");
return;
}
if (!this.mydb.items[blackCoreID]?.enable) {
return;
}
if (!this.db.templates.items[itemToClone]) {
this.logger.error(`Template item ${itemToClone} not found`);
return;
}
if (this.mydb.items[blackCoreID].enable == true) {
let blackCoreItemOut = this.jsonUtil.clone(this.db.templates.items[itemToClone]);
blackCoreItemOut._id = blackCoreID;
blackCoreItemOut = this.compareAndReplace(blackCoreItemOut, this.mydb.items[blackCoreID]["items"]);
const bcCompatibilities: object = (typeof this.mydb.items[blackCoreID].bcCompatibilities == "undefined") ? {} : this.mydb.items[blackCoreID].bcCompatibilities;
const bcConflicts: Array<string> = (typeof this.mydb.items[blackCoreID].bcConflicts == "undefined") ? [] : this.mydb.items[blackCoreID].bcConflicts;
for (const modSlotName in bcCompatibilities) {
for (const slot of blackCoreItemOut._props.Slots) {
if (slot._name === modSlotName) for (const id of bcCompatibilities[modSlotName]) slot._props.filters[0].Filter.push(id);
}
}
blackCoreItemOut._props.ConflictingItems = blackCoreItemOut._props.ConflictingItems.concat(bcConflicts);
this.db.templates.items[blackCoreID] = blackCoreItemOut;
const handbookEntry: IHandbookEntry = {
"Id": blackCoreID,
"ParentId": this.mydb.items[blackCoreID]["handbook"]["ParentId"],
"Price": this.mydb.items[blackCoreID]["handbook"]["Price"]
};
this.db.templates.handbook.Items.push(handbookEntry);
}
}
private compareAndReplace(originalItem: any, attributesToChange: any): any {
for (const key in attributesToChange) {
if ((["boolean", "string", "number"].includes(typeof attributesToChange[key])) || Array.isArray(attributesToChange[key])) {
if (key in originalItem) originalItem[key] = attributesToChange[key];
else this.logger.error("Error finding the attribute: \"" + key + "\", default value is used instead.");
}
else originalItem[key] = this.compareAndReplace(originalItem[key], attributesToChange[key]);
}
return originalItem;
}
private addCompatibilitiesAndConflicts(itemClone: string, blackCoreID: string): void {
for (const item in this.db.templates.items) {
if (item in this.mydb.items) continue;
const slots = (typeof this.db.templates.items[item]._props.Slots === "undefined") ? [] : this.db.templates.items[item]._props.Slots;
const chambers = (typeof this.db.templates.items[item]._props.Chambers === "undefined") ? [] : this.db.templates.items[item]._props.Chambers;
const cartridges = (typeof this.db.templates.items[item]._props.Cartridges === "undefined") ? [] : this.db.templates.items[item]._props.Cartridges;
const combined = slots.concat(chambers, cartridges)
for (const entry of combined) {
for (const id of entry._props.filters[0].Filter) {
if (id === itemClone) entry._props.filters[0].Filter.push(blackCoreID);
}
}
const conflictingItems = (typeof this.db.templates.items[item]._props.ConflictingItems === "undefined") ? [] : this.db.templates.items[item]._props.ConflictingItems;
for (const conflictID of conflictingItems) if (conflictID === itemClone) conflictingItems.push(blackCoreID);
}
}
private addTraderAssort(trader: string): void {
if (!this.db.traders[trader]?.assort || !this.mydb.traders[trader]?.assort) {
this.logger.error(`Invalid trader assort data for trader: ${trader}`);
return;
}
for (const item in this.mydb.traders[trader].assort.items) {
this.db.traders[trader].assort.items.push(this.mydb.traders[trader].assort.items[item]);
}
for (const item in this.mydb.traders[trader].assort.barter_scheme) {
this.db.traders[trader].assort.barter_scheme[item] = this.mydb.traders[trader].assort.barter_scheme[item];
}
for (const item in this.mydb.traders[trader].assort.loyal_level_items) {
this.db.traders[trader].assort.loyal_level_items[item] = this.mydb.traders[trader].assort.loyal_level_items[item];
}
}
}
module.exports = { mod: new BlackCore() }
@@ -193,15 +193,15 @@ PmcWaveDistribution = 0.8
## Multiplies wave counts seen in the server's mapConfig.json by this number
# Setting type: Double
# Default value: 1.5
# Default value: 1
# Acceptable value range: From 0 to 10
ScavWaveQuantity = 1.5
ScavWaveQuantity = 0.5
## Multiplies wave counts seen in the server's mapConfig.json by this number
# Setting type: Double
# Default value: 1.5
# Default value: 1
# Acceptable value range: From 0 to 10
PmcWaveQuantity = 1.5
PmcWaveQuantity = 0.5
[3.Debug]
@@ -51,7 +51,7 @@ Gating level = 0
## Will reset when the game opens. You are supposed to use the gating increase/decrease keys to change the gating level, but you are free to change it manually if you want to make sure you are at a specific gating level.
# Setting type: Int32
# Default value: 0
Gating level = 0
Gating level = -2
1.Manual gating increase = KeypadPlus
+11 -8
View File
@@ -7,6 +7,7 @@
"tyfon-uifixes",
"MoreCheckmarksBackend",
"ExpandedTaskText",
"aMoxoPixel-Painter",
"acidphantasm-bosseshavelegamedals",
"acidphantasm-defaultfiremode",
"acidphantasm-refsptfriendlyquests",
@@ -17,6 +18,9 @@
"choccy-striker-1.0.5",
"flir-betterkeysng",
"redlaser42-Increase Climb Height",
"MoxoPixel-BlackCore",
"Additional Clothing USEC",
"Additional Clothing BEAR",
"WTT-LittleDrummerBoy",
"WTTArmoryAk5C",
"WTTArmoryHK417",
@@ -24,21 +28,20 @@
"WTTArmorySVD",
"choccy-rpg7-1.1.4",
"choccy-saa-1.0.7",
"raid_review__0.3.0",
"BRNVG_N-15Adapter",
"z_hacker228-makevalvssgreatagain",
"OpticRework-310",
"tyfon-weaponcustomizer",
"ArenaLockboxes-Delod-1.0.0",
"lacyway-mergeconsumables",
"acidphantasm-brightlasers",
"AUG_AttachmentPack",
"shibdib-shibsexpandedcrafts",
"zSolarint-SAIN-ServerMod",
"Skwizzy-LootingBots-ServerMod",
"acidphantasm-progressivebotsystem",
"DewardianDev-MOAR",
"inory-dynamicgoons",
"acidphantasm-progressivebotsystem",
"ArenaLockboxes-Delod-1.0.0",
"tyfon-weaponcustomizer",
"Additional Clothing BEAR",
"Additional Clothing USEC",
"BRNVG_N-15Adapter",
"OpticRework-310"
"raid_review__0.3.0"
]
}
+1 -1
View File
@@ -6,7 +6,7 @@ newestVersion=
category="1,"
nexusFileStatus=1
installationFile=DewardianDev-MOAR-2.6.7.zip
repository=Nexus
repository=
ignoredVersion=
comments=
notes=
@@ -5,7 +5,7 @@
"scavDifficulty": 0.4,
"scavWaveDistribution": 0.5,
"scavWaveQuantity": 1.5,
"scavWaveQuantity": 1,
"startingPmcs": false,
@@ -13,20 +13,20 @@
"pmcOpenZones": true,
"allOpenZones": false,
"pmcWaveDistribution": 0.8,
"pmcWaveQuantity": 1.5,
"pmcWaveDistribution": 0.7,
"pmcWaveQuantity": 1,
"zombiesEnabled": true,
"zombieWaveDistribution": 0.2,
"zombiesEnabled": false,
"zombieWaveDistribution": 0.5,
"zombieWaveQuantity": 1,
"zombieHealth": 0.5,
"zombieHealth": 1,
"maxBotCap": 25,
"maxBotPerZone": 5,
"moreScavGroups": false,
"morePmcGroups": false,
"pmcMaxGroupSize": 5,
"pmcMaxGroupSize": 4,
"scavMaxGroupSize": 4,
"snipersHaveFriends": false,
@@ -1,11 +1,11 @@
[General]
gameName=spt
modid=0
version=d2025.1.14.0
version=d2025.1.13.0
newestVersion=
category="1,"
nexusFileStatus=1
installationFile=SWAG-Donuts-v4.0.0RC4-SPT310x.7z
installationFile=DewardianDev-MOAR-2.6.7.zip
repository=Nexus
ignoredVersion=
comments=
@@ -15,7 +15,7 @@ url=
hasCustomURL=false
lastNexusQuery=
lastNexusUpdate=
nexusLastModified=2024-12-18T07:07:11Z
nexusLastModified=2024-12-16T06:46:30Z
nexusCategory=0
converted=false
validated=false
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2023 Kevin
Copyright (c) 2023 Dushaoan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,12 @@
{
"live-like": 25,
"more-scavs": 8,
"more-pmcs": 8,
"more-scavs-and-pmcs": 5,
"main-boss-roaming": 5,
"sniper-buddies": 4,
"boss-invasion": 2,
"rogue-invasion": 0,
"raider-invasion": 0,
"insanity": 0
}
@@ -0,0 +1,64 @@
{
"live-like": {},
"more-scavs": {
"moreScavGroups": true,
"scavMaxGroupSize": 5,
"scavWaveQuantity": 1.2
},
"more-pmcs": {
"scavWaveDistribution": 0.4,
"morePmcGroups": true,
"pmcMaxGroupSize": 5,
"pmcWaveQuantity": 1.2
},
"more-scavs-and-pmcs": {
"scavWaveDistribution": 0.4,
"moreScavGroups": true,
"scavMaxGroupSize": 5,
"morePmcGroups": true,
"pmcMaxGroupSize": 5,
"scavWaveQuantity": 1.2,
"pmcWaveQuantity": 1.2,
"mainBossChanceBuff": 25
},
"boss-invasion": {
"bossOpenZones": true,
"bossInvasion": true,
"bossInvasionSpawnChance": 10,
"mainBossChanceBuff": 25,
"gradualBossInvasion": true
},
"rogue-invasion": {
"randomRaiderGroup": true,
"randomRaiderGroupChance": 50
},
"raider-invasion": {
"randomRaiderGroup": true,
"randomRaiderGroupChance": 50
},
"insanity": {
"scavWaveDistribution": 0.4,
"scavWaveQuantity": 1.3,
"pmcWaveQuantity": 1.3,
"moreScavGroups": true,
"morePmcGroups": true,
"pmcMaxGroupSize": 6,
"scavMaxGroupSize": 6,
"snipersHaveFriends": true,
"bossOpenZones": true,
"randomRaiderGroup": true,
"randomRaiderGroupChance": 50,
"randomRogueGroup": true,
"randomRogueGroupChance": 50,
"mainBossChanceBuff": 50,
"bossInvasion": true,
"bossInvasionSpawnChance": 10
},
"main-boss-roaming": {
"bossOpenZones": true,
"mainBossChanceBuff": 35
},
"sniper-buddies": {
"snipersHaveFriends": true
}
}
@@ -0,0 +1,63 @@
{
"ADD_THESE_TO_A_MAP_TO_OVERRIDE_OR_ADD_A_BOSS_TO_A_MAP": {
"BOSS_NAME_EXAMPLE": "CHANCE_OF_SPAWNING_PERCENT",
"sectantPriest": 0,
"arenaFighterEvent": 0,
"bossBoarSniper": 0,
"pmcBot": 0,
"bossZryachiy": 0,
"exUsec": 0,
"crazyAssaultEvent": 0,
"peacemaker": 0,
"bossKojaniy": 0,
"bossGluhar": 0,
"bossSanitar": 0,
"bossKilla": 0,
"bossTagilla": 0,
"bossKnight": 0,
"bossBoar": 0,
"bossKolontay": 0,
"bossPartisan": 0,
"bossBully": 0
},
"customs": {
"bossKnight": 30,
"bossPartisan": 30,
"bossBully": 30
},
"factoryDay": {
"bossTagilla": 30
},
"factoryNight": {
"bossTagilla": 30
},
"interchange": {
"bossKilla": 30
},
"laboratory": {},
"lighthouse": {
"bossKnight": 30,
"bossPartisan": 30
},
"rezervbase": {
"bossGluhar": 30
},
"shoreline": {
"bossKnight": 30,
"bossPartisan": 30,
"bossSanitar": 30
},
"tarkovstreets": {
"bossBoar": 30,
"bossKolontay": 30
},
"woods": {
"bossKojaniy": 30,
"bossKnight": 30,
"bossPartisan": 30
},
"gzLow": {},
"gzHigh": {
"bossKolontay": 30
}
}
@@ -0,0 +1,50 @@
{
"enableBotSpawning": true,
"pmcDifficulty": 0.6,
"scavDifficulty": 0.4,
"scavWaveDistribution": 0.5,
"scavWaveQuantity": 1.0,
"startingPmcs": false,
"playerOpenZones": false,
"pmcOpenZones": true,
"allOpenZones": false,
"pmcWaveDistribution": 0.8,
"pmcWaveQuantity": 1.0,
"zombiesEnabled": true,
"zombieWaveDistribution": 0.2,
"zombieWaveQuantity": 1,
"zombieHealth": 0.5,
"maxBotCap": 25,
"maxBotPerZone": 5,
"moreScavGroups": false,
"morePmcGroups": false,
"pmcMaxGroupSize": 5,
"scavMaxGroupSize": 4,
"snipersHaveFriends": false,
"bossOpenZones": false,
"randomRaiderGroup": false,
"randomRaiderGroupChance": 10,
"randomRogueGroup": false,
"randomRogueGroupChance": 10,
"disableBosses": false,
"mainBossChanceBuff": 0,
"bossInvasion": false,
"bossInvasionSpawnChance": 5,
"gradualBossInvasion": true,
"debug": false
}
@@ -0,0 +1,110 @@
{
"customs": {
"spawnMinDistance": 30,
"pmcWaveCount": 14,
"scavWaveCount": 21,
"zombieWaveCount": 9,
"scavHotZones": [
"ZoneDormitory"
],
"pmcHotZones": [
"ZoneDormitory"
]
},
"factoryDay": {
"spawnMinDistance": 20,
"maxBotCapOverride": 12,
"maxBotPerZoneOverride": 10,
"pmcWaveCount": 10,
"scavWaveCount": 10,
"zombieWaveCount": 6
},
"factoryNight": {
"spawnMinDistance": 20,
"maxBotCapOverride": 12,
"maxBotPerZoneOverride": 10,
"pmcWaveCount": 10,
"scavWaveCount": 10,
"zombieWaveCount": 6
},
"interchange": {
"spawnMinDistance": 40,
"pmcWaveCount": 16,
"scavWaveCount": 32,
"zombieWaveCount": 12,
"scavHotZones": [
"ZoneCenterBot",
"ZoneCenter"
]
},
"laboratory": {
"spawnMinDistance": 20,
"pmcWaveCount": 12,
"scavWaveCount": 0,
"zombieWaveCount": 12
},
"lighthouse": {
"spawnMinDistance": 40,
"pmcWaveCount": 14,
"scavWaveCount": 22,
"zombieWaveCount": 10,
"scavHotZones": [
"Zone_LongRoad",
"Zone_LongRoad"
]
},
"rezervbase": {
"spawnMinDistance": 40,
"pmcWaveCount": 14,
"scavWaveCount": 26,
"zombieWaveCount": 9,
"scavHotZones": [
"ZoneRailStrorage"
],
"pmcHotZones": [
"ZoneBarrack"
]
},
"shoreline": {
"spawnMinDistance": 40,
"pmcWaveCount": 16,
"scavWaveCount": 32,
"zombieWaveCount": 12,
"scavHotZones": [
"ZoneSanatorium1"
],
"pmcHotZones": [
"ZoneSanatorium2"
]
},
"tarkovstreets": {
"spawnMinDistance": 40,
"pmcWaveCount": 16,
"scavWaveCount": 28,
"zombieWaveCount": 13
},
"woods": {
"spawnMinDistance": 40,
"pmcWaveCount": 16,
"scavWaveCount": 28,
"zombieWaveCount": 10,
"scavHotZones": [
"ZoneWoodCutter"
],
"pmcHotZones": [
"ZoneWoodCutter"
]
},
"gzLow": {
"spawnMinDistance": 30,
"pmcWaveCount": 12,
"scavWaveCount": 18,
"zombieWaveCount": 9
},
"gzHigh": {
"spawnMinDistance": 30,
"pmcWaveCount": 12,
"scavWaveCount": 18,
"zombieWaveCount": 9
}
}
@@ -0,0 +1,25 @@
{
"name": "MOAR",
"version": "2.6.7",
"main": "src/mod.js",
"license": "MIT",
"author": "DewardianDev",
"sptVersion": "^3.10.x",
"scripts": {
"setup": "npm i",
"build": "node ./packageBuild.ts"
},
"devDependencies": {
"@semantic-release/git": "^10.0.1",
"@types/node": "16.18.10",
"@typescript-eslint/eslint-plugin": "5.46.1",
"@typescript-eslint/parser": "5.46.1",
"bestzip": "2.2.1",
"eslint": "8.30.0",
"fs-extra": "11.1.0",
"glob": "8.0.3",
"semantic-release": "^24.2.0",
"tsyringe": "4.7.0",
"typescript": "4.9.4"
}
}
@@ -0,0 +1,11 @@
import config from "../config/config.json";
import { ILocationBase } from "@spt/models/eft/common/ILocationBase";
export class globalValues {
public static baseConfig: typeof config = undefined;
public static overrideConfig: Partial<typeof config> = undefined;
public static locationsBase: ILocationBase[] = undefined;
public static currentPreset: string = "";
public static forcedPreset: string = "custom";
public static addedMapZones: Record<string, string[]> = {};
}
@@ -0,0 +1,168 @@
import { DependencyContainer } from "tsyringe";
import { buildWaves } from "../Spawning/Spawning";
import { StaticRouterModService } from "@spt/services/mod/staticRouter/StaticRouterModService";
// import { DynamicRouterModService } from "@spt/services/mod/dynamicRouter/DynamicRouterModService";
import { globalValues } from "../GlobalValues";
import { kebabToTitle } from "../utils";
import PresetWeightingsConfig from "../../config/PresetWeightings.json";
export const setupRoutes = (container: DependencyContainer) => {
const staticRouterModService = container.resolve<StaticRouterModService>(
"StaticRouterModService"
);
// const dynamicRouterModService = container.resolve<DynamicRouterModService>(
// "DynamicRouterModService"
// );
// Make buildwaves run on game end
staticRouterModService.registerStaticRouter(
`moarUpdater`,
[
{
url: "/client/match/local/end",
action: async (_url, info, sessionId, output) => {
buildWaves(container);
return output;
},
},
],
"moarUpdater"
);
staticRouterModService.registerStaticRouter(
`moarGetCurrentPreset`,
[
{
url: "/moar/currentPreset",
action: async () => {
return globalValues.forcedPreset || "random";
},
},
],
"moarGetCurrentPreset"
);
staticRouterModService.registerStaticRouter(
`moarGetAnnouncePreset`,
[
{
url: "/moar/announcePreset",
action: async () => {
if (globalValues.forcedPreset?.toLowerCase() === "random") {
return globalValues.currentPreset;
}
return globalValues.forcedPreset || globalValues.currentPreset;
},
},
],
"moarGetAnnouncePreset"
);
staticRouterModService.registerStaticRouter(
`getDefaultConfig`,
[
{
url: "/moar/getDefaultConfig",
action: async () => {
return JSON.stringify(globalValues.baseConfig);
},
},
],
"getDefaultConfig"
);
staticRouterModService.registerStaticRouter(
`getServerConfigWithOverrides`,
[
{
url: "/moar/getServerConfigWithOverrides",
action: async () => {
return JSON.stringify({
...(globalValues.baseConfig || {}),
...(globalValues.overrideConfig || {}),
});
},
},
],
"getServerConfigWithOverrides"
);
staticRouterModService.registerStaticRouter(
`getServerConfigWithOverrides`,
[
{
url: "/moar/getServerConfigWithOverrides",
action: async () => {
return JSON.stringify({
...globalValues.baseConfig,
...globalValues.overrideConfig,
});
},
},
],
"getServerConfigWithOverrides"
);
staticRouterModService.registerStaticRouter(
`moarGetPresetsList`,
[
{
url: "/moar/getPresets",
action: async () => {
let result = [
...Object.keys(PresetWeightingsConfig).map((preset) => ({
Name: kebabToTitle(preset),
Label: preset,
})),
{ Name: "Random", Label: "random" },
{ Name: "Custom", Label: "custom" },
];
return JSON.stringify({ data: result });
},
},
],
"moarGetPresetsList"
);
staticRouterModService.registerStaticRouter(
"setOverrideConfig",
[
{
url: "/moar/setOverrideConfig",
action: async (
url: string,
overrideConfig: typeof globalValues.overrideConfig = {},
sessionID,
output
) => {
globalValues.overrideConfig = overrideConfig;
buildWaves(container);
return "Success";
},
},
],
"setOverrideConfig"
);
staticRouterModService.registerStaticRouter(
"moarSetPreset",
[
{
url: "/moar/setPreset",
action: async (url: string, { Preset }, sessionID, output) => {
globalValues.forcedPreset = Preset;
buildWaves(container);
return `Current Preset: ${kebabToTitle(
globalValues.forcedPreset || "Random"
)}`;
},
},
],
"moarSetPreset"
);
};
@@ -0,0 +1,158 @@
import { IBotConfig } from "@spt/models/spt/config/IBotConfig.d";
import { IPmcConfig } from "@spt/models/spt/config/IPmcConfig.d";
import { DatabaseServer } from "@spt/servers/DatabaseServer";
import _config from "../../config/config.json";
import _mapConfig from "../../config/mapConfig.json";
import { ConfigServer } from "@spt/servers/ConfigServer";
import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
import { DependencyContainer } from "tsyringe";
import { globalValues } from "../GlobalValues";
import {
cloneDeep,
getRandomPresetOrCurrentlySelectedPreset,
saveToFile,
} from "../utils";
import { ILocationConfig } from "@spt/models/spt/config/ILocationConfig.d";
import { originalMapList } from "./constants";
import { buildBossWaves } from "./buildBossWaves";
import buildZombieWaves from "./buildZombieWaves";
import buildScavMarksmanWaves from "./buildScavMarksmanWaves";
import buildPmcs from "./buildPmcs";
import { setEscapeTimeOverrides } from "./utils";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import updateSpawnLocations from "./updateSpawnLocations";
export const buildWaves = (container: DependencyContainer) => {
const configServer = container.resolve<ConfigServer>("ConfigServer");
const Logger = container.resolve<ILogger>("WinstonLogger");
const pmcConfig = configServer.getConfig<IPmcConfig>(ConfigTypes.PMC);
const botConfig = configServer.getConfig<IBotConfig>(ConfigTypes.BOT);
const locationConfig = configServer.getConfig<ILocationConfig>(
ConfigTypes.LOCATION
);
locationConfig.rogueLighthouseSpawnTimeSettings.waitTimeSeconds = 60;
locationConfig.enableBotTypeLimits = false;
locationConfig.fitLootIntoContainerAttempts = 1; // Move to ALP
locationConfig.addCustomBotWavesToMaps = false;
locationConfig.customWaves = { boss: {}, normal: {} };
const databaseServer = container.resolve<DatabaseServer>("DatabaseServer");
const { locations, bots, globals } = databaseServer.getTables();
let config = cloneDeep(globalValues.baseConfig) as typeof _config;
const preset = getRandomPresetOrCurrentlySelectedPreset();
Object.keys(globalValues.overrideConfig).forEach((key) => {
if (config[key] !== globalValues.overrideConfig[key]) {
config.debug &&
console.log(
`[MOAR] overrideConfig ${key} changed from ${config[key]} to ${globalValues.overrideConfig[key]}`
);
config[key] = globalValues.overrideConfig[key];
}
});
// Set from preset if preset above is not empty
Object.keys(preset).forEach((key) => {
if (config[key] !== preset[key]) {
config.debug &&
console.log(
`[MOAR] preset ${globalValues.currentPreset}: ${key} changed from ${config[key]} to ${preset[key]}`
);
config[key] = preset[key];
}
});
// config.debug &&
console.log(
globalValues.forcedPreset === "custom"
? "custom"
: globalValues.currentPreset
);
const {
bigmap: customs,
factory4_day: factoryDay,
factory4_night: factoryNight,
interchange,
laboratory,
lighthouse,
rezervbase,
shoreline,
tarkovstreets,
woods,
sandbox: gzLow,
sandbox_high: gzHigh,
} = locations;
let locationList = [
customs,
factoryDay,
factoryNight,
interchange,
laboratory,
lighthouse,
rezervbase,
shoreline,
tarkovstreets,
woods,
gzLow,
gzHigh,
];
// This resets all locations to original state
if (!globalValues.locationsBase) {
globalValues.locationsBase = locationList.map(({ base }) =>
cloneDeep(base)
);
} else {
locationList = locationList.map((item, key) => ({
...item,
base: cloneDeep(globalValues.locationsBase[key]),
}));
}
pmcConfig.convertIntoPmcChance = {
default: {
assault: { min: 0, max: 0 },
cursedassault: { min: 0, max: 0 },
pmcbot: { min: 0, max: 0 },
exusec: { min: 0, max: 0 },
arenafighter: { min: 0, max: 0 },
arenafighterevent: { min: 0, max: 0 },
crazyassaultevent: { min: 0, max: 0 },
},
factory4_day: { assault: { min: 0, max: 0 } },
laboratory: { pmcbot: { min: 0, max: 0 } },
rezervbase: { pmcbot: { min: 0, max: 0 } },
};
updateSpawnLocations(locationList, config);
setEscapeTimeOverrides(locationList, _mapConfig, Logger, config);
// Make main waves
buildScavMarksmanWaves(config, locationList, botConfig);
// BOSS RELATED STUFF!
buildBossWaves(config, locationList);
//Zombies
if (config.zombiesEnabled) {
buildZombieWaves(config, locationList, bots);
}
buildPmcs(config, locationList);
originalMapList.forEach((name, index) => {
if (!locations[name]) {
console.log("[MOAR] OH CRAP we have a problem!", name);
} else {
locations[name] = locationList[index];
}
});
};
@@ -0,0 +1,277 @@
import { ILocation } from "@spt/models/eft/common/ILocation";
import _config from "../../config/config.json";
import bossConfig from "../../config/bossConfig.json";
import mapConfig from "../../config/mapConfig.json";
import {
bossesToRemoveFromPool,
configLocations,
mainBossNameList,
originalMapList,
} from "./constants";
import { buildBossBasedWave, shuffle } from "./utils";
import { IBossLocationSpawn } from "@spt/models/eft/common/ILocationBase";
import { cloneDeep } from "../utils";
export function buildBossWaves(
config: typeof _config,
locationList: ILocation[]
) {
let {
randomRaiderGroup,
randomRaiderGroupChance,
randomRogueGroup,
randomRogueGroupChance,
mainBossChanceBuff,
bossInvasion,
bossInvasionSpawnChance,
disableBosses,
bossOpenZones,
gradualBossInvasion,
} = config;
const bossList = mainBossNameList.filter(
(bossName) => !["bossKnight"].includes(bossName)
);
const allBosses: Record<string, IBossLocationSpawn> = {};
for (const key in locationList) {
locationList[key].base.BossLocationSpawn.forEach((boss) => {
if (!allBosses[boss.BossName]) {
allBosses[boss.BossName] = boss;
}
});
}
// CreateBossList
const bosses: Record<string, IBossLocationSpawn> = {};
for (let indx = 0; indx < locationList.length; indx++) {
// Disable Bosses
if (disableBosses && !!locationList[indx].base?.BossLocationSpawn) {
locationList[indx].base.BossLocationSpawn = [];
} else {
//Remove all other spawns from pool now that we have the spawns zone list
locationList[indx].base.BossLocationSpawn = locationList[
indx
].base.BossLocationSpawn.filter(
(boss) => !bossesToRemoveFromPool.has(boss.BossName)
);
const location = locationList[indx];
const defaultBossSettings =
mapConfig?.[configLocations[indx]]?.defaultBossSettings;
// Sets bosses spawn chance from settings
if (
location?.base?.BossLocationSpawn &&
defaultBossSettings &&
Object.keys(defaultBossSettings)?.length
) {
const filteredBossList = Object.keys(defaultBossSettings).filter(
(name) => defaultBossSettings[name]?.BossChance !== undefined
);
if (filteredBossList?.length) {
filteredBossList.forEach((bossName) => {
location.base.BossLocationSpawn =
location.base.BossLocationSpawn.map((boss) => ({
...boss,
...(boss.BossName === bossName
? { BossChance: defaultBossSettings[bossName].BossChance }
: {}),
}));
});
}
}
if (randomRaiderGroup) {
const raiderWave = buildBossBasedWave(
randomRaiderGroupChance,
"1,2,2,2,3",
"pmcBot",
"pmcBot",
"",
locationList[indx].base.EscapeTimeLimit
);
location.base.BossLocationSpawn.push(raiderWave);
}
if (randomRogueGroup) {
const rogueWave = buildBossBasedWave(
randomRogueGroupChance,
"1,2,2,2,3",
"exUsec",
"exUsec",
"",
locationList[indx].base.EscapeTimeLimit
);
location.base.BossLocationSpawn.push(rogueWave);
}
//Add each boss from each map to bosses object
const filteredBosses = location.base.BossLocationSpawn?.filter(
({ BossName }) => mainBossNameList.includes(BossName)
);
if (filteredBosses.length) {
for (let index = 0; index < filteredBosses.length; index++) {
const boss = filteredBosses[index];
if (
!bosses[boss.BossName] ||
(bosses[boss.BossName] &&
bosses[boss.BossName].BossChance < boss.BossChance)
) {
bosses[boss.BossName] = { ...boss };
}
}
}
}
}
if (!disableBosses) {
// Make boss Invasion
if (bossInvasion) {
if (bossInvasionSpawnChance) {
bossList.forEach((bossName) => {
if (bosses[bossName])
bosses[bossName].BossChance = bossInvasionSpawnChance;
});
}
for (let key = 0; key < locationList.length; key++) {
//Gather bosses to avoid duplicating.
const duplicateBosses = [
...locationList[key].base.BossLocationSpawn.filter(
({ BossName, BossZone }) => bossList.includes(BossName)
).map(({ BossName }) => BossName),
"bossKnight", // So knight doesn't invade
];
//Build bosses to add
const bossesToAdd = shuffle<IBossLocationSpawn[]>(Object.values(bosses))
.filter(({ BossName }) => !duplicateBosses.includes(BossName))
.map((boss, j) => ({
...boss,
BossZone: "",
BossEscortAmount:
boss.BossEscortAmount === "0" ? boss.BossEscortAmount : "1",
...(gradualBossInvasion ? { Time: j * 20 + 1 } : {}),
}));
// UpdateBosses
locationList[key].base.BossLocationSpawn = [
...locationList[key].base.BossLocationSpawn,
...bossesToAdd,
];
}
}
let hasChangedBossSpawns = false;
// console.log(Object.keys(allBosses));
configLocations.forEach((mapName, index) => {
const bossLocationSpawn = locationList[index].base.BossLocationSpawn;
const mapBossConfig: Record<string, number> = cloneDeep(
bossConfig[mapName] || {}
);
// if (Object.keys(mapBossConfig).length === 0) console.log(name, "empty");
const adjusted = new Set<string>([]);
bossLocationSpawn.forEach(({ BossName, BossChance }, bossIndex) => {
if (typeof mapBossConfig[BossName] === "number") {
if (BossChance !== mapBossConfig[BossName]) {
if (!hasChangedBossSpawns) {
console.log(
`\n[MOAR]: --- Adjusting default boss spawn rates --- `
);
hasChangedBossSpawns = true;
}
console.log(
`[MOAR]: ${mapName} ${BossName}: ${locationList[index].base.BossLocationSpawn[bossIndex].BossChance} => ${mapBossConfig[BossName]}`
);
locationList[index].base.BossLocationSpawn[bossIndex].BossChance =
mapBossConfig[BossName];
}
adjusted.add(BossName);
}
});
const bossesToAdd = Object.keys(mapBossConfig)
.filter(
(adjustName) => !adjusted.has(adjustName) && !!allBosses[adjustName]
)
.map((bossName) => {
`[MOAR]: Adding non-default boss ${bossName} to ${originalMapList[index]}`;
const newBoss: IBossLocationSpawn = cloneDeep(
allBosses[bossName] || {}
);
newBoss.BossChance = mapBossConfig[bossName];
// console.log(
// "Adding boss",
// bossName,
// "to ",
// originalMapList[index],
// "spawn chance =>",
// mapBossConfig[bossName]
// );
return newBoss;
});
// console.log(bossesToAdd);
if (bossOpenZones || mainBossChanceBuff) {
locationList[index].base?.BossLocationSpawn?.forEach((boss, key) => {
if (bossList.includes(boss.BossName)) {
if (bossOpenZones) {
locationList[index].base.BossLocationSpawn[key] = {
...locationList[index].base.BossLocationSpawn[key],
BossZone: "",
};
}
if (!!boss.BossChance && mainBossChanceBuff > 0) {
locationList[index].base.BossLocationSpawn[key] = {
...locationList[index].base.BossLocationSpawn[key],
BossChance:
boss.BossChance + mainBossChanceBuff > 100
? 100
: Math.round(boss.BossChance + mainBossChanceBuff),
};
}
}
});
}
locationList[index].base.BossLocationSpawn = [
...locationList[index].base.BossLocationSpawn,
...bossesToAdd,
];
bossesToAdd.length &&
console.log(
`[MOAR] Adding the following bosses to map ${
configLocations[index]
}: ${bossesToAdd.map(({ BossName }) => BossName)}`
);
// console.log(locationList[index].base.BossLocationSpawn.length);
// Apply the percentages on all bosses, cull those that won't spawn, make all bosses 100 chance that remain.
locationList[index].base.BossLocationSpawn = locationList[
index
].base.BossLocationSpawn.filter(({ BossChance, BossName }, bossIndex) => {
if (BossChance < 100 && BossChance / 100 < Math.random()) {
return false;
}
return true;
}).map((boss) => ({ ...boss, ...{ BossChance: 100 } }));
// if (mapName === "customs")
// console.log(mapName, locationList[index].base.BossLocationSpawn);
});
if (hasChangedBossSpawns) {
console.log(
`[MOAR]: --- Adjusting default boss spawn rates complete --- \n`
);
}
}
}
@@ -0,0 +1,88 @@
import { ILocation } from "@spt/models/eft/common/ILocation";
import _config from "../../config/config.json";
import mapConfig from "../../config/mapConfig.json";
import {
bossesToRemoveFromPool,
defaultEscapeTimes,
defaultHostility,
} from "./constants";
import { buildPmcWaves, MapSettings, shuffle } from "./utils";
import { saveToFile } from "../utils";
export default function buildPmcs(
config: typeof _config,
locationList: ILocation[]
) {
for (let index = 0; index < locationList.length; index++) {
const mapSettingsList = Object.keys(mapConfig) as Array<
keyof typeof mapConfig
>;
const map = mapSettingsList[index];
locationList[index].base.BotLocationModifier.AdditionalHostilitySettings =
defaultHostility;
const { pmcHotZones = [] } = (mapConfig?.[map] as MapSettings) || {};
let pmcZones = shuffle<string[]>([
...new Set(
[...locationList[index].base.SpawnPointParams]
.filter(
({ Categories, BotZoneName }) =>
!!BotZoneName &&
!BotZoneName.includes("snipe") &&
(Categories.includes("Player") || Categories.includes("All")) &&
!BotZoneName.includes("BotZoneGate")
)
.map(({ BotZoneName, ...rest }) => {
return BotZoneName;
})
),
]);
// Make labs have only named zones
if (map === "laboratory") {
pmcZones = new Array(10).fill(pmcZones).flat(1);
}
const { pmcWaveCount } = mapConfig[map];
const escapeTimeLimitRatio = Math.round(
locationList[index].base.EscapeTimeLimit / defaultEscapeTimes[map]
);
const totalWaves = Math.round(
pmcWaveCount * config.pmcWaveQuantity * escapeTimeLimitRatio
);
const numberOfZoneless = totalWaves - pmcZones.length;
if (numberOfZoneless > 0) {
const addEmpty = new Array(numberOfZoneless).fill("");
pmcZones = shuffle<string[]>([...pmcZones, ...addEmpty]);
}
if (config.debug) {
console.log(`${map} PMC count ${totalWaves} \n`);
escapeTimeLimitRatio !== 1 &&
console.log(
`${map} PMC wave count changed from ${pmcWaveCount} to ${totalWaves} due to escapeTimeLimit adjustment`
);
}
const timeLimit = locationList[index].base.EscapeTimeLimit * 60;
const waves = buildPmcWaves(
totalWaves,
timeLimit,
config,
pmcZones,
pmcHotZones
);
locationList[index].base.BossLocationSpawn = [
...waves,
...locationList[index].base.BossLocationSpawn,
];
}
}
@@ -0,0 +1,218 @@
import { ILocation } from "@spt/models/eft/common/ILocation";
import _config from "../../config/config.json";
import mapConfig from "../../config/mapConfig.json";
import {
configLocations,
defaultEscapeTimes,
defaultHostility,
originalMapList,
} from "./constants";
import { MapSettings, shuffle, waveBuilder } from "./utils";
import { IWave, WildSpawnType } from "@spt/models/eft/common/ILocationBase";
import { IBotConfig } from "@spt/models/spt/config/IBotConfig";
import { saveToFile } from "../utils";
export default function buildScavMarksmanWaves(
config: typeof _config,
locationList: ILocation[],
botConfig: IBotConfig
) {
let {
debug,
maxBotCap,
scavWaveQuantity,
scavWaveDistribution,
snipersHaveFriends,
maxBotPerZone,
scavMaxGroupSize,
scavDifficulty,
moreScavGroups,
} = config;
for (let index = 0; index < locationList.length; index++) {
const mapSettingsList = Object.keys(mapConfig) as Array<
keyof typeof mapConfig
>;
const map = mapSettingsList[index];
locationList[index].base = {
...locationList[index].base,
...{
NewSpawn: false,
OcculsionCullingEnabled: true,
OfflineNewSpawn: false,
OfflineOldSpawn: true,
OldSpawn: true,
BotSpawnCountStep: 0,
},
};
locationList[index].base.NonWaveGroupScenario.Enabled = false;
locationList[index].base["BotStartPlayer"] = 0;
if (
locationList[index].base.BotStop <
locationList[index].base.EscapeTimeLimit * 60
) {
locationList[index].base.BotStop =
locationList[index].base.EscapeTimeLimit * 60;
}
const {
maxBotPerZoneOverride,
maxBotCapOverride,
EscapeTimeLimit,
scavHotZones,
} = (mapConfig?.[map] as MapSettings) || {};
// Set per map EscapeTimeLimit
if (EscapeTimeLimit) {
locationList[index].base.EscapeTimeLimit = EscapeTimeLimit;
locationList[index].base.exit_access_time = EscapeTimeLimit + 1;
}
// Set default or per map maxBotCap
if (maxBotCapOverride || maxBotCap) {
const capToSet = maxBotCapOverride || maxBotCap;
// console.log(map, capToSet, maxBotCapOverride, maxBotCap);
locationList[index].base.BotMax = capToSet;
locationList[index].base.BotMaxPvE = capToSet;
botConfig.maxBotCap[originalMapList[index]] = capToSet;
}
// Adjust botZone quantity
if (maxBotPerZoneOverride || maxBotPerZone) {
const BotPerZone = maxBotPerZoneOverride || maxBotPerZone;
// console.log(map, BotPerZone, maxBotPerZoneOverride, maxBotPerZone);
locationList[index].base.MaxBotPerZone = BotPerZone;
}
const sniperLocations = new Set(
[...locationList[index].base.SpawnPointParams]
.filter(
({ Categories, DelayToCanSpawnSec, BotZoneName, Sides }) =>
!Categories.includes("Boss") &&
Sides[0] === "Savage" &&
(BotZoneName?.toLowerCase().includes("snipe") ||
DelayToCanSpawnSec > 40)
)
.map(({ BotZoneName }) => BotZoneName || "")
);
if (sniperLocations.size) {
locationList[index].base.MinMaxBots = [
{
WildSpawnType: "marksman",
max: sniperLocations.size * 5,
min: sniperLocations.size,
},
];
}
let scavZones = shuffle<string[]>([
...new Set(
[...locationList[index].base.SpawnPointParams]
.filter(
({ Categories, Sides, BotZoneName }) =>
!!BotZoneName &&
Categories.includes("Bot") &&
(Sides.includes("Savage") || Sides.includes("All"))
)
.map(({ BotZoneName }) => BotZoneName)
.filter((name) => !sniperLocations.has(name))
),
]);
const { scavWaveCount } = mapConfig[map];
const escapeTimeLimitRatio = Math.round(
locationList[index].base.EscapeTimeLimit / defaultEscapeTimes[map]
);
// Scavs
const scavTotalWaveCount = Math.round(
scavWaveCount * scavWaveQuantity * escapeTimeLimitRatio
);
const numberOfZoneless = scavTotalWaveCount - scavZones.length;
// console.log(numberOfZoneless);
if (numberOfZoneless > 0) {
const addEmpty = new Array(numberOfZoneless).fill("");
scavZones = shuffle<string[]>([...scavZones, ...addEmpty]);
}
// console.log(scavZones);
config.debug &&
escapeTimeLimitRatio !== 1 &&
console.log(
`${map} Scav wave count changed from ${scavWaveCount} to ${scavTotalWaveCount} due to escapeTimeLimit adjustment`
);
const timeLimit = locationList[index].base.EscapeTimeLimit * 60;
let snipers = waveBuilder(
sniperLocations.size,
Math.round(timeLimit / 4),
0.5,
WildSpawnType.MARKSMAN,
0.7,
false,
2,
[],
shuffle([...sniperLocations]),
80,
true,
true
);
if (snipersHaveFriends)
snipers = snipers.map((wave) => ({
...wave,
...(snipersHaveFriends && wave.slots_max < 2
? { slots_min: 1, slots_max: 2 }
: {}),
}));
const scavWaves = waveBuilder(
scavTotalWaveCount,
timeLimit,
scavWaveDistribution,
WildSpawnType.ASSAULT,
scavDifficulty,
false,
scavMaxGroupSize,
map === "gzHigh" ? [] : scavZones,
scavHotZones,
0,
false,
!!moreScavGroups
);
if (debug) {
let totalscav = 0;
scavWaves.forEach(({ slots_max }) => (totalscav += slots_max));
console.log(configLocations[index]);
console.log(
"Scavs:",
totalscav,
"configVal",
Math.round((totalscav / scavWaveCount) * 100) / 100,
"configWaveCount",
scavWaveCount,
"waveCount",
scavWaves.length,
"\n"
);
}
// const finalSniperWaves = snipers?.map(({ ...rest }, snipKey) => ({
// ...rest,
// number: snipKey,
// time_min: snipKey * 120,
// time_max: snipKey * 120 + 120,
// }));
// if (map === "customs") saveToFile({ scavWaves }, "scavWaves.json");
locationList[index].base.waves = [...snipers, ...scavWaves]
.sort(({ time_min: a }, { time_min: b }) => a - b)
.map((wave, i) => ({ ...wave, number: i + 1 }));
}
}
@@ -0,0 +1,80 @@
import { ILocation } from "@spt/models/eft/common/ILocation";
import _config from "../../config/config.json";
import mapConfig from "../../config/mapConfig.json";
import { configLocations, defaultEscapeTimes } from "./constants";
import {
buildZombie,
getHealthBodyPartsByPercentage,
zombieTypes,
} from "./utils";
import { IBots } from "@spt/models/spt/bots/IBots";
export default function buildZombieWaves(
config: typeof _config,
locationList: ILocation[],
bots: IBots
) {
let { debug, zombieWaveDistribution, zombieWaveQuantity, zombieHealth } =
config;
const zombieBodyParts = getHealthBodyPartsByPercentage(zombieHealth);
zombieTypes.forEach((type) => {
bots.types?.[type]?.health?.BodyParts?.forEach((_, index) => {
bots.types[type].health.BodyParts[index] = zombieBodyParts;
});
});
for (let indx = 0; indx < locationList.length; indx++) {
const location = locationList[indx].base;
const mapSettingsList = Object.keys(mapConfig) as Array<
keyof typeof mapConfig
>;
const map = mapSettingsList[indx];
const { zombieWaveCount } = mapConfig?.[configLocations[indx]];
// if (location.Events?.Halloween2024?.MaxCrowdAttackSpawnLimit)
// location.Events.Halloween2024.MaxCrowdAttackSpawnLimit = 100;
// if (location.Events?.Halloween2024?.CrowdCooldownPerPlayerSec)
// location.Events.Halloween2024.CrowdCooldownPerPlayerSec = 60;
// if (location.Events?.Halloween2024?.CrowdCooldownPerPlayerSec)
// location.Events.Halloween2024.CrowdsLimit = 10;
// if (location.Events?.Halloween2024?.CrowdAttackSpawnParams)
// location.Events.Halloween2024.CrowdAttackSpawnParams = [];
if (!zombieWaveCount) return;
const escapeTimeLimitRatio = Math.round(
locationList[indx].base.EscapeTimeLimit / defaultEscapeTimes[map]
);
const zombieTotalWaveCount = Math.round(
zombieWaveCount * zombieWaveQuantity * escapeTimeLimitRatio
);
config.debug &&
escapeTimeLimitRatio !== 1 &&
console.log(
`${map} Zombie wave count changed from ${zombieWaveCount} to ${zombieTotalWaveCount} due to escapeTimeLimit adjustment`
);
const zombieWaves = buildZombie(
zombieTotalWaveCount,
location.EscapeTimeLimit,
zombieWaveDistribution,
9999
);
debug &&
console.log(
configLocations[indx],
" generated ",
zombieWaves.length,
"Zombies"
);
location.BossLocationSpawn.push(...zombieWaves);
// console.log(zombieWaves[0], zombieWaves[7]);
}
}
@@ -0,0 +1,204 @@
export const defaultHostility = [
{
AlwaysEnemies: [
"bossTest",
"followerTest",
"bossKilla",
"bossKojaniy",
"followerKojaniy",
"cursedAssault",
"bossGluhar",
"followerGluharAssault",
"followerGluharSecurity",
"followerGluharScout",
"followerGluharSnipe",
"followerSanitar",
"bossSanitar",
"test",
"assaultGroup",
"sectantWarrior",
"sectantPriest",
"bossTagilla",
"followerTagilla",
"bossKnight",
"followerBigPipe",
"followerBirdEye",
"bossBoar",
"followerBoar",
"arenaFighter",
"arenaFighterEvent",
"bossBoarSniper",
"crazyAssaultEvent",
"sectactPriestEvent",
"followerBoarClose1",
"followerBoarClose2",
"bossKolontay",
"followerKolontayAssault",
"followerKolontaySecurity",
"shooterBTR",
"bossPartisan",
"spiritWinter",
"spiritSpring",
"peacemaker",
"skier",
"assault",
"marksman",
"pmcUSEC",
"pmcBEAR",
"exUsec",
"pmcBot",
"bossBully",
],
AlwaysFriends: [
"bossZryachiy",
"followerZryachiy",
"peacefullZryachiyEvent",
"ravangeZryachiyEvent",
"gifter",
],
BearEnemyChance: 100,
BearPlayerBehaviour: "AlwaysEnemies",
BotRole: "pmcBEAR",
ChancedEnemies: [],
Neutral: [],
SavagePlayerBehaviour: "AlwaysEnemies",
UsecEnemyChance: 100,
UsecPlayerBehaviour: "AlwaysEnemies",
Warn: ["sectactPriestEvent"],
},
{
AlwaysEnemies: [
"bossTest",
"followerTest",
"bossKilla",
"bossKojaniy",
"followerKojaniy",
"cursedAssault",
"bossGluhar",
"followerGluharAssault",
"followerGluharSecurity",
"followerGluharScout",
"followerGluharSnipe",
"followerSanitar",
"bossSanitar",
"test",
"assaultGroup",
"sectantWarrior",
"sectantPriest",
"bossTagilla",
"followerTagilla",
"bossKnight",
"followerBigPipe",
"followerBirdEye",
"bossBoar",
"followerBoar",
"arenaFighter",
"arenaFighterEvent",
"bossBoarSniper",
"crazyAssaultEvent",
"sectactPriestEvent",
"followerBoarClose1",
"followerBoarClose2",
"bossKolontay",
"followerKolontayAssault",
"followerKolontaySecurity",
"shooterBTR",
"bossPartisan",
"spiritWinter",
"spiritSpring",
"peacemaker",
"skier",
"assault",
"marksman",
"pmcUSEC",
"pmcBEAR",
"exUsec",
"pmcBot",
"bossBully",
],
AlwaysFriends: [
"bossZryachiy",
"followerZryachiy",
"peacefullZryachiyEvent",
"ravangeZryachiyEvent",
"gifter",
],
BearEnemyChance: 100,
BearPlayerBehaviour: "AlwaysEnemies",
BotRole: "pmcUSEC",
ChancedEnemies: [],
Neutral: [],
SavagePlayerBehaviour: "AlwaysEnemies",
UsecEnemyChance: 100,
UsecPlayerBehaviour: "AlwaysEnemies",
Warn: ["sectactPriestEvent"],
},
];
export const configLocations = [
"customs",
"factoryDay",
"factoryNight",
"interchange",
"laboratory",
"lighthouse",
"rezervbase",
"shoreline",
"tarkovstreets",
"woods",
"gzLow",
"gzHigh",
];
export const originalMapList = [
"bigmap",
"factory4_day",
"factory4_night",
"interchange",
"laboratory",
"lighthouse",
"rezervbase",
"shoreline",
"tarkovstreets",
"woods",
"sandbox",
"sandbox_high",
];
export const bossesToRemoveFromPool = new Set([
"assault",
"pmcBEAR",
"pmcUSEC",
"infectedAssault",
"infectedTagilla",
"infectedLaborant",
"infectedCivil",
]);
export const mainBossNameList = [
"bossKojaniy",
"bossGluhar",
"bossSanitar",
"bossKilla",
"bossTagilla",
"bossKnight",
"bossBoar",
"bossKolontay",
"bossPartisan",
"bossBully",
];
export const defaultEscapeTimes = {
customs: 40,
factoryDay: 20,
factoryNight: 25,
interchange: 40,
laboratory: 35,
lighthouse: 40,
rezervbase: 40,
shoreline: 45,
tarkovstreets: 50,
woods: 40,
gzLow: 35,
gzHigh: 35,
};

Some files were not shown because too many files have changed in this diff Show More