diff --git a/RageCoop.Client/Networking/Receive.cs b/RageCoop.Client/Networking/Receive.cs
index 914394a..c8fe10a 100644
--- a/RageCoop.Client/Networking/Receive.cs
+++ b/RageCoop.Client/Networking/Receive.cs
@@ -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;
}
}
diff --git a/RageCoop.Client/Networking/Send.cs b/RageCoop.Client/Networking/Send.cs
index 112ede2..7fb5e77 100644
--- a/RageCoop.Client/Networking/Send.cs
+++ b/RageCoop.Client/Networking/Send.cs
@@ -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);
}
diff --git a/RageCoop.Client/Sync/Entities/SyncedEntity.cs b/RageCoop.Client/Sync/Entities/SyncedEntity.cs
index 21d19ca..d3ad4bf 100644
--- a/RageCoop.Client/Sync/Entities/SyncedEntity.cs
+++ b/RageCoop.Client/Sync/Entities/SyncedEntity.cs
@@ -39,7 +39,7 @@ namespace RageCoop.Client
}
}
- internal Player Owner { get; private set; }
+ internal virtual Player Owner { get; private set; }
///
///
///
diff --git a/RageCoop.Client/Sync/Entities/SyncedPed.cs b/RageCoop.Client/Sync/Entities/SyncedPed.cs
index e5b34f0..4313fbd 100644
--- a/RageCoop.Client/Sync/Entities/SyncedPed.cs
+++ b/RageCoop.Client/Sync/Entities/SyncedPed.cs
@@ -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)
diff --git a/RageCoop.Client/Sync/Entities/SyncedProjectile.cs b/RageCoop.Client/Sync/Entities/SyncedProjectile.cs
index 67efb7c..03ac942 100644
--- a/RageCoop.Client/Sync/Entities/SyncedProjectile.cs
+++ b/RageCoop.Client/Sync/Entities/SyncedProjectile.cs
@@ -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);
+
+ ///
+ /// Invalid property for projectile.
+ ///
+ 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; }
-
- ///
- /// Invalid property for projectile.
- ///
- 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);
}
}
diff --git a/RageCoop.Client/Sync/EntityPool.cs b/RageCoop.Client/Sync/EntityPool.cs
index ad790b5..b1b45d0 100644
--- a/RageCoop.Client/Sync/EntityPool.cs
+++ b/RageCoop.Client/Sync/EntityPool.cs
@@ -19,15 +19,15 @@ namespace RageCoop.Client
#endif
#region ACTIVE INSTANCES
- private static Dictionary PedsByID = new Dictionary();
- private static Dictionary PedsByHandle = new Dictionary();
+ public static Dictionary PedsByID = new Dictionary();
+ public static Dictionary PedsByHandle = new Dictionary();
- private static Dictionary VehiclesByID = new Dictionary();
- private static Dictionary VehiclesByHandle = new Dictionary();
+ public static Dictionary VehiclesByID = new Dictionary();
+ public static Dictionary VehiclesByHandle = new Dictionary();
- private static Dictionary ProjectilesByID = new Dictionary();
- private static Dictionary ProjectilesByHandle = new Dictionary();
+ public static Dictionary ProjectilesByID = new Dictionary();
+ public static Dictionary ProjectilesByHandle = new Dictionary();
public static Dictionary ServerProps = new Dictionary();
public static Dictionary ServerBlips = new Dictionary();
@@ -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);
}
}
diff --git a/RageCoop.Core/CoreUtils.cs b/RageCoop.Core/CoreUtils.cs
index c5e6c7a..57b4512 100644
--- a/RageCoop.Core/CoreUtils.cs
+++ b/RageCoop.Core/CoreUtils.cs
@@ -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)
{
diff --git a/RageCoop.Core/Packets/Packets.cs b/RageCoop.Core/Packets/Packets.cs
index 0e3cf9e..c819c45 100644
--- a/RageCoop.Core/Packets/Packets.cs
+++ b/RageCoop.Core/Packets/Packets.cs
@@ -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
{
diff --git a/RageCoop.Core/Packets/ProjectileSync.cs b/RageCoop.Core/Packets/ProjectileSync.cs
index be918df..5295a72 100644
--- a/RageCoop.Core/Packets/ProjectileSync.cs
+++ b/RageCoop.Core/Packets/ProjectileSync.cs
@@ -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
}