Merge pull request #633 from sp-tarkov/develop

4.0.1
This commit is contained in:
Cj
2025-10-17 14:02:30 -04:00
committed by GitHub
47 changed files with 1427 additions and 794 deletions
+3 -3
View File
@@ -12,7 +12,7 @@ body:
- You must be able to replicate the issue with a fresh profile, running no mods. If you can't, we can't fix it.
- If you are using a profile from an older version, please make a fresh profile and replicate the issue before submitting.
- You must upload all the required log files, even if you think they are useless.
- Failure to comply with any of the above requirements will result in your issue being closed without notice.
- Failure to comply with any of the above requirements will result in your issue being closed without notice.
- type: dropdown
id: version
attributes:
@@ -59,7 +59,7 @@ body:
id: log_server
attributes:
label: "Server Log"
description: "Upload a copy of your *entire* server log: `/user/logs/spt/spt.txt`."
description: "Upload a copy of your *entire* server log: `SPT/user/logs/spt/spt.txt`."
placeholder: "Attach the log file. Do not paste the contents."
validations:
required: true
@@ -83,7 +83,7 @@ body:
id: profile
attributes:
label: "Player Profile"
description: "If helpful, upload a copy of your *entire* player profile: `/user/profiles/<profileId>.json`."
description: "If helpful, upload a copy of your *entire* player profile: `SPT/user/profiles/<profileId>.json`."
placeholder: "Attach the profile file. Do not paste the contents."
validations:
required: false
@@ -2838,5 +2838,6 @@
"bossKnight"
],
"resetDay": "Monday"
}
},
"replaceScavWith": "assault"
}
@@ -190,7 +190,7 @@
"giveCommandEnabled": true
},
"commandUseLimits": {
"StashRows": 29
"StashRows": 28
},
"ids": {
"commando": "6723fd51c5924c57ce0ca01e",
@@ -584,7 +584,10 @@
"68418091b5b0c9e4c60f0e7a",
"684180ee9b6d80d840042e8a",
"684181208d035f60230f63f9",
"6866665cdf54e1190902df55"
"6866665cdf54e1190902df55",
"6841b6b674a3c16f5e03d653",
"679bab714e9ca6b3d80586b4",
"64d4b23dc1b37504b41ac2b6"
],
"rewardItemTypeBlacklist": [
"65649eb40bf0ed77b8044453"
@@ -182,11 +182,9 @@
"pmcType": {
"pmcbear": {
"factory4_day": {
"bossTagilla": 1,
"pmcBEAR": 10
},
"factory4_night": {
"bossTagilla": 1,
"pmcBEAR": 10
},
"bigmap": {
@@ -225,11 +223,9 @@
},
"pmcusec": {
"factory4_day": {
"bossTagilla": 1,
"pmcUSEC": 10
},
"factory4_night": {
"bossTagilla": 1,
"pmcUSEC": 10
},
"bigmap": {
@@ -37,7 +37,7 @@
"max": 0
},
"fog": {
"0.0013": 35,
"0.0013": 30,
"0.0018": 6,
"0.002": 4,
"0.004": 3,
@@ -60,12 +60,14 @@
},
"RAINY": {
"clouds": {
"0.4": 5,
"1": 4
"0.7": 2,
"0.9": 4,
"1": 4,
"1.2": 1
},
"windSpeed": {
"0": 6,
"1": 3,
"0": 3,
"1": 2,
"2": 2,
"3": 1,
"4": 1
@@ -2976,7 +2976,9 @@
"YukoVR",
"ZenosBleed",
"chrispawl89",
"hulkhan"
"hulkhan",
"LycorisOni",
"Quik"
],
"generation": {
"items": {
@@ -2967,7 +2967,9 @@
"YukoVR",
"ZenosBleed",
"chrispawl89",
"hulkhan"
"hulkhan",
"LycorisOni",
"Quik"
],
"generation": {
"items": {
@@ -138,7 +138,7 @@
"TriggerName": ""
},
{
"BossChance": 0,
"BossChance": 18,
"BossDifficult": "normal",
"BossEscortAmount": "2",
"BossEscortDifficult": "normal",
@@ -1,209 +1,201 @@
{
"AccessKeys": [],
"AccessKeysPvE": [],
"Area": 0,
"AveragePlayTime": 2,
"AveragePlayerLevel": 10,
"BotAssault": 0,
"BotEasy": 0,
"BotHard": 0,
"BotImpossible": 0,
"BotMarksman": 0,
"BotMax": 5,
"BotMaxPvE": 5,
"BotNormal": 0,
"BotSpawnCountStep": 3,
"BotSpawnPeriodCheck": 15,
"BotSpawnTimeOffMax": 0,
"BotSpawnTimeOffMin": 0,
"BotSpawnTimeOnMax": 0,
"BotSpawnTimeOnMin": 0,
"BotStart": 30,
"BotStartPlayer": 0,
"BotStop": 2400,
"DisabledScavExits": "",
"EnableCoop": false,
"Enabled": false,
"EscapeTimeLimit": 60000,
"EscapeTimeLimitCoop": 60000,
"ForceOnlineRaidInPVE": false,
"GlobalContainerChanceModifier": 1,
"HeatmapCellSize": {
"x": 1,
"y": 2,
"z": 1
},
"HeatmapLayers": [
"AllCharactersPositions",
"AllBotsPositions",
"AllRealPlayersPositions",
"RealPlayersSavagesPositions",
"RealPlayersSavagesDeads",
"RealPlayersSavagesDamages",
"RealPlayersPmcPositions",
"RealPlayersPmcDeads",
"RealPlayersPmcDamages",
"RealPlayersPmcLaydownPositions",
"RealPlayersPmcEquipmentDropPositions",
"RealPlayersPmcHealingPositions",
"BotsBossPositions",
"BotsBossDeads",
"BotsBossDamages",
"BotsSavagesPositions",
"BotsSavagesDeads",
"BotsSavagesDamages",
"AllCharactersDamageSources",
"RealPlayerDamageSources",
"BotsDamageSources",
"LootPositions"
],
"IconX": 156,
"IconY": 551,
"IsSecret": false,
"Locked": false,
"Insurance": false,
"SafeLocation": false,
"MaxBotPerZone": 0,
"MaxCoopGroup": 10,
"MaxDistToFreePoint": 900,
"MaxPlayers": 10,
"MinDistToFreePoint": 10,
"MinPlayerLvlAccessKeys": 0,
"MinPlayers": 1,
"Name": "Arena",
"NewSpawn": false,
"NewSpawnForPlayers": false,
"NonWaveGroupScenario": {
"Chance": 50,
"Enabled": true,
"MaxToBeGroup": 3,
"MinToBeGroup": 2
},
"OcculsionCullingEnabled": true,
"OfflineNewSpawn": true,
"OfflineOldSpawn": true,
"OldSpawn": true,
"OpenZones": "",
"PlayersRequestCount": -1,
"PmcMaxPlayersInGroup": 5,
"RequiredPlayerLevelMax": 100,
"RequiredPlayerLevelMin": 0,
"Rules": "Normal",
"ScavMaxPlayersInGroup": 4,
"Scene": {
"path": "maps/develop_preset.bundle",
"rcid": "develop.scenespreset.asset"
},
"Area": 0,
"RequiredPlayerLevel": 1,
"MinPlayers": 1,
"MaxPlayers": 10,
"exit_count": 0,
"exit_access_time": 0,
"exit_time": 0,
"IconX": 156,
"IconY": 551,
"UnixDateTime": 1600869802,
"doors": [],
"limits": [],
"waves": [
{
"number": 0,
"time_min": 0,
"time_max": 10,
"slots_min": 1,
"slots_max": 2,
"BotSide": "Savage",
"BotPreset": "normal",
"SpawnPoints": "BotZoneMain",
"WildSpawnType": "assault",
"isPlayers": true
},
{
"number": 1,
"time_min": 10,
"time_max": 120,
"slots_min": 2,
"slots_max": 3,
"BotSide": "Savage",
"BotPreset": "easy",
"KeepZoneOnSpawn": false,
"SpawnMode": [],
"SpawnPoints": "BotZoneMain",
"WildSpawnType": "assault",
"isPlayers": true
},
{
"isPlayers": false,
"number": 0,
"time_min": 120,
"time_max": 240,
"slots_min": 3,
"slots_max": 4,
"slots_max": 2,
"slots_min": 1,
"time_max": 10,
"time_min": 0
},
{
"BotPreset": "easy",
"BotSide": "Savage",
"BotPreset": "hard",
"KeepZoneOnSpawn": false,
"SpawnMode": [],
"SpawnPoints": "BotZoneMain",
"WildSpawnType": "assault",
"isPlayers": true
"isPlayers": false,
"number": 1,
"slots_max": 3,
"slots_min": 2,
"time_max": 120,
"time_min": 10
},
{
"BotPreset": "hard",
"BotSide": "Savage",
"KeepZoneOnSpawn": false,
"SpawnMode": [],
"SpawnPoints": "BotZoneMain",
"WildSpawnType": "assault",
"isPlayers": false,
"number": 0,
"slots_max": 4,
"slots_min": 3,
"time_max": 240,
"time_min": 120
}
],
"AirdropParameters": [
{
"AirdropPointDeactivateDistance": 50,
"MinPlayersCountToSpawnAirdrop": 0,
"PlaneAirdropChance": 0,
"PlaneAirdropCooldownMax": 900,
"PlaneAirdropCooldownMin": 600,
"PlaneAirdropEnd": 2100,
"PlaneAirdropMax": 0,
"PlaneAirdropStartMax": 900,
"PlaneAirdropStartMin": 300,
"UnsuccessfulTryPenalty": 10
}
],
"limits": [],
"AveragePlayTime": 2,
"AveragePlayerLevel": 10,
"escape_time_limit": 60000,
"Rules": "Normal",
"IsSecret": false,
"doors": [],
"tmp_location_field_remove_me": 0,
"MinDistToExitPoint": 0,
"MaxDistToFreePoint": 900,
"MinDistToFreePoint": 10,
"MaxBotPerZone": 0,
"OpenZones": "",
"OcculsionCullingEnabled": true,
"GlobalLootChanceModifier": 0,
"OldSpawn": true,
"NewSpawn": false,
"BotMax": 5,
"BotStart": 30,
"BotStop": 2400,
"BotMaxTimePlayer": 0,
"BotSpawnTimeOnMin": 0,
"BotSpawnTimeOnMax": 0,
"BotSpawnTimeOffMin": 0,
"BotSpawnTimeOffMax": 0,
"BotMaxPlayer": 0,
"BotEasy": 0,
"BotNormal": 0,
"BotHard": 0,
"BotImpossible": 0,
"BotAssault": 0,
"BotMarksman": 0,
"DisabledScavExits": "",
"AccessKeys": [],
"UnixDateTime": 1600869802,
"users_gather_seconds": 0,
"users_spawn_seconds_n": 0,
"users_spawn_seconds_n2": 0,
"users_summon_seconds": 0,
"sav_summon_seconds": 0,
"matching_min_seconds": 0,
"MinMaxBots": [],
"BotLocationModifier": {
"AccuracySpeed": 1,
"Scattering": 1,
"GainSight": 1,
"MarksmanAccuratyCoef": 1,
"VisibleDistance": 1,
"DistToSleep": 100,
"DistToActivate": 80,
"MagnetPower": 10
"DistToActivatePvE": 80,
"DistToSleep": 100,
"DistToSleepPvE": 100,
"FogVisibilityDistanceCoef": 0,
"FogVisibilitySpeedCoef": 0,
"GainSight": 1,
"MagnetPower": 10,
"MarksmanAccuratyCoef": 1,
"RainVisibilityDistanceCoef": 0,
"RainVisibilitySpeedCoef": 0,
"Scattering": 1,
"VisibleDistance": 1
},
"exits": [
{
"Name": "UN Roadblock",
"EntryPoints": "House,Houseb",
"Chance": 100,
"MinTime": 0,
"MaxTime": 0,
"PlayersCount": 0,
"ExfiltrationTime": 10,
"PassageRequirement": "TransferItem",
"ExfiltrationType": "SharedTimer",
"RequiredSlot": "FirstPrimaryWeapon",
"Id": "5449016a4bdc2d6f028b456f",
"RequirementTip": "Сотку должен",
"Count": 100
},
{
"Name": "Elevator",
"EntryPoints": "House,Houseb",
"Chance": 100,
"MinTime": 0,
"MaxTime": 0,
"PlayersCount": 3,
"ExfiltrationTime": 10,
"PassageRequirement": "None",
"ExfiltrationType": "Individual",
"RequiredSlot": "FirstPrimaryWeapon",
"Id": "",
"RequirementTip": "",
"Count": 0
},
{
"Name": "Outskirts",
"EntryPoints": "House,Houseb",
"Chance": 100,
"MinTime": 0,
"MaxTime": 0,
"PlayersCount": 0,
"ExfiltrationTime": 10,
"PassageRequirement": "None",
"ExfiltrationType": "Individual",
"RequiredSlot": "FirstPrimaryWeapon",
"Id": "",
"RequirementTip": "",
"Count": 0
},
{
"Name": "Hangar Gate",
"EntryPoints": "House,Houseb",
"Chance": 100,
"MinTime": 0,
"MaxTime": 0,
"PlayersCount": 0,
"ExfiltrationTime": 10,
"PassageRequirement": "None",
"ExfiltrationType": "Individual",
"RequiredSlot": "FirstPrimaryWeapon",
"Id": "",
"RequirementTip": "",
"Count": 0
},
{
"Name": "Tunnel",
"EntryPoints": "House,Houseb",
"Chance": 100,
"MinTime": 0,
"MaxTime": 0,
"PlayersCount": 0,
"ExfiltrationTime": 10,
"PassageRequirement": "None",
"ExfiltrationType": "Individual",
"RequiredSlot": "FirstPrimaryWeapon",
"Id": "",
"RequirementTip": "",
"Count": 0
},
{
"Name": "EXFIL_Train",
"EntryPoints": "House,Houseb",
"Chance": 100,
"MinTime": 30,
"MaxTime": 60,
"PlayersCount": 0,
"ExfiltrationTime": 5,
"PassageRequirement": "Train",
"ExfiltrationType": "SharedTimer",
"RequiredSlot": "FirstPrimaryWeapon",
"Id": "0",
"RequirementTip": "TIP IS HARDCODED",
"Count": 90
}
],
"DisabledForScav": false,
"BossLocationSpawn": [],
"MinMaxBots": [],
"SpawnPointParams": [
{
"BotZoneName": "",
"Categories": [
"Player"
],
"ColliderParams": {
"_parent": "SpawnBoxParams",
"_props": {
"Center": {
"x": 0,
"y": 0,
"z": 0
},
"Size": {
"x": 2.2,
"y": 2.04,
"z": 2.14
}
}
},
"CorePointId": 0,
"DelayToCanSpawnSec": 4,
"Id": "03841924-ea1a-4e5c-bf27-82af7868beb1",
"Infiltration": "House",
"Position": {
"x": -30.359436,
"y": 0.1,
@@ -212,12 +204,13 @@
"Rotation": 87.10709,
"Sides": [
"Bear"
],
]
},
{
"BotZoneName": "",
"Categories": [
"Player"
],
"Infiltration": "House",
"DelayToCanSpawnSec": 4,
"ColliderParams": {
"_parent": "SpawnBoxParams",
"_props": {
@@ -233,10 +226,10 @@
}
}
},
"BotZoneName": ""
},
{
"CorePointId": 0,
"DelayToCanSpawnSec": 4,
"Id": "0da5b986-424a-44d1-906a-1d7cc118413a",
"Infiltration": "Houseb",
"Position": {
"x": 19.715271,
"y": 0.06,
@@ -245,12 +238,13 @@
"Rotation": 269.253418,
"Sides": [
"Bear"
],
]
},
{
"BotZoneName": "",
"Categories": [
"Player"
],
"Infiltration": "Houseb",
"DelayToCanSpawnSec": 4,
"ColliderParams": {
"_parent": "SpawnBoxParams",
"_props": {
@@ -266,10 +260,10 @@
}
}
},
"BotZoneName": ""
},
{
"CorePointId": 0,
"DelayToCanSpawnSec": 4,
"Id": "110e3c75-e58d-461c-ab61-9f6a715ca6b1",
"Infiltration": "House",
"Position": {
"x": -30.0410156,
"y": 0.1,
@@ -278,12 +272,13 @@
"Rotation": 87.10709,
"Sides": [
"Bear"
],
]
},
{
"BotZoneName": "",
"Categories": [
"Player"
],
"Infiltration": "House",
"DelayToCanSpawnSec": 4,
"ColliderParams": {
"_parent": "SpawnBoxParams",
"_props": {
@@ -299,10 +294,10 @@
}
}
},
"BotZoneName": ""
},
{
"CorePointId": 0,
"DelayToCanSpawnSec": 4,
"Id": "1a40138b-6f65-4866-bad2-64162d7772de",
"Infiltration": "House",
"Position": {
"x": -29.2000122,
"y": 0.1,
@@ -311,12 +306,13 @@
"Rotation": 87.10709,
"Sides": [
"Bear"
],
]
},
{
"BotZoneName": "",
"Categories": [
"Player"
],
"Infiltration": "House",
"DelayToCanSpawnSec": 4,
"ColliderParams": {
"_parent": "SpawnBoxParams",
"_props": {
@@ -332,10 +328,10 @@
}
}
},
"BotZoneName": ""
},
{
"CorePointId": 0,
"DelayToCanSpawnSec": 4,
"Id": "3feb492c-8c45-405a-8e7a-8dd903433eb0",
"Infiltration": "House",
"Position": {
"x": -23.7852783,
"y": 0.1,
@@ -344,12 +340,13 @@
"Rotation": 87.10709,
"Sides": [
"Bear"
],
]
},
{
"BotZoneName": "",
"Categories": [
"Player"
],
"Infiltration": "House",
"DelayToCanSpawnSec": 4,
"ColliderParams": {
"_parent": "SpawnBoxParams",
"_props": {
@@ -365,10 +362,10 @@
}
}
},
"BotZoneName": ""
},
{
"CorePointId": 0,
"DelayToCanSpawnSec": 4,
"Id": "52d3284b-0e8f-47e8-a7d1-701bf4cd8e5b",
"Infiltration": "House",
"Position": {
"x": -23.4979248,
"y": 0.1,
@@ -377,12 +374,13 @@
"Rotation": 87.10709,
"Sides": [
"Bear"
],
]
},
{
"BotZoneName": "",
"Categories": [
"Player"
],
"Infiltration": "House",
"DelayToCanSpawnSec": 4,
"ColliderParams": {
"_parent": "SpawnBoxParams",
"_props": {
@@ -398,10 +396,10 @@
}
}
},
"BotZoneName": ""
},
{
"CorePointId": 0,
"DelayToCanSpawnSec": 4,
"Id": "870629fd-e4d5-4fa1-8274-94c223ad9692",
"Infiltration": "Houseb",
"Position": {
"x": 12.9941406,
"y": 0.06,
@@ -410,12 +408,13 @@
"Rotation": 269.253418,
"Sides": [
"Bear"
],
]
},
{
"BotZoneName": "",
"Categories": [
"Player"
],
"Infiltration": "Houseb",
"DelayToCanSpawnSec": 4,
"ColliderParams": {
"_parent": "SpawnBoxParams",
"_props": {
@@ -431,10 +430,10 @@
}
}
},
"BotZoneName": ""
},
{
"CorePointId": 0,
"DelayToCanSpawnSec": 4,
"Id": "93a1c6d6-1379-43e6-99c2-c346178bb3e0",
"Infiltration": "Houseb",
"Position": {
"x": 18.1246338,
"y": 0.06,
@@ -443,45 +442,13 @@
"Rotation": 269.253418,
"Sides": [
"Bear"
],
"Categories": [
"Player"
],
"Infiltration": "Houseb",
"DelayToCanSpawnSec": 4,
"ColliderParams": {
"_parent": "SpawnBoxParams",
"_props": {
"Center": {
"x": 0,
"y": 0,
"z": 0
},
"Size": {
"x": 2.2,
"y": 2.04,
"z": 2.14
}
}
},
"BotZoneName": ""
]
},
{
"Id": "971882ef-596f-4419-acfb-ca2bfe52d043",
"Position": {
"x": -17.92,
"y": 0,
"z": 5.55
},
"Rotation": 0,
"Sides": [
"Savage"
],
"BotZoneName": "BotZoneMain",
"Categories": [
"Bot"
],
"Infiltration": "",
"DelayToCanSpawnSec": 10,
"ColliderParams": {
"_parent": "SpawnSphereParams",
"_props": {
@@ -493,10 +460,44 @@
"Radius": 4
}
},
"BotZoneName": "BotZoneMain"
"CorePointId": 0,
"DelayToCanSpawnSec": 10,
"Id": "971882ef-596f-4419-acfb-ca2bfe52d043",
"Infiltration": "",
"Position": {
"x": -17.92,
"y": 0,
"z": 5.55
},
"Rotation": 0,
"Sides": [
"Savage"
]
},
{
"BotZoneName": "",
"Categories": [
"Player"
],
"ColliderParams": {
"_parent": "SpawnBoxParams",
"_props": {
"Center": {
"x": 0,
"y": 0,
"z": 0
},
"Size": {
"x": 2.2,
"y": 2.04,
"z": 2.14
}
}
},
"CorePointId": 0,
"DelayToCanSpawnSec": 4,
"Id": "cf24125e-1c3a-457e-a024-613a8df98b06",
"Infiltration": "Houseb",
"Position": {
"x": 12.47467,
"y": 0.06,
@@ -505,12 +506,13 @@
"Rotation": 269.253418,
"Sides": [
"Bear"
],
]
},
{
"BotZoneName": "",
"Categories": [
"Player"
],
"Infiltration": "Houseb",
"DelayToCanSpawnSec": 4,
"ColliderParams": {
"_parent": "SpawnBoxParams",
"_props": {
@@ -526,10 +528,10 @@
}
}
},
"BotZoneName": ""
},
{
"CorePointId": 0,
"DelayToCanSpawnSec": 4,
"Id": "d052b031-b477-465f-8913-ae108c9ca2c3",
"Infiltration": "Houseb",
"Position": {
"x": 19.210022,
"y": 0.06,
@@ -538,28 +540,135 @@
"Rotation": 269.253418,
"Sides": [
"Bear"
],
"Categories": [
"Player"
],
"Infiltration": "Houseb",
"DelayToCanSpawnSec": 4,
"ColliderParams": {
"_parent": "SpawnBoxParams",
"_props": {
"Center": {
"x": 0,
"y": 0,
"z": 0
},
"Size": {
"x": 2.2,
"y": 2.04,
"z": 2.14
}
}
},
"BotZoneName": ""
]
}
],
"exits": [
{
"Chance": 100,
"ChancePVE": 100,
"Count": 100,
"CountPVE": 100,
"EntryPoints": "House,Houseb",
"ExfiltrationTime": 10,
"ExfiltrationTimePVE": 10,
"ExfiltrationType": "SharedTimer",
"Id": "5449016a4bdc2d6f028b456f",
"MaxTime": 0,
"MaxTimePVE": 0,
"MinTime": 0,
"MinTimePVE": 0,
"Name": "UN Roadblock",
"PassageRequirement": "TransferItem",
"PlayersCount": 0,
"PlayersCountPVE": 0,
"RequiredSlot": "FirstPrimaryWeapon",
"RequirementTip": "Сотку должен"
},
{
"Chance": 100,
"ChancePVE": 100,
"Count": 0,
"CountPVE": 0,
"EntryPoints": "House,Houseb",
"ExfiltrationTime": 10,
"ExfiltrationTimePVE": 10,
"ExfiltrationType": "Individual",
"Id": "",
"MaxTime": 0,
"MaxTimePVE": 0,
"MinTime": 0,
"MinTimePVE": 0,
"Name": "Elevator",
"PassageRequirement": "None",
"PlayersCount": 3,
"PlayersCountPVE": 3,
"RequiredSlot": "FirstPrimaryWeapon",
"RequirementTip": ""
},
{
"Chance": 100,
"ChancePVE": 100,
"Count": 0,
"CountPVE": 0,
"EntryPoints": "House,Houseb",
"ExfiltrationTime": 10,
"ExfiltrationTimePVE": 10,
"ExfiltrationType": "Individual",
"Id": "",
"MaxTime": 0,
"MaxTimePVE": 0,
"MinTime": 0,
"MinTimePVE": 0,
"Name": "Outskirts",
"PassageRequirement": "None",
"PlayersCount": 0,
"PlayersCountPVE": 0,
"RequiredSlot": "FirstPrimaryWeapon",
"RequirementTip": ""
},
{
"Chance": 100,
"ChancePVE": 100,
"Count": 0,
"CountPVE": 0,
"EntryPoints": "House,Houseb",
"ExfiltrationTime": 10,
"ExfiltrationTimePVE": 10,
"ExfiltrationType": "Individual",
"Id": "",
"MaxTime": 0,
"MaxTimePVE": 0,
"MinTime": 0,
"MinTimePVE": 0,
"Name": "Hangar Gate",
"PassageRequirement": "None",
"PlayersCount": 0,
"PlayersCountPVE": 0,
"RequiredSlot": "FirstPrimaryWeapon",
"RequirementTip": ""
},
{
"Chance": 100,
"ChancePVE": 100,
"Count": 0,
"CountPVE": 0,
"EntryPoints": "House,Houseb",
"ExfiltrationTime": 10,
"ExfiltrationTimePVE": 10,
"ExfiltrationType": "Individual",
"Id": "",
"MaxTime": 0,
"MaxTimePVE": 0,
"MinTime": 0,
"MinTimePVE": 0,
"Name": "Tunnel",
"PassageRequirement": "None",
"PlayersCount": 0,
"PlayersCountPVE": 0,
"RequiredSlot": "FirstPrimaryWeapon",
"RequirementTip": ""
},
{
"Chance": 100,
"ChancePVE": 100,
"Count": 90,
"CountPVE": 90,
"EntryPoints": "House,Houseb",
"ExfiltrationTime": 5,
"ExfiltrationTimePVE": 5,
"ExfiltrationType": "SharedTimer",
"Id": "0",
"MaxTime": 60,
"MaxTimePVE": 60,
"MinTime": 30,
"MinTimePVE": 30,
"Name": "EXFIL_Train",
"PassageRequirement": "Train",
"PlayersCount": 0,
"PlayersCountPVE": 0,
"RequiredSlot": "FirstPrimaryWeapon",
"RequirementTip": "TIP IS HARDCODED"
}
],
"maxItemCountInLocation": [],
@@ -570,23 +679,12 @@
{
"id": "5805f617245977100b2c1f41",
"pic": {
"path": "CONTENT/banners/tglabs.jpg",
"rcid": ""
}
},
{
"id": "5807be8924597742c603fa19",
"pic": {
"path": "CONTENT/banners/banner_tarkov.jpg",
"rcid": ""
}
},
{
"id": "5c1b857086f77465f465faa4",
"pic": {
"path": "CONTENT/banners/banner_scavraider.jpg",
"rcid": ""
"file": "67e404d9bec96f5d8e097331.jpg",
"path": "banners/67e404d9bec96f5d8e097331.jpg",
"rcid": "",
"type": "banners"
}
}
]
],
"BossLocationSpawn": []
}
@@ -1,81 +1,139 @@
{
"Enabled": false,
"AccessKeys": [],
"AccessKeysPvE": [],
"Area": 0,
"AveragePlayTime": 1000000,
"AveragePlayerLevel": 10,
"BotAssault": 0,
"BotEasy": 0,
"BotHard": 0,
"BotImpossible": 0,
"BotMarksman": 0,
"BotMax": 0,
"BotMaxPvE": 0,
"BotNormal": 0,
"BotSpawnCountStep": 3,
"BotSpawnPeriodCheck": 15,
"BotSpawnTimeOffMax": 0,
"BotSpawnTimeOffMin": 0,
"BotSpawnTimeOnMax": 0,
"BotSpawnTimeOnMin": 0,
"BotStart": 0,
"BotStartPlayer": 0,
"BotStop": 0,
"DisabledScavExits": "",
"EnableCoop": true,
"Enabled": false,
"EscapeTimeLimit": 99999,
"EscapeTimeLimitCoop": 99999,
"ForceOnlineRaidInPVE": false,
"GlobalContainerChanceModifier": 1,
"HeatmapCellSize": {
"x": 1,
"y": 2,
"z": 1
},
"HeatmapLayers": [
"AllCharactersPositions",
"AllBotsPositions",
"AllRealPlayersPositions",
"RealPlayersSavagesPositions",
"RealPlayersSavagesDeads",
"RealPlayersSavagesDamages",
"RealPlayersPmcPositions",
"RealPlayersPmcDeads",
"RealPlayersPmcDamages",
"RealPlayersPmcLaydownPositions",
"RealPlayersPmcEquipmentDropPositions",
"RealPlayersPmcHealingPositions",
"BotsBossPositions",
"BotsBossDeads",
"BotsBossDamages",
"BotsSavagesPositions",
"BotsSavagesDeads",
"BotsSavagesDamages",
"AllCharactersDamageSources",
"RealPlayerDamageSources",
"BotsDamageSources",
"LootPositions"
],
"IconX": 0,
"IconY": 0,
"IsSecret": false,
"Locked": true,
"MaxBotPerZone": 0,
"MaxCoopGroup": 10,
"MaxDistToFreePoint": 900,
"MaxPlayers": 10,
"MinDistToFreePoint": 10,
"MinPlayerLvlAccessKeys": 0,
"MinPlayers": 1,
"Name": "Hideout",
"NewSpawn": false,
"NewSpawnForPlayers": false,
"NonWaveGroupScenario": {
"Chance": 50,
"Enabled": true,
"MaxToBeGroup": 3,
"MinToBeGroup": 2
},
"OcculsionCullingEnabled": false,
"OfflineNewSpawn": true,
"OfflineOldSpawn": true,
"OldSpawn": true,
"OpenZones": "",
"PlayersRequestCount": -1,
"PmcMaxPlayersInGroup": 5,
"RequiredPlayerLevelMax": 100,
"RequiredPlayerLevelMin": 1,
"Rules": "Normal",
"ScavMaxPlayersInGroup": 4,
"Scene": {
"path": "maps/bunker_preset.bundle",
"rcid": "bunker.ScenesPreset.asset"
},
"Area": 0,
"RequiredPlayerLevelMin": 1,
"RequiredPlayerLevelMax": 100,
"PmcMaxPlayersInGroup": 5,
"ScavMaxPlayersInGroup": 4,
"MinPlayers": 1,
"MaxPlayers": 10,
"MaxCoopGroup": 10,
"IconX": 0,
"IconY": 0,
"waves": [],
"limits": [],
"AveragePlayTime": 1000000,
"AveragePlayerLevel": 10,
"EscapeTimeLimit": 99999,
"EscapeTimeLimitCoop": 99999,
"Rules": "Normal",
"IsSecret": false,
"doors": [],
"MaxDistToFreePoint": 900,
"MinDistToFreePoint": 10,
"MaxBotPerZone": 0,
"OpenZones": "",
"OcculsionCullingEnabled": false,
"OldSpawn": true,
"OfflineOldSpawn": true,
"NewSpawn": false,
"OfflineNewSpawn": true,
"BotMax": 0,
"BotStart": 0,
"BotStartPlayer": 0,
"BotStop": 0,
"BotSpawnTimeOnMin": 0,
"BotSpawnTimeOnMax": 0,
"BotSpawnTimeOffMin": 0,
"BotSpawnTimeOffMax": 0,
"BotEasy": 0,
"BotNormal": 0,
"BotHard": 0,
"BotImpossible": 0,
"BotAssault": 0,
"BotMarksman": 0,
"DisabledScavExits": "",
"MinPlayerLvlAccessKeys": 0,
"AccessKeys": [],
"UnixDateTime": 1689772567,
"PlayersRequestCount": -1,
"NonWaveGroupScenario": {
"MinToBeGroup": 2,
"MaxToBeGroup": 3,
"Chance": 50,
"Enabled": false
},
"BotSpawnCountStep": 3,
"BotSpawnPeriodCheck": 15,
"GlobalContainerChanceModifier": 1,
"MinMaxBots": [],
"doors": [],
"limits": [],
"waves": [],
"BotLocationModifier": {
"AccuracySpeed": 1,
"Scattering": 1,
"DistToActivatePvE": 0,
"DistToSleepPvE": 0,
"FogVisibilityDistanceCoef": 0,
"FogVisibilitySpeedCoef": 0,
"GainSight": 1,
"MarksmanAccuratyCoef": 1,
"VisibleDistance": 0
"RainVisibilityDistanceCoef": 0,
"RainVisibilitySpeedCoef": 0,
"Scattering": 1,
"VisibleDistance": 0,
"DistToActivate": 0,
"DistToSleep": 0
},
"exits": [],
"DisabledForScav": false,
"MinMaxBots": [],
"SpawnPointParams": [
{
"BotZoneName": "",
"Categories": [
"Player",
"Bot"
],
"ColliderParams": {
"_parent": "SpawnSphereParams",
"_props": {
"Center": {
"x": 0,
"y": 0,
"z": 0
},
"Radius": 10
}
},
"DelayToCanSpawnSec": 0.5,
"Id": "f656a561-6524-49e2-90c0-1cbbece183ce",
"Infiltration": "",
"Position": {
"x": -5.8,
"y": 0.1,
@@ -84,13 +142,13 @@
"Rotation": 45.0000038,
"Sides": [
"Usec"
],
]
},
{
"BotZoneName": "",
"Categories": [
"Player",
"Bot"
"Player"
],
"Infiltration": "",
"DelayToCanSpawnSec": 0.5,
"ColliderParams": {
"_parent": "SpawnSphereParams",
"_props": {
@@ -102,10 +160,9 @@
"Radius": 10
}
},
"BotZoneName": ""
},
{
"DelayToCanSpawnSec": 4,
"Id": "f92541a9-08ab-4c9e-957a-d802e143b705",
"Infiltration": "Hideout",
"Position": {
"x": -5.8,
"y": 0.1,
@@ -114,12 +171,14 @@
"Rotation": 45.0000038,
"Sides": [
"All"
],
]
},
{
"BotZoneName": "",
"Categories": [
"Player"
"Player",
"Bot"
],
"Infiltration": "Hideout",
"DelayToCanSpawnSec": 4,
"ColliderParams": {
"_parent": "SpawnSphereParams",
"_props": {
@@ -131,10 +190,9 @@
"Radius": 10
}
},
"BotZoneName": ""
},
{
"DelayToCanSpawnSec": 0.5,
"Id": "faf351a1-e5f5-4642-8ece-267508fdfea6",
"Infiltration": "",
"Position": {
"x": -5.8,
"y": 0.1,
@@ -143,27 +201,10 @@
"Rotation": 45.0000038,
"Sides": [
"Bear"
],
"Categories": [
"Player",
"Bot"
],
"Infiltration": "",
"DelayToCanSpawnSec": 0.5,
"ColliderParams": {
"_parent": "SpawnSphereParams",
"_props": {
"Center": {
"x": 0,
"y": 0,
"z": 0
},
"Radius": 10
}
},
"BotZoneName": ""
]
}
],
"exits": [],
"maxItemCountInLocation": [
{
"TemplateId": "604b47caa16c2359315ad047",
@@ -177,15 +218,19 @@
{
"id": "5805f617245977100b2c1f41",
"pic": {
"path": "CONTENT/banners/tglabs.jpg",
"rcid": ""
"file": "67e404d9bec96f5d8e097331.jpg",
"path": "banners/67e404d9bec96f5d8e097331.jpg",
"rcid": "",
"type": "banners"
}
},
{
"id": "5807be8924597742c603fa19",
"pic": {
"path": "CONTENT/banners/banner_tarkov.jpg",
"rcid": ""
"file": "67e4046dbec96f5d8e09732a.jpg",
"path": "banners/67e4046dbec96f5d8e09732a.jpg",
"rcid": "",
"type": "banners"
}
}
],
@@ -1,106 +1,149 @@
{
"AccessKeys": [],
"AccessKeysPvE": [],
"Area": 0,
"AveragePlayTime": 100,
"AveragePlayerLevel": 10,
"BotAssault": 0,
"BotEasy": 0,
"BotHard": 0,
"BotImpossible": 0,
"BotMarksman": 0,
"BotMax": 0,
"BotMaxPvE": 0,
"BotNormal": 0,
"BotSpawnCountStep": 3,
"BotSpawnPeriodCheck": 15,
"BotSpawnTimeOffMax": 0,
"BotSpawnTimeOffMin": 0,
"BotSpawnTimeOnMax": 0,
"BotSpawnTimeOnMin": 0,
"BotStart": 0,
"BotStartPlayer": 0,
"BotStop": 0,
"DisabledScavExits": "",
"EnableCoop": true,
"Enabled": false,
"EscapeTimeLimit": 0,
"EscapeTimeLimitCoop": 0,
"ForceOnlineRaidInPVE": false,
"GlobalContainerChanceModifier": 1,
"HeatmapCellSize": {
"x": 1,
"y": 2,
"z": 1
},
"HeatmapLayers": [
"AllCharactersPositions",
"AllBotsPositions",
"AllRealPlayersPositions",
"RealPlayersSavagesPositions",
"RealPlayersSavagesDeads",
"RealPlayersSavagesDamages",
"RealPlayersPmcPositions",
"RealPlayersPmcDeads",
"RealPlayersPmcDamages",
"RealPlayersPmcLaydownPositions",
"RealPlayersPmcEquipmentDropPositions",
"RealPlayersPmcHealingPositions",
"BotsBossPositions",
"BotsBossDeads",
"BotsBossDamages",
"BotsSavagesPositions",
"BotsSavagesDeads",
"BotsSavagesDamages",
"AllCharactersDamageSources",
"RealPlayerDamageSources",
"BotsDamageSources",
"LootPositions"
],
"IconX": 224,
"IconY": 646,
"IsSecret": true,
"Locked": true,
"Insurance": true,
"SafeLocation": false,
"MaxBotPerZone": 0,
"MaxCoopGroup": 9,
"MaxDistToFreePoint": 900,
"MaxPlayers": 9,
"MinDistToFreePoint": 10,
"MinPlayerLvlAccessKeys": 0,
"MinPlayers": 6,
"Name": "Private Sector",
"Description": "Private residential sector, built up with cottages of the upper-class citizens of Tarkov. In the first weeks of emerging chaos it served as a refugee staging camp, but has become a known scavenger haunt afterwards.",
"NewSpawn": false,
"NewSpawnForPlayers": false,
"NonWaveGroupScenario": {
"Chance": 50,
"Enabled": true,
"MaxToBeGroup": 3,
"MinToBeGroup": 2
},
"OcculsionCullingEnabled": false,
"OfflineNewSpawn": true,
"OfflineOldSpawn": true,
"OldSpawn": true,
"OpenZones": "",
"PlayersRequestCount": -1,
"PmcMaxPlayersInGroup": 5,
"RequiredPlayerLevelMax": 100,
"RequiredPlayerLevelMin": 0,
"Rules": "Normal",
"ScavMaxPlayersInGroup": 4,
"Scene": {
"path": "",
"rcid": ""
},
"Area": 0,
"RequiredPlayerLevel": 0,
"MinPlayers": 6,
"MaxPlayers": 9,
"exit_count": 1,
"exit_access_time": 10,
"exit_time": 2,
"Preview": {
"path": "",
"rcid": ""
},
"IconX": 224,
"IconY": 646,
"filter_ex": [],
"UnixDateTime": 0,
"doors": [],
"limits": [],
"waves": [
{
"number": 0,
"time_min": 1,
"time_max": 2,
"slots_min": 3,
"slots_max": 6,
"SpawnPoints": "",
"BotSide": "Savage",
"BotPreset": "normal",
"BotSide": "Savage",
"KeepZoneOnSpawn": false,
"SpawnMode": [],
"SpawnPoints": "",
"WildSpawnType": "assault",
"isPlayers": false,
"WildSpawnType": "assault"
"number": 0,
"slots_max": 6,
"slots_min": 3,
"time_max": 2,
"time_min": 1
},
{
"number": 1,
"time_min": 10,
"time_max": 12,
"slots_min": 3,
"slots_max": 5,
"SpawnPoints": "",
"BotSide": "Usec",
"BotPreset": "hard",
"BotSide": "Usec",
"KeepZoneOnSpawn": false,
"SpawnMode": [],
"SpawnPoints": "",
"WildSpawnType": "assault",
"isPlayers": false,
"WildSpawnType": "assault"
"number": 1,
"slots_max": 5,
"slots_min": 3,
"time_max": 12,
"time_min": 10
}
],
"limits": [],
"AveragePlayTime": 100,
"AveragePlayerLevel": 10,
"escape_time_limit": 0,
"Rules": "Normal",
"IsSecret": true,
"doors": [],
"tmp_location_field_remove_me": 0,
"MinDistToExitPoint": 30,
"MaxDistToFreePoint": 900,
"MinDistToFreePoint": 10,
"MaxBotPerZone": 0,
"OpenZones": "",
"OcculsionCullingEnabled": false,
"GlobalLootChanceModifier": 1,
"OldSpawn": true,
"NewSpawn": false,
"BotMax": 0,
"BotStart": 0,
"BotStop": 0,
"BotMaxTimePlayer": 0,
"BotSpawnTimeOnMin": 0,
"BotSpawnTimeOnMax": 0,
"BotSpawnTimeOffMin": 0,
"BotSpawnTimeOffMax": 0,
"BotMaxPlayer": 0,
"BotEasy": 0,
"BotNormal": 0,
"BotHard": 0,
"BotImpossible": 0,
"BotAssault": 0,
"BotMarksman": 0,
"DisabledScavExits": "",
"AccessKeys": [],
"UnixDateTime": 0,
"users_gather_seconds": 120,
"users_spawn_seconds_n": 60,
"users_spawn_seconds_n2": 90,
"users_summon_seconds": 0,
"sav_summon_seconds": 60,
"matching_min_seconds": 120,
"MinMaxBots": [],
"BotLocationModifier": {
"AccuracySpeed": 0,
"Scattering": 0,
"DistToActivatePvE": 0,
"DistToSleepPvE": 0,
"FogVisibilityDistanceCoef": 0,
"FogVisibilitySpeedCoef": 0,
"GainSight": 0,
"MarksmanAccuratyCoef": 0,
"VisibleDistance": 0
"RainVisibilityDistanceCoef": 0,
"RainVisibilitySpeedCoef": 0,
"Scattering": 0,
"VisibleDistance": 0,
"DistToActivate": 0,
"DistToSleep": 0
},
"exits": [],
"DisabledForScav": false,
"MinMaxBots": [],
"SpawnPointParams": [],
"exits": [],
"maxItemCountInLocation": [],
"Id": "Private Area",
"_Id": "5704e64ad2720bb55b8b456e",
@@ -109,15 +152,19 @@
{
"id": "5803a58524597710ca36fcb2",
"pic": {
"path": "CONTENT/banners/banner_terragroup.jpg",
"rcid": ""
"file": "67e404d9bec96f5d8e097331.jpg",
"path": "banners/67e404d9bec96f5d8e097331.jpg",
"rcid": "",
"type": "banners"
}
},
{
"id": "5c1b857086f77465f465faa4",
"pic": {
"path": "CONTENT/banners/banner_scavraider.jpg",
"rcid": ""
"file": "67e404c5bec96f5d8e09732f.jpg",
"path": "banners/67e404c5bec96f5d8e09732f.jpg",
"rcid": "",
"type": "banners"
}
}
],
@@ -1,101 +1,149 @@
{
"AccessKeys": [],
"AccessKeysPvE": [],
"Area": 0,
"AveragePlayTime": 100,
"AveragePlayerLevel": 10,
"BotAssault": 0,
"BotEasy": 0,
"BotHard": 0,
"BotImpossible": 0,
"BotMarksman": 0,
"BotMax": 0,
"BotMaxPvE": 0,
"BotNormal": 0,
"BotSpawnCountStep": 3,
"BotSpawnPeriodCheck": 15,
"BotSpawnTimeOffMax": 0,
"BotSpawnTimeOffMin": 0,
"BotSpawnTimeOnMax": 0,
"BotSpawnTimeOnMin": 0,
"BotStart": 0,
"BotStartPlayer": 0,
"BotStop": 0,
"DisabledScavExits": "",
"EnableCoop": true,
"Enabled": false,
"EscapeTimeLimit": 0,
"EscapeTimeLimitCoop": 0,
"ForceOnlineRaidInPVE": false,
"GlobalContainerChanceModifier": 1,
"HeatmapCellSize": {
"x": 1,
"y": 2,
"z": 1
},
"HeatmapLayers": [
"AllCharactersPositions",
"AllBotsPositions",
"AllRealPlayersPositions",
"RealPlayersSavagesPositions",
"RealPlayersSavagesDeads",
"RealPlayersSavagesDamages",
"RealPlayersPmcPositions",
"RealPlayersPmcDeads",
"RealPlayersPmcDamages",
"RealPlayersPmcLaydownPositions",
"RealPlayersPmcEquipmentDropPositions",
"RealPlayersPmcHealingPositions",
"BotsBossPositions",
"BotsBossDeads",
"BotsBossDamages",
"BotsSavagesPositions",
"BotsSavagesDeads",
"BotsSavagesDamages",
"AllCharactersDamageSources",
"RealPlayerDamageSources",
"BotsDamageSources",
"LootPositions"
],
"IconX": 480,
"IconY": 577,
"IsSecret": false,
"Locked": true,
"Insurance": false,
"SafeLocation": false,
"MaxBotPerZone": 0,
"MaxCoopGroup": 9,
"MaxDistToFreePoint": 900,
"MaxPlayers": 9,
"MinDistToFreePoint": 10,
"MinPlayerLvlAccessKeys": 0,
"MinPlayers": 6,
"Name": "Suburbs",
"NewSpawn": false,
"NewSpawnForPlayers": false,
"NonWaveGroupScenario": {
"Chance": 50,
"Enabled": true,
"MaxToBeGroup": 3,
"MinToBeGroup": 2
},
"OcculsionCullingEnabled": false,
"OfflineNewSpawn": true,
"OfflineOldSpawn": true,
"OldSpawn": true,
"OpenZones": "",
"PlayersRequestCount": -1,
"PmcMaxPlayersInGroup": 5,
"RequiredPlayerLevelMax": 100,
"RequiredPlayerLevelMin": 0,
"Rules": "Normal",
"ScavMaxPlayersInGroup": 4,
"Scene": {
"path": "",
"rcid": ""
},
"Area": 0,
"RequiredPlayerLevel": 0,
"MinPlayers": 6,
"MaxPlayers": 9,
"exit_count": 0,
"exit_access_time": 0,
"exit_time": 0,
"IconX": 480,
"IconY": 577,
"UnixDateTime": 0,
"doors": [],
"limits": [],
"waves": [
{
"number": 0,
"time_min": 1,
"time_max": 2,
"slots_min": 3,
"slots_max": 6,
"SpawnPoints": "",
"BotSide": "Savage",
"BotPreset": "normal",
"BotSide": "Savage",
"KeepZoneOnSpawn": false,
"SpawnMode": [],
"SpawnPoints": "",
"WildSpawnType": "assault",
"isPlayers": false,
"WildSpawnType": "assault"
"number": 0,
"slots_max": 6,
"slots_min": 3,
"time_max": 2,
"time_min": 1
},
{
"number": 1,
"time_min": 10,
"time_max": 12,
"slots_min": 3,
"slots_max": 5,
"SpawnPoints": "",
"BotSide": "Usec",
"BotPreset": "easy",
"BotSide": "Usec",
"KeepZoneOnSpawn": false,
"SpawnMode": [],
"SpawnPoints": "",
"WildSpawnType": "assault",
"isPlayers": false,
"WildSpawnType": "assault"
"number": 1,
"slots_max": 5,
"slots_min": 3,
"time_max": 12,
"time_min": 10
}
],
"limits": [],
"AveragePlayTime": 100,
"AveragePlayerLevel": 10,
"escape_time_limit": 0,
"Rules": "Normal",
"IsSecret": false,
"doors": [],
"tmp_location_field_remove_me": 0,
"MinDistToExitPoint": 0,
"MaxDistToFreePoint": 900,
"MinDistToFreePoint": 10,
"MaxBotPerZone": 0,
"OpenZones": "",
"OcculsionCullingEnabled": false,
"GlobalLootChanceModifier": 0,
"OldSpawn": true,
"NewSpawn": false,
"BotMax": 0,
"BotStart": 0,
"BotStop": 0,
"BotMaxTimePlayer": 0,
"BotSpawnTimeOnMin": 0,
"BotSpawnTimeOnMax": 0,
"BotSpawnTimeOffMin": 0,
"BotSpawnTimeOffMax": 0,
"BotMaxPlayer": 0,
"BotEasy": 0,
"BotNormal": 0,
"BotHard": 0,
"BotImpossible": 0,
"BotAssault": 0,
"BotMarksman": 0,
"DisabledScavExits": "",
"AccessKeys": [],
"UnixDateTime": 0,
"users_gather_seconds": 0,
"users_spawn_seconds_n": 0,
"users_spawn_seconds_n2": 0,
"users_summon_seconds": 0,
"sav_summon_seconds": 0,
"matching_min_seconds": 0,
"MinMaxBots": [],
"BotLocationModifier": {
"AccuracySpeed": 0,
"Scattering": 0,
"DistToActivatePvE": 0,
"DistToSleepPvE": 0,
"FogVisibilityDistanceCoef": 0,
"FogVisibilitySpeedCoef": 0,
"GainSight": 0,
"MarksmanAccuratyCoef": 0,
"VisibleDistance": 0
"RainVisibilityDistanceCoef": 0,
"RainVisibilitySpeedCoef": 0,
"Scattering": 0,
"VisibleDistance": 0,
"DistToActivate": 0,
"DistToSleep": 0
},
"exits": [],
"DisabledForScav": false,
"BossLocationSpawn": [],
"MinMaxBots": [],
"SpawnPointParams": [],
"exits": [],
"maxItemCountInLocation": [],
"Id": "Suburbs",
"_Id": "5714dc342459777137212e0b",
@@ -104,16 +152,21 @@
{
"id": "5807be8924597742c603fa19",
"pic": {
"path": "CONTENT/banners/banner_tarkov.jpg",
"rcid": ""
"file": "67e4046dbec96f5d8e09732a.jpg",
"path": "banners/67e4046dbec96f5d8e09732a.jpg",
"rcid": "",
"type": "banners"
}
},
{
"id": "5c1b857086f77465f465faa4",
"pic": {
"path": "CONTENT/banners/banner_scavraider.jpg",
"rcid": ""
"file": "67e404c5bec96f5d8e09732f.jpg",
"path": "banners/67e404c5bec96f5d8e09732f.jpg",
"rcid": "",
"type": "banners"
}
}
]
],
"BossLocationSpawn": []
}
@@ -1,104 +1,161 @@
{
"AccessKeys": [],
"AccessKeysPvE": [],
"Area": 0,
"AveragePlayTime": 100,
"AveragePlayerLevel": 10,
"BotAssault": 0,
"BotEasy": 0,
"BotHard": 0,
"BotImpossible": 0,
"BotMarksman": 0,
"BotMax": 0,
"BotMaxPvE": 0,
"BotNormal": 0,
"BotSpawnCountStep": 3,
"BotSpawnPeriodCheck": 15,
"BotSpawnTimeOffMax": 0,
"BotSpawnTimeOffMin": 0,
"BotSpawnTimeOnMax": 0,
"BotSpawnTimeOnMin": 0,
"BotStart": 0,
"BotStartPlayer": 0,
"BotStop": 0,
"DisabledScavExits": "",
"EnableCoop": true,
"Enabled": true,
"EscapeTimeLimit": 0,
"EscapeTimeLimitCoop": 0,
"ForceOnlineRaidInPVE": false,
"GlobalContainerChanceModifier": 1,
"HeatmapCellSize": {
"x": 1,
"y": 2,
"z": 1
},
"HeatmapLayers": [
"AllCharactersPositions",
"AllBotsPositions",
"AllRealPlayersPositions",
"RealPlayersSavagesPositions",
"RealPlayersSavagesDeads",
"RealPlayersSavagesDamages",
"RealPlayersPmcPositions",
"RealPlayersPmcDeads",
"RealPlayersPmcDamages",
"RealPlayersPmcLaydownPositions",
"RealPlayersPmcEquipmentDropPositions",
"RealPlayersPmcHealingPositions",
"BotsBossPositions",
"BotsBossDeads",
"BotsBossDamages",
"BotsSavagesPositions",
"BotsSavagesDeads",
"BotsSavagesDamages",
"AllCharactersDamageSources",
"RealPlayerDamageSources",
"BotsDamageSources",
"LootPositions"
],
"IconX": 280,
"IconY": 160,
"IsSecret": false,
"Locked": true,
"Insurance": false,
"SafeLocation": false,
"MaxBotPerZone": 0,
"MaxCoopGroup": 9,
"MaxDistToFreePoint": 900,
"MaxPlayers": 9,
"MinDistToFreePoint": 10,
"MinPlayerLvlAccessKeys": 0,
"MinPlayers": 6,
"Name": "Terminal",
"NewSpawn": false,
"NewSpawnForPlayers": false,
"NonWaveGroupScenario": {
"Chance": 50,
"Enabled": true,
"MaxToBeGroup": 3,
"MinToBeGroup": 2
},
"OcculsionCullingEnabled": false,
"OfflineNewSpawn": true,
"OfflineOldSpawn": true,
"OldSpawn": true,
"OpenZones": "",
"PlayersRequestCount": -1,
"PmcMaxPlayersInGroup": 5,
"RequiredPlayerLevelMax": 100,
"RequiredPlayerLevelMin": 0,
"Rules": "Normal",
"ScavMaxPlayersInGroup": 4,
"Scene": {
"path": "",
"rcid": ""
},
"Area": 0,
"RequiredPlayerLevel": 0,
"MinPlayers": 6,
"MaxPlayers": 9,
"exit_count": 0,
"exit_access_time": 0,
"exit_time": 0,
"IconX": 280,
"IconY": 160,
"UnixDateTime": 0,
"doors": [],
"limits": [],
"waves": [
{
"number": 0,
"time_min": 1,
"time_max": 2,
"slots_min": 3,
"slots_max": 6,
"SpawnPoints": "",
"BotSide": "Savage",
"BotPreset": "easy",
"BotSide": "Savage",
"KeepZoneOnSpawn": false,
"SpawnMode": [],
"SpawnPoints": "",
"WildSpawnType": "assault",
"isPlayers": false,
"WildSpawnType": "assault"
"number": 0,
"slots_max": 6,
"slots_min": 3,
"time_max": 2,
"time_min": 1
},
{
"number": 1,
"time_min": 10,
"time_max": 12,
"slots_min": 3,
"slots_max": 5,
"SpawnPoints": "",
"BotSide": "Savage",
"BotPreset": "easy",
"BotSide": "Savage",
"KeepZoneOnSpawn": false,
"SpawnMode": [],
"SpawnPoints": "",
"WildSpawnType": "assault",
"isPlayers": false,
"WildSpawnType": "assault"
"number": 1,
"slots_max": 5,
"slots_min": 3,
"time_max": 12,
"time_min": 10
}
],
"limits": [],
"AveragePlayTime": 100,
"AveragePlayerLevel": 10,
"escape_time_limit": 0,
"Rules": "Normal",
"IsSecret": false,
"doors": [],
"tmp_location_field_remove_me": 0,
"MinDistToExitPoint": 0,
"MaxDistToFreePoint": 900,
"MinDistToFreePoint": 10,
"MaxBotPerZone": 0,
"OpenZones": "",
"OcculsionCullingEnabled": false,
"GlobalLootChanceModifier": 0,
"OldSpawn": true,
"NewSpawn": false,
"BotMax": 0,
"BotStart": 0,
"BotStop": 0,
"BotMaxTimePlayer": 0,
"BotSpawnTimeOnMin": 0,
"BotSpawnTimeOnMax": 0,
"BotSpawnTimeOffMin": 0,
"BotSpawnTimeOffMax": 0,
"BotMaxPlayer": 0,
"BotEasy": 0,
"BotNormal": 0,
"BotHard": 0,
"BotImpossible": 0,
"BotAssault": 0,
"BotMarksman": 0,
"DisabledScavExits": "",
"AccessKeys": [],
"UnixDateTime": 0,
"users_gather_seconds": 0,
"users_spawn_seconds_n": 0,
"users_spawn_seconds_n2": 0,
"users_summon_seconds": 0,
"sav_summon_seconds": 0,
"matching_min_seconds": 0,
"MinMaxBots": [],
"BotLocationModifier": {
"AccuracySpeed": 0,
"Scattering": 0,
"DistToActivatePvE": 0,
"DistToSleepPvE": 0,
"FogVisibilityDistanceCoef": 0,
"FogVisibilitySpeedCoef": 0,
"GainSight": 0,
"LockSpawnCheckRadius": 150,
"LockSpawnCheckRadiusPvE": 150,
"LockSpawnStartTime": 10,
"LockSpawnStartTimePvE": 10,
"LockSpawnStepTime": 50,
"LockSpawnStepTimePvE": 50,
"MarksmanAccuratyCoef": 0,
"VisibleDistance": 0
"NonWaveSpawnBotsLimitPerPlayer": 10,
"NonWaveSpawnBotsLimitPerPlayerPvE": 15,
"RainVisibilityDistanceCoef": 0,
"RainVisibilitySpeedCoef": 0,
"Scattering": 0,
"VisibleDistance": 0,
"DistToActivate": 0,
"DistToSleep": 0
},
"exits": [],
"DisabledForScav": false,
"BossLocationSpawn": [],
"MinMaxBots": [],
"SpawnPointParams": [],
"exits": [],
"maxItemCountInLocation": [],
"Id": "Terminal",
"_Id": "5704e5a4d2720bb45b8b4567",
"Loot": [],
"Banners": []
"Banners": [],
"BossLocationSpawn": []
}
@@ -1,101 +1,149 @@
{
"AccessKeys": [],
"AccessKeysPvE": [],
"Area": 0,
"AveragePlayTime": 100,
"AveragePlayerLevel": 10,
"BotAssault": 0,
"BotEasy": 0,
"BotHard": 0,
"BotImpossible": 0,
"BotMarksman": 0,
"BotMax": 0,
"BotMaxPvE": 0,
"BotNormal": 0,
"BotSpawnCountStep": 3,
"BotSpawnPeriodCheck": 15,
"BotSpawnTimeOffMax": 0,
"BotSpawnTimeOffMin": 0,
"BotSpawnTimeOnMax": 0,
"BotSpawnTimeOnMin": 0,
"BotStart": 0,
"BotStartPlayer": 0,
"BotStop": 0,
"DisabledScavExits": "",
"EnableCoop": true,
"Enabled": false,
"EscapeTimeLimit": 0,
"EscapeTimeLimitCoop": 0,
"ForceOnlineRaidInPVE": false,
"GlobalContainerChanceModifier": 1,
"HeatmapCellSize": {
"x": 1,
"y": 2,
"z": 1
},
"HeatmapLayers": [
"AllCharactersPositions",
"AllBotsPositions",
"AllRealPlayersPositions",
"RealPlayersSavagesPositions",
"RealPlayersSavagesDeads",
"RealPlayersSavagesDamages",
"RealPlayersPmcPositions",
"RealPlayersPmcDeads",
"RealPlayersPmcDamages",
"RealPlayersPmcLaydownPositions",
"RealPlayersPmcEquipmentDropPositions",
"RealPlayersPmcHealingPositions",
"BotsBossPositions",
"BotsBossDeads",
"BotsBossDamages",
"BotsSavagesPositions",
"BotsSavagesDeads",
"BotsSavagesDamages",
"AllCharactersDamageSources",
"RealPlayerDamageSources",
"BotsDamageSources",
"LootPositions"
],
"IconX": 72,
"IconY": 413,
"IsSecret": false,
"Locked": true,
"Insurance": false,
"SafeLocation": false,
"MaxBotPerZone": 0,
"MaxCoopGroup": 9,
"MaxDistToFreePoint": 900,
"MaxPlayers": 9,
"MinDistToFreePoint": 10,
"MinPlayerLvlAccessKeys": 0,
"MinPlayers": 6,
"Name": "Town",
"NewSpawn": false,
"NewSpawnForPlayers": false,
"NonWaveGroupScenario": {
"Chance": 50,
"Enabled": true,
"MaxToBeGroup": 3,
"MinToBeGroup": 2
},
"OcculsionCullingEnabled": false,
"OfflineNewSpawn": true,
"OfflineOldSpawn": true,
"OldSpawn": true,
"OpenZones": "",
"PlayersRequestCount": -1,
"PmcMaxPlayersInGroup": 5,
"RequiredPlayerLevelMax": 100,
"RequiredPlayerLevelMin": 0,
"Rules": "Normal",
"ScavMaxPlayersInGroup": 4,
"Scene": {
"path": "",
"rcid": ""
},
"Area": 0,
"RequiredPlayerLevel": 0,
"MinPlayers": 6,
"MaxPlayers": 9,
"exit_count": 0,
"exit_access_time": 0,
"exit_time": 0,
"IconX": 72,
"IconY": 413,
"UnixDateTime": 0,
"doors": [],
"limits": [],
"waves": [
{
"number": 0,
"time_min": 1,
"time_max": 2,
"slots_min": 3,
"slots_max": 6,
"SpawnPoints": "",
"BotSide": "Usec",
"BotPreset": "hard",
"BotSide": "Usec",
"KeepZoneOnSpawn": false,
"SpawnMode": [],
"SpawnPoints": "",
"WildSpawnType": "assault",
"isPlayers": false
"isPlayers": false,
"number": 0,
"slots_max": 6,
"slots_min": 3,
"time_max": 2,
"time_min": 1
},
{
"number": 1,
"time_min": 10,
"time_max": 12,
"slots_min": 3,
"slots_max": 5,
"SpawnPoints": "",
"BotSide": "Savage",
"BotPreset": "normal",
"BotSide": "Savage",
"KeepZoneOnSpawn": false,
"SpawnMode": [],
"SpawnPoints": "",
"WildSpawnType": "assault",
"isPlayers": false
"isPlayers": false,
"number": 1,
"slots_max": 5,
"slots_min": 3,
"time_max": 12,
"time_min": 10
}
],
"limits": [],
"AveragePlayTime": 100,
"AveragePlayerLevel": 10,
"escape_time_limit": 0,
"Rules": "Normal",
"IsSecret": false,
"doors": [],
"tmp_location_field_remove_me": 0,
"MinDistToExitPoint": 0,
"MaxDistToFreePoint": 900,
"MinDistToFreePoint": 10,
"MaxBotPerZone": 0,
"OpenZones": "",
"OcculsionCullingEnabled": false,
"GlobalLootChanceModifier": 0,
"OldSpawn": true,
"NewSpawn": false,
"BotMax": 0,
"BotStart": 0,
"BotStop": 0,
"BotMaxTimePlayer": 0,
"BotSpawnTimeOnMin": 0,
"BotSpawnTimeOnMax": 0,
"BotSpawnTimeOffMin": 0,
"BotSpawnTimeOffMax": 0,
"BotMaxPlayer": 0,
"BotEasy": 0,
"BotNormal": 0,
"BotHard": 0,
"BotImpossible": 0,
"BotAssault": 0,
"BotMarksman": 0,
"DisabledScavExits": "",
"AccessKeys": [],
"UnixDateTime": 0,
"users_gather_seconds": 0,
"users_spawn_seconds_n": 0,
"users_spawn_seconds_n2": 0,
"users_summon_seconds": 0,
"sav_summon_seconds": 0,
"matching_min_seconds": 0,
"MinMaxBots": [],
"BotLocationModifier": {
"AccuracySpeed": 0,
"Scattering": 0,
"DistToActivatePvE": 0,
"DistToSleepPvE": 0,
"FogVisibilityDistanceCoef": 0,
"FogVisibilitySpeedCoef": 0,
"GainSight": 0,
"MarksmanAccuratyCoef": 0,
"VisibleDistance": 0
"RainVisibilityDistanceCoef": 0,
"RainVisibilitySpeedCoef": 0,
"Scattering": 0,
"VisibleDistance": 0,
"DistToActivate": 0,
"DistToSleep": 0
},
"exits": [],
"DisabledForScav": false,
"BossLocationSpawn": [],
"MinMaxBots": [],
"SpawnPointParams": [],
"exits": [],
"maxItemCountInLocation": [],
"Id": "Town",
"_Id": "5704e47ed2720bb35b8b4568",
@@ -104,16 +152,21 @@
{
"id": "5464e0454bdc2d06708b4567",
"pic": {
"path": "CONTENT/banners/banner_bear.jpg",
"rcid": ""
"file": "67e4045225a1aca9270117e7.jpg",
"path": "banners/67e4045225a1aca9270117e7.jpg",
"rcid": "",
"type": "banners"
}
},
{
"id": "5c1b857086f77465f465faa4",
"pic": {
"path": "CONTENT/banners/banner_scavraider.jpg",
"rcid": ""
"file": "67e404c5bec96f5d8e09732f.jpg",
"path": "banners/67e404c5bec96f5d8e09732f.jpg",
"rcid": "",
"type": "banners"
}
}
]
],
"BossLocationSpawn": []
}
@@ -17,7 +17,15 @@
</PropertyGroup>
<ItemGroup>
<None Include="build\PostBuild.cs" />
<None Include="SPT_Data\**">
<None Include="SPT_Data\**" Exclude="SPT_Data\checks.dat">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<PackageCopyToOutput>True</PackageCopyToOutput>
<ExcludeFromSingleFile>True</ExcludeFromSingleFile>
<buildAction>None</buildAction>
<Pack>true</Pack>
<PackagePath>contentFiles\any\any\SPT_Data\</PackagePath>
</None>
<None Include="SPT_Data\checks.dat" Condition="'$(Configuration)' == 'Release'">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<PackageCopyToOutput>True</PackageCopyToOutput>
<ExcludeFromSingleFile>True</ExcludeFromSingleFile>
@@ -26,8 +34,11 @@
<PackagePath>contentFiles\any\any\SPT_Data\</PackagePath>
</None>
</ItemGroup>
<Target Name="PostBuildHashFile" AfterTargets="Build" Condition="'$(Configuration)' == 'Release'">
<Exec Command="pwsh -NoProfile -ExecutionPolicy Bypass -File &quot;$(ProjectDir)PostBuild.ps1&quot;" />
<Target Name="PreBuildHashFile" BeforeTargets="BeforeBuild" Condition="'$(Configuration)' == 'Release'">
<Exec Command="pwsh -NoProfile -ExecutionPolicy Bypass -File &quot;$(ProjectDir)PostBuild.ps1&quot;">
<Output TaskParameter="ExitCode" PropertyName="HashFileExitCode" />
</Exec>
<Error Message="Failed to hash files" Condition=" '$(HashFileExitCode)' != '0'" />
</Target>
<ItemGroup>
<Compile Remove="build\PostBuild.cs" />
@@ -842,7 +842,7 @@ public class InsuranceController(
)
)
{
logger.Warning(
logger.Debug(
$"Unable to add item id: {itemId.ToString()} to client/insurance/items/list/cost response, already exists"
);
}
@@ -509,7 +509,7 @@ public class InventoryController(
return presetHelper.GetBaseItemTpl(request.ItemId);
}
if (request.FromOwner.Id == Traders.FENCE)
if (Traders.FENCE.Equals(request.FromOwner.Id))
// Get tpl from fence assorts
{
return fenceService.GetRawFenceAssorts().Items.FirstOrDefault(x => x.Id == request.ItemId)?.Template;
@@ -519,10 +519,7 @@ public class InventoryController(
// Not fence
// get tpl from trader assort
{
return databaseService
.GetTrader(request.FromOwner.Id.Value)
.Assort.Items.FirstOrDefault(item => item.Id == request.ItemId)
?.Template;
return databaseService.GetTrader(request.FromOwner.Id).Assort.Items.FirstOrDefault(item => item.Id == request.ItemId)?.Template;
}
if (request.FromOwner.Type == "RagFair")
@@ -536,7 +533,7 @@ public class InventoryController(
// Try alternate way of getting offer if first approach fails
var offer =
ragfairOfferService.GetOfferByOfferId(request.ItemId) ?? ragfairOfferService.GetOfferByOfferId(request.FromOwner.Id.Value);
ragfairOfferService.GetOfferByOfferId(request.ItemId) ?? ragfairOfferService.GetOfferByOfferId(request.FromOwner.Id);
// Try find examine item inside offer items array
var matchingItem = offer.Items.FirstOrDefault(offerItem => offerItem.Id == request.ItemId);
@@ -555,6 +552,12 @@ public class InventoryController(
return request.ItemId;
}
// Hideout upgrade
if (request.FromOwner.Type == "HideoutUpgrade")
{
return request.ItemId;
}
if (request.FromOwner.Type == "Mail")
{
// when inspecting an item in mail rewards, we are given on the message its in and its mongoId, not the Template, so we have to go find it ourselves
@@ -343,7 +343,7 @@ public class RagfairController(
var offers = ragfairOfferService.GetOffersOfType(getPriceRequest.TemplateId);
// Offers exist for item, get averages of what's listed
if (offers.Any())
if (offers != null && offers.Any())
{
// These get calculated while iterating through the list below
var minMax = new MinMax<double>(int.MaxValue, 0);
@@ -858,7 +858,7 @@ public class RagfairController(
if (logger.IsLogEnabled(LogLevel.Debug))
{
logger.Debug($"Offer tax to charge: {tax}, pulled from client: {storedClientTaxValue.Count is not null}");
logger.Debug($"Offer tax to charge: {tax}, pulled from client: {storedClientTaxValue?.Count is not null}");
}
// Cleanup of cache now we've used the tax value from it
@@ -0,0 +1,5 @@
using SPTarkov.Server.Core.Helpers.Dialog.Commando;
namespace SPTarkov.Server.Core.Helpers.Dialogue.Commando;
public interface ICommandoCommand : IChatCommand { }
@@ -1,5 +1,6 @@
using SPTarkov.DI.Annotations;
using SPTarkov.Server.Core.Helpers.Dialog.Commando.SptCommands;
using SPTarkov.Server.Core.Helpers.Dialogue.Commando;
using SPTarkov.Server.Core.Models.Common;
using SPTarkov.Server.Core.Models.Eft.Dialog;
using SPTarkov.Server.Core.Models.Eft.Profile;
@@ -10,7 +11,7 @@ using SPTarkov.Server.Core.Services;
namespace SPTarkov.Server.Core.Helpers.Dialog.Commando;
[Injectable]
public class SptCommandoCommands : IChatCommand
public class SptCommandoCommands : ICommandoCommand
{
protected readonly ServerLocalisationService _serverLocalisationService;
protected readonly IDictionary<string, ISptCommand> _sptCommands;
@@ -1,5 +1,6 @@
using SPTarkov.DI.Annotations;
using SPTarkov.Server.Core.Helpers.Dialog.Commando;
using SPTarkov.Server.Core.Helpers.Dialogue.Commando;
using SPTarkov.Server.Core.Models.Eft.Profile;
using SPTarkov.Server.Core.Models.Enums;
using SPTarkov.Server.Core.Models.Spt.Config;
@@ -15,7 +16,7 @@ public class CommandoDialogChatBot(
MailSendService mailSendService,
ServerLocalisationService localisationService,
ConfigServer configServer,
IEnumerable<IChatCommand> chatCommands
IEnumerable<ICommandoCommand> chatCommands
) : AbstractDialogChatBot(logger, mailSendService, localisationService, chatCommands)
{
protected readonly CoreConfig CoreConfig = configServer.GetConfig<CoreConfig>();
@@ -860,7 +860,7 @@ public class InventoryHelper(
else if (string.Equals(request.FromOwner.Type, "mail", StringComparison.OrdinalIgnoreCase))
{
// Split requests don't use 'use' but 'splitItem' property
fromInventoryItems = dialogueHelper.GetMessageItemContents(request.FromOwner.Id.Value, sessionId, itemId);
fromInventoryItems = dialogueHelper.GetMessageItemContents(request.FromOwner.Id, sessionId, itemId);
fromType = "mail";
}
}
@@ -28,7 +28,6 @@ public class PrestigeHelper(
var indexOfPrestigeObtained = Math.Clamp((prestige.PrestigeLevel ?? 1) - 1, 0, prestigeLevels.Count - 1); // Levels are 1 to 4, Index is 0 to 3
// Skill copy
var skillProgressCopyAmount = (float)(1 - prestigeLevels[indexOfPrestigeObtained].TransferConfigs.SkillConfig.TransferMultiplier);
var masteringProgressCopyAmount = (float)(
1 - prestigeLevels[indexOfPrestigeObtained].TransferConfigs.MasteringConfig.TransferMultiplier
@@ -90,6 +89,9 @@ public class PrestigeHelper(
AddPrestigeRewardsToProfile(sessionId!.Value, newProfile, prestigeRewards);
// Copy profile stats
CopyStats(newProfile, oldProfile);
// Flag profile as having achieved this prestige level
if (newProfile.CharacterData?.PmcData?.Prestige?.TryAdd(currentPrestigeData!.Id, timeUtil.GetTimeStamp()) is false)
{
@@ -126,6 +128,36 @@ public class PrestigeHelper(
newProfile.CharacterData!.PmcData!.Info!.PrestigeLevel = prestige.PrestigeLevel;
}
/// <summary>
/// Copy over profile stats from old profile to new
/// Remove some stats once copied over
/// </summary>
/// <param name="newProfile">Profile to add stats to</param>
/// <param name="oldProfile">Profile to copy stats from</param>
protected void CopyStats(SptProfile newProfile, SptProfile oldProfile)
{
var newPmcStats = newProfile.CharacterData.PmcData.Stats;
var oldPmcStats = oldProfile.CharacterData.PmcData.Stats;
newPmcStats.Eft = oldPmcStats.Eft;
// Reset some PMC stats that should not be copied over
newPmcStats.Eft.CarriedQuestItems = [];
newPmcStats.Eft.FoundInRaidItems = [];
newPmcStats.Eft.LastSessionDate = 0;
// TODO: find evidence scav stats are copied over in live
//var newScavStats = newProfile.CharacterData.ScavData.Stats;
//var oldScavStats = oldProfile.CharacterData.ScavData.Stats;
//newPmcStats.Eft = oldScavStats.Eft;
//// Reset some Scav stats that should not be copied over
//newScavStats.Eft.CarriedQuestItems = [];
//newScavStats.Eft.FoundInRaidItems = [];
//newScavStats.Eft.LastSessionDate = 0;
}
private void AddPrestigeRewardsToProfile(MongoId sessionId, SptProfile newProfile, IEnumerable<Reward> rewards)
{
var itemsToSend = new List<Item>();
@@ -1245,7 +1245,7 @@ public class QuestHelper(
}
/// <summary>
/// Create a clone of the given quest Collection with the rewards updated to reflect the given game version
/// Remove rewards from quests that do not fulfil the gameversion requirement
/// </summary>
/// <param name="quests">List of quests to check</param>
/// <param name="gameVersion">Game version of the profile</param>
@@ -1255,15 +1255,15 @@ public class QuestHelper(
foreach (var quest in quests)
{
// Remove any reward that doesn't pass the game edition check
var propsAsDict = quest.Rewards;
foreach (var rewardType in propsAsDict)
foreach (var rewardType in quest.Rewards)
{
if (rewardType.Value is null)
{
continue;
}
propsAsDict[rewardType.Key] = propsAsDict[rewardType.Key]
quest.Rewards[rewardType.Key] = quest
.Rewards[rewardType.Key]
.Where(reward => rewardHelper.RewardIsForGameEdition(reward, gameVersion))
.ToList();
}
@@ -14,6 +14,7 @@ using SPTarkov.Server.Core.Routers;
using SPTarkov.Server.Core.Servers;
using SPTarkov.Server.Core.Services;
using SPTarkov.Server.Core.Utils;
using SPTarkov.Server.Core.Utils.Cloners;
namespace SPTarkov.Server.Core.Helpers;
@@ -38,7 +39,8 @@ public class RagfairOfferHelper(
RagfairRequiredItemsService ragfairRequiredItemsService,
ProfileHelper profileHelper,
EventOutputHolder eventOutputHolder,
ConfigServer configServer
ConfigServer configServer,
ICloner cloner
)
{
protected const string GoodSoldTemplate = "5bdabfb886f7743e152e867e 0"; // Your {soldItem} {itemCount} items were bought by {buyerNickname}.
@@ -63,8 +65,10 @@ public class RagfairOfferHelper(
var playerIsFleaBanned = pmcData.PlayerIsFleaBanned(timeUtil.GetTimeStamp());
var tieredFlea = RagfairConfig.TieredFlea;
var tieredFleaLimitTypes = tieredFlea.UnlocksType;
return ragfairOfferService
.GetOffers()
// Clone offers if tiered flea is enabled as we perform modification of offer data prior to return
var offers = tieredFlea.Enabled ? cloner.Clone(ragfairOfferService.GetOffers()) : ragfairOfferService.GetOffers();
return offers
.Where(offer =>
{
var offerRootItem = offer.Items.FirstOrDefault();
@@ -128,6 +132,7 @@ public class RagfairOfferHelper(
{
// Lock the offer if player's level is below the ammo's unlock requirement
offer.Locked = true;
offer.User.Nickname = $"Unlock level: {unlockLevel}";
return;
}
@@ -140,6 +145,7 @@ public class RagfairOfferHelper(
{
// Lock the offer if player's level is below the item's specific requirement
offer.Locked = true;
offer.User.Nickname = $"Unlock level: {itemLevelRequirement}";
return;
}
@@ -152,14 +158,22 @@ public class RagfairOfferHelper(
}
// Check if the item belongs to any restricted type and if player level is insufficient
if (
tieredFleaLimitTypes
.Where(tieredItemType => itemHelper.IsOfBaseclass(offerItemTpl, tieredItemType))
.Any(tieredItemType => playerLevel < tieredFlea.UnlocksType[tieredItemType])
)
var matchingTypes = tieredFleaLimitTypes.Where(tieredItemType => itemHelper.IsOfBaseclass(offerItemTpl, tieredItemType));
if (!matchingTypes.Any())
{
return;
}
//Get all matches
var levelRequirements = tieredFlea.UnlocksType.Where(x => matchingTypes.Contains(x.Key)).Select(x => x.Value);
// Get highest requirement
var highestRequirement = levelRequirements.Max();
if (playerLevel < highestRequirement)
{
// Players level is below matching types requirement, flag as locked
offer.Locked = true;
offer.User.Nickname = $"Unlock level: {levelRequirements.Max()}";
}
}
@@ -182,7 +196,7 @@ public class RagfairOfferHelper(
var result = new List<RagfairOffer>();
foreach (
var offer in offerIDsForItem
.Select(ragfairOfferService.GetOfferByOfferId)
.Select(tieredFlea.Enabled ? cloner.Clone(ragfairOfferService.GetOfferByOfferId) : ragfairOfferService.GetOfferByOfferId) // Clone offer when tiered flea enabled as we may modify offer data
.Where(offer => PassesSearchFilterCriteria(searchRequest, offer, offer.Items.FirstOrDefault(), pmcData))
)
{
@@ -220,7 +234,10 @@ public class RagfairOfferHelper(
foreach (var desiredItemTpl in searchRequest.BuildItems)
{
var matchingOffers = ragfairOfferService.GetOffersOfType(desiredItemTpl.Key);
// Clone offers when tiered flea enabled as we may modify the offer
var matchingOffers = tieredFlea.Enabled
? cloner.Clone(ragfairOfferService.GetOffersOfType(desiredItemTpl.Key))
: ragfairOfferService.GetOffersOfType(desiredItemTpl.Key);
if (matchingOffers is null)
// No offers found for this item, skip
{
@@ -33,7 +33,8 @@ public class RagfairSortHelper(LocaleService localeService)
break;
case RagfairSort.OFFER_TITLE:
offers.Sort(SortOffersByName);
var locale = localeService.GetLocaleDb();
offers.Sort((offer, ragfairOffer) => SortOffersByName(offer, ragfairOffer, locale));
break;
case RagfairSort.PRICE:
@@ -75,14 +76,12 @@ public class RagfairSortHelper(LocaleService localeService)
return ratingA.CompareTo(ratingB);
}
protected int SortOffersByName(RagfairOffer a, RagfairOffer b)
protected int SortOffersByName(RagfairOffer a, RagfairOffer b, Dictionary<string, string> locale)
{
var locale = localeService.GetLocaleDb();
var tplA = a.Items[0].Template;
var tplB = b.Items[0].Template;
var nameA = locale.GetValueOrDefault($"{tplA} Name", tplA);
var nameB = locale.GetValueOrDefault($"{tplB} Name", tplB);
var tplA = a.Items.First().Template;
var tplB = b.Items.First().Template;
var nameA = locale.GetValueOrDefault($"{tplA} Name", tplA.ToString());
var nameB = locale.GetValueOrDefault($"{tplB} Name", tplB.ToString());
return string.CompareOrdinal(nameA, nameB);
}
@@ -586,7 +586,7 @@ public record BotLocationModifier
public double? AccuracySpeed { get; set; }
[JsonPropertyName("AdditionalHostilitySettings")]
public IEnumerable<AdditionalHostilitySettings> AdditionalHostilitySettings { get; set; }
public IEnumerable<AdditionalHostilitySettings>? AdditionalHostilitySettings { get; set; }
[JsonPropertyName("DistToActivate")]
public double? DistanceToActivate { get; set; }
@@ -18,7 +18,7 @@ public record BaseInteractionRequestData
public record OwnerInfo
{
[JsonPropertyName("id")]
public MongoId? Id { get; set; }
public string? Id { get; set; }
[JsonPropertyName("type")]
public string? Type { get; set; }
@@ -425,6 +425,7 @@ public record MasterySkill
public record CommonSkill
{
[JsonConverter(typeof(SafeDoubleConverter))]
public double PointsEarnedDuringSession { get; set; }
public long LastAccess { get; set; }
@@ -131,6 +131,12 @@ public record BotConfig : BaseConfig
/// </summary>
[JsonPropertyName("weeklyBoss")]
public required WeeklyBossSettings WeeklyBoss { get; set; }
/// <summary>
/// Replace all scavs across all maps with the provided WildSpawnType
/// </summary>
[JsonPropertyName("replaceScavWith")]
public required WildSpawnType ReplaceScavWith { get; set; }
}
public record WeeklyBossSettings
@@ -1,4 +1,6 @@
using Range = SemanticVersioning.Range;
using System.Text.Json.Serialization;
using SPTarkov.Server.Core.Utils.Json.Converters;
using Range = SemanticVersioning.Range;
using Version = SemanticVersioning.Version;
namespace SPTarkov.Server.Core.Models.Spt.Mod;
@@ -40,6 +42,7 @@ public abstract record AbstractModMetadata
/// <br/>
/// Version = new Version("1.0.0.0"); is not
/// </summary>
[JsonConverter(typeof(ToStringJsonConverter<Version>))]
public abstract Version Version { get; init; }
/// <summary>
@@ -49,6 +52,7 @@ public abstract record AbstractModMetadata
/// <br/>
/// Version = new Version("4.0.0.0"); is not
/// </summary>
[JsonConverter(typeof(ToStringJsonConverter<Range>))]
public abstract Range SptVersion { get; init; }
/// <summary>
@@ -210,7 +210,7 @@ public class LocationLifecycleService(
foreach (var botId in PMCConfig.HostilitySettings)
{
var configHostilityChanges = PMCConfig.HostilitySettings[botId.Key];
var locationBotHostilityDetails = location.BotLocationModifier.AdditionalHostilitySettings.FirstOrDefault(botSettings =>
var locationBotHostilityDetails = location.BotLocationModifier.AdditionalHostilitySettings?.FirstOrDefault(botSettings =>
string.Equals(botSettings.BotRole, botId.Key, StringComparison.OrdinalIgnoreCase)
);
@@ -252,9 +252,15 @@ public class CustomItemService(
{
lazyLoad.AddTransformer(localeData =>
{
localeData.Add($"{newItemId} Name", newLocaleDetails.Name);
localeData.Add($"{newItemId} ShortName", newLocaleDetails.ShortName);
localeData.Add($"{newItemId} Description", newLocaleDetails.Description);
if (!localeData.TryAdd($"{newItemId} Name", newLocaleDetails.Name))
{
logger.Error($"Error adding locale `{newItemId} Name` to {shortNameKey.Key}, duplicate key");
}
else
{
localeData.TryAdd($"{newItemId} ShortName", newLocaleDetails.ShortName);
localeData.TryAdd($"{newItemId} Description", newLocaleDetails.Description);
}
return localeData;
});
@@ -131,6 +131,30 @@ public class PostDbLoadService(
var chosenBoss = GetWeeklyBoss(BotConfig.WeeklyBoss.BossPool, BotConfig.WeeklyBoss.ResetDay);
FlagMapAsGuaranteedBoss(chosenBoss);
}
if (BotConfig.ReplaceScavWith != WildSpawnType.assault)
{
ReplaceScavWavesWithRole(BotConfig.ReplaceScavWith);
}
}
protected void ReplaceScavWavesWithRole(WildSpawnType newScavRole)
{
foreach (var location in databaseService.GetLocations().GetDictionary().Values)
{
if (location.Base?.Waves is null)
{
continue;
}
foreach (var wave in location.Base.Waves)
{
if (wave.WildSpawnType == WildSpawnType.assault)
{
wave.WildSpawnType = newScavRole;
}
}
}
}
/// <summary>
@@ -198,7 +198,7 @@ public class ProfileFixerService(
if (customizationDb.ContainsKey(pmcProfile.Customization.Feet.Value))
{
var defaultFeet = playerIsUsec
? customizationDbArray.FirstOrDefault(x => x.Name == "DefaultUsecFeet")
? customizationDbArray.FirstOrDefault(x => x.Name == "DefaulUsecFeet")
: customizationDbArray.FirstOrDefault(x => x.Name == "DefaultBearFeet");
pmcProfile.Customization.Feet = defaultFeet.Id;
}
@@ -49,6 +49,11 @@ public class RagfairOfferService(
return ragfairOfferHolder.GetOfferById(offerId);
}
/// <summary>
/// Get offers for a desired item tpl
/// </summary>
/// <param name="templateId">Id of item to get offers for</param>
/// <returns>IEnumerable <see cref="RagfairOffer"/></returns>
public IEnumerable<RagfairOffer>? GetOffersOfType(MongoId templateId)
{
return ragfairOfferHolder.GetOffersByTemplate(templateId);
@@ -1,4 +1,5 @@
using SPTarkov.DI.Annotations;
using SPTarkov.Server.Core.Constants;
using SPTarkov.Server.Core.Helpers;
using SPTarkov.Server.Core.Models.Common;
using SPTarkov.Server.Core.Models.Eft.Common;
@@ -157,6 +158,21 @@ public class RaidTimeAdjustmentService(
wave.TimeMax -= (int)Math.Max(startSeconds, 0);
}
// Now additionally move all PMCs back so they spawn starting at the beginning of the raid
var pmcSpawns = mapBase.BossLocationSpawn.Where(boss => boss.BossName is Sides.PmcUsec or Sides.PmcBear);
var firstPmcSpawn = pmcSpawns.OrderBy(boss => boss.Time).FirstOrDefault();
if (firstPmcSpawn != null)
{
var pmcStartSeconds = firstPmcSpawn.Time.GetValueOrDefault(1);
foreach (var spawn in pmcSpawns)
{
// Sanity check, the client won't spawn a time of 0
spawn.Time = (double)Math.Max(spawn.Time.GetValueOrDefault(1) - pmcStartSeconds, 1);
}
logger.Debug($"Offset PMC spawns by {pmcStartSeconds} seconds");
}
logger.Debug(
$"Removed: {originalPmcWaveCount - mapBase.BossLocationSpawn.Count} boss waves from map due to simulated raid start time of {raidAdjustments.SimulatedRaidStartSeconds / 60} minutes"
);
@@ -615,7 +615,7 @@ public class SeasonalEventService(
foreach (var settings in newHostilitySettings)
{
var matchingBaseSettings = locationBase.Base.BotLocationModifier.AdditionalHostilitySettings.FirstOrDefault(x =>
var matchingBaseSettings = locationBase.Base.BotLocationModifier?.AdditionalHostilitySettings?.FirstOrDefault(x =>
x.BotRole == settings.BotRole
);
if (matchingBaseSettings is null)
@@ -32,7 +32,15 @@ public class App(
if (logger.IsLogEnabled(LogLevel.Debug))
{
var totalMemoryBytes = GC.GetGCMemoryInfo().TotalAvailableMemoryBytes;
// Convert bytes to GB
var totalMemoryGb = totalMemoryBytes / (1024.0 * 1024.0 * 1024.0);
var pageFileGb = Environment.SystemPageSize / (1024.0 * 1024.0 * 1024.0);
logger.Debug($"OS: {Environment.OSVersion.Version} | {Environment.OSVersion.Platform}");
logger.Debug($"Pagefile: {pageFileGb:F2} GB");
logger.Debug($"RAM: {totalMemoryGb:F2} GB");
logger.Debug($"Ran as admin: {Environment.IsPrivilegedProcess}");
logger.Debug($"CPU cores: {Environment.ProcessorCount}");
logger.Debug($"PATH: {(Environment.ProcessPath ?? "null returned").Encode(EncodeType.BASE64)}");
@@ -159,7 +159,13 @@ public class ProbabilityObjectArray<K, V> : List<ProbabilityObject<K, V>>
for (var i = 0; i < itemCountToDraw; i++)
{
var rand = Random.Shared.NextDouble();
var randomIndex = cumulativeProbabilities.FindIndex(probability => probability > rand);
var randomIndex = cumulativeProbabilities.FindIndex(probability => probability >= rand);
if (randomIndex == -1)
{
continue;
}
results.Add(this[randomIndex].Key);
}
@@ -1,3 +1,4 @@
using System.Text;
using SPTarkov.DI.Annotations;
namespace SPTarkov.Server.Core.Utils;
@@ -101,27 +102,52 @@ public class FileUtil
public async Task WriteFileAsync(string filePath, string fileContent)
{
if (!DirectoryExists(Path.GetDirectoryName(filePath)))
{
CreateDirectory(Path.GetDirectoryName(filePath));
}
if (!FileExists(filePath))
{
CreateFile(filePath);
}
await File.WriteAllTextAsync(filePath, fileContent);
var bytes = Encoding.UTF8.GetBytes(fileContent);
await WriteFileAsync(filePath, bytes);
}
/// <summary>
/// Writes a file atomically by first writing to a temporary file, then replacing the original.
/// This prevents corruption if the write operation fails or is interrupted.
/// </summary>
public async Task WriteFileAsync(string filePath, byte[] fileContent)
{
if (!FileExists(filePath))
var directoryPath = Path.GetDirectoryName(filePath);
if (!string.IsNullOrEmpty(directoryPath) && !Directory.Exists(directoryPath))
{
CreateFile(filePath);
Directory.CreateDirectory(directoryPath);
}
await File.WriteAllBytesAsync(filePath, fileContent);
var tempFilePath = filePath + ".bak";
try
{
await using (
var fs = new FileStream(tempFilePath, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true)
)
{
await fs.WriteAsync(fileContent);
// We flush here so we can be sure it's immediately committed to disk
await fs.FlushAsync();
}
// Overwrite over the old file
File.Move(tempFilePath, filePath, overwrite: true);
}
catch
{
if (File.Exists(tempFilePath))
{
try
{
File.Delete(tempFilePath);
}
catch { }
}
throw;
}
}
private void CreateFile(string filePath)
@@ -0,0 +1,49 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace SPTarkov.Server.Core.Utils.Json.Converters;
public class SafeDoubleConverter : JsonConverter<double>
{
public override double Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
switch (reader.TokenType)
{
case JsonTokenType.Number:
try
{
return reader.GetDouble();
}
catch (FormatException)
{
try
{
var decimalValue = reader.GetDecimal();
return decimalValue > 0 ? double.MaxValue : 0;
}
catch
{
return double.MaxValue;
}
}
case JsonTokenType.String:
if (double.TryParse(reader.GetString(), out var stringParsed))
{
return stringParsed;
}
return 0;
case JsonTokenType.Null:
return 0;
default:
return 0;
}
}
public override void Write(Utf8JsonWriter writer, double value, JsonSerializerOptions options)
{
writer.WriteNumberValue(value);
}
}
@@ -0,0 +1,42 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace SPTarkov.Server.Core.Utils.Json.Converters;
internal class ToStringJsonConverter<T> : JsonConverter<T>
{
public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Null)
{
return default;
}
if (reader.TokenType == JsonTokenType.String)
{
var value = reader.GetString();
try
{
return (T?)Activator.CreateInstance(typeToConvert, value);
}
catch (Exception ex)
{
throw new JsonException($"Unable to convert \"{value}\" to {typeof(T).Name}.", ex);
}
}
throw new JsonException($"Expected string to deserialize {typeof(T).Name} but got {reader.TokenType}.");
}
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
{
if (value == null)
{
writer.WriteNullValue();
}
else
{
writer.WriteStringValue(value.ToString());
}
}
}
@@ -20,7 +20,9 @@ public class JsonUtil
ReadCommentHandling = JsonCommentHandling.Skip,
WriteIndented = false,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
#if DEBUG
UnmappedMemberHandling = JsonUnmappedMemberHandling.Disallow,
#endif
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
};
+3 -3
View File
@@ -17,7 +17,6 @@ public static class SPTWeb
builder.WebHost.UseStaticWebAssets();
builder.Services.AddMudServices();
builder.Services.AddRazorComponents().AddInteractiveServerComponents();
var mvcBuilder = builder.Services.AddControllers();
@@ -25,6 +24,8 @@ public static class SPTWeb
{
mvcBuilder.AddApplicationPart(assembly);
}
builder.Services.AddRazorComponents().AddInteractiveServerComponents();
}
public static void UseSptBlazor(this WebApplication app)
@@ -33,6 +34,7 @@ public static class SPTWeb
app.UseAntiforgery();
app.UseStaticFiles();
app.MapControllers();
var razorBuilder = app.MapRazorComponents<App>().AddInteractiveServerRenderMode();
@@ -67,7 +69,5 @@ public static class SPTWeb
);
}
}
app.MapControllers();
}
}
+11 -1
View File
@@ -32,6 +32,14 @@ public static class Program
{
await StartServer(args);
}
catch (SocketException)
{
Console.WriteLine("=========================================================================================================");
Console.WriteLine("You have multiple servers running or another process using port 6969");
Console.WriteLine("=========================================================================================================");
Console.WriteLine("Press any key to exit...");
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine("=========================================================================================================");
@@ -226,7 +234,9 @@ public static class Program
private static void SetConsoleOutputMode()
{
if (!OperatingSystem.IsWindows())
var disableFlag = Environment.GetEnvironmentVariable("DISABLE_VIRTUAL_TERMINAL");
if (!OperatingSystem.IsWindows() || disableFlag == "1" || string.Equals(disableFlag, "true", StringComparison.OrdinalIgnoreCase))
{
return;
}