// Creates server sided vehicle damage detection version 1.0
// By [uL]Pottus
//
// This uses a method of checking when a player shoots if a line representing an origin and destination intersects a sphere
// an intersection will result in the vehicle being damaged.
//
// Just compile and load
#include <a_samp>
// native IsValidVehicle(vehicleid);
forward OnPlayerShoot(playerid,weaponid,ammo);
new OldAmmo[MAX_PLAYERS], OldWeap[MAX_PLAYERS];
new CurrAmmo[MAX_PLAYERS], CurrWeap[MAX_PLAYERS];
//------------------------------------------------------------------------------
// Update the players weapon and possibly call OnPlayerShoot()
public OnPlayerUpdate(playerid)
{
// Get the current weapon and ammo
CurrWeap[playerid] = GetPlayerWeapon(playerid);
CurrAmmo[playerid] = GetPlayerAmmo(playerid);
// Player still has old weapon does this weapon now have less ammo?
if(CurrWeap[playerid] == OldWeap[playerid] && CurrAmmo[playerid] < OldAmmo[playerid])
{
OnPlayerShoot(playerid, CurrWeap[playerid], CurrAmmo[playerid]);
}
OldWeap[playerid] = CurrWeap[playerid];
OldAmmo[playerid] = CurrAmmo[playerid];
return 1;
}
// Check if a vehicle is occupied
stock IsVehicleOccupied(vehicleid)
{
for(new i = 0; i < MAX_PLAYERS; i++)
{
if(!IsPlayerConnected(i)) continue;
if(IsPlayerInAnyVehicle(i))
{
if(GetPlayerVehicleID(i)==vehicleid)
{
return 1;
}
}
}
return 0;
}
public OnPlayerShoot(playerid, weaponid, ammo)
{
for(new i = 0; i < MAX_VEHICLES; i++)
{
if(IsValidVehicle(i))
{
if(IsVehicleStreamedIn(i, playerid) && !IsVehicleOccupied(i))
{
new Float:vx, Float:vy, Float:vz, Float:radius, Float:dist, Float:amount;
GetVehiclePos(i, vx, vy, vz);
// This offsets the sphere (Add vehicle models later for better detection)
vz -= 1.0;
radius = 2.0;
// Select damage amount and collision radius
switch(weaponid)
{
case 22: // 9MM
{
amount = 40.0;
dist = 30.0;
}
case 23: // Silencer
{
amount = 40.0;
dist = 50.0;
}
case 24: // Deagle
{
amount = 140.0;
dist = 50.0;
}
case 25: // Shotgun
{
amount = 80.0;
dist = 50.0;
}
case 26: // Sawn
{
amount = 80.0;
dist = 50.0;
}
case 27: // Combat
{
amount = 80.0;
dist = 50.0;
}
case 28: // Uzi
{
amount = 25.0;
dist = 20.0;
}
case 29: // MP5
{
amount = 25.0;
dist = 50.0;
}
case 30: // AK
{
amount = 30.0;
dist = 150.0;
}
case 31: // m4
{
amount = 30.0;
dist = 150.0;
}
case 32: // Tec
{
amount = 25.0;
dist = 30.0;
}
case 33: // Rifle
{
amount = 75.0;
dist = 200.0;
}
case 34: // Sniper
{
amount = 125.0;
dist = 300.0;
}
case 35: // RPG
{
amount = 751.0;
dist = 100.0;
}
case 36: // HEatseek
{
amount = 751.0;
dist = 100.0;
}
case 38: // Mini
{
amount = 50.0;
dist = 100.0;
}
}
if(BulletCollision(playerid, weaponid, vx, vy, vz, dist, radius))
{
new Float:vhp;
GetVehicleHealth(i, vhp);
if(vhp >= 250.0)
{
vhp -= amount;
if(vhp < 250.0) SetTimerEx("ResetVehicle", 15000, false, "i", i);
SetVehicleHealth(i, vhp);
}
// SendClientMessage(playerid, -1, "Collision");
}
// else SendClientMessage(playerid, -1, "No Collision");
}
}
}
return 1;
}
// Respawn vehicle (They bug if you don't do this)
forward ResetVehicle(vid);
public ResetVehicle(vid)
{
SetVehicleToRespawn(vid);
return 1;
}
// Checks if a players bullet intersects a sphere
stock BulletCollision(playerid, weapon, Float:sx, Float:sy, Float:sz, Float:fScale = 30.0, Float:radius = 1.0)
{
new
Float:fP[3],
Float:fV[3],
Float:object[3],
Float:sphere[3];
sphere[0] = sx, sphere[1] = sy, sphere[2] = sz;
GetPlayerCameraPos(playerid, fP[0], fP[1], fP[2]);
GetPlayerCameraFrontVector(playerid, fV[0], fV[1], fV[2]);
// Compensate (This is not perfect yet any ideas anyone?)
if(weapon != 34 && weapon != 35 && weapon != 36)
{
new Float:FacingA;
GetPlayerFacingAngle(playerid, FacingA);
FacingA -= 90.0;
if(FacingA < 0.0) FacingA += 360.0;
else if(FacingA > 360.0) FacingA -= 360.0;
fP[0] = (fP[0] + 0.6 * floatsin(-FacingA,degrees));
fP[2] += 1.2;
}
object[0] = fP[0] + floatmul(fV[0], fScale);
object[1] = fP[1] + floatmul(fV[1], fScale);
object[2] = fP[2] + floatmul(fV[2], fScale);
// Check if line intersects sphere
if(RaySphere(fP, object, sphere, radius)) return 1;
return 0;
}
// This checks to see if a line intersects a sphere
stock RaySphere(Float:p1[3],Float:p2[3],Float:sc[3],Float:r)
{
new Float:a, Float:b, Float:c;
new Float:bb4ac;
new Float:dp[3];
dp[0] = p2[0] - p1[0];
dp[1] = p2[1] - p1[1];
dp[2] = p2[2] - p1[2];
a = dp[0] * dp[0] + dp[1] * dp[1] + dp[2] * dp[2];
b = 2 * (dp[0] * (p1[0] - sc[0]) + dp[1] * (p1[1] - sc[1]) + dp[2] * (p1[2] - sc[2]));
c = sc[0] * sc[0] + sc[1] * sc[1] + sc[2] * sc[2];
c += p1[0] * p1[0] + p1[1] * p1[1] + p1[2] * p1[2];
c -= 2 * (sc[0] * p1[0] + sc[1] * p1[1] + sc[2] * p1[2]);
c -= r * r;
bb4ac = b * b - 4 * a * c;
if(bb4ac < 0) return 0;
return 1;
}
E:\Rockstar Games\Server\samp03x_svr_win32\filterscripts\vehicledamage.pwn(57) : error 017: undefined symbol "IsValidVehicle" Pawn compiler 3.2.3664 Copyright © 1997-2006, ITB CompuPhase 1 Error.
Nice! I suppose you could use this to improve the precision.
|