Author Topic: Ballistic functions  (Read 5407 times)

0 Members and 1 Guest are viewing this topic.

Offline tk

  • Soldier
  • **
  • Posts: 235
Ballistic functions
« on: January 02, 2011, 07:52:04 am »
Script Name: Ballistic functions
Original Author(s): tk
Core Version: 2.6.5
Script Description:

Here are some useful ballistic functions I made some time ago:

function ProjectileTime(sx, vx: single): single;
function BallisticAim(x1, y1, x2, y2, v, gravity: single; var target_in_range: boolean): single;
function BallisticCast(x, y, g: single; var vec: tVector): boolean;


They can be used for:
-accurate aiming including in calculations variables such as gravity, air resistance etc; so if you had problems with other aiming functions failing on longer distances due to gravity and air resistance, here's the solution
-retrieving coords, veloctity and time of bullet's collision; information about bullet's collision can be used for many purposes

Code: [Select]
const
g_ = 0.135; // soldat's default acceleration of gravity in pixels/tick^2
k_ = 0.01; // air resistance factor
e = 2.71828182846;

function arctan2(X, Y: single): single;
begin
  if X < 0 then Result := arctan(Y/X) + Pi else
  if X > 0 then Result := arctan(Y/X) else
  if Y > 0 then Result := 2.3562 else
  Result := -0.7854;
end;

// returns time in ticks of bullet's flight
// sx - x component of distance beetween start position and destination
// vx - x component of velocity of a bullet
function ProjectileTime(sx, vx: single): single;
begin
Result := -LogN(e, 1 - k_*sx/vx) / k_;
end;

// x1, y1: poistion of bullet's start
// x2, y2: position of bullet's destination
// v: velocity of a bullet
// gravity: current server's gravity (default is 0.06)
// target_in_range: boolean returned via reference, tells us if destination is in bullet's range
// returns angle which the bullet should be shot with
function BallisticAim(x1, y1, x2, y2, v, gravity: single; var target_in_range: boolean): single;
var x, y, sine, cosine, diff, last_diff, y3, g2, a, a2: single; dir, last_dir: boolean;
kx_v, g_k_v, g_k2: single;
begin
x := x2 - x1;
y := y1 - y2; // inverted y axis
a := arctan2(x, y);
if x1 < x2 then begin // direction increasement angle
a2 := 0.3;
end else begin
a2 := -0.3;
end;
diff := 10e6;
kx_v := k_*x/v; // calculate constants
g2 := g_ * gravity / 0.06;
g_k_v := g2/k_/v;
g_k2 := g2/k_/k_;
repeat
sine := sin(a); cosine := cos(a);
// y(x) = (tan(a) + g/k/v/cos(a))*x  + g/k^2*ln(1 - k*x/v/cos(a))
y3 := (sine/cosine + g_k_v/cosine)*x + g_k2*LogN(e, 1 - kx_v/cosine);
if y3 = 0 then begin // if NAN is returned - target is out of range
Result := -Result;
exit;
end;
last_diff := diff;
diff := abs(y3-y);
if diff < last_diff then Result := a;
if diff < 5 then break; // if found the angle
last_dir := dir;
dir := y3 > y;
if (dir) xor (last_dir) then begin // if passed the proper angle, change direction and increase accuracy
a2 := a2/-2;
end;
a := a + a2;
until false;
Result := -Result; // invert angle due to inverted y axis
target_in_range := true;
end;

type
tVector = record
x, y, vx, vy: single;
t: word;
end;
 
// returns coordinates, velocity and time to collision of a bullet
// returns true if bullet doesn't collide with a poligon on it's way
const ik_ = 1 - k_;
function BallisticCast(x, y, g: single; var vec: tVector): boolean;
var x2, y2, rd: single; dist: word;
begin
if abs(vec.vy) < 13.5 then rd := 13.5 else rd := vec.vy;
dist := Trunc(1 + Sqrt(vec.vx*vec.vx + rd*rd));
while vec.t > 0 do begin
vec.t := vec.t - 1;
x2 := x;
x := x + vec.vx;
vec.vx := vec.vx * ik_;
vec.vy := vec.vy + g;
y2 := y;
y := y + vec.vy;
vec.vy := vec.vy * ik_;
if not RayCast(x, y, x2, y2, rd, dist) then begin
vec.X := x2;
vec.Y := y2;
exit;
end;
end;
vec.X := x2;
vec.Y := y2;
Result := true;
end;

How it works: finds alpha in the ballistic curve equation F(x, y), x, y - target position from [0, 0], x = const:

using a form of bisection algorithm.

Example use of BallisticAim and ProjectileTime, shooting a bullet from player 1 to player 2
Code: (Pascal) [Select]
var x1, y1, x2, y2, speed, gravity, angle: single;
target_in_range: boolean;
time: word;

// ...

// get players' position
GetPlayerXY(1, x1, y1);
GetPlayerXY(2, x2, y2);

// increase height to not aim at player's legs
y1 := y1 - 10;
y2 := y2 - 10;

// set bullet's velocity
speed := 15;

// set gravity (0.06 is Soldat's default)
gravity := 0.06;

// aim
angle := BallisticAim(x1, y1, x2, y2, speed, gravity, target_in_range);

if target_in_range then begin
  // shoot a bullet
  CreateBullet(x1, y1, speed*cos(angle), speed*sin(angle), 0, 7, 1);
 
  // idk if someone may find it useful, however here's example use of ProjectileTime too:
  // calculate time of bullet's flight
  time := Round(ProjectileTime(Abs(x1 - x2), cos(angle)*speed);
  WriteConsole(0, 'Bullet will reach it''s destination in ' + IntToStr(time) + ' ticks', $FFFFFF);
 
end else begin
  WriteConsole(0, 'Target is out of bullet''s range', $FFFFFF);
end;

example use of BallisticCast:
Code: (Pascal) [Select]
var vec: tVector;
x, y, gravity: single
start_time: word;
// ...

// setting some example start position;
x := 0.0;
y := 0.0;

// setting some example velocity for a casted projectile
vec.vx := 5.0;
vec.vy := 2.5;

// sets time of projectile's flight to check, in this case first 3 seconds will be checked
start_time := 180;
vec.t := start_time;

// setting current gravity (default 0.06);
gravity := 0.06;

// shoot the projectile
CreateBullet(x, y, vec.vx, vec.vy, 0, 7, 1);
if not BallisticCast(x, y, g_*gravity/0.06, vec) then begin // if false is returned it means that collision occured
// ...
WriteLn('bullet will collide in ' + IntToStr(start_time - vec.t)+ ' ticks');
WriteLn('it will collide at point (' + FloatToStr(vec.x) + ', ' + FloaToStr(vec.y) +') with velocity [' + FloatToStr(vec.vx) + ', ' + FloaToStr(vec.vy) +']');
end else
WriteLn('bullet will not collide in the next ' + IntToStr(start_time) + ' ticks');


// edit
 Attached dll version, which includes some additional stuff, like enhanced version of ballistic aim, taking players velocity into calculation.
« Last Edit: February 25, 2016, 10:24:47 am by tk »

Offline dnmr

  • Camper
  • ***
  • Posts: 315
  • emotionally handicapped
Re: Ballistic functions
« Reply #1 on: January 02, 2011, 08:03:04 am »
Props for releasing this, great functions (:

Offline BRADEN

  • Camper
  • ***
  • Posts: 319
Re: Ballistic functions
« Reply #2 on: January 02, 2011, 09:00:18 am »
As a soldat fan and an a-level physics student I say this is some excellent work...

Death is the solution to all problems. No man; no problem.
-Joseph Stalin

DarkCrusade

  • Guest
Re: Ballistic functions
« Reply #3 on: January 02, 2011, 09:07:16 am »
Excellent, this looks really useful!

Offline demoniac93

  • Veteran
  • *****
  • Posts: 1554
Re: Ballistic functions
« Reply #4 on: January 02, 2011, 01:26:30 pm »
This can make arcade gameplay just a bit more realistic, enough to keep it simple, and fun.
b&

Offline Hacktank

  • Camper
  • ***
  • Posts: 462
  • Soldat Scripter
    • HTZRPG
Re: Ballistic functions
« Reply #5 on: January 02, 2011, 03:42:23 pm »
Awesome, great work.


Offline Foxconn

  • Major
  • *
  • Posts: 53
  • Common sense abandoned me.
Re: Ballistic functions
« Reply #6 on: January 02, 2011, 03:49:39 pm »
A bit more realism in a simple arcade game never hurts. Good job. But we need to remember that adding MORE and MORE awesome stuff will kill the game and the fun.
« Last Edit: January 02, 2011, 03:52:52 pm by Foxconn »

Offline JotEmI

  • Soldier
  • **
  • Posts: 188
Re: Ballistic functions
« Reply #7 on: January 03, 2011, 08:30:37 am »
I've tried combining BallisticAim() with Avarax's Wave() and I've encountered some troubles:
  • arctan2(x, y); - "Unknown identifier"; I figured arctan2() should return arctan(y/x) so I've changed it that way,
  • bullets created by Wave() seem to aim properly when target's X is greater than starting X (when target's on the right from bullet's starting position) but when target's X is lower than starting X (when target's on the left from bullet's starting position) then bullets aim just the other way about. Like X and Y axis were inverted.

Offline DorkeyDear

  • Veteran
  • *****
  • Posts: 1507
  • I also go by Curt or menturi
Re: Ballistic functions
« Reply #8 on: January 03, 2011, 11:24:33 am »
JotEmI: I'm not exactly sure why arctan2 isn't defined (probably server version issues), but refer to Wikipedia for the definition of it. (note: I think x and y are flipped on the wiki)

Offline tk

  • Soldier
  • **
  • Posts: 235
Re: Ballistic functions
« Reply #9 on: January 03, 2011, 11:42:16 am »
Oh, I'm using arctan2 often so I forgot it's not built in function, added it to the code in the first post.
And it aims properly no matter which x (of source or destination) is greater, I have been using ballistic aim for some time on Last Stand servers and it works perfectly, your problem was caused by using normal arctan instead; arctan is something different than arctan2
« Last Edit: January 03, 2011, 11:51:19 am by tk »

Offline JotEmI

  • Soldier
  • **
  • Posts: 188
Re: Ballistic functions
« Reply #10 on: January 03, 2011, 12:29:44 pm »
Thx for your response, I'll try using your arctan2().

EDIT: Yep, with your version of arctan2() BallisticAim() works like a charm.
« Last Edit: January 03, 2011, 10:27:55 pm by JotEmI »

Offline Savage

  • Soldier
  • **
  • Posts: 155
Re: Ballistic functions
« Reply #11 on: November 19, 2015, 11:50:45 am »
Could some1 explain how to load that dll into SC3 script?

Offline soldat-game

  • Camper
  • ***
  • Posts: 407
Re: Ballistic functions
« Reply #12 on: November 20, 2015, 11:05:48 am »
In Script:
Code: [Select]
implementation

function Direction(x1, y1, x2, y2, v, gravity, vx, vy: single): single; 
external 'ballistic_aim_x@NAME OF DLL.dll';

In Config Must:
AllowDlls=1


Example USEAGE (Auto Aimbot Shoot If ReloadKey is press and u is admin):
//This use sc2 + sc3 Legacy=1
Code: [Select]
unit Aimbot;

interface

implementation

function Direction(x1, y1, x2, y2, v, gravity, vx, vy: single): single; 
external 'ballistic_aim_x@aim.dll';

var
wait, ShootingTimes: array [1..32] of integer;
WeapSpeed: array [1..32] of single;
i:byte;

function lookForTarget(ID: byte; MinDistance, MaxDistance: integer; UsingRaycast: boolean): byte;
var i,Team: byte; X,Y,X2,Y2,sqrdist,maxdist: single;
begin
GetPlayerXY(ID,X,Y);
maxdist:=MaxDistance*MaxDistance;
Result:=0;
Team := GetPlayerStat(ID,'Team');
for i:=1 to 32 do if (i<>ID) then if GetPlayerStat(i,'Active') then if GetPlayerStat(i,'Alive') then if (GetPlayerStat(i,'team') <> Team) then begin
GetPlayerXY(i,X2,Y2);
if (UsingRayCast) then if Map.RayCast(X,Y-7,X2,Y2-7,false, false, true, true, 2) then continue;
X2:=X2-X; Y2:=Y2-Y; sqrdist:=X2*X2+Y2*Y2;
if (sqrdist < maxdist) and (sqrdist >= MinDistance) then begin
Result:=i;
maxdist:=sqrdist;
end;
end;
end;

procedure Wave(X,Y,Direction,Offset,Radius,Speed,Power,RoomPerBullet,Radiation: single; Bullettype,Bulletcount,Owner: byte);
var i: integer; angle,centerX,centerY: single;
begin
centerX:=X-cos(Direction)*Radius;
centerY:=Y-sin(Direction)*Radius;
angle := (Bulletcount * RoomPerBullet) / (2 * pi * Radius);
for i:=-Bulletcount div 2 to Bulletcount div 2 + Bulletcount mod 2 do CreateBullet(centerX+cos(Direction+angle*i)*Radius+cos(Direction)*Offset,centerY+sin(Direction+angle*i)*Radius+sin(Direction)*Offset, cos(Direction+angle*i*Radiation)*Speed, sin(Direction+angle*i*Radiation)*speed,power,Bullettype,Owner);
end;

procedure OnTick(Ticks: integer);
var enemy: byte; i:byte; NewPrimary, NewSecondary: TNewWeapon; dodo:integer;
begin
for i := 1 to 32 do if (GetPlayerStat(i,'Active') = true) then begin
if (players[i].isadmin=true) then begin
if (GetKeyPress(i,'Down') = true) then begin
case (GetPlayerStat(i,'Primary')) of
0: begin //USOSOCM
enemy := lookForTarget(i, 0, 850, true);
if Ticks mod (6) = 0 then begin
if (Enemy <> 0) and (wait[i]<=0) and (GetPlayerStat(i,'Ammo')>0) then begin
Players[i].MouseAimX:=GetPlayerStat(enemy,'x');
Players[i].MouseAimy:=GetPlayerStat(enemy,'y')-8;
NewPrimary := TNewWeapon.Create();
NewSecondary := TNewWeapon.Create();
try
NewPrimary.WType := 0; //Spas
NewPrimary.Ammo := (GetPlayerStat(i,'Ammo')-1);
NewSecondary.WType := GetPlayerStat(i,'Secondary');
NewSecondary.Ammo := GetPlayerStat(i,'Secammo');
Players[i].ForceWeapon(TWeapon(NewPrimary), TWeapon(NewSecondary));
finally
NewPrimary.Free();
NewSecondary.Free();
end;
wait[i]:=10;
PlaySound(0,'colt1911-fire.wav',GetPlayerStat(i,'x'),GetPlayerStat(i,'y'));
Wave(GetPlayerStat(i,'x'),GetPlayerStat(i,'y')-8,Direction(GetPlayerStat(i,'x'),GetPlayerStat(i,'y')-8,GetPlayerStat(enemy,'X'),GetPlayerStat(enemy,'y')-8,WeapSpeed[1],0.06,GetPlayerStat(enemy,'Velx'),GetPlayerStat(enemy,'vely')),8,59,  WeapSpeed[1],0.81,12,24,  1,0,i);
end;
end;
end;
1: begin
enemy := lookForTarget(i, 0, 850, true);
if Ticks mod (6) = 0 then begin
if (Enemy <> 0) and (wait[i]<=0) and (GetPlayerStat(i,'Ammo')>0) then begin
NewPrimary := TNewWeapon.Create();
NewSecondary := TNewWeapon.Create();
try
NewPrimary.WType := 1; //Spas
NewPrimary.Ammo := (GetPlayerStat(i,'Ammo')-1);
NewSecondary.WType := GetPlayerStat(i,'Secondary');
NewSecondary.Ammo := GetPlayerStat(i,'Secammo');
Players[i].ForceWeapon(TWeapon(NewPrimary), TWeapon(NewSecondary));
finally
NewPrimary.Free();
NewSecondary.Free();
end;
wait[i]:=25;
PlaySound(0,'deserteagle-fire.wav',GetPlayerStat(i,'x'),GetPlayerStat(i,'y'));
Wave(GetPlayerStat(i,'x'),GetPlayerStat(i,'y'),Direction(GetPlayerStat(i,'x'),GetPlayerStat(i,'y'),GetPlayerStat(enemy,'X'),GetPlayerStat(enemy,'y')-8,WeapSpeed[2],0.06,GetPlayerStat(enemy,'Velx'),GetPlayerStat(enemy,'vely')),8,96,  WeapSpeed[2],2.2,0.7,7.64,  1,1,i);
ShootingTimes[i]:=0;
end;
end;
end;
2: begin
enemy := lookForTarget(i,0,850,true);
if Ticks mod (6) = 0 then begin
if (Enemy <> 0) and (wait[i]<=0) and (GetPlayerStat(i,'Ammo')>0) then begin
NewPrimary := TNewWeapon.Create();
NewSecondary := TNewWeapon.Create();
try
NewPrimary.WType := 2; //Spas
NewPrimary.Ammo := (GetPlayerStat(i,'Ammo')-1); // Full one
NewSecondary.WType := GetPlayerStat(i,'Secondary'); // Hands
NewSecondary.Ammo := GetPlayerStat(i,'Secammo'); // Hands
Players[i].ForceWeapon(TWeapon(NewPrimary), TWeapon(NewSecondary));
finally
NewPrimary.Free();
NewSecondary.Free();
end;
PlaySound(0,'mp5-fire.wav',GetPlayerStat(i,'x'),GetPlayerStat(i,'y'));
Wave(GetPlayerStat(i,'x'),GetPlayerStat(i,'y')-8,Direction(GetPlayerStat(i,'x'),GetPlayerStat(i,'y')-8,GetPlayerStat(enemy,'X'),GetPlayerStat(enemy,'y')-8,WeapSpeed[3],0.06,GetPlayerStat(enemy,'Velx'),GetPlayerStat(enemy,'vely')),8,59,  WeapSpeed[3],0.776,12,24,  1,0,i);
end;
end;
end;
3: begin
enemy := lookForTarget(i,0,850,true);
if Ticks mod (11) = 0 then begin
if (Enemy <> 0) and (wait[i]<=0) and (GetPlayerStat(i,'Ammo')>0) then begin
NewPrimary := TNewWeapon.Create();
NewSecondary := TNewWeapon.Create();
try
NewPrimary.WType := 3; //Spas
NewPrimary.Ammo := (GetPlayerStat(i,'Ammo')-1);
NewSecondary.WType := GetPlayerStat(i,'Secondary');
NewSecondary.Ammo := GetPlayerStat(i,'Secammo');
Players[i].ForceWeapon(TWeapon(NewPrimary), TWeapon(NewSecondary));
finally
NewPrimary.Free();
NewSecondary.Free();
end;
PlaySound(0,'ak74-fire.wav',GetPlayerStat(i,'x'),GetPlayerStat(i,'y'));
Wave(GetPlayerStat(i,'x'),GetPlayerStat(i,'y')-8,Direction(GetPlayerStat(i,'x'),GetPlayerStat(i,'y')-8,GetPlayerStat(enemy,'X'),GetPlayerStat(enemy,'y')-8,WeapSpeed[4],0.06,GetPlayerStat(enemy,'Velx'),GetPlayerStat(enemy,'vely')),8,59,  WeapSpeed[4],0.92,12,24,  1,0,i);
end;
end;
end;
4: begin
enemy := lookForTarget(i,0,850,true);
if Ticks mod (7) = 0 then begin
if (Enemy <> 0) and (wait[i]<=0) and (GetPlayerStat(i,'Ammo')>0) then begin
NewPrimary := TNewWeapon.Create();
NewSecondary := TNewWeapon.Create();
try
NewPrimary.WType := 4; //Spas
NewPrimary.Ammo := (GetPlayerStat(i,'Ammo')-1);
NewSecondary.WType := GetPlayerStat(i,'Secondary');
NewSecondary.Ammo := GetPlayerStat(i,'Secammo');
Players[i].ForceWeapon(TWeapon(NewPrimary), TWeapon(NewSecondary));
finally
NewPrimary.Free();
NewSecondary.Free();
end;
PlaySound(0,'steyraug-fire.wav',GetPlayerStat(i,'x'),GetPlayerStat(i,'y'));
Wave(GetPlayerStat(i,'x'),GetPlayerStat(i,'y')-8,Direction(GetPlayerStat(i,'x'),GetPlayerStat(i,'y')-8,GetPlayerStat(enemy,'X'),GetPlayerStat(enemy,'y')-8,WeapSpeed[5],0.06,GetPlayerStat(enemy,'Velx'),GetPlayerStat(enemy,'vely')),8,59,  WeapSpeed[5],0.71,12,24,  1,0,i);
end;
end;
end;
5: begin
enemy := lookForTarget(i, 0, 850, true);
if Ticks mod (6) = 0 then begin
if (Enemy <> 0) and (wait[i]<=0) and (GetPlayerStat(i,'Ammo')>0) then begin
wait[i]:=33;
inc(ShootingTimes[i],1);
PlaySound(0,'spas12-fire.wav',GetPlayerStat(i,'x'),GetPlayerStat(i,'y'));
Wave(GetPlayerStat(i,'x'),GetPlayerStat(i,'y'),Direction(GetPlayerStat(i,'x'),GetPlayerStat(i,'y'),GetPlayerStat(enemy,'X'),GetPlayerStat(enemy,'y')-8,WeapSpeed[6],0.06,GetPlayerStat(enemy,'Velx'),GetPlayerStat(enemy,'vely')),8,96,  WeapSpeed[6],1.63,0.46,2.71,  3,5,i);
if (ShootingTimes[i]>=7) then begin
ForceWeaponEx(i,GetPlayerStat(i,'Primary'),GetPlayerStat(i,'Secondary'),255,GetPlayerStat(i,'Secammo')); //Reload
ShootingTimes[i]:=0;
wait[i]:=225;
end;
end;
end;
end;
6: begin
enemy := lookForTarget(i, 0, 850, true);
if Ticks mod (6) = 0 then begin
if (Enemy <> 0) and (wait[i]<=0) and (GetPlayerStat(i,'Ammo')>0) then begin
wait[i]:=46;
inc(ShootingTimes[i],1);
PlaySound(0,'ruger77-fire.wav',GetPlayerStat(i,'x'),GetPlayerStat(i,'y'));
Wave(GetPlayerStat(i,'x'),GetPlayerStat(i,'y'),Direction(GetPlayerStat(i,'x'),GetPlayerStat(i,'y'),GetPlayerStat(enemy,'X'),GetPlayerStat(enemy,'y')-8,WeapSpeed[7],0.06,GetPlayerStat(enemy,'Velx'),GetPlayerStat(enemy,'vely')),8,59,  WeapSpeed[7],3.5,12,24,  1,0,i);
if (ShootingTimes[i]>=4) then begin
ForceWeaponEx(i,GetPlayerStat(i,'Primary'),GetPlayerStat(i,'Secondary'),255,GetPlayerStat(i,'Secammo')); //Reload
ShootingTimes[i]:=0;
end;
end;
end;
end;
7: begin
enemy := lookForTarget(i, 0, 850, true);
if Ticks mod (6) = 0 then begin
if (Enemy <> 0) and (wait[i]<=0) and (GetPlayerStat(i,'Ammo')>0) then begin
wait[i]:=200;
ForceWeaponEx(i,GetPlayerStat(i,'Primary'),GetPlayerStat(i,'Secondary'),255,GetPlayerStat(i,'SecAmmo'));
PlaySound(0,'m79-fire.wav',GetPlayerStat(i,'x'),GetPlayerStat(i,'y'));
Wave(GetPlayerStat(i,'x'),GetPlayerStat(i,'y'),Direction(GetPlayerStat(i,'x'),GetPlayerStat(i,'y'),GetPlayerStat(enemy,'X'),GetPlayerStat(enemy,'y'),WeapSpeed[8],0.06,GetPlayerStat(enemy,'Velx'),GetPlayerStat(enemy,'vely')),8,59,  WeapSpeed[8],40,12,24,  4,0,i);
end;
end;
end;
8: begin
enemy := lookForTarget(i, 0, 112000, true); if (Enemy=0) then enemy := lookForTarget(i, 0, 2000, false);
if Ticks mod (6) = 0 then begin
if (Enemy <> 0) and (wait[i]<=0) and (GetPlayerStat(i,'Ammo')>0) then begin
wait[i]:=225;
inc(ShootingTimes[i],1);
PlaySound(0,'barretm82-fire.wav',GetPlayerStat(i,'x'),GetPlayerStat(i,'y'));
Wave(GetPlayerStat(i,'x'),GetPlayerStat(i,'y'),Direction(GetPlayerStat(i,'x'),GetPlayerStat(i,'y'),GetPlayerStat(enemy,'X'),GetPlayerStat(enemy,'y'),WeapSpeed[9],0.06,GetPlayerStat(enemy,'Velx'),GetPlayerStat(enemy,'vely')),8,59,  WeapSpeed[9],20,12,24,  1,0,i);
if (ShootingTimes[i]>=10) then begin
ForceWeaponEx(i,GetPlayerStat(i,'Primary'),GetPlayerStat(i,'Secondary'),255,GetPlayerStat(i,'Secammo')); //Reload
ShootingTimes[i]:=0;
end;
end;
end;
end;
9: begin
enemy := lookForTarget(i,0,850,true);
if Ticks mod (9) = 0 then begin
if (Enemy <> 0) and (wait[i]<=0) and (GetPlayerStat(i,'Ammo')>0) then begin
if (ShootingTimes[i]>=44) then begin
wait[i]:=272; //Reload Time
ForceWeaponEx(i,GetPlayerStat(i,'Primary'),GetPlayerStat(i,'Secondary'),255,GetPlayerStat(i,'Secammo'));
end else
begin
inc(ShootingTimes[i],1);
PlaySound(0,'m249-fire.wav',GetPlayerStat(i,'x'),GetPlayerStat(i,'y'));
Wave(GetPlayerStat(i,'x'),GetPlayerStat(i,'y')-8,Direction(GetPlayerStat(i,'x'),GetPlayerStat(i,'y')-8,GetPlayerStat(enemy,'X'),GetPlayerStat(enemy,'y')-8,WeapSpeed[10],0.06,GetPlayerStat(enemy,'Velx'),GetPlayerStat(enemy,'vely')),8,59,  WeapSpeed[10],0.735,12,24,  1,0,i);
end;
end;
end;
end;
10: begin
end;
11: begin //Knife
enemy := lookForTarget(i,0,850,true);
if Ticks mod (6) = 0 then begin
if (Enemy <> 0) and (wait[i]<=0) then begin
wait[i]:=60;
ForceWeaponEx(i,255,GetPlayerStat(i,'Secondary'),255,GetPlayerStat(i,'SecAmmo'));
PlaySound(0,'knife.wav',GetPlayerStat(i,'x'),GetPlayerStat(i,'y'));
Wave(GetPlayerStat(i,'x'),GetPlayerStat(i,'y')-10,Direction(GetPlayerStat(i,'x'),GetPlayerStat(i,'y')-10,GetPlayerStat(enemy,'X'),GetPlayerStat(enemy,'y')-10,WeapSpeed[12],0.06,GetPlayerStat(enemy,'Velx'),GetPlayerStat(enemy,'vely')),8,59,  WeapSpeed[12],4120,12,24,  13,0,i);
end;
end;
end;
12: begin //Saw
end;
13: begin //LAW
enemy := lookForTarget(i,0,900,true);
if Ticks mod (6) = 0 then begin
if (Enemy <> 0) and (wait[i]<=0) and (GetPlayerStat(i,'Ammo')>0) and (GetPlayerStat(i,'Ground')=true) and ((GetKeyPress(i,'Prone')=true) or (GetKeyPress(i,'down')=true)) then begin
wait[i]:=295;
ForceWeaponEx(i,GetPlayerStat(i,'Primary'),GetPlayerStat(i,'Secondary'),255,GetPlayerStat(i,'SecAmmo'));
PlaySound(0,'law.wav',GetPlayerStat(i,'x'),GetPlayerStat(i,'y'));
Wave(GetPlayerStat(i,'x'),GetPlayerStat(i,'y')-8,Direction(GetPlayerStat(i,'x'),GetPlayerStat(i,'y')-8,GetPlayerStat(enemy,'X'),GetPlayerStat(enemy,'y')-8,WeapSpeed[14],0.06,GetPlayerStat(enemy,'Velx'),GetPlayerStat(enemy,'vely')),8,59,  WeapSpeed[14],4120,12,24,  12,0,i);
end;
end;
end;
14: begin //Fire
end;
15: begin //Bow
enemy := lookForTarget(i,0,900,true);
if Ticks mod (8) = 0 then begin
if (Enemy <> 0) and (wait[i]<=0) and (GetPlayerStat(i,'Ammo')>0) then begin
wait[i]:=37;
ForceWeaponEx(i,GetPlayerStat(i,'Primary'),GetPlayerStat(i,'Secondary'),255,GetPlayerStat(i,'SecAmmo'));
PlaySound(0,'bow-fire.wav',GetPlayerStat(i,'x'),GetPlayerStat(i,'y'));
Wave(GetPlayerStat(i,'x'),GetPlayerStat(i,'y'),Direction(GetPlayerStat(i,'x'),GetPlayerStat(i,'y'),GetPlayerStat(enemy,'X'),GetPlayerStat(enemy,'y')-5,WeapSpeed[15],0.06,GetPlayerStat(enemy,'Velx'),GetPlayerStat(enemy,'vely')),8,59,  WeapSpeed[15],4120,12,24,  7,0,i);
end;
end;
end;
16: begin //Fire
enemy := lookForTarget(i,0,900,true);
if Ticks mod (13) = 0 then begin
if (Enemy <> 0) and (wait[i]<=0) and (GetPlayerStat(i,'Ammo')>0) then begin
wait[i]:=42;
ForceWeaponEx(i,GetPlayerStat(i,'Primary'),GetPlayerStat(i,'Secondary'),255,GetPlayerStat(i,'SecAmmo'));
PlaySound(0,'bow-fire.wav',GetPlayerStat(i,'x'),GetPlayerStat(i,'y'));
Wave(GetPlayerStat(i,'x'),GetPlayerStat(i,'y'),Direction(GetPlayerStat(i,'x'),GetPlayerStat(i,'y'),GetPlayerStat(enemy,'X'),GetPlayerStat(enemy,'y')-5,WeapSpeed[16],0.06,GetPlayerStat(enemy,'Velx'),GetPlayerStat(enemy,'vely')),8,59,  WeapSpeed[16],4120,12,24,  8,0,i);
end;
end;
end;
end;
end;
if (wait[i]>0) then begin
dec(wait[i],1);
if (wait[i]<=0) and (GetPlayerStat(i,'Primary')<>8) and (GetPlayerStat(i,'Primary')<>6) and (GetPlayerStat(i,'Primary')<>1) and (GetPlayerStat(i,'Primary')<>5) and (GetPlayerStat(i,'Primary')<>0) then ShootingTimes[i]:=0;
end;
end;
end;
end;

initialization
begin
if (Game.Realistic=false) then begin
WeapSpeed[1]:=single(strtoint(ReadINI('weapons.ini','USSOCOM','Speed','0')))/10;
WeapSpeed[2]:=single(strtoint(ReadINI('weapons.ini','Desert Eagles','Speed','0')))/10;
WeapSpeed[3]:=single(strtoint(ReadINI('weapons.ini','HK MP5','Speed','0')))/10;
WeapSpeed[4]:=single(strtoint(ReadINI('weapons.ini','Ak-74','Speed','0')))/10;
WeapSpeed[5]:=single(strtoint(ReadINI('weapons.ini','Steyr AUG','Speed','0')))/10;
WeapSpeed[6]:=single(strtoint(ReadINI('weapons.ini','Spas-12','Speed','0')))/10;
WeapSpeed[7]:=single(strtoint(ReadINI('weapons.ini','Ruger 77','Speed','0')))/10;
WeapSpeed[8]:=single(strtoint(ReadINI('weapons.ini','M79','Speed','0')))/10;
WeapSpeed[9]:=single(strtoint(ReadINI('weapons.ini','Barret M82A1','Speed','0')))/10;
WeapSpeed[10]:=single(strtoint(ReadINI('weapons.ini','FN Minimi','Speed','0')))/10;
WeapSpeed[11]:=single(strtoint(ReadINI('weapons.ini','XM214 Minigun','Speed','0')))/10;
WeapSpeed[12]:=single(strtoint(ReadINI('weapons.ini','Combat Knife','Speed','0')))/10;
WeapSpeed[13]:=single(strtoint(ReadINI('weapons.ini','Chainsaw','Speed','0')))/10;
WeapSpeed[14]:=single(strtoint(ReadINI('weapons.ini','M72 LAW','Speed','0')))/10;
WeapSpeed[15]:=single(strtoint(ReadINI('weapons.ini','Punch','Speed','0')))/10;
WeapSpeed[16]:=single(strtoint(ReadINI('weapons.ini','Rambo Bow','Speed','0')))/10;
WeapSpeed[16]:=single(strtoint(ReadINI('weapons.ini','Flamed Arrows','Speed','0')))/10;
end else
begin
WeapSpeed[1]:=single(strtoint(ReadINI('weapons_realistic.ini','USSOCOM','Speed','0')))/10;
WeapSpeed[2]:=single(strtoint(ReadINI('weapons_realistic.ini','Desert Eagles','Speed','0')))/10;
WeapSpeed[3]:=single(strtoint(ReadINI('weapons_realistic.ini','HK MP5','Speed','0')))/10;
WeapSpeed[4]:=single(strtoint(ReadINI('weapons_realistic.ini','Ak-74','Speed','0')))/10;
WeapSpeed[5]:=single(strtoint(ReadINI('weapons_realistic.ini','Steyr AUG','Speed','0')))/10;
WeapSpeed[6]:=single(strtoint(ReadINI('weapons_realistic.ini','Spas-12','Speed','0')))/10;
WeapSpeed[7]:=single(strtoint(ReadINI('weapons_realistic.ini','Ruger 77','Speed','0')))/10;
WeapSpeed[8]:=single(strtoint(ReadINI('weapons_realistic.ini','M79','Speed','0')))/10;
WeapSpeed[9]:=single(strtoint(ReadINI('weapons_realistic.ini','Barret M82A1','Speed','0')))/10;
WeapSpeed[10]:=single(strtoint(ReadINI('weapons_realistic.ini','FN Minimi','Speed','0')))/10;
WeapSpeed[11]:=single(strtoint(ReadINI('weapons_realistic.ini','XM214 Minigun','Speed','0')))/10;
WeapSpeed[12]:=single(strtoint(ReadINI('weapons_realistic.ini','Combat Knife','Speed','0')))/10;
WeapSpeed[13]:=single(strtoint(ReadINI('weapons_realistic.ini','Chainsaw','Speed','0')))/10;
WeapSpeed[14]:=single(strtoint(ReadINI('weapons_realistic.ini','M72 LAW','Speed','0')))/10;
WeapSpeed[15]:=single(strtoint(ReadINI('weapons_realistic.ini','Punch','Speed','0')))/10;
WeapSpeed[16]:=single(strtoint(ReadINI('weapons_realistic.ini','Rambo Bow','Speed','0')))/10;
WeapSpeed[16]:=single(strtoint(ReadINI('weapons_realistic.ini','Flamed Arrows','Speed','0')))/10;
end;
Game.OnClockTick := @OnTick;
Game.TickThreshold := 1;
end;

finalization;
end.

If you want to track down the player nearest the cursor, use my fuction instead of lookfortager:
Code: [Select]
function FindPlayerForMissile(ID: byte; MaxDistance: integer; UsingRaycast: boolean): byte; //FindPlayerForMissile (SC3)
var i: byte; X, Y, X2, Y2, CursorMaxDist, NearestDistCursor, MaxDist, Dist: single;
begin
X:=Players[ID].X; Y:=Players[ID].Y;
MaxDist:=MaxDistance*MaxDistance; CursorMaxDist:=CursorMaxSearch*CursorMaxSearch;
Result:=0;
for i:= 1 to 32 do if (Players[i].Active) then begin
if (Players[i].Alive) and (Players[i].Team<>Players[ID].Team) and (i<>ID) then begin
X2:=Players[i].X; Y2:=Players[i].Y;
if (UsingRayCast) then if Map.RayCast(X,Y-7,X2,Y2-7,false, false, true, true, 2) then continue;

X2:=X2-Players[ID].MouseAimX; Y2:=Y2-Players[ID].MouseAimY; NearestDistCursor:=X2*X2+Y2*Y2;
X2:=Players[i].X; Y2:=Players[i].Y;
X2:=X2-X; Y2:=Y2-Y; Dist:=X2*X2+Y2*Y2;

if (NearestDistCursor<CursorMaxDist) and (Dist<MaxDist) then begin
Result:=i;
CursorMaxDist:=NearestDistCursor;
end;
end;
end;
end;
Admin sharing dll is still forbidden, I request for removal of the entire topic.
« Last Edit: November 20, 2015, 11:09:29 am by soldat-game »

Offline Savage

  • Soldier
  • **
  • Posts: 155
Re: Ballistic functions
« Reply #13 on: November 20, 2015, 02:53:48 pm »
Ah I haven't noticed AllowDlls setting in config.ini, tyvm.

Offline soldat-game

  • Camper
  • ***
  • Posts: 407
Re: Ballistic functions
« Reply #14 on: November 20, 2015, 05:00:21 pm »
What are creating brother?