[FilterScript] Distance bug fix
#1

Most of you are probably not aware of this bug. When you exit a vehicle that isn't a bike, all weapons will have a virtually infinite range when you're being shot at.

This filterscript takes care of that problem.

How does it work?
The filterscript waits for everyone to leave the vehicle, then for the vehicle to stop moving (if it's rolling or something).

Beware:
  • You must set the vehicle's color again in OnVehicleSpawn.
  • You must add vehicle components again in OnVehicleSpawn.
  • Vehicles that end up in the water will not be respawned (due to OnVehicleDeath being called). You could respawn or destroy it in OnVehicleDeath.
  • The fix will not be applied until all players leave the vehicle.
Credits
F0rce helped develop this (sssssssss).

The code:

pawn Код:
#include <a_samp>

#if !defined IsValidVehicle
    native IsValidVehicle(vehicleid);
#endif

enum E_VEHICLE_DATA {
          Monitor,
          Timer,
          RePosition,
          SetZAngle,
    Float:Health,
    Float:ZAngle,
    Float:X,
    Float:Y,
    Float:Z,
          DamagePanels,
          DamageDoors,
          DamageLights,
          DamageTires
}

new
    g_VehicleData[MAX_VEHICLES][E_VEHICLE_DATA],
    g_EnteringVehicle[MAX_PLAYERS] = {INVALID_VEHICLE_ID, ...},
    g_EnteringTimer[MAX_PLAYERS] = {-1, ...},
    g_LastVehicleId[MAX_PLAYERS] = {INVALID_VEHICLE_ID, ...}
;

stock IsVehicleBeingEntered(vehicleid) {
    for (new i = 0; i < MAX_PLAYERS; i++) {
        if (g_EnteringVehicle[i] == vehicleid) {
            return true;
        }
    }
   
    return false;
}

stock GetPlayerInVehicle(vehicleid, seat = 0) {
    for (new i = 0; i < MAX_PLAYERS; i++) {
        if (!IsPlayerConnected(i)) {
            continue;
        }
         
        if (GetPlayerVehicleID(i) == vehicleid &&
            GetPlayerVehicleSeat(i) == seat) {
            return i;
        }
    }

    return INVALID_PLAYER_ID;
}

stock IsVehicleEmpty(vehicleid, except = INVALID_PLAYER_ID) {
    for (new i = 0; i < MAX_PLAYERS; i++) {
        if (!IsPlayerConnected(i) || i == except) {
            continue;
        }
       
        if (GetPlayerVehicleID(i) == vehicleid) {
            return false;
        }
    }

    return true;
}

stock EnteringStopped(playerid) {
    new vehicleid = g_EnteringVehicle[playerid];
   
    if (vehicleid == INVALID_VEHICLE_ID) {
        return;
    }
   
    g_EnteringVehicle[playerid] = INVALID_VEHICLE_ID;
    g_EnteringTimer[playerid] = -1;
   
    if (g_EnteringTimer[playerid] != -1) {
        KillTimer(g_EnteringTimer[playerid]);
    }
}

public OnFilterScriptInit() {
    for (new i = 0; i < MAX_VEHICLES; i++) {
        g_VehicleData[i][Timer] = -1;
    }
   
    for (new i = 0; i < MAX_PLAYERS; i++) {
        new vehicleid = GetPlayerVehicleID(i);
       
        if (vehicleid != 0) {
            g_LastVehicleId[i] = vehicleid;
        }
    }
}

public OnPlayerConnect(playerid) {
    g_LastVehicleId[playerid] = INVALID_VEHICLE_ID;
   
    return 1;
}

public OnPlayerDisconnect(playerid, reason) {
    EnteringStopped(playerid);
   
    return 1;
}

public OnPlayerDeath(playerid, killerid, reason) {
    EnteringStopped(playerid);
   
    return 1;
}

public OnPlayerStateChange(playerid, newstate, oldstate) {
    EnteringStopped(playerid);
   
    if (oldstate == PLAYER_STATE_DRIVER || oldstate == PLAYER_STATE_PASSENGER) {
        new vehicleid = g_LastVehicleId[playerid];
       
        if (IsVehicleEmpty(vehicleid, playerid)) {
            UpdateMonitoring(vehicleid);
        }
    }
   
    if (newstate == PLAYER_STATE_DRIVER || newstate == PLAYER_STATE_PASSENGER) {
        g_LastVehicleId[playerid] = GetPlayerVehicleID(playerid);
       
        StopMonitoring(GetPlayerVehicleID(playerid));
    }
   
    return 1;
}

public OnVehicleDeath(vehicleid, killerid) {
    StopMonitoring(vehicleid);
   
    for (new i = 0; i < MAX_PLAYERS; i++) {
        if (g_EnteringVehicle[i] == vehicleid) {
            EnteringStopped(i);
        }
    }
   
    return 1;
}

public OnVehicleSpawn(vehicleid) {
    if (g_VehicleData[vehicleid][RePosition]) {
        SetVehicleHealth(vehicleid, g_VehicleData[vehicleid][Health]);
        SetVehiclePos(
            vehicleid,
            g_VehicleData[vehicleid][X],
            g_VehicleData[vehicleid][Y],
            g_VehicleData[vehicleid][Z] + 0.3
        );
       
        UpdateVehicleDamageStatus(
            vehicleid,
            g_VehicleData[vehicleid][DamagePanels],
            g_VehicleData[vehicleid][DamageDoors],
            g_VehicleData[vehicleid][DamageLights],
            g_VehicleData[vehicleid][DamageTires]
        );
       
        StopMonitoring(vehicleid);
       
        g_VehicleData[vehicleid][SetZAngle] = 30;
       
        SetTimerEx("UpdateZAngle", 50, false, "i", vehicleid);
    } else {
        StopMonitoring(vehicleid);
    }
   
    return 1;
}

forward UpdateZAngle(vehicleid);
public UpdateZAngle(vehicleid) {
    if (g_VehicleData[vehicleid][SetZAngle]) {
        SetVehicleZAngle(vehicleid, g_VehicleData[vehicleid][ZAngle]);
       
        g_VehicleData[vehicleid][SetZAngle]--;
       
        SetTimerEx("UpdateZAngle", 50, false, "i", vehicleid);
    }
}

public OnPlayerEnterVehicle(playerid, vehicleid, ispassenger) {
    EnteringStopped(playerid);
   
    g_EnteringVehicle[playerid] = vehicleid;
    g_EnteringTimer[playerid] = SetTimerEx("OnEnteringAborted", 7000, false, "i", playerid);
   
    return 1;
}

forward OnEnteringAborted(playerid);
public OnEnteringAborted(playerid) {
    EnteringStopped(playerid);
}

stock StopMonitoring(vehicleid) {
    g_VehicleData[vehicleid][Monitor] = false;
    g_VehicleData[vehicleid][RePosition] = false;

    if (g_VehicleData[vehicleid][Timer] != -1) {
        KillTimer(g_VehicleData[vehicleid][Timer]);

        g_VehicleData[vehicleid][Timer] = -1;
    }
}

stock UpdateMonitoring(vehicleid, finish_delay = 2000) {
    StopMonitoring(vehicleid);
   
    if (!IsValidVehicle(vehicleid)) {
        return;
    }
   
    g_VehicleData[vehicleid][Monitor] = true;
    g_VehicleData[vehicleid][Timer] = SetTimerEx("OnMonitoringFinish", finish_delay, false, "i", vehicleid);
}

forward OnMonitoringFinish(vehicleid);
public OnMonitoringFinish(vehicleid) {
    if (!IsValidVehicle(vehicleid)) {
        return;
    }
   
    if (IsVehicleBeingEntered(vehicleid)) {
        UpdateMonitoring(vehicleid, 150);
       
        return;
    }
   
    StopMonitoring(vehicleid);
   
    CallRemoteFunction("OnVehicleStoppedMoving", "i", vehicleid);
   
    GetVehicleHealth(vehicleid, g_VehicleData[vehicleid][Health]);
    GetVehicleZAngle(vehicleid, g_VehicleData[vehicleid][ZAngle]);
    GetVehiclePos(
        vehicleid,
        g_VehicleData[vehicleid][X],
        g_VehicleData[vehicleid][Y],
        g_VehicleData[vehicleid][Z]
    );
   
    GetVehicleDamageStatus(
        vehicleid,
        g_VehicleData[vehicleid][DamagePanels],
        g_VehicleData[vehicleid][DamageDoors],
        g_VehicleData[vehicleid][DamageLights],
        g_VehicleData[vehicleid][DamageTires]
    );
   
    g_VehicleData[vehicleid][RePosition] = true;
   
    SetVehicleToRespawn(vehicleid);
}

public OnUnoccupiedVehicleUpdate(vehicleid, playerid, passenger_seat) {
    if (g_VehicleData[vehicleid][Monitor]) {
        UpdateMonitoring(vehicleid);
    }
   
    return 1;
}
Reply


Messages In This Thread
Distance bug fix - by Slice - 16.07.2013, 22:29
Re: Distance bug fix - by Darius - 18.07.2013, 00:20
Re: Distance bug fix - by WhaTJr - 18.07.2013, 00:54
Re: Distance bug fix - by Whitetiger - 18.07.2013, 01:57
Re: Distance bug fix - by Slice - 18.07.2013, 11:48

Forum Jump:


Users browsing this thread: 1 Guest(s)