diff --git a/config/Presets.json b/config/Presets.json index df1a70b..c27bd47 100644 --- a/config/Presets.json +++ b/config/Presets.json @@ -51,7 +51,7 @@ "pmcGroupChance": 0.8, "pmcMaxGroupSize": 6, "scavMaxGroupSize": 6, - "sniperGroupChance": 1, + "sniperGroupChance": 0.5, "bossOpenZones": true, "randomRaiderGroup": true, "randomRaiderGroupChance": 50, @@ -66,7 +66,7 @@ "mainBossChanceBuff": 35 }, "sniper-buddies": { - "sniperMaxGroupSize": 2.5, + "sniperMaxGroupSize": 2, "sniperGroupChance": 1 } } \ No newline at end of file diff --git a/config/config.json b/config/config.json index c77437f..f872a24 100644 --- a/config/config.json +++ b/config/config.json @@ -5,7 +5,7 @@ "pmcDifficulty": 0.6, "scavDifficulty": 0.4, - "scavWaveDistribution": 0.8, + "scavWaveDistribution": 1, "scavWaveQuantity": 1, "startingPmcs": false, @@ -28,7 +28,7 @@ "pmcMaxGroupSize": 4, "scavMaxGroupSize": 3, - "sniperMaxGroupSize": 1.6, + "sniperMaxGroupSize": 1, "bossOpenZones": false, diff --git a/config/mapConfig.json b/config/mapConfig.json index e8cb033..a21a886 100644 --- a/config/mapConfig.json +++ b/config/mapConfig.json @@ -1,5 +1,6 @@ { "customs": { + "sniperQuantity": 3, "initialSpawnDelay": 15, "smoothingDistribution": 0.9, "mapCullingNearPointValuePlayer": 8, @@ -16,6 +17,7 @@ ] }, "factoryDay": { + "sniperQuantity": 3, "initialSpawnDelay": 10, "smoothingDistribution": 0.6, "mapCullingNearPointValuePlayer": 2, @@ -28,6 +30,7 @@ "zombieWaveCount": 6 }, "factoryNight": { + "sniperQuantity": 3, "initialSpawnDelay": 10, "smoothingDistribution": 0.6, "mapCullingNearPointValuePlayer": 2, @@ -40,6 +43,7 @@ "zombieWaveCount": 6 }, "interchange": { + "sniperQuantity": 3, "initialSpawnDelay": 20, "smoothingDistribution": 0.9, "mapCullingNearPointValuePlayer": 3, @@ -54,6 +58,7 @@ ] }, "laboratory": { + "sniperQuantity": 0, "initialSpawnDelay": 15, "smoothingDistribution": 0.9, "mapCullingNearPointValuePlayer": 4, @@ -64,6 +69,7 @@ "zombieWaveCount": 12 }, "lighthouse": { + "sniperQuantity": 3, "initialSpawnDelay": 20, "smoothingDistribution": 0.9, "mapCullingNearPointValuePlayer": 2.5, @@ -78,6 +84,7 @@ ] }, "rezervbase": { + "sniperQuantity": 3, "initialSpawnDelay": 20, "smoothingDistribution": 0.9, "mapCullingNearPointValuePlayer": 3, @@ -94,6 +101,7 @@ ] }, "shoreline": { + "sniperQuantity": 3, "initialSpawnDelay": 20, "smoothingDistribution": 0.9, "mapCullingNearPointValuePlayer": 5, @@ -110,6 +118,7 @@ ] }, "tarkovstreets": { + "sniperQuantity": 5, "initialSpawnDelay": 20, "smoothingDistribution": 0.9, "mapCullingNearPointValuePlayer": 4, @@ -120,6 +129,7 @@ "zombieWaveCount": 13 }, "woods": { + "sniperQuantity": 20, "initialSpawnDelay": 20, "smoothingDistribution": 0.9, "mapCullingNearPointValuePlayer": 6, @@ -136,6 +146,7 @@ ] }, "gzLow": { + "sniperQuantity": 3, "initialSpawnDelay": 10, "smoothingDistribution": 0.7, "mapCullingNearPointValuePlayer": 4, @@ -147,6 +158,7 @@ "zombieWaveCount": 9 }, "gzHigh": { + "sniperQuantity": 3, "initialSpawnDelay": 10, "smoothingDistribution": 0.7, "mapCullingNearPointValuePlayer": 4, diff --git a/package.json b/package.json index 97d5e1f..4865d6c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "MOAR", - "version": "3.0.0-alpha.1", + "version": "3.0.0-alpha.2", "main": "src/mod.js", "license": "MIT", "author": "DewardianDev", diff --git a/src/SpawnZoneChanges/setupSpawn.ts b/src/SpawnZoneChanges/setupSpawn.ts index 7fe1c4b..aa4a80d 100644 --- a/src/SpawnZoneChanges/setupSpawn.ts +++ b/src/SpawnZoneChanges/setupSpawn.ts @@ -42,10 +42,25 @@ export const setupSpawns = (container: DependencyContainer) => { let sniperSpawnSpawnPoints: ISpawnPointParam[] = []; let coopSpawns: ISpawnPointParam[] = []; + const bossZoneList = new Set([ + "Zone_Blockpost", + "Zone_RoofRocks", + "Zone_RoofContainers", + "Zone_RoofBeach", + "Zone_TreatmentRocks", + "Zone_TreatmentBeach", + "Zone_Hellicopter", + "Zone_Island", + "BotZoneGate1", + "BotZoneGate2", + "BotZoneBasement", + ]); + shuffle(locations[map].base.SpawnPointParams).forEach( (point) => { switch (true) { - case point.Categories.includes("Boss"): + case point.Categories.includes("Boss") || + bossZoneList.has(point.BotZoneName): bossSpawn.push(point); break; @@ -71,12 +86,6 @@ export const setupSpawns = (container: DependencyContainer) => { return val; }); - const sniperZones = new Set( - sniperSpawnSpawnPoints - .map((point) => point.BotZoneName) - .filter((item) => !!item) - ); - const limit = mapConfig[configLocations[mapIndex]].spawnMinDistance; coopSpawns = cleanClosest( @@ -142,10 +151,10 @@ export const setupSpawns = (container: DependencyContainer) => { ); indexedMapSpawns[mapIndex] = [ - ...sniperSpawnSpawnPoints, - ...bossSpawn, - ...nonBossSpawns, - ...coopSpawns, + ...sniperSpawnSpawnPoints.map((point) => ({ ...point, type: "sniper" })), + ...bossSpawn.map((point) => ({ ...point, type: "boss" })), + ...nonBossSpawns.map((point) => ({ ...point, type: "nonBoss" })), + ...coopSpawns.map((point) => ({ ...point, type: "coop" })), ]; // const added = indexedMapSpawns[mapIndex].filter( diff --git a/src/Spawning/buildPmcs.ts b/src/Spawning/buildPmcs.ts index 207bc54..262db6b 100644 --- a/src/Spawning/buildPmcs.ts +++ b/src/Spawning/buildPmcs.ts @@ -35,15 +35,8 @@ export default function buildPmcs( let pmcZones = getSortedSpawnPointList( locationList[index].base.SpawnPointParams.filter( - ({ Categories, DelayToCanSpawnSec, BotZoneName }, index) => - index % 3 === 0 && - !Categories.includes("Boss") && - Categories[0] === "Bot" && - !( - BotZoneName?.toLowerCase().includes("snipe") || - DelayToCanSpawnSec > 40 - ) - ), + (point) => point["type"] === "nonBoss" + ).filter((_, sIndex) => sIndex % 3 === 0), x, y, z, @@ -51,6 +44,8 @@ export default function buildPmcs( ).map(({ BotZoneName }) => BotZoneName); looselyShuffle(pmcZones); + // console.log(pmcZones); + if (map === "laboratory") { pmcZones = new Array(10).fill(pmcZones).flat(1); } diff --git a/src/Spawning/buildScavMarksmanWaves.ts b/src/Spawning/buildScavMarksmanWaves.ts index d9b01da..185bf12 100644 --- a/src/Spawning/buildScavMarksmanWaves.ts +++ b/src/Spawning/buildScavMarksmanWaves.ts @@ -59,6 +59,7 @@ export default function buildScavMarksmanWaves( maxBotCapOverride, EscapeTimeLimit, scavHotZones = [], + sniperQuantity = 1, scavWaveCount, initialSpawnDelay, } = (mapConfig?.[map] as MapSettings) || {}; @@ -105,23 +106,29 @@ export default function buildScavMarksmanWaves( locationList[index].base.SpawnPointParams.length - 1 ]; - let sniperLocations = getSortedSpawnPointList( - [...locationList[index].base.SpawnPointParams].filter( - ({ Categories, DelayToCanSpawnSec, BotZoneName, Sides }) => - !Categories.includes("Boss") && - Sides[0] === "Savage" && - (BotZoneName?.toLowerCase().includes("snipe") || - DelayToCanSpawnSec > 40) + const sniperSpawns = getSortedSpawnPointList( + locationList[index].base.SpawnPointParams.filter( + (point) => point["type"] === "sniper" ), x, y, z - ).map(({ BotZoneName }) => BotZoneName); + ); - // Prevent too many snipers on streets - if (map === "tarkovstreets") { - sniperLocations = sniperLocations.filter((_, index) => index % 2 === 0); - } + let sniperLocations = sniperSpawns.map(({ BotZoneName }) => BotZoneName); + // console.log(sniperLocations); + + const sniperDelay = 20; + // Make sure that the sniper spawns permit snipers to actually spawn early. + const sniperIds = new Set(sniperSpawns.map(({ Id }) => Id)); + + locationList[index].base.SpawnPointParams.forEach((point, snipeIndex) => { + if (sniperIds.has(point.Id)) { + locationList[index].base.SpawnPointParams[ + snipeIndex + ].DelayToCanSpawnSec = 20; + } + }); if (sniperLocations.length) { locationList[index].base.MinMaxBots = [ @@ -135,15 +142,8 @@ export default function buildScavMarksmanWaves( let scavZones = getSortedSpawnPointList( locationList[index].base.SpawnPointParams.filter( - ({ Categories, DelayToCanSpawnSec, BotZoneName }, index) => - !Categories.includes("Boss") && - index % 3 !== 0 && - Categories[0] === "Bot" && - !( - BotZoneName?.toLowerCase().includes("snipe") || - DelayToCanSpawnSec > 40 - ) - ), + (point) => point["type"] === "nonBoss" + ).filter((_, sIndex) => sIndex % 3 !== 0), x, y, z, @@ -183,11 +183,13 @@ export default function buildScavMarksmanWaves( ); const timeLimit = locationList[index].base.EscapeTimeLimit * 60; + if (config.disableCascadingSpawns) sniperLocations = shuffle(sniperLocations); + // console.log(map); const snipers = buildBotWaves( - sniperLocations.length, - timeLimit, + Math.min(sniperQuantity, sniperLocations.length), + timeLimit / 2, //TODO: sniperMaxGroupSize, sniperGroupChance, sniperLocations, @@ -195,7 +197,7 @@ export default function buildScavMarksmanWaves( WildSpawnType.MARKSMAN, true, 0.3, - 60 + sniperDelay ); if (config.disableCascadingSpawns) scavZones = shuffle(scavZones); diff --git a/src/Spawning/spawnZoneUtils.ts b/src/Spawning/spawnZoneUtils.ts index 8d31825..629adef 100644 --- a/src/Spawning/spawnZoneUtils.ts +++ b/src/Spawning/spawnZoneUtils.ts @@ -195,7 +195,7 @@ export const AddCustomBotSpawnPoints = ( Id: uuidv4(), Infiltration: "", Position: coords, - Rotation: 116.208389, + Rotation: random360(), Sides: ["Savage"], })); @@ -212,7 +212,9 @@ export const AddCustomSniperSpawnPoints = ( } const sniperSpawns = SniperSpawns[map].map((coords: Ixyz, index: number) => ({ - BotZoneName: "SniperZone_" + index, + BotZoneName: + getClosestZone(SpawnPointParams, coords.x, coords.y, coords.z) || + "custom_snipe_" + index, Categories: ["Bot"], ColliderParams: { _parent: "SpawnSphereParams", @@ -230,13 +232,14 @@ export const AddCustomSniperSpawnPoints = ( Id: uuidv4(), Infiltration: "", Position: coords, - Rotation: 116.208389, + Rotation: random360(), Sides: ["Savage"], })); return [...SpawnPointParams, ...sniperSpawns]; }; +export const random360 = () => Math.random() * 360; export const AddCustomPlayerSpawnPoints = ( SpawnPointParams: ISpawnPointParam[], map: string @@ -295,7 +298,7 @@ export const AddCustomPlayerSpawnPoints = ( Id: uuidv4(), Infiltration: getClosestInfil(coords.x, coords.y, coords.z), Position: coords, - Rotation: 116.208389, + Rotation: random360(), Sides: ["Pmc"], })); @@ -358,14 +361,14 @@ export const removeClosestSpawnsFromCustomBots = ( return result; }); - console.log( - map, - coords.length, - ">", - filteredCoords.length, - "culled", - coords.length - filteredCoords.length, - "spawns" - ); + // console.log( + // map, + // coords.length, + // ">", + // filteredCoords.length, + // "culled", + // coords.length - filteredCoords.length, + // "spawns" + // ); return filteredCoords; }; diff --git a/src/Spawning/utils.ts b/src/Spawning/utils.ts index 37fa229..39ae530 100644 --- a/src/Spawning/utils.ts +++ b/src/Spawning/utils.ts @@ -229,25 +229,20 @@ export const buildBotWaves = ( if (bossEscortAmount < 0) bossEscortAmount = 0; - const totalCountThisWave = isMarksman ? 1 : bossEscortAmount + 1; + const totalCountThisWave = bossEscortAmount + 1; const totalCountThusFar = botTotal - maxSlotsReached; const BossDifficult = getDifficulty(difficulty); waves.push({ - BossChance: isMarksman ? 85 : 100, + BossChance: 100, BossDifficult, BossEscortAmount: bossEscortAmount.toString(), BossEscortDifficult: BossDifficult, BossEscortType: botType, BossName: botType, BossPlayer: false, - BossZone: - bossZones[ - isMarksman - ? totalCountThusFar - : Math.floor(totalCountThusFar * botToZoneTotal) - ] || "", + BossZone: bossZones[Math.floor(totalCountThusFar * botToZoneTotal)] || "", Delay: 0, DependKarma: false, DependKarmaPVE: false, @@ -267,12 +262,12 @@ export const buildBotWaves = ( if (maxSlotsReached <= 0) break; } // isMarksman && - // console.log( - // // bossZones, - // botType, - // bossZones.length, - // waves.map(({ Time, BossZone }) => ({ Time, BossZone })) - // ); + // console.log( + // // bossZones, + // botType, + // bossZones.length, + // waves.map(({ Time, BossZone }) => ({ Time, BossZone })) + // ); return waves; }; @@ -341,6 +336,7 @@ export const buildZombie = ( }; export interface MapSettings { + sniperQuantity?: number; initialSpawnDelay: number; smoothingDistribution: number; mapCullingNearPointValue: number; @@ -518,7 +514,7 @@ export const enforceSmoothing = (locationList: ILocation[]) => { } }; -export const looselyShuffle = (arr: T[], shuffleStep: number = 2): T[] => { +export const looselyShuffle = (arr: T[], shuffleStep: number = 3): T[] => { const n = arr.length; const halfN = Math.floor(n / 2); for (let i = shuffleStep - 1; i < halfN; i += shuffleStep) { diff --git a/src/Spawns/botSpawns.json b/src/Spawns/botSpawns.json index 710e062..b907aaa 100644 --- a/src/Spawns/botSpawns.json +++ b/src/Spawns/botSpawns.json @@ -539,6 +539,16 @@ "x": 543.3302, "y": 0.320250139, "z": -0.442697 + }, + { + "x": 84.10119, + "y": 5.209759, + "z": -157.497711 + }, + { + "x": 81.6217346, + "y": 2.00750268, + "z": -151.027039 } ], "factory4_day": [ diff --git a/src/Spawns/sniperSpawns.json b/src/Spawns/sniperSpawns.json index 8fdfcd7..e22ba85 100644 --- a/src/Spawns/sniperSpawns.json +++ b/src/Spawns/sniperSpawns.json @@ -1,5 +1,31 @@ { - "bigmap": [], + "bigmap": [ + { + "x": 369.272278, + "y": 11.2302418, + "z": -72.96668 + }, + { + "x": 197.6982, + "y": 20.6448269, + "z": -99.9941 + }, + { + "x": -195.447922, + "y": 12.2605534, + "z": -99.21204 + }, + { + "x": 426.789185, + "y": 8.655911, + "z": 141.028671 + }, + { + "x": 655.7491, + "y": 13.0718241, + "z": 5.93848372 + } + ], "factory4_day": [], "factory4_night": [], "interchange": [], @@ -8,7 +34,33 @@ "rezervbase": [], "shoreline": [], "tarkovstreets": [], - "woods": [], + "woods": [ + { + "x": 107.892273, + "y": -0.4766239, + "z": 114.376709 + }, + { + "x": 347.58255, + "y": 8.07130527, + "z": -81.14405 + }, + { + "x": 256.352234, + "y": 29.62652, + "z": -443.1618 + }, + { + "x": -588.0022, + "y": 32.740387, + "z": -149.905914 + }, + { + "x": 83.43207, + "y": 16.8122787, + "z": -148.1193 + } + ], "sandbox": [], "sandbox_high": [] } \ No newline at end of file