jacob404 / promod-future

GNU General Public License v3.0
7 stars 1 forks source link

Don't pass tank AI when rage meter expires: instead, set it on fire #105

Closed rpdelaney closed 9 years ago

rpdelaney commented 9 years ago

This would cure various issues with bot tanks:

In general, tank play is the most important source of damage on every map and it is somewhat anti-competitive to enable infected to get damage due to something AI does (or doesn't do) with a tank. This would ensure that any damage caused by tank was done because someone on that team was controlling the tank, not the random stupidity of bot tank.

Counter-arguments / problems / risks:

jbzdarkid commented 9 years ago

Pretty sure I've got the fire figured out, I talked to jacob about it and he's got a patch waiting whenever he feels like merging it.

"Dusting" a tank is already a problem, and not currently solved by AI tanks. The survivors merely take the next SI hit (they can't wait forever), and then turn on the tank.

MattNF commented 9 years ago

Having the Tank get set on fire out of nowhere sounds random / dumb / randumb

rpdelaney commented 9 years ago

@jbzdarkid "Dusting" a tank is already a problem, and not currently solved by AI tanks. The survivors merely take the next SI hit (they can't wait forever), and then turn on the tank. I don't particularly disagree. However, there may be (conceivably) additional pain from the fact that bot tank chasing the survivors still allows a 4th SI, whereas burning tank would not.

@MattNF Tank get set on fire out of nowhere R->C->P :)

HighCookie commented 9 years ago

I actually like the idea, (you've seen my previous posts about it). I think if this was implement it would have to lose health at 1.5 burn speed. A full health tank on fire can take almost 50? seconds to burn out. That's a lot of rocks that can be thrown while not requiring the tank to give sight at all.

I like the idea. I think it's going to be an impossible sell to the community as it's such a big departure from normal l4d2.

jbzdarkid commented 9 years ago

inferno_damage : 40 : , "sv", "cheat" : Damage per second 6000 / 40 = 150

Seems, low, game is lying mebe

MattNF commented 9 years ago

@rpdelaney

R->C->P :)

u w0t m8

Also, this wouldn't solve no spitters during AI tank. The no-spitter plugin needs to be modified so that the spitter limit is only in effect while a player controls the Tank, rather than when a Tank is in play at all.

I think this would also fix High Cookie's gripes with 4 SI being too powerful with an AI tank. If the spitter limit ended when the Tank goes AI, the player who had Tank should (theoretically) get a Spitter spawn. Spitters aren't hugely useful during Tanks most of the time, so this would nerf that strategy significantly. (You would have [2 Cappers 1 Boomer 1 Spitter] or [3 Cappers 1 Spitter], which is worse than [3 cappers 1 Boomer])

EDIT: My b, I misunderstood. I thought you meant send the Tank AI AND set it on fire, but your solution is to not have AI Tanks and just set the player on fire, which would force him to commit or die? Is that right? Either way the solution I posted would work for balancing AI Tanks + 4 SI if people believe it's too powerful.

HighCookie commented 9 years ago

I like it.

jacob404 commented 9 years ago

inferno_damage : 40 : , "sv", "cheat" : Damage per second

tanks and witches don't follow inferno damage. they use these cvars: tank_burn_duration 75 (aka 80 dps) z_witch_burn_time 15 (aka 67 dps)

jacob404 commented 9 years ago

im ok with this idea but we would have to make some kind of global variable to pass onto the si fire immunity plugin or it would just be extinguished.

rpdelaney commented 9 years ago

@MattNF

EDIT: My b, I misunderstood. I thought you meant send the Tank AI AND set it on fire, but your solution is to not have AI Tanks and just set the player on fire, which would force him to commit or die? Is that right?

Correct.

jbzdarkid commented 9 years ago

@jacob404 Just create a convar in that plugin to do with tank and being on fire. Then turn it off.

Also, if nobody's going to do this one, I'll take it.

Attano commented 9 years ago

@jbzdarkid go ahead. I'll help if needed.

jbzdarkid commented 9 years ago

@Attano What's a good amount of time to burn for? 75 is the game's suggestion, which feels way too long. Rocks are thrown every 5 seconds, punches every 1.5, so 75 seconds is 15 rocks. I'd go with something between 20-40, maybe 35. One pass worth of time feels too short for a commit tank, but two passes seems too long for a rock tank.

jacob404 commented 9 years ago

Make it do 240 damage per second. (25 seconds from max hp) also keep in mind maps with water, we don't want tank to be able to extinguish himself and then have infinite rage

Attano commented 9 years ago

I imagine it's best not to use any hardcoded values and instead design an adaptive configurable algorithm. To put it simple, have the "rage burn" duration cvar'd.

As for the value that should be used de-facto in real configs. Personally I wouldn't pull it out of my ass and instead make it somehow related to the time it takes to fully lose one control. Perhaps 1.5 of that amount. I'm treating the "burning passion" period as a kind of third, last control, but one that lasts a little longer than a normal control.

jacob404 commented 9 years ago

Yea it should obviously be cvar'd. I was just talking numbers. 18 * 1.5 rounded to nearest 5 is 25. I think any higher would be a bit much. We can always tweak numbers later

jbzdarkid commented 9 years ago

I'm not totally clear on how fire damage works. I know I can ignite the tank with IgniteEntity, will that follow the tank_burn_duration? Also, it looks like you can detect if someone is in water with a player flag (FL_INWATER), but that's not an event, so I probably just have to re-ignite them every .2 sec or so.

jacob404 commented 9 years ago

it doesn't have to be actual fire damage, it could just be applied with sourcemod. maybe have a print to the infected team "Tank is overtaken by his rage, and is losing health every second!" idk just an idea. maybe not a good one. lol

jbzdarkid commented 9 years ago

Could just have a fire effect, and not have it deal damage?

Alternately, use the aforementioned timer, and deal direct damage while tank is in water. Once the tank exits the water, re-ignite. It could probably be trolled by someone juking in and out of water with good timing, but fuck them.

jacob404 commented 9 years ago

yea, then just apply the damage separately

Attano commented 9 years ago

You can't block the AI from taking control without igniting the Tank player. Not in any cheap way at least. The low-level solution is complex and requires extension additions. Another solution is to keep adding frustration manually and not let it go below 5%(which is ugly I think).

Also, it looks like you can detect if someone is in water with a player flag (FL_INWATER), but that's not an event, so I probably just have to re-ignite them every .2 sec or so.

https://github.com/Attano/Left4Downtown2/blob/master/scripting/include/left4downtown.inc#L395

jbzdarkid commented 9 years ago

Target function in promod By removing/delaying line 349, I expect to be able to delay passing the tank. SetTankPassedCount I'm assuming that OnTryOfferingTankBot gets called when a tank passes. Here is my code, see line 354 for updates to the mentioned function.

Attano commented 9 years ago

I'd like to see the results of your testing. If you are able to "fool" the Director by changing the pass count, that would be reasonably effective, though not ideal. Mainly because the HUDs will keep showing the Tank pass count at 2.

Edit: Double checked your code. The current implementation is not going to work. CDirector::TryOfferingTankBot() doesn't get invoked when the Tank is passed to AI. ZombieManager::ReplaceTank() is. This function is not virtual so it cannot be hooked via Sourcemod, only through an extension. Hence why I suggested that the cleanest, non-hacky approach would be too troublesome to bother. Try decreasing the pass count instead and see if that helps. I misinterpreted your code at the first glance and thought that's what you were doing already.

Edit 2: You don't need to change a cvar's flags in order to modify its value, as long as it's not a FCVAR_DEVELOPMENT_ONLY (which shouldn't even be accessible within Sourcemod in the first place).

jbzdarkid commented 9 years ago

In my code (yet untested, school takes priority), the pass count never increases.

jbzdarkid commented 9 years ago

After some testing with Fig, I've got the plugin working. It handles water by starting a timer and dealing "fire" damage on that timer. What should I do with the source?

jacob404 commented 9 years ago

post the source to this repo and i will take a look

jbzdarkid commented 9 years ago

@jacob404 1ed00f9

I didn't test out the hud changes, I might need to modify tank_pass_number more frequently, and I'm not certain why I set it as a cheat cvar.

Attano commented 9 years ago

I suggest removing any and all cvar flag stripping work. It's redundant.

Also,

if (GetEntityFlags(client) & FL_INWATER != FL_INWATER) return;

This is a bit weird. Bitflags don't work like that. Change to

if (!(GetEntityFlags(client) & FL_INWATER)) return;

OnWaterMove() triggers for noclipped players for some reason(when they are above water, I think -- not sure though). I might fix this in the next release of Downtown though.

jbzdarkid commented 9 years ago

CVARs weren't changing when I didn't remove the cheats flag, how would you suggest I get around that otherwise?

That's how you compare against a bit mask, so I use it for flags as well. Unknown & MASK == MASK. For a single flag, it works because there's only one bit -- if it's off, you get 0, which is false.

How relevant is that for noclipped players? The tank should never be noclipping.

Attano commented 9 years ago

I don't know why they aren't changing. Plenty of plugins are doing the same thing without any issues. See examples.

Googled a bit on the bitflags subject. That's something new to me. Either way, in your particular case, both methods will work identically. But personally, I'd use my approach anyway, multiple times if I have to, for the sake of maintaining code clarity. I also believe that the highest rated reply is suggesting the same thing in the last sentence.

jbzdarkid commented 9 years ago

I don't know why they aren't changing. Plenty of plugins are doing the same thing without any issues. (See examples.)[https://github.com/Attano/L4D2-Competitive-Framework/search?utf8=%E2%9C%93&q=SetConVarInt&type=Code]

Ok, I'll change the handling there. (Googled a bit on the bitflags subject.)[http://stackoverflow.com/questions/4649231/if-mask-value-or-if-mask-value-value] That's something new to me. Either way, in your particular case, both methods will work identically. But personally, I'd use my approach anyway, multiple times if I have to, for the sake of maintaining code clarity. I also believe that the highest rated reply is suggesting the same thing in the last sentence.

"get into the habit of explicitly testing for all bits" "if ((mask & FLAG3) == FLAG3) tests if all bits" But it's a moot point, anyways.

Attano commented 9 years ago

Agreed. Everyone has his own tastes.

jbzdarkid commented 9 years ago

Well failing any other serious concerns, I'm going to commit this into the main repo.