Projectile refactor

This commit is contained in:
Sardelka 2022-08-14 17:08:43 +08:00
parent 4acf964f0a
commit b5f6fc578d
9 changed files with 120 additions and 75 deletions

View File

@ -416,17 +416,17 @@ namespace RageCoop.Client
var p = EntityPool.GetProjectileByID(packet.ID);
if (p==null)
{
if (packet.Exploded) { return; }
if (packet.Flags.HasProjDataFlag(ProjectileDataFlags.Exploded)) { return; }
// Main.Logger.Debug($"Creating new projectile: {(WeaponHash)packet.WeaponHash}");
EntityPool.ThreadSafe.Add(p=new SyncedProjectile(packet.ID));
}
p.Flags=packet.Flags;
p.Position=packet.Position;
p.Rotation=packet.Rotation;
p.Velocity=packet.Velocity;
p.Hash=(WeaponHash)packet.WeaponHash;
p.ShooterID=packet.ShooterID;
p.Exploded=packet.Exploded;
p.WeaponHash=(WeaponHash)packet.WeaponHash;
p.Shooter= packet.Flags.HasProjDataFlag(ProjectileDataFlags.IsShotByVehicle) ?
(SyncedEntity)EntityPool.GetVehicleByID(packet.ShooterID) : EntityPool.GetPedByID(packet.ShooterID);
p.LastSynced=Main.Ticked;
}
}

View File

@ -164,17 +164,9 @@ namespace RageCoop.Client
}
public static void SendProjectile(SyncedProjectile sp)
{
var p = sp.MainProjectile;
var packet = SendPackets.ProjectilePacket;
packet.ID =sp.ID;
packet.ShooterID=sp.ShooterID;
packet.Rotation=p.Rotation;
packet.Position=p.Position;
packet.Velocity=p.Velocity;
packet.WeaponHash=(uint)p.WeaponHash;
packet.Exploded=p.IsDead;
if (p.IsDead) { EntityPool.RemoveProjectile(sp.ID, "Dead"); }
SendSync(packet, ConnectionChannel.ProjectileSync);
sp.ExtractData(ref SendPackets.ProjectilePacket);
if (sp.MainProjectile.IsDead) { EntityPool.RemoveProjectile(sp.ID, "Dead"); }
SendSync(SendPackets.ProjectilePacket, ConnectionChannel.ProjectileSync);
}

View File

@ -39,7 +39,7 @@ namespace RageCoop.Client
}
}
internal Player Owner { get; private set; }
internal virtual Player Owner { get; private set; }
/// <summary>
///
/// </summary>

View File

@ -667,9 +667,12 @@ namespace RageCoop.Client
MainPed.PositionNoOffset=Position;
return;
}
if (!(localRagdoll || MainPed.IsDead || IsAiming))
if (!(localRagdoll || MainPed.IsDead))
{
MainPed.Heading=Heading;
if (!IsAiming)
{
MainPed.Heading=Heading;
}
MainPed.Velocity=Velocity+5*dist*(Position-MainPed.ReadPosition());
}
else if (Main.Ticked-_lastRagdollTime<10)

View File

@ -1,61 +1,95 @@
using GTA;
using GTA.Math;
using RageCoop.Core;
using GTA.Native;
namespace RageCoop.Client
{
internal class SyncedProjectile : SyncedEntity
{
public ProjectileDataFlags Flags { private get; set; }=ProjectileDataFlags.None;
public readonly Vector3 Origin;
private bool _firstSend = false;
public bool IsValid { get; private set; } = true;
public new bool IsLocal { get; private set; } = false;
public Projectile MainProjectile { get; set; }
public SyncedEntity Shooter { get; set; }
public bool Exploded => Flags.HasProjDataFlag(ProjectileDataFlags.Exploded);
/// <summary>
/// Invalid property for projectile.
/// </summary>
private new int OwnerID { set { } }
internal override Player Owner => Shooter.Owner;
public WeaponHash WeaponHash { get; set; }
private WeaponAsset Asset { get; set; }
public void ExtractData(ref Packets.ProjectileSync p)
{
p.Position=MainProjectile.Position;
p.Velocity=MainProjectile.Velocity;
p.Rotation=MainProjectile.Rotation;
p.ID=ID;
p.ShooterID=Shooter.ID;
p.WeaponHash=(uint)MainProjectile.WeaponHash;
p.Flags=ProjectileDataFlags.None;
if (MainProjectile.IsDead)
{
p.Flags |= ProjectileDataFlags.Exploded;
}
if (MainProjectile.AttachedEntity!=null)
{
p.Flags |= ProjectileDataFlags.IsAttached;
}
if (Shooter is SyncedVehicle)
{
p.Flags |= ProjectileDataFlags.IsShotByVehicle;
}
if (_firstSend)
{
p.Flags |= ProjectileDataFlags.IsAttached;
_firstSend=false;
}
}
public SyncedProjectile(Projectile p)
{
var owner = p.OwnerEntity;
if (owner==null) { IsValid=false;return; }
ID=EntityPool.RequestNewID();
MainProjectile = p;
Origin=p.Position;
var shooter = EntityPool.GetPedByHandle((p.OwnerEntity?.Handle).GetValueOrDefault());
if (shooter==null)
if(EntityPool.PedsByHandle.TryGetValue(owner.Handle,out var shooter))
{
// Owner will be the vehicle if projectile is shot with a vehicle
var shooterVeh = EntityPool.GetVehicleByHandle((p.OwnerEntity?.Handle).GetValueOrDefault());
if (shooterVeh!=null && shooterVeh.MainVehicle.Driver!=null)
{
shooter=shooterVeh.MainVehicle.Driver?.GetSyncEntity();
}
else
{
Main.Logger.Warning($"Could not find owner for projectile:{Hash}");
}
}
if (shooter != null)
{
if (shooter.MainPed!=null && (p.AttachedEntity==shooter.MainPed.Weapons.CurrentWeaponObject || p.AttachedEntity== shooter.MainPed))
if (shooter.MainPed!=null
&& (p.AttachedEntity==shooter.MainPed.Weapons.CurrentWeaponObject
|| p.AttachedEntity== shooter.MainPed))
{
// Reloading
IsValid=false;
return;
}
ShooterID=shooter.ID;
Shooter=shooter;
IsLocal=shooter.IsLocal;
}
else if(EntityPool.VehiclesByHandle.TryGetValue(owner.Handle,out var shooterVeh))
{
Shooter=shooterVeh;
IsLocal=shooterVeh.IsLocal;
}
else
{
IsValid=false;
}
}
public SyncedProjectile(int id)
{
ID= id;
IsLocal=false;
}
public bool IsValid { get; private set; } = true;
public new bool IsLocal { get; private set; } = false;
public bool Exploded { get; set; } = false;
public Projectile MainProjectile { get; set; }
public int ShooterID { get; set; }
private SyncedPed Shooter { get; set; }
public Vector3 Origin { get; set; }
/// <summary>
/// Invalid property for projectile.
/// </summary>
private new int OwnerID { set { } }
public WeaponHash Hash { get; set; }
private WeaponAsset Asset { get; set; }
internal override void Update()
{
@ -74,19 +108,20 @@ namespace RageCoop.Client
private void CreateProjectile()
{
Asset=new WeaponAsset(Hash);
if (!Asset.IsLoaded) { Asset.Request(); }
World.ShootBullet(Position, Position+Velocity, (Shooter=EntityPool.GetPedByID(ShooterID))?.MainPed, Asset, 0);
Asset=new WeaponAsset(WeaponHash);
if (!Asset.IsLoaded) { Asset.Request(); return; }
if(Shooter == null) { return; }
Entity owner;
owner=(Shooter as SyncedPed)?.MainPed ?? (Entity)(Shooter as SyncedVehicle)?.MainVehicle;
var end = Position+Velocity;
Function.Call(Hash.SHOOT_SINGLE_BULLET_BETWEEN_COORDS_IGNORE_ENTITY, Position.X, Position.Y, Position.Z, end.X, end.Y, end.Z, 0, 1, WeaponHash, owner?.Handle ?? 0, 1, 0, -1,owner);
var ps = World.GetAllProjectiles();
MainProjectile=ps[ps.Length-1];
if (Hash==(WeaponHash)VehicleWeaponHash.Tank)
{
var v = Shooter?.MainPed?.CurrentVehicle;
if (v!=null)
{
World.CreateParticleEffectNonLooped(SyncEvents.CorePFXAsset, "muz_tank", v.Bones[v.GetMuzzleIndex()].Position, v.Bones[35].ForwardVector.ToEulerRotation(v.Bones[35].UpVector), 1);
}
}
MainProjectile.IsCollisionEnabled=false;
MainProjectile.Position=Position;
MainProjectile.Rotation =Rotation;
MainProjectile.Velocity=Velocity;
Main.Delay(()=>MainProjectile.IsCollisionEnabled=true, 100);
EntityPool.Add(this);
}
}

View File

@ -19,15 +19,15 @@ namespace RageCoop.Client
#endif
#region ACTIVE INSTANCES
private static Dictionary<int, SyncedPed> PedsByID = new Dictionary<int, SyncedPed>();
private static Dictionary<int, SyncedPed> PedsByHandle = new Dictionary<int, SyncedPed>();
public static Dictionary<int, SyncedPed> PedsByID = new Dictionary<int, SyncedPed>();
public static Dictionary<int, SyncedPed> PedsByHandle = new Dictionary<int, SyncedPed>();
private static Dictionary<int, SyncedVehicle> VehiclesByID = new Dictionary<int, SyncedVehicle>();
private static Dictionary<int, SyncedVehicle> VehiclesByHandle = new Dictionary<int, SyncedVehicle>();
public static Dictionary<int, SyncedVehicle> VehiclesByID = new Dictionary<int, SyncedVehicle>();
public static Dictionary<int, SyncedVehicle> VehiclesByHandle = new Dictionary<int, SyncedVehicle>();
private static Dictionary<int, SyncedProjectile> ProjectilesByID = new Dictionary<int, SyncedProjectile>();
private static Dictionary<int, SyncedProjectile> ProjectilesByHandle = new Dictionary<int, SyncedProjectile>();
public static Dictionary<int, SyncedProjectile> ProjectilesByID = new Dictionary<int, SyncedProjectile>();
public static Dictionary<int, SyncedProjectile> ProjectilesByHandle = new Dictionary<int, SyncedProjectile>();
public static Dictionary<int, SyncedProp> ServerProps = new Dictionary<int, SyncedProp>();
public static Dictionary<int, Blip> ServerBlips = new Dictionary<int, Blip>();
@ -62,7 +62,7 @@ namespace RageCoop.Client
foreach (var p in ProjectilesByID.Values)
{
if (p.ShooterID!=Main.LocalPlayerID && p.MainProjectile!=null && p.MainProjectile.Exists())
if (p.Shooter.ID!=Main.LocalPlayerID && p.MainProjectile!=null && p.MainProjectile.Exists())
{
p.MainProjectile.Delete();
}
@ -242,6 +242,10 @@ namespace RageCoop.Client
public static void Add(SyncedProjectile p)
{
if (!p.IsValid) { return; }
if (p.WeaponHash==(WeaponHash)VehicleWeaponHash.Tank)
{
Networking.SendBullet(p.Position, p.Position+p.Velocity, (uint)VehicleWeaponHash.Tank, ((SyncedVehicle)p.Shooter).MainVehicle.Driver.GetSyncEntity().ID);
}
if (ProjectilesByID.ContainsKey(p.ID))
{
ProjectilesByID[p.ID]=p;
@ -339,12 +343,10 @@ namespace RageCoop.Client
if (p.MainProjectile.AttachedEntity==null)
{
// Prevent projectiles from exploding next to vehicle
if (WeaponUtil.VehicleProjectileWeapons.Contains((VehicleWeaponHash)p.MainProjectile.WeaponHash) &&
p.MainProjectile.WeaponHash != (WeaponHash)VehicleWeaponHash.Tank && p.Origin.DistanceTo(p.MainProjectile.Position) < 2)
if (p.WeaponHash==(WeaponHash)VehicleWeaponHash.Tank )
{
continue;
}
Networking.SendProjectile(p);
}
}

View File

@ -305,6 +305,10 @@ namespace RageCoop.Core
{
return (flagToCheck & flag)!=0;
}
public static bool HasProjDataFlag(this ProjectileDataFlags flagToCheck, ProjectileDataFlags flag)
{
return (flagToCheck & flag)!=0;
}
public static bool HasVehFlag(this VehicleDataFlags flagToCheck, VehicleDataFlags flag)
{

View File

@ -97,6 +97,15 @@ namespace RageCoop.Core
IsInCover = 1 << 10,
IsFullSync = 1<<15 ,
}
internal enum ProjectileDataFlags:byte
{
None = 0,
Exploded = 1 << 0,
IsAttached = 1 << 1,
IsOrgin = 1 << 2,
IsShotByVehicle = 1 << 3,
}
#region ===== VEHICLE DATA =====
internal enum VehicleDataFlags:ushort
{

View File

@ -22,7 +22,7 @@ namespace RageCoop.Core
public Vector3 Velocity { get; set; }
public bool Exploded { get; set; }
public ProjectileDataFlags Flags { get; set; }
@ -48,7 +48,7 @@ namespace RageCoop.Core
// Write velocity
byteArray.AddVector3(Velocity);
byteArray.AddBool(Exploded);
byteArray.Add((byte)Flags);
return byteArray.ToArray();
@ -76,7 +76,7 @@ namespace RageCoop.Core
// Read velocity
Velocity =reader.ReadVector3();
Exploded=reader.ReadBoolean();
Flags=(ProjectileDataFlags)reader.ReadByte();
#endregion
}