=VG= XOR Posted March 10, 2021 at 05:21 AM Report Share Posted March 10, 2021 at 05:21 AM Changing the number of bots relative to player count has long been discussed and is somewhat of a long standing 'unresolved issue' as it can't be done using configs or without server restart, and given some recent discussion on discord about map difficulty, i figured i might as well post this up as at the very least an alternate 'POSSIBILITY', which at present it is not. So there's two ways to change bot count, either set ENTITY COUNT in server config or change LOGICAL COUNT by manipulating spawn times such that the mean number of bots SPAWNED at any point in time is lower or higher, Classical interpretation of 'count' signifies entity iterations, Logical interpretation that i use here signifies 'INTERACTIVE entity iterations', additionally (re)spawn time based entity count is the most computationally efficient way of dynamically adjusting such count without fucking up server performance, as more bots generally tend to tax a server's performance more, especially in such an old engine. TLDR; It's a fairly trivial script that separates respawn times of bots & players, dynamically not only on round start but through a round as well, as players JOIN & LEAVE. It occurs to me that most people don't download attachments & since one needs to login to download attachments anyway, I'll just embed it below, as it's fairly trivial. SEE CHEATSHEET IN EMBED BELOW TO SEE HOW SPAWN TIME CHANGES RELATIVE TO PLAYER COUNT, it was automatically generated so it should be a fairly accurate representation import sys, host, bf2, math, realitycore as rcore, realityadmin as radmin difficultyMultiplier = 5 #lower is more difficult as bots spawn more frequently whereas higher is less difficult as bots spawn less frequently, see cheatsheet below def init(): host.registerHandler('PlayerKilled', onPlDeath) #wounded host.registerHandler('PlayerDeath', onPlDeath) #deded def onPlDeath(player, soldier): if player.isAIPlayer(): botSpawnTime(player, soldier, difficultyMultiplier) def botSpawnTime(player, soldier, difficultyMultiplier): botSpawnTime = math.ceil((bf2.playerManager.getNumberOfPlayersInTeam(1) / bf2.playerManager.getNumberOfPlayersInTeam(2)) * difficultyMultiplier) radmin.globalMessage("DEBUG: respawning " + str(player.getName()) + " in " + str(player.getTimeToSpawn()) + " sec [" + str(botSpawnTime) + player.setTimeToSpawn(botSpawnTime) "]secComputed") for p in bf2.playerManager.getPlayers(): #redundancy to reset all bot spawn times to specified timer, ignoring PR set spawntimes... if p.isAIPlayer(): p.setTimeToSpawn(botSpawnTime) return """ dynamic difficulty scaling applied for every killed & spawned bot,bot respawn time proportional to number of players & number of bots there's 2 ways to change bot count, change actual number of bots spawned OR change spawn times to logically define the number of bots active at any given time comparison cheat sheet: spawn times @difficulty N for a given Number of players, assuming 40bots @difficulty=1 40sec@1players 20sec@2players 14sec@3players 10sec@4players 8sec@5players 7sec@6players 6sec@7players 5sec@8players 5sec@9players 4sec@10players 4sec@11players 4sec@12players 4sec@13players 3sec@14players 3sec@15players 3sec@16players 3sec@17players 3sec@18players 3sec@19players 2sec@20players 2sec@21players 2sec@22players 2sec@23players 2sec@24players 2sec@25players 2sec@26players 2sec@27players 2sec@28players 2sec@29players 2sec@30players 2sec@31players 2sec@32players 2sec@33players 2sec@34players 2sec@35players 2sec@36players 2sec@37players 2sec@38players 2sec@39players 1sec@40players @difficulty=2 80sec@1players 40sec@2players 28sec@3players 20sec@4players 16sec@5players 14sec@6players 12sec@7players 10sec@8players 10sec@9players 8sec@10players 8sec@11players 8sec@12players 8sec@13players 6sec@14players 6sec@15players 6sec@16players 6sec@17players 6sec@18players 6sec@19players 4sec@20players 4sec@21players 4sec@22players 4sec@23players 4sec@24players 4sec@25players 4sec@26players 4sec@27players 4sec@28players 4sec@29players 4sec@30players 4sec@31players 4sec@32players 4sec@33players 4sec@34players 4sec@35players 4sec@36players 4sec@37players 4sec@38players 4sec@39players 2sec@40players @difficulty=3 120sec@1players 60sec@2players 42sec@3players 30sec@4players 24sec@5players 21sec@6players 18sec@7players 15sec@8players 15sec@9players 12sec@10players 12sec@11players 12sec@12players 12sec@13players 9sec@14players 9sec@15players 9sec@16players 9sec@17players 9sec@18players 9sec@19players 6sec@20players 6sec@21players 6sec@22players 6sec@23players 6sec@24players 6sec@25players 6sec@26players 6sec@27players 6sec@28players 6sec@29players 6sec@30players 6sec@31players 6sec@32players 6sec@33players 6sec@34players 6sec@35players 6sec@36players 6sec@37players 6sec@38players 6sec@39players 3sec@40players @difficulty=4 160sec@1players 80sec@2players 56sec@3players 40sec@4players 32sec@5players 28sec@6players 24sec@7players 20sec@8players 20sec@9players 16sec@10players 16sec@11players 16sec@12players 16sec@13players 12sec@14players 12sec@15players 12sec@16players 12sec@17players 12sec@18players 12sec@19players 8sec@20players 8sec@21players 8sec@22players 8sec@23players 8sec@24players 8sec@25players 8sec@26players 8sec@27players 8sec@28players 8sec@29players 8sec@30players 8sec@31players 8sec@32players 8sec@33players 8sec@34players 8sec@35players 8sec@36players 8sec@37players 8sec@38players 8sec@39players 4sec@40players --default-- default PR bot respawn time is ~60seconds if deded and 0sec if wounded before deded @difficulty=5 200sec@1players 100sec@2players 70sec@3players 50sec@4players 40sec@5players 35sec@6players 30sec@7players 25sec@8players 25sec@9players 20sec@10players 20sec@11players 20sec@12players 20sec@13players 15sec@14players 15sec@15players 15sec@16players 15sec@17players 15sec@18players 15sec@19players 10sec@20players 10sec@21players 10sec@22players 10sec@23players 10sec@24players 10sec@25players 10sec@26players 10sec@27players 10sec@28players 10sec@29players 10sec@30players 10sec@31players 10sec@32players 10sec@33players 10sec@34players 10sec@35players 10sec@36players 10sec@37players 10sec@38players 10sec@39players 5sec@40players @difficulty=6 240sec@1players 120sec@2players 84sec@3players 60sec@4players 48sec@5players 42sec@6players 36sec@7players 30sec@8players 30sec@9players 24sec@10players 24sec@11players 24sec@12players 24sec@13players 18sec@14players 18sec@15players 18sec@16players 18sec@17players 18sec@18players 18sec@19players 12sec@20players 12sec@21players 12sec@22players 12sec@23players 12sec@24players 12sec@25players 12sec@26players 12sec@27players 12sec@28players 12sec@29players 12sec@30players 12sec@31players 12sec@32players 12sec@33players 12sec@34players 12sec@35players 12sec@36players 12sec@37players 12sec@38players 12sec@39players 6sec@40players @difficulty=7 280sec@1players 140sec@2players 98sec@3players 70sec@4players 56sec@5players 49sec@6players 42sec@7players 35sec@8players 35sec@9players 28sec@10players 28sec@11players 28sec@12players 28sec@13players 21sec@14players 21sec@15players 21sec@16players 21sec@17players 21sec@18players 21sec@19players 14sec@20players 14sec@21players 14sec@22players 14sec@23players 14sec@24players 14sec@25players 14sec@26players 14sec@27players 14sec@28players 14sec@29players 14sec@30players 14sec@31players 14sec@32players 14sec@33players 14sec@34players 14sec@35players 14sec@36players 14sec@37players 14sec@38players 14sec@39players 7sec@40players @difficulty=8 320sec@1players 160sec@2players 112sec@3players 80sec@4players 64sec@5players 56sec@6players 48sec@7players 40sec@8players 40sec@9players 32sec@10players 32sec@11players 32sec@12players 32sec@13players 24sec@14players 24sec@15players 24sec@16players 24sec@17players 24sec@18players 24sec@19players 16sec@20players 16sec@21players 16sec@22players 16sec@23players 16sec@24players 16sec@25players 16sec@26players 16sec@27players 16sec@28players 16sec@29players 16sec@30players 16sec@31players 16sec@32players 16sec@33players 16sec@34players 16sec@35players 16sec@36players 16sec@37players 16sec@38players 16sec@39players 8sec@40players @difficulty=9 360sec@1players 180sec@2players 126sec@3players 90sec@4players 72sec@5players 63sec@6players 54sec@7players 45sec@8players 45sec@9players 36sec@10players 36sec@11players 36sec@12players 36sec@13players 27sec@14players 27sec@15players 27sec@16players 27sec@17players 27sec@18players 27sec@19players 18sec@20players 18sec@21players 18sec@22players 18sec@23players 18sec@24players 18sec@25players 18sec@26players 18sec@27players 18sec@28players 18sec@29players 18sec@30players 18sec@31players 18sec@32players 18sec@33players 18sec@34players 18sec@35players 18sec@36players 18sec@37players 18sec@38players 18sec@39players 9sec@40players @difficulty=10 400sec@1players 200sec@2players 140sec@3players 100sec@4players 80sec@5players 70sec@6players 60sec@7players 50sec@8players 50sec@9players 40sec@10players 40sec@11players 40sec@12players 40sec@13players 30sec@14players 30sec@15players 30sec@16players 30sec@17players 30sec@18players 30sec@19players 20sec@20players 20sec@21players 20sec@22players 20sec@23players 20sec@24players 20sec@25players 20sec@26players 20sec@27players 20sec@28players 20sec@29players 20sec@30players 20sec@31players 20sec@32players 20sec@33players 20sec@34players 20sec@35players 20sec@36players 20sec@37players 20sec@38players 20sec@39players 10sec@40players """ botCountBySpawnTime.py 1 5 Quote Link to comment Share on other sites More sharing options...
TH0M Posted March 10, 2021 at 08:18 AM Report Share Posted March 10, 2021 at 08:18 AM Whiskey & Skit are gonna be too OP for the Bot if this got implemented, they finished Muttrah on their lonesome, they don't need this 1 2 Quote Link to comment Share on other sites More sharing options...
=VG= Skitalez Posted March 10, 2021 at 10:43 AM Report Share Posted March 10, 2021 at 10:43 AM Bots are bots. These are not live players. And despite the preponderance in the number (when, say, 5-10 people play on the server) and the complexity, they can always be deceived and outplayed. 2 Quote Link to comment Share on other sites More sharing options...
=VG= Connor Posted March 10, 2021 at 06:00 PM Report Share Posted March 10, 2021 at 06:00 PM Goodluck. 1 Quote Link to comment Share on other sites More sharing options...
=VG= XOR Posted March 10, 2021 at 07:42 PM Author Report Share Posted March 10, 2021 at 07:42 PM 2 hours ago, Connor said: Goodluck. This one's more of a hail mary... Just putting it out there for posterity 1 Quote Link to comment Share on other sites More sharing options...
=VG= SemlerPDX Posted March 10, 2021 at 09:09 PM Report Share Posted March 10, 2021 at 09:09 PM That's some impressive scritping there, X0R! Can I assume you've tested this already? Or is that something that would require a dedicated server and a live environment? @=VG= Melon Muncher @=VG= Fastjack Thoughts? Notes? Feedback? Can we implement this, or would there be compromises to doing so that would make it undesirable? If this gets to the live testing phase here, it could be done on our Event Server since it remains offline most of the time, so long as we can set up a proper test environment (maybe dumbed down the key numbers to call a full server "10 people" and low pop "2 people", then scale it up to proper numbers after testing? This is all assuming that this system does not require a server restart, and that the next map loaded bot count is based on currently connected players. Yes, we are all about running a stable ship, and it was a year or more before we implemented the VG Maplist Randomizer for 'reasons', but all it takes is time to evaluate all reasons and outcomes, and then take a chance (or not). We can always roll back or undo any changes if they don't pan out over time. Happy to have an open discussion about this finally, when 'dynamic bot count' proposals get put on the back burner, it is so they can be brought to the front again before too long, and this is not the first time this has come up. It deserves proper attention and deliberation for implementation, or good reasons not to. 1 1 Quote Link to comment Share on other sites More sharing options...
=VG= Fastjack Posted March 11, 2021 at 12:09 AM Report Share Posted March 11, 2021 at 12:09 AM 3 hours ago, =VG= SemlerPDX said: @=VG= Melon Muncher @=VG= Fastjack Thoughts? Notes? Feedback? Can we implement this, or would there be compromises to doing so that would make it undesirable? That's outstanding work from him, Semler. I dont know if we need this for our server(s) because some maps can be handled with 10 players. Doesn`t matter how many bots are on the other side. Than we have maps where 40 players aren't enough. The main problems i see are the maps with their asset layout. Khami lrg is horrible. Lashkar Infantry is a meatgrinder (i can and will not understand why we have no logitruck on it). But the biggest problem is : Why we have fucking botspawnpoints inside of controlpoint areas? Or why we have active spawnpoints in a flagcap radius that is linked by another flag? To name one, Kashan with his amazing respawntime of the Milan. Those spawnpoint placements only provoking things like spawnpoint camping or causing missing boots on other important places when the server population is low. What Coop really need is : DYNAMIC GAMEPLAY A pythonscript that choose randomly some objectspawners and let spawn their shit. Like the ammocaches in Insurgency. I want more dynamic gameplay and not the static gameplay we currently have in coop. I will not have anymore what we have on muttrah like : CAS spawning - flying to castle - destroying Milan and AA - 5 minutes later the same again. Here an excample what i want: I place 50 mortars, 50 bipods and 50 AA-AT static defense in the GPO but the randomcode will only pick 4 mortars, 10 bipods and 2 Static AA's in a random manner. After one of this asset got destroyed another mortar/bipod/static AA-AT will spawn 5-10 minutes later on a different objectspawner, so not on the same position again. No one at roundstart knows where the mortars/bipod/static AA-AT's will spawn, so CAS has to be carefully, vehicles have to play carefully and the troops also has to Move carefully. No Round will be the same because the shit that will screw up the humans not spawn anymore on the same places. 1 2 2 Quote Link to comment Share on other sites More sharing options...
=VG= XOR Posted March 11, 2021 at 04:17 AM Author Report Share Posted March 11, 2021 at 04:17 AM 7 hours ago, =VG= SemlerPDX said: Can I assume you've tested this already? Or is that something that would require a dedicated server and a live environment? Tested on both, it was part of a server side minimod i wrote for bf2. 7 hours ago, =VG= SemlerPDX said: Can we implement this, or would there be compromises to doing so that would make it undesirable? Not that i can think off, that's why i posted it here, to create discourse if nothing else. 7 hours ago, =VG= SemlerPDX said: This is all assuming that this system does not require a server restart, and that the next map loaded bot count is based on currently connected players. Not only does it not require a server restart, it changes through a round,so if a round starts off with 35people and shrinks to 20people, logical bot count changes accordingly as it's constantly recalculated for every bot killed, there should be no performance penalty. 4 hours ago, =VG= Fastjack said: I dont know if we need this for our server(s) because some maps can be handled with 10 players. Doesn`t matter how many bots are on the other side. Absolutely true, however on the flipside, with an appropriate (per testing) difficulty multiplier applied, it makes it more challenging for a more full server, as normally whether or not there's a full server or not, bot respawn time is same as player respawn time, about 60sec by default which on a full server or even half full, imho is too much.... So one might say it makes maps easier or no easier(depending on difficulty multiplier) for few, inexperienced players and makes maps harder for lots of experienced or inexperienced players alike. I thought about having it check game tracker to check player's played hours to scale for player experience, but figured that wouldn't go down as well.... 4 hours ago, =VG= Fastjack said: What Coop really need is : DYNAMIC GAMEPLAY CAN'T AGREE MORE, I'll port over some other scripts for THAT with time, when motivation strikes.... 4 hours ago, =VG= Fastjack said: Khami lrg is horrible. Blasphemy, it's one of double's finest, imho. Agree to Disagree. 4 hours ago, =VG= Fastjack said: A pythonscript that choose randomly some objectspawners and let spawn their shit. 4 hours ago, =VG= Fastjack said: Why we have fucking botspawnpoints inside of controlpoint areas? Or why we have active spawnpoints in a flagcap radius that is linked by another flag? To name one, Kashan with his amazing respawntime of the Milan. Those spawnpoint placements only provoking things like spawnpoint camping or causing missing boots on other important places when the server population is low. My solution for that was making every bot a contextual spawn point(contingent on vehicle type, cappable cp in range) and making every bot killed a probabilistic contextual respawn trigger(ex. every bot cas kills gets a 60% probability of respawning every shilka on map instead of current fixed respawn time AND 40% probability of cloning spawned shilka on killed bot pos instead of mapper designated pos after a delay), I'll port it at some point, It's part of a much larger script so, it's finicky to clean up. Started porting but got stuck writing a function to validate position as being in navmesh to prevent bots dying, so i can also use player positions too as that's a more random position seed, and a 2dTo3DPos function to resolve 2d coords to 3d from height map, i'll sort that out too when motivation strikes. 4 hours ago, =VG= Fastjack said: I want more dynamic gameplay and not the static gameplay we currently have in coop. Me & you both, and just about every person who plays coop. 4 hours ago, =VG= Fastjack said: I place 50 mortars, 50 bipods and 50 AA-AT static defense in the GPO but the randomcode will only pick 4 mortars, 10 bipods and 2 Static AA's in a random manner. After one of this asset got destroyed another mortar/bipod/static AA-AT will spawn 5-10 minutes later on a different objectspawner, so not on the same position again. 4 hours ago, =VG= Fastjack said: No one at roundstart knows where the mortars/bipod/static AA-AT's will spawn, so CAS has to be carefully, vehicles have to play carefully and the troops also has to Move carefully. No Round will be the same because the shit that will screw up the humans not spawn anymore on the same places. I implemented this at your request, but found a bug that causes python crash after the first dozen selections(which simply changes the minMax (re)spawn time of random spawners & despawns all on round start), been looking for a fix and what causes that for a while.... still at it, when once again motivation strikes. 1 1 3 Quote Link to comment Share on other sites More sharing options...
=VG= Zeee Posted March 11, 2021 at 10:22 PM Report Share Posted March 11, 2021 at 10:22 PM I absolutely love the idea of randomly generated implements and stuff 2 Quote Link to comment Share on other sites More sharing options...
=VG= Fastjack Posted March 11, 2021 at 11:26 PM Report Share Posted March 11, 2021 at 11:26 PM 19 hours ago, X0R said: My solution for that was making every bot a contextual spawn point(contingent on vehicle type, cappable cp in range) and making every bot killed a probabilistic contextual respawn trigger(ex. every bot cas kills gets a 60% probability of respawning every shilka on map instead of current fixed respawn time AND 40% probability of cloning spawned shilka on killed bot pos instead of mapper designated pos after a delay), Wait, wait, wait .... what? A spawnlogic that is based on situation on the battlefield and not based on spawn/respawn timers and without fixed positions (objectspawner positions). Yeah i think that would improve much. Some things can also be handled by mapstrategies but PR's temperature values are lightyears away from that. I could life with having fixed objectspawners on the map because you can place many of them that make memorizing hard but your idea is great. Would it be possible to spawn a bot with a kit that isn't in the selection menu? Excample: Multiple bots got killed by CAS. Now, a trigger let spawn a bot with a manpad. or : Multiple bots got killed by tank. Trigger let spawn a bot with a HATkit. Come on please say YES its possible. 1 Quote Link to comment Share on other sites More sharing options...
=VG= XOR Posted March 12, 2021 at 04:16 AM Author Report Share Posted March 12, 2021 at 04:16 AM 4 hours ago, =VG= Fastjack said: Would it be possible to spawn a bot with a kit that isn't in the selection menu? Excample: Multiple bots got killed by CAS. Now, a trigger let spawn a bot with a manpad. or : Multiple bots got killed by tank. Trigger let spawn a bot with a HATkit. Come on please say YES its possible. It's not only possible, it's fairly trivial. The only caveat being, though host.rcon_invoke("gamelogic.setkit ****") sets ANY KIT initialized for a given faction in real-time, it changes OVERALL kit composition of bots on successive re-spawns & not immediately, instead of only INDIVIDUAL bot kits. Which might actually be more ideal, if it's constantly being set to a different kit relative to dominant threat at any given point in time, though not as targeted, it makes it so that if armor dominates the battlefield, a majority of bots that re-spawn do so with AT, though i'm sure you already know of the issue with bots using MANPADS. There is of course also a targeted solution, a simple (re)spawn handler can be used to shuffle spawns, such that any bot that spawns with AT kit spawns at pos of any other bot killed by ARMOR(with random delay) for instance, or just at closest spawn point to killer(player). In-fact I recall writing a dumb little function for this, I called it DIE_VERSION, it was supposed to signify that the player was going to die in the next encounter with a bot the player killed.... I digress though, I'll probably pack it along with some other stuff I've written over the years and make a post or something at some point, I've thought about doing so, just got lazy. 1 Quote Link to comment Share on other sites More sharing options...
=VG= Fastjack Posted March 12, 2021 at 08:54 PM Report Share Posted March 12, 2021 at 08:54 PM 15 hours ago, X0R said: though i'm sure you already know of the issue with bots using MANPADS Not really, what issue do you mean? Hipfiring is one problem i'm aware about or the old look up wrapper error but that is fixed. It's also possible to bypass problems - generally done when you think out of the box. About the motivation thingy - i know what you mean and can understand that. In my case i lose focus or interrest because i'm working alone the most time on coop insurgency and there are so many things todo to improve coop but unbearable for one person. To much work. 2 Quote Link to comment Share on other sites More sharing options...
=VG= Connor Posted March 12, 2021 at 11:18 PM Report Share Posted March 12, 2021 at 11:18 PM Im liking this whole conversation, some real promise to make the server better here!! 2 hours ago, =VG= Fastjack said: i know what you mean and can understand that. In my case i lose focus or interrest because i'm working alone the most time on coop insurgency and there are so many things todo to improve coop but unbearable for one person. To much work. X0R, R-DEV when????? 1 Quote Link to comment Share on other sites More sharing options...
=VG= GRNANDGLD Posted March 13, 2021 at 12:29 AM Report Share Posted March 13, 2021 at 12:29 AM why would you want less bots? I want random spawn points so nobody Volods the spawns is that a thing? 4 Quote Link to comment Share on other sites More sharing options...
=VG= XOR Posted March 13, 2021 at 05:27 AM Author Report Share Posted March 13, 2021 at 05:27 AM 10 hours ago, =VG= Fastjack said: Not really, what issue do you mean? Hipfiring is one problem i'm aware about or the old look up wrapper error but that is fixed. Well there you go, never knew that got fixed, was out of the loop for a while, so I guess manpads shouldn't be a problem then. 10 hours ago, =VG= Fastjack said: It's also possible to bypass problems - generally done when you think out of the box. Always. 10 hours ago, =VG= Fastjack said: About the motivation thingy - i know what you mean and can understand that. In my case i lose focus or interrest because i'm working alone the most time on coop insurgency and there are so many things todo to improve coop but unbearable for one person. To much work. Touchè brother. 6 hours ago, GRNANDGLD said: why would you want less bots? Let's assume you wouldn't, surely you want more bots though, eh? So that's the flip side, depending on how you configure the difficulty multiplier, you can avoid fewer bots while having more for higher player numbers, it's entirely left to configs, like all good things in life 6 hours ago, GRNANDGLD said: I want random spawn points so nobody Volods the spawns is that a thing? It can be, but not on any officially sanctioned server, at least not anytime soon. You'll most likely come across it in events, should anyone choose to use such functionality. But as for is it possible, absolutely, I've done it & so have others. 2 Quote Link to comment Share on other sites More sharing options...
=VG= XOR Posted March 14, 2021 at 11:06 AM Author Report Share Posted March 14, 2021 at 11:06 AM Just to crystalize a particularly important point I failed to articulate, such a system for the most part removes server population as a variable in map selection, which meaningfully translates to, ANY MAP CAN BE PLAYED BY ANY NUMBER OF PLAYERS, and thus repetition is reduced and variety of viable maps increased exponentially. Just wanted to put that out there, as I'd forgotten to do so. 4 Quote Link to comment Share on other sites More sharing options...
=VG= SemlerPDX Posted March 15, 2021 at 05:38 PM Report Share Posted March 15, 2021 at 05:38 PM Ya know, some good points where brought up here that made me come to some odd conclusions and I don't even know if this line of thinking is productive, or these things possible... Say it's low population - the system knows that it shouldn't pelt them with too many bots, so it does what you designed it to do... how about the scenario where no new players join, but this same small team starts killing it - like not just taking points, but steamrolling them. Can the system have functions to differentiate such swift advancement from what we could term 'standard flow' advancement which typically only sees one to two points capped in a sort period (but not 3, or 4)? What I'm thinking is that the system could figure out if it's gone 'too' easy on a low pop scenario and adjust accordingly... maybe the 7 people that are on have 4000+ hours each in the game, right? But it needs to be able to 'be easy' for 6 noobs and a single trained regular player, too, right? Just thoughts - not trying to make extra work, or anything like that... merely posing the idea or question of possibility (dynamics within dynamics). The more I read about this, the more I'm feeling we should make it happen - even if it means some minor requests if feasible, or fine tuning based on feedback from our PR Server Managers here (if you don't mind, of course). I think the future of PR COOP might very well need this, since the population swing is more of an issue the more PR ages. 1 Quote Link to comment Share on other sites More sharing options...
=VG= SemlerPDX Posted March 15, 2021 at 05:40 PM Report Share Posted March 15, 2021 at 05:40 PM How about a 'retreat' bleed? BLUFOR has capped all zones, and admins would otherwise need to 'run next' or kill bots streaming out of main for 30+ minutes, so instead, the system notices and issues a 'retreat' which causes OPFOR ticket bleed to increase dramatically and swiftly? When no admins present, this would allow map to progress swiftly to next map without someone seeking out an Admin just so players don't need to 'run out the clock' as it were. 1 Quote Link to comment Share on other sites More sharing options...
=VG= XOR Posted March 15, 2021 at 05:47 PM Author Report Share Posted March 15, 2021 at 05:47 PM 5 hours ago, =VG= SemlerPDX said: How about a 'retreat' bleed? BLUFOR has capped all zones, and admins would otherwise need to 'run next' or kill bots streaming out of main for 30+ minutes, so instead, the system notices and issues a 'retreat' which causes OPFOR ticket bleed to increase dramatically and swiftly? When no admins present, this would allow map to progress swiftly to next map without someone seeking out an Admin just so players don't need to 'run out the clock' as it were. I already wrote a script that on every CP capped checks if all capable CP's are owned by team 2 && if so sets bot team tickets to 0 after 15 sec triggering end of round by team 2 victory. I'll post it if you wish, should certainly make no-ticket bleed a thing of the past, with rare exceptions like cappable CP in dod for instance. *also attached below* @=VG= SemlerPDX Spoiler import sys, host, bf2, math, realitycore as rcore, realityadmin as radmin, realitytimer as rtimer #simple script to detect end of round on maps where there may be no end of round ticket bleed or where eor ticket bleed might be too slow,and force end of round with victory instead of draw def init(): host.registerHandler('ControlPointChangedOwner', onCPStatusChange) def eorEnum(thisCp): for cp in rcore.getControlPoints(): #if cp is capturable, and is capturable by team 2 and is not owned by team 2 then return as there's at least one capturable flag owned by bot team if cp.cp_getParam('unableToChangeTeam') != 1 and cp.cp_getParam('allowCaptureByTeam', 2) == 1 and cp.cp_getParam('team') == 1: radmin.globalMessage("bot team owns at least 1 capturable flag") return #if cp is capturable, and is capturable by team 2 and is not owned by team 2 or team 1 then return as there's at least one capturable flag that remains to be captured. if cp.cp_getParam('unableToChangeTeam') != 1 and cp.cp_getParam('allowCaptureByTeam', 2) == 1 and cp.cp_getParam('team') != 2: radmin.globalMessage("at least one flag remains to be captured.") #i.e at least one flag is neutral return #if this line is reached, all cappable cp's are owned by player team, so set bot team tickets to 0 & trigger end of round radmin.globalMessage("End Of Round Will Now Be Forcefully Invoked, As There Appears To Be No Ticket Bleed... GG") bf2.gameLogic.setTickets(1, 0) #set team 1/bot team tickets to 0 def onCPStatusChange(cp, top): #invoke end of round check N seconds after any flag status changes rtimer.fireOnce(eorEnum, 15, cp) forceEndOfRound.py 1 1 Quote Link to comment Share on other sites More sharing options...
=VG= XOR Posted March 15, 2021 at 05:50 PM Author Report Share Posted March 15, 2021 at 05:50 PM 6 hours ago, =VG= SemlerPDX said: What I'm thinking is that the system could figure out if it's gone 'too' easy on a low pop scenario and adjust accordingly... maybe the 7 people that are on have 4000+ hours each in the game, right? But it needs to be able to 'be easy' for 6 noobs and a single trained regular player, too, right? Should be simple enough, it's a simple matter of adding a factorial that uses KD to evaluate player skill relative to time elapsed, higher KD in a given unit of time signifying higher skilled player. An even simple way to balance this would be to increase the difficulty by .1% for every bot killed and reduce it by 1% for every player killed which results in a more emergent & fluid difficulty balance. Here's an updated script, also attached, that uses a sigmoid function to dynamically adjust difficultyMultiplier based on KD ratio of players for every bot killed, such that the more players there are with high KD ratios the lower the difficultyMultiplier, which translates to higher bot count, with difficultyMultiplier never exceeding config defind value, such that it' can get exponentially more difficult relative to more experienced players but it never gets easier beyond value defined in config. tldr; player KD ratios continually modify difficultyMultiplier with an upper limit for every bot killed and player count continually forces recalculation of bot respawn times relative to player count for every bot killed so as to modify the mean number of bots active in a given unit of time, i.e logical bot count. @=VG= SemlerPDX Spoiler import sys, host, bf2, math, realitycore as rcore, realityadmin as radmin difficultyMultiplier = 5 #lower is more difficult as bots spawn more frequently whereas higher is less difficult as bots spawn less frequently, see cheatsheet below #value set ABOVE signifies minimum base difficultyMultiplier, such that difficulty will not go higher than this value, such that this will be the LOWEST difficulty, as higher is lower difficulty difficultyMultiplierMax = difficultyMultiplier def sigmoid(x): #applying the sigmoid function return 1 / (1 + math.exp(-x)) def sigmoid_derivative(x): #computing derivative to the Sigmoid function return x * (1 - x) def normalize(x, max, min): #function that takes a number and normalizes it from 0 - 1 between its min and max bounds. return (x - min) / (max - min) def normalizeInverse(x, max, min): #function that takes a number and normalizes it from 0 - 10 between its min and max bounds. then inverts return value so high val becomes low val & vice versa. x = max - 1 if x >= max else x x = min if x <= min else x nI = max - max*((x - min) / (max - min)) return min if nI == 0 else nI def init(): host.registerHandler('PlayerKilled', onPlKilled) #wounded, also resolves outright kills if killer host.registerHandler('PlayerDeath', onPlDeath) #deded def onPlKilled(victim, attacker, weapon, assists, obj): attackerKills = attacker.score.kills attackerDeaths = attacker.score.deaths attackerKD = 1 if attackerKills == 0 or attackerDeaths == 0 else attackerKills/attackerDeaths #dynamically adjust global difficultyMultiplier on every kill, which logically resolves to the dominant multiplier corresponding to the skill of most dominant players #use sigmoid normalisation function to normalise KD to a value between 1 & 0, where if 0 value is changed to 0.1 #the inverse of the sigmoid is then used as the difficultyMultiplier, inverse is used as lower values signify higher difficulty thisDifficulty = normalizeInverse(attackerKD, 10, 1) difficultyMultiplier = difficultyMultiplierMax if thisDifficulty > difficultyMultiplierMax else thisDifficulty #above signifies that difficultyMultiplier will only get as easy as manually set difficulty while being incremented to maximum difficulty based on player performance radmin.globalMessage("DEBUG: current difficultyMultiplier is: " + str(difficultyMultiplier)) if victim.isAIPlayer() and not attacker.isAIPlayer(): #if player killed bot botSpawnTime(victim, victim, difficultyMultiplier) elif victim.isAIPlayer() and attacker.isAIPlayer(): #if bot killed bot, respawn instantly victim.setTimeToSpawn(0) else: botSpawnTime(victim, victim, difficultyMultiplier) def onPlDeath(player, soldier): if player.isAIPlayer(): botSpawnTime(player, soldier, difficultyMultiplier) def botSpawnTime(player, soldier, difficultyMultiplier): botSpawnTime = math.ceil((bf2.playerManager.getNumberOfPlayersInTeam(1) / bf2.playerManager.getNumberOfPlayersInTeam(2)) * difficultyMultiplier) radmin.globalMessage("DEBUG: respawning " + str(player.getName()) + " in " + str(player.getTimeToSpawn()) + " sec [" + str(botSpawnTime) + "]secComputed") player.setTimeToSpawn(botSpawnTime) for p in bf2.playerManager.getPlayers(): #redundancy to reset all bot spawn times to specified timer, ignoring PR set spawntimes... if p.isAIPlayer(): p.setTimeToSpawn(botSpawnTime) return """ dynamic difficulty scaling applied for every killed & spawned bot,bot respawn time proportional to number of players & number of bots there's 2 ways to change bot count, change actual number of bots spawned OR change spawn times to logically define the number of bots active at any given time comparison cheat sheet: spawn times @difficulty N for a given Number of players, assuming 40bots @difficulty=1 40sec@1players 20sec@2players 14sec@3players 10sec@4players 8sec@5players 7sec@6players 6sec@7players 5sec@8players 5sec@9players 4sec@10players 4sec@11players 4sec@12players 4sec@13players 3sec@14players 3sec@15players 3sec@16players 3sec@17players 3sec@18players 3sec@19players 2sec@20players 2sec@21players 2sec@22players 2sec@23players 2sec@24players 2sec@25players 2sec@26players 2sec@27players 2sec@28players 2sec@29players 2sec@30players 2sec@31players 2sec@32players 2sec@33players 2sec@34players 2sec@35players 2sec@36players 2sec@37players 2sec@38players 2sec@39players 1sec@40players @difficulty=2 80sec@1players 40sec@2players 28sec@3players 20sec@4players 16sec@5players 14sec@6players 12sec@7players 10sec@8players 10sec@9players 8sec@10players 8sec@11players 8sec@12players 8sec@13players 6sec@14players 6sec@15players 6sec@16players 6sec@17players 6sec@18players 6sec@19players 4sec@20players 4sec@21players 4sec@22players 4sec@23players 4sec@24players 4sec@25players 4sec@26players 4sec@27players 4sec@28players 4sec@29players 4sec@30players 4sec@31players 4sec@32players 4sec@33players 4sec@34players 4sec@35players 4sec@36players 4sec@37players 4sec@38players 4sec@39players 2sec@40players @difficulty=3 120sec@1players 60sec@2players 42sec@3players 30sec@4players 24sec@5players 21sec@6players 18sec@7players 15sec@8players 15sec@9players 12sec@10players 12sec@11players 12sec@12players 12sec@13players 9sec@14players 9sec@15players 9sec@16players 9sec@17players 9sec@18players 9sec@19players 6sec@20players 6sec@21players 6sec@22players 6sec@23players 6sec@24players 6sec@25players 6sec@26players 6sec@27players 6sec@28players 6sec@29players 6sec@30players 6sec@31players 6sec@32players 6sec@33players 6sec@34players 6sec@35players 6sec@36players 6sec@37players 6sec@38players 6sec@39players 3sec@40players @difficulty=4 160sec@1players 80sec@2players 56sec@3players 40sec@4players 32sec@5players 28sec@6players 24sec@7players 20sec@8players 20sec@9players 16sec@10players 16sec@11players 16sec@12players 16sec@13players 12sec@14players 12sec@15players 12sec@16players 12sec@17players 12sec@18players 12sec@19players 8sec@20players 8sec@21players 8sec@22players 8sec@23players 8sec@24players 8sec@25players 8sec@26players 8sec@27players 8sec@28players 8sec@29players 8sec@30players 8sec@31players 8sec@32players 8sec@33players 8sec@34players 8sec@35players 8sec@36players 8sec@37players 8sec@38players 8sec@39players 4sec@40players --default-- default PR bot respawn time is ~60seconds if deded and 0sec if wounded before deded @difficulty=5 200sec@1players 100sec@2players 70sec@3players 50sec@4players 40sec@5players 35sec@6players 30sec@7players 25sec@8players 25sec@9players 20sec@10players 20sec@11players 20sec@12players 20sec@13players 15sec@14players 15sec@15players 15sec@16players 15sec@17players 15sec@18players 15sec@19players 10sec@20players 10sec@21players 10sec@22players 10sec@23players 10sec@24players 10sec@25players 10sec@26players 10sec@27players 10sec@28players 10sec@29players 10sec@30players 10sec@31players 10sec@32players 10sec@33players 10sec@34players 10sec@35players 10sec@36players 10sec@37players 10sec@38players 10sec@39players 5sec@40players @difficulty=6 240sec@1players 120sec@2players 84sec@3players 60sec@4players 48sec@5players 42sec@6players 36sec@7players 30sec@8players 30sec@9players 24sec@10players 24sec@11players 24sec@12players 24sec@13players 18sec@14players 18sec@15players 18sec@16players 18sec@17players 18sec@18players 18sec@19players 12sec@20players 12sec@21players 12sec@22players 12sec@23players 12sec@24players 12sec@25players 12sec@26players 12sec@27players 12sec@28players 12sec@29players 12sec@30players 12sec@31players 12sec@32players 12sec@33players 12sec@34players 12sec@35players 12sec@36players 12sec@37players 12sec@38players 12sec@39players 6sec@40players @difficulty=7 280sec@1players 140sec@2players 98sec@3players 70sec@4players 56sec@5players 49sec@6players 42sec@7players 35sec@8players 35sec@9players 28sec@10players 28sec@11players 28sec@12players 28sec@13players 21sec@14players 21sec@15players 21sec@16players 21sec@17players 21sec@18players 21sec@19players 14sec@20players 14sec@21players 14sec@22players 14sec@23players 14sec@24players 14sec@25players 14sec@26players 14sec@27players 14sec@28players 14sec@29players 14sec@30players 14sec@31players 14sec@32players 14sec@33players 14sec@34players 14sec@35players 14sec@36players 14sec@37players 14sec@38players 14sec@39players 7sec@40players @difficulty=8 320sec@1players 160sec@2players 112sec@3players 80sec@4players 64sec@5players 56sec@6players 48sec@7players 40sec@8players 40sec@9players 32sec@10players 32sec@11players 32sec@12players 32sec@13players 24sec@14players 24sec@15players 24sec@16players 24sec@17players 24sec@18players 24sec@19players 16sec@20players 16sec@21players 16sec@22players 16sec@23players 16sec@24players 16sec@25players 16sec@26players 16sec@27players 16sec@28players 16sec@29players 16sec@30players 16sec@31players 16sec@32players 16sec@33players 16sec@34players 16sec@35players 16sec@36players 16sec@37players 16sec@38players 16sec@39players 8sec@40players @difficulty=9 360sec@1players 180sec@2players 126sec@3players 90sec@4players 72sec@5players 63sec@6players 54sec@7players 45sec@8players 45sec@9players 36sec@10players 36sec@11players 36sec@12players 36sec@13players 27sec@14players 27sec@15players 27sec@16players 27sec@17players 27sec@18players 27sec@19players 18sec@20players 18sec@21players 18sec@22players 18sec@23players 18sec@24players 18sec@25players 18sec@26players 18sec@27players 18sec@28players 18sec@29players 18sec@30players 18sec@31players 18sec@32players 18sec@33players 18sec@34players 18sec@35players 18sec@36players 18sec@37players 18sec@38players 18sec@39players 9sec@40players @difficulty=10 400sec@1players 200sec@2players 140sec@3players 100sec@4players 80sec@5players 70sec@6players 60sec@7players 50sec@8players 50sec@9players 40sec@10players 40sec@11players 40sec@12players 40sec@13players 30sec@14players 30sec@15players 30sec@16players 30sec@17players 30sec@18players 30sec@19players 20sec@20players 20sec@21players 20sec@22players 20sec@23players 20sec@24players 20sec@25players 20sec@26players 20sec@27players 20sec@28players 20sec@29players 20sec@30players 20sec@31players 20sec@32players 20sec@33players 20sec@34players 20sec@35players 20sec@36players 20sec@37players 20sec@38players 20sec@39players 10sec@40players """ And I welcome any & all feedbacks & suggestion, I posted it here so it might be used by anyone who finds it useful, and so I take no issue with customising it to requests. botCountBySpawnTime.py 1 1 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.