[SCRIPT] Anvil's Don't Run Over Your Teammates!

Party-approved programming
Post Reply
Anvilfolk
Posts: 119
Joined: Thu Jan 17, 2013 3:56 pm
Location: Portugal
Contact:

[SCRIPT] Anvil's Don't Run Over Your Teammates!

Post by Anvilfolk »

Hi all!

I've been learning ArmA 2 editing/scripting. Since so many people have been vehicling other people to death at the start of missions, I decided to try my hand at making that impossible/harder! I present to you Anvil's Don't Run Over Your Teammates script (ADROYT, isn't that fancy?).

Code: Select all

// Anvilfolk's Don't Run Over Your Teammates script
// Thanks to Harakka and Head for their great help, as well as everyone else over at the FA Skype chat who helped!
// Apologies to those that I've forgotten, there were quite a few Q&A's!


if (f_var_debugMode == 1) then {
  hint "Now running Anvil's Don't Run Over Your Teammates script!";
};

_FRONT_DISTANCE = 15;   // Center point in front of vehicle used to check for friendlies.
_SAFE_RADIUS = 15;      // Radius in front of vehicle to check for friendlies.
_MAX_SPEED = 0.5;       // Maximum vehicle speed (m/s) if friendlies are in front.
_REDUCE_INTERVAL = 0.2; // How often to reduce speed (until maximum) if there are friendlies in front.
_REDUCE_RATIO = 0.8;    // Percentage of speed to reduce every interval.
_SAFE_INTERVAL = 0.2;   // How often to look for whether the player is still in the vehicle.


// CheckSafe checks for friendly troops in front of the player's vehicle.
CheckFriendlies = {
  // Get vehicle position and heading.
  _vehicle = vehicle player;
  _currX = getPosATL _vehicle select 0;
  _currY = getPosATL _vehicle select 1;
  _dir = getDir _vehicle;
  
  // Grab all nearest troops on foot.
  _nObjs = nearestObjects [_vehicle, ["man"], 20];
  _friendlies = [];
  
  // Put into _friendlies only those troops that are alive and within 
  // _SAFE_RADIUS of a point _FRONT_DISTANCE in front of the vehicle.
  {
    _inFrontPos = [_currX + sin(_dir)*_FRONT_DISTANCE, _currY + cos(_dir)*_FRONT_DISTANCE];
    if (alive _x && _x distance _inFrontPos < _SAFE_RADIUS) then {
      _friendlies set [(count _friendlies), _x];
    };
  } forEach _nObjs;
  
  // Check if there are any friendlies among those troops.
  _numFriendlies = player countFriendly _friendlies;
  _numFriendlies > 0;
};

// Make sure game has initialised properly. (Is this necessary?)
waitUntil {alive player};
while {alive player} do {

  // For the lifetime of the player, we check whether he has entered a vehicle.
  waitUntil {vehicle player != player};
  if (f_var_debugMode == 1) then { player sideChat "Entered vehicle."; };
  while {vehicle player != player} do { // While the player is in the vehicle
  
    // As long as there are enemies in front
    while {[] call CheckFriendlies && vehicle player != player} do { 
      _vel = velocity (vehicle player);
      _vx = (_vel select 0);
      _vy = (_vel select 1);
      _vz = (_vel select 2);
      
      // If player is going above _MAX_SPEED, reduce it with REDUCE_RATIO.
      if (sqrt(_vx*_vx + _vy*_vy +_vz*_vz) > _MAX_SPEED * 1000 / 3600) then {
        (vehicle player) setVelocity[_vx*_REDUCE_RATIO, _vy*_REDUCE_RATIO, _vz*_REDUCE_RATIO];
        if (f_var_debugMode == 1) then { hintSilent "Slowing... people ahead."; };
      };
      sleep _REDUCE_INTERVAL;
    };
    if (f_var_debugMode == 1) then { hintSilent ""; };
    sleep _SAFE_INTERVAL;
  };
  if (f_var_debugMode == 1) then { player sideChat "Left vehicle."; };
};

Big thanks go out to Harakka, Head, Kale, Headspace and all others I've forgotten, who put up with my questions for hours on end :)

I also just noticed that wolfenswan has a script here for limiting player speed, which is actually what I wanted. I think I'll try to incorporate that later.

What I'm currently doing is that whenever the player's in a vehicle, he will not be able to go above a certain speed if there is friendly infantry in front of him (car will brake until below threshold). It currently checks a sphere in front of the player, but I am hoping to upgrade it to a rectangle of sorts, which is more sane. It doesn't work for backing up, but perhaps in due time.

I'll comment, etc, later!

All comments, criticisms, suggestions, etc, are highly appreciated!
Last edited by Anvilfolk on Sun Feb 10, 2013 12:14 pm, edited 3 times in total.

Black Mamba
Posts: 335
Joined: Sun May 27, 2012 12:11 pm

Re: [Script] Anvil's Don't Run Over Your Teammates!

Post by Black Mamba »

Good job, sir!

Tip: the more recent commands getPosASL and getPosATL are about 25 times faster than the old getpos. Thus ,it's usually good practice to use those instead.
Another thing, when you choose to include a hint in a loop, it's usually nicer for the user to use hintSilent, so that his ears don't get spammed with that beep sound.

Anvilfolk
Posts: 119
Joined: Thu Jan 17, 2013 3:56 pm
Location: Portugal
Contact:

Re: [Script] Anvil's Don't Run Over Your Teammates!

Post by Anvilfolk »

Oooh, awesome tips, thanks! It's definitely unfinished so I'll give it a few touches as soon as I get time. The hints are essentially debug things :) Then it's on to making a proper mission!

Anvilfolk
Posts: 119
Joined: Thu Jan 17, 2013 3:56 pm
Location: Portugal
Contact:

Re: [SCRIPT] Anvil's Don't Run Over Your Teammates!

Post by Anvilfolk »

Updated code with comments and with easily modified variables :)

I'd like for this only to apply to land vehicles. Any ideas how I could do that? Cheers!

Black Mamba
Posts: 335
Joined: Sun May 27, 2012 12:11 pm

Re: [SCRIPT] Anvil's Don't Run Over Your Teammates!

Post by Black Mamba »

Have a look at my BM_vehicleSeats_Enhancement script. The function BM_fn_JOVehicleType might help you, even though you probably don't need to discriminate all kinds of vehicles.

Post Reply