Vehicle kills can be attributed to no one by dying or switching positions while projectile is in flight

Issue #17 resolved
Andrew Theel created an issue

Vehicle A kills vehicle B but dies while round in mid-flight. No killer for vehicle B.

This is also done by changing positions while round is in flight.

Friendly Fire exploit allows you to kill a team mate by switching positions after firing! with no punishment.

Steps to reproduce: 1. As a crewman spawn friendly bots out away from a tank/vehicle (further away when no slomo is used) 2. Enter the vehicle and use HE or MG 3. Fire at the bots, but quickly switch positions after doing so (use slomo if you aren't fast enough)

Results: Bots should die and the kill messages will show no killer and you will not get any Team Kill warnings etc.

Comments (13)

  1. Andrew Theel reporter

    I looked into this and it can be done, but with quite a bit of undesired hacks. This is mainly due to the poor design in the class tree. If we had a DHVehicle class and a DHVehicleWeaponPawn it would be much better. Still the insane amount of TakeDamage functions that exist that would need to be modified is sickening. So many problems exist because we don't have a DHVehicle class.

  2. Colin Basnett

    This would take a considerable amount of effort and time. Putting this as on hold until some enterprising young programmer tackles this.

  3. Andrew Theel reporter

    The problem: Currently the system gets the pawn that fired the projectile, it works fine with player pawns, but with vehicles it only gets the vehicle (commander/hull gun/etc) pawn and if no controller is controlling it, it gets 'none'. Thus allowing players to bypass team killing prevention and not be punished.

    The Solution: There are now 2 parent projectile classes that would need this integrated: "DHBullet" and "DHAntiVehicleProjectile"

    1. Each should have a Projectile Instigator actor variable that can store the Player that fired the projectile. I'm astounded one does not already exist.
    2. Then a class needs to set the spawned projectile's new variable (Instigator), I'm not sure which branch of classes to use, pawns, cannons, weapon fire?
    3. Once the value is properly set it needs to properly check it in all Take Damage functions, which should be much easier now that we have less of them!

    Make sure to have a comment for child classes that do not call the parent's function, so we know that it is needed and that it doesn't call the super.

    Hope this helps.

  4. Colin Basnett

    Both @AndrewTheel and I witnessed some dude on the 29th Server come in and start team killing people. They were getting away with it by exploiting this bug. This behavior is extraordinarily disruptive; had an admin not been around to kick the player, they could have easily killed the server for the day.

  5. Matt Hands

    At a very quick glance, before I head off to kip, projectile classes have an InstigatorController, which is set in the Projectile class PostBeginPlay. But ROBallaisticProjectile, the parent of all RO/DH projectiles, doesn't call the super in PostBeginPlay, so looks like InstigatorController is never set. I need to log to check. Maybe TWI needed to skip the super but it could just be an error.

  6. Matt Hands

    Have done some investigation & work on this. Should be able to commit tonight or tomorrow morning.

    Projectiles already have an Instigator (pawn) and an InstigatorController variable.

    I can't see where Instigator is set and think it's probably in native code (projectiles use a fair bit of native). But it does get set. InstigatorController was set in Unreal's PostBeginPlay, i.e. as the projectile is spawned. RO removed that, as I mentioned. Maybe just a mistake. Easy to add back.

    Neither variables change, or are deigned to change, after the projectile spawns. Problem with Instigator is it records the pawn that fired the projectile - and the pawn may subsequently switch. InstigatorController is better, as the player's Controller doesn't change. But TakeDamage() requires a passed pawn, not a controller, so Instigator is always passed. That's the problem & I think the solution is:

    1. Set InstigatorController when projectile spawns.

    2. When causing damage, get the player's current pawn from the InstigatorController (i.e. InstigatorController.Pawn) & pass that to the damage function as the InstigatedBy pawn, instead of passing Instigator (which may be out of date).

  7. Matt Hands

    Should be fixed in commit 62f9d4b.

    Looks like quite a lot of changes, but nearly all of it is just formatting, commenting or debug. Actual functional changes are minimal: New function UpdateInstigator() in both projectile classes, just to update Instigator reference to be the pawn currently controlled by the player's controller. Called to update whenever projectile will/may call TakeDamage & pass the Instigator as the damage-causer.

    Will check for any other non-child projectile classes that need the same.

  8. Andrew Theel reporter

    I tested this in full MP environment and was working. I however did not test 2 tanks killing each other, but we can report that as a separate bug if still around (but likely fixed also). The anti-grief portion of this bug is the 'blocker' and important fix I was looking for. Great work Matt.

  9. Log in to comment