Various weapon fixes and some change on vehicle sync

This commit is contained in:
sardelka9515
2022-12-04 19:34:54 +08:00
parent 4cc5054b91
commit 3a9068f060
24 changed files with 247 additions and 290 deletions

View File

@ -22,19 +22,26 @@ namespace RageCoop.Client
private void OnTick(object sender, EventArgs e)
{
var wb = Game.Player.Character?.Weapons?.CurrentWeaponObject?.Bones["gun_muzzle"];
if (wb?.IsValid == true) World.DrawLine(wb.Position, wb.Position + wb.RightVector, Color.Blue);
foreach (var p in World.GetAllPeds()) DrawWeaponBone(p);
if (ToMark == null) return;
if (WeaponUtil.VehicleWeapons.TryGetValue((uint)(int)ToMark.Model, out var info))
foreach (var ws in info.Weapons)
foreach (var w in ws.Value.Bones)
DrawBone(w.BoneName, ws.Value.Name + ":" + ws.Key.ToHex());
foreach (var w in ws.Value.Bones)
DrawBone(w.BoneName, ws.Value.Name + ":" + ws.Key.ToHex());
var P = Game.Player.Character;
var b = ToMark.GetMuzzleBone(P.VehicleWeapon);
if (b != null) World.DrawLine(b.Position, b.Position + b.ForwardVector * 5, Color.Brown);
}
public static void DrawWeaponBone(Ped p)
{
var wb = p.Weapons?.CurrentWeaponObject?.Bones["gun_muzzle"];
if (wb?.IsValid == true) World.DrawLine(wb.Position, wb.Position + wb.RightVector, Color.Blue);
if (wb?.IsValid == true) World.DrawLine(wb.Position, wb.Position + wb.ForwardVector, Color.Red);
if (wb?.IsValid == true) World.DrawLine(wb.Position, wb.Position + wb.UpVector, Color.Green);
}
private void FindAndDraw()
{
DrawBone("weapon_1a");

View File

@ -12,6 +12,7 @@ using GTA.UI;
using LemonUI.Elements;
using LemonUI.Menus;
using Lidgren.Network;
using Newtonsoft.Json.Linq;
using RageCoop.Client.GUI;
using RageCoop.Client.Menus;
using RageCoop.Client.Scripting;

View File

@ -307,7 +307,6 @@ namespace RageCoop.Client
c.Flags = packet.Flags;
c.Heading = packet.Heading;
c.Position = packet.Position;
c.LastSyncedStopWatch.Restart();
if (c.IsRagdoll)
{
c.HeadPosition = packet.HeadPosition;
@ -319,12 +318,14 @@ namespace RageCoop.Client
c.VehicleID = packet.VehicleID;
c.Seat = packet.Seat;
}
c.LastSynced = Main.Ticked;
if (c.IsAiming) c.AimCoords = packet.AimCoords;
if (packet.Flags.HasPedFlag(PedDataFlags.IsFullSync))
bool full = packet.Flags.HasPedFlag(PedDataFlags.IsFullSync);
if (full)
{
c.CurrentWeaponHash = packet.CurrentWeaponHash;
if (packet.Speed == 4)
c.VehicleWeapon = packet.VehicleWeapon;
c.CurrentWeapon = packet.CurrentWeapon;
c.Clothes = packet.Clothes;
c.WeaponComponents = packet.WeaponComponents;
c.WeaponTint = packet.WeaponTint;
@ -332,8 +333,8 @@ namespace RageCoop.Client
c.BlipColor = packet.BlipColor;
c.BlipSprite = packet.BlipSprite;
c.BlipScale = packet.BlipScale;
c.LastFullSynced = Main.Ticked;
}
c.SetLastSynced(full);
}
private static void VehicleSync(Packets.VehicleSync packet)
@ -345,6 +346,7 @@ namespace RageCoop.Client
v.OwnerID = packet.OwnerID;
v.Flags = packet.Flags;
v.Position = packet.Position;
v.LastQuaternion = v.Quaternion;
v.Quaternion = packet.Quaternion;
v.SteeringAngle = packet.SteeringAngle;
v.ThrottlePower = packet.ThrottlePower;
@ -352,9 +354,8 @@ namespace RageCoop.Client
v.Velocity = packet.Velocity;
v.RotationVelocity = packet.RotationVelocity;
v.DeluxoWingRatio = packet.DeluxoWingRatio;
v.LastSynced = Main.Ticked;
v.LastSyncedStopWatch.Restart();
if (packet.Flags.HasVehFlag(VehicleDataFlags.IsFullSync))
bool full = packet.Flags.HasVehFlag(VehicleDataFlags.IsFullSync);
if (full)
{
v.DamageModel = packet.DamageModel;
v.EngineHealth = packet.EngineHealth;
@ -367,8 +368,8 @@ namespace RageCoop.Client
v.RadioStation = packet.RadioStation;
v.LicensePlate = packet.LicensePlate;
v.Livery = packet.Livery;
v.LastFullSynced = Main.Ticked;
}
v.SetLastSynced(full);
}
private static void ProjectileSync(Packets.ProjectileSync packet)
@ -389,8 +390,7 @@ namespace RageCoop.Client
p.Shooter = packet.Flags.HasProjDataFlag(ProjectileDataFlags.IsShotByVehicle)
? (SyncedEntity)EntityPool.GetVehicleByID(packet.ShooterID)
: EntityPool.GetPedByID(packet.ShooterID);
p.LastSynced = Main.Ticked;
p.LastSyncedStopWatch.Restart();
p.SetLastSynced(false);
}
/// <summary>

View File

@ -65,8 +65,9 @@ namespace RageCoop.Client
sp.LastSentStopWatch.Restart();
if (full)
{
var w = ped.VehicleWeapon;
p.CurrentWeaponHash = w != VehicleWeaponHash.Invalid ? (uint)w : (uint)ped.Weapons.Current.Hash;
if (p.Speed == 4)
p.VehicleWeapon = ped.VehicleWeapon;
p.CurrentWeapon = ped.Weapons.Current.Hash;
p.Flags |= PedDataFlags.IsFullSync;
p.Clothes = ped.GetPedClothes();
p.ModelHash = ped.Model.Hash;
@ -153,7 +154,7 @@ namespace RageCoop.Client
public static void SendChatMessage(string message)
{
Peer.SendTo(new Packets.ChatMessage(s => Security.Encrypt(s.GetBytes()))
{ Username = Main.Settings.Username, Message = message }, ServerConnection, ConnectionChannel.Chat,
{ Username = Main.Settings.Username, Message = message }, ServerConnection, ConnectionChannel.Chat,
NetDeliveryMethod.ReliableOrdered);
Peer.FlushSendQueue();
}
@ -177,29 +178,16 @@ namespace RageCoop.Client
#region SYNC EVENTS
public static void SendBullet(Vector3 start, Vector3 end, uint weapon, int ownerID)
public static void SendBullet(int ownerID, uint weapon, Vector3 end)
{
SendSync(new Packets.BulletShot
{
StartPosition = start,
EndPosition = end,
OwnerID = ownerID,
WeaponHash = weapon
}, ConnectionChannel.SyncEvents);
}
public static void SendVehicleBullet(uint hash, SyncedPed owner, EntityBone b)
{
SendSync(new Packets.VehicleBulletShot
{
StartPosition = b.Position,
EndPosition = b.Position + b.ForwardVector,
OwnerID = owner.ID,
Bone = (ushort)b.Index,
WeaponHash = hash
});
}
#endregion
}
}

View File

@ -13,6 +13,6 @@ using System.Resources;
// Version information
[assembly: AssemblyVersion("1.6.0.21")]
[assembly: AssemblyFileVersion("1.6.0.21")]
[assembly: AssemblyVersion("1.6.0.24")]
[assembly: AssemblyFileVersion("1.6.0.24")]
[assembly: NeutralResourcesLanguageAttribute("en-US")]

View File

@ -73,7 +73,7 @@ namespace RageCoop.Client
if (!IsInCover) return "";
var altitude = IsInLowCover ? "low" : "high";
var hands = GetWeaponHandsHeld(CurrentWeaponHash);
var hands = GetWeaponHandsHeld((uint)CurrentWeapon);
if (IsBlindFiring)
{
if (hands == 1) return "cover@weapon@1h";

View File

@ -15,12 +15,12 @@ namespace RageCoop.Client
private bool _lastDriveBy;
private bool _lastInCover;
private bool _lastIsJumping;
private WeaponHash _lastWeaponHash;
private bool _lastMoving;
private bool _lastRagdoll;
private ulong _lastRagdollTime;
private Dictionary<uint, bool> _lastWeaponComponents;
private Entity _weaponObj;
internal Entity WeaponObj;
internal BlipColor BlipColor = (BlipColor)255;
internal float BlipScale = 1;
internal BlipSprite BlipSprite = 0;
@ -41,16 +41,16 @@ namespace RageCoop.Client
internal SyncedVehicle CurrentVehicle { get; private set; }
public bool IsPlayer => OwnerID == ID && ID != 0;
public Ped MainPed { get; internal set; }
internal int Health { get; set; }
internal int Health;
internal Vector3 HeadPosition { get; set; }
internal Vector3 RightFootPosition { get; set; }
internal Vector3 LeftFootPosition { get; set; }
internal Vector3 HeadPosition;
internal Vector3 RightFootPosition;
internal Vector3 LeftFootPosition;
internal byte WeaponTint { get; set; }
internal byte[] Clothes { get; set; }
internal byte WeaponTint;
internal byte[] Clothes;
internal float Heading { get; set; }
internal float Heading;
internal ulong LastSpeakingTime { get; set; } = 0;
internal bool IsSpeaking { get; set; } = false;
@ -70,9 +70,10 @@ namespace RageCoop.Client
internal bool IsInCoverFacingLeft => Flags.HasPedFlag(PedDataFlags.IsInCoverFacingLeft);
internal bool IsBlindFiring => Flags.HasPedFlag(PedDataFlags.IsBlindFiring);
internal bool IsInStealthMode => Flags.HasPedFlag(PedDataFlags.IsInStealthMode);
internal Prop ParachuteProp { get; set; } = null;
internal uint CurrentWeaponHash { get; set; }
internal Dictionary<uint, bool> WeaponComponents { get; set; } = null;
internal Vector3 AimCoords { get; set; }
internal Prop ParachuteProp = null;
internal WeaponHash CurrentWeapon = WeaponHash.Unarmed;
internal VehicleWeaponHash VehicleWeapon = VehicleWeaponHash.Invalid;
internal Dictionary<uint, bool> WeaponComponents = null;
internal Vector3 AimCoords;
}
}

View File

@ -466,29 +466,45 @@ namespace RageCoop.Client
private void CheckCurrentWeapon()
{
if (MainPed.Weapons.Current.Hash != (WeaponHash)CurrentWeaponHash ||
!WeaponComponents.Compare(_lastWeaponComponents) || (Speed <= 3 && _weaponObj?.IsVisible != true))
if (MainPed.VehicleWeapon != VehicleWeapon) MainPed.VehicleWeapon = VehicleWeapon;
var compChanged = WeaponComponents != null && WeaponComponents.Count != 0 && WeaponComponents != _lastWeaponComponents && !WeaponComponents.Compare(_lastWeaponComponents);
if (_lastWeaponHash != CurrentWeapon || compChanged)
{
new WeaponAsset(CurrentWeaponHash).Request();
MainPed.Weapons.RemoveAll();
_weaponObj = Entity.FromHandle(Function.Call<int>(Hash.CREATE_WEAPON_OBJECT, CurrentWeaponHash, -1,
Position.X, Position.Y, Position.Z, true, 0, 0));
if (_weaponObj == null) return;
if (CurrentWeaponHash != (uint)WeaponHash.Unarmed)
if (_lastWeaponHash == WeaponHash.Unarmed && WeaponObj?.Exists() == true)
{
if (WeaponComponents != null && WeaponComponents.Count != 0)
foreach (var comp in WeaponComponents)
if (comp.Value)
Function.Call(Hash.GIVE_WEAPON_COMPONENT_TO_WEAPON_OBJECT, _weaponObj, comp.Key);
Function.Call(Hash.GIVE_WEAPON_OBJECT_TO_PED, _weaponObj, MainPed.Handle);
WeaponObj.Delete();
}
else
{
var model = Function.Call<uint>(Hash.GET_WEAPONTYPE_MODEL, CurrentWeapon);
if (!Function.Call<bool>(Hash.HAS_MODEL_LOADED, model))
{
Function.Call(Hash.REQUEST_MODEL, model);
return;
}
if (WeaponObj?.Exists() == true)
WeaponObj.Delete();
MainPed.Weapons.RemoveAll();
WeaponObj = Entity.FromHandle(Function.Call<int>(Hash.CREATE_WEAPON_OBJECT, CurrentWeapon, -1, Position.X, Position.Y, Position.Z, true, 0, 0));
}
_lastWeaponComponents = WeaponComponents;
if (compChanged)
{
foreach (var comp in WeaponComponents)
{
if (comp.Value)
{
Function.Call(Hash.GIVE_WEAPON_COMPONENT_TO_WEAPON_OBJECT, WeaponObj.Handle, comp.Key);
}
}
_lastWeaponComponents = WeaponComponents;
}
Function.Call(Hash.GIVE_WEAPON_OBJECT_TO_PED, WeaponObj.Handle, MainPed.Handle);
_lastWeaponHash = CurrentWeapon;
}
if (Function.Call<int>(Hash.GET_PED_WEAPON_TINT_INDEX, MainPed, CurrentWeaponHash) != WeaponTint)
Function.Call<int>(Hash.SET_PED_WEAPON_TINT_INDEX, MainPed, CurrentWeaponHash, WeaponTint);
if (Function.Call<int>(Hash.GET_PED_WEAPON_TINT_INDEX, MainPed, CurrentWeapon) != WeaponTint)
Function.Call<int>(Hash.SET_PED_WEAPON_TINT_INDEX, MainPed, CurrentWeapon, WeaponTint);
}
private void DisplayAiming()
@ -633,6 +649,7 @@ namespace RageCoop.Client
if (CurrentVehicle?.MainVehicle == null) return;
switch (Speed)
{
// In vehicle
case 4:
if (MainPed.CurrentVehicle != CurrentVehicle.MainVehicle || MainPed.SeatIndex != Seat ||
(!MainPed.IsSittingInVehicle() && !MainPed.IsBeingJacked))
@ -640,9 +657,10 @@ namespace RageCoop.Client
if (MainPed.IsOnTurretSeat())
Function.Call(Hash.TASK_VEHICLE_AIM_AT_COORD, MainPed.Handle, AimCoords.X, AimCoords.Y,
AimCoords.Z);
if (MainPed.VehicleWeapon == VehicleWeaponHash.Invalid)
// Drive-by
if (VehicleWeapon == VehicleWeaponHash.Invalid)
{
// World.DrawMarker(MarkerType.DebugSphere,AimCoords,default,default,new Vector3(0.2f,0.2f,0.2f),Color.AliceBlue);
if (IsAiming)
{
Function.Call(Hash.SET_DRIVEBY_TASK_TARGET, MainPed, 0, 0, AimCoords.X, AimCoords.Y,
@ -660,31 +678,24 @@ namespace RageCoop.Client
_lastDriveBy = false;
}
}
else if (MainPed.VehicleWeapon != (VehicleWeaponHash)CurrentWeaponHash)
{
MainPed.VehicleWeapon = (VehicleWeaponHash)CurrentWeaponHash;
}
break;
// Entering vehicle
case 5:
if (MainPed.VehicleTryingToEnter != CurrentVehicle.MainVehicle ||
MainPed.GetSeatTryingToEnter() != Seat)
MainPed.Task.EnterVehicle(CurrentVehicle.MainVehicle, Seat, -1, 5,
EnterVehicleFlags.AllowJacking);
EnterVehicleFlags.JackAnyone);
break;
// Leaving vehicle
case 6:
if (!MainPed.IsTaskActive(TaskType.CTaskExitVehicle))
MainPed.Task.LeaveVehicle(CurrentVehicle.Velocity.Length() > 5f
MainPed.Task.LeaveVehicle(CurrentVehicle.Velocity.LengthSquared() > 5 * 5
? LeaveVehicleFlags.BailOut
: LeaveVehicleFlags.None);
break;
}
/*
Function.Call(Hash.SET_PED_STEALTH_MOVEMENT, P,true, 0);
return Function.Call<bool>(Hash.GET_PED_STEALTH_MOVEMENT, P);
*/
}
}
}

View File

@ -10,13 +10,8 @@ namespace RageCoop.Client
{
private float _accumulatedOff;
/// <summary>
/// </summary>
protected internal bool _lastFrozen = false;
private int _ownerID;
public Stopwatch LastSyncedStopWatch = new Stopwatch();
/// <summary>
/// Indicates whether the current player is responsible for syncing this entity.
@ -70,7 +65,11 @@ namespace RageCoop.Client
protected Vector3 Predict(Vector3 input)
{
return (Owner.PacketTravelTime + 0.001f * LastSyncedStopWatch.ElapsedMilliseconds) * Velocity + input;
return Diff() + input;
}
protected Vector3 Diff()
{
return (Owner.PacketTravelTime + 0.001f * LastSyncedStopWatch.ElapsedMilliseconds) * Velocity;
}
protected bool IsOff(float thisOff, float tolerance = 3, float limit = 30)
@ -91,6 +90,24 @@ namespace RageCoop.Client
#region LAST STATE
public void SetLastSynced(bool full)
{
LastSyncInterval = LastSentStopWatch.ElapsedMilliseconds;
LastSynced = Main.Ticked;
if (full)
{
LastFullSynced = Main.Ticked;
}
LastSyncedStopWatch.Restart();
}
public Stopwatch LastSyncedStopWatch = new Stopwatch();
/// <summary>
/// The interval between last sync and the earlier one
/// </summary>
public long LastSyncInterval;
/// <summary>
/// Last time a new sync message arrived.
/// </summary>

View File

@ -61,9 +61,13 @@ namespace RageCoop.Client
internal bool IsDeluxo;
internal bool IsTrain;
internal Vector3 TopExtent;
internal Vector3 BottomExtent;
internal Vector3 FrontExtent;
internal Vector3 RearExtent;
internal Vector3 LeftExtent;
internal Vector3 RightExtent;
private const float RotCalMult = 0.2f;
private const float ExtentLength = 5;
#endregion
@ -74,9 +78,8 @@ namespace RageCoop.Client
private bool _lastHornActive;
private bool _lastTransformed;
internal int _lastLivery = -1;
private readonly List<Vector3> _predictedTrace = new List<Vector3>();
private readonly List<Vector3> _orgTrace = new List<Vector3>();
private Vector3 _predictedPosition;
internal Quaternion LastQuaternion;
#endregion

View File

@ -22,7 +22,7 @@ namespace RageCoop.Client
return;
DisplayVehicle();
DisplayVehicle(NeedUpdate);
// Skip update if no new sync message has arrived.
if (!NeedUpdate) return;
@ -155,7 +155,7 @@ namespace RageCoop.Client
LastUpdated = Main.Ticked;
}
private void DisplayVehicle()
private void DisplayVehicle(bool updated)
{
_predictedPosition = Predict(Position);
var current = MainVehicle.ReadPosition();
@ -170,37 +170,22 @@ namespace RageCoop.Client
return;
}
// Calibrate rotation
var curQuat = MainVehicle.Quaternion;
MainVehicle.ApplyForce(Quaternion * TopExtent - curQuat * TopExtent, TopExtent);
MainVehicle.ApplyForce(Quaternion * FrontExtent - curQuat * FrontExtent, FrontExtent);
// Calibrate position
if (distSquared < 0.03 * 0.03) return;
if (IsTrain || distSquared > 20 * 20) MainVehicle.Velocity = Velocity + cali;
else MainVehicle.ApplyForce(cali);
}
if (distSquared > 0.03 * 0.03)
{
if (IsTrain || distSquared > 20 * 20) MainVehicle.Velocity = Velocity + cali;
else MainVehicle.ApplyForce(cali);
}
private Vector3 GetCalibrationRotation()
{
var rot = Quaternion.LookRotation(Quaternion * Vector3.RelativeFront, Quaternion * Vector3.RelativeTop)
.ToEulerAngles();
var curRot = Quaternion.LookRotation(MainVehicle.ReadQuaternion() * Vector3.RelativeFront,
MainVehicle.ReadQuaternion() * Vector3.RelativeTop).ToEulerAngles();
Quaternion predictedQuat = updated ? Quaternion :
Quaternion.Lerp(LastQuaternion, Quaternion, 1 + LastSyncedStopWatch.ElapsedMilliseconds / (float)LastSyncInterval);
var curQuat = MainVehicle.Quaternion;
MainVehicle.ApplyForce((predictedQuat * TopExtent - curQuat * TopExtent) * RotCalMult, TopExtent);
MainVehicle.ApplyForce((predictedQuat * FrontExtent - curQuat * FrontExtent) * RotCalMult, FrontExtent);
// MainVehicle.ApplyForce((predictedQuat * BottomExtent - curQuat * BottomExtent) * RotCalMult, BottomExtent);
var r = (rot - curRot).ToDegree();
if (r.X > 180)
r.X = r.X - 360;
else if (r.X < -180) r.X = 360 + r.X;
if (r.Y > 180)
r.Y = r.Y - 360;
else if (r.Y < -180) r.Y = 360 + r.Y;
if (r.Z > 180)
r.Z = r.Z - 360;
else if (r.Z < -180) r.Z = 360 + r.Z;
return r;
}
private bool CreateVehicle()
@ -257,11 +242,13 @@ namespace RageCoop.Client
IsSubmarineCar = MainVehicle.IsSubmarineCar;
IsDeluxo = MainVehicle.Model == 1483171323;
IsTrain = MainVehicle.IsTrain;
var (rbl, ftr) = MainVehicle.Model.Dimensions;
FrontExtent = new Vector3(0, ftr.Y, 0);
TopExtent = new Vector3(0, 0, ftr.Z);
LeftExtent = new Vector3(rbl.X, 0, 0);
RightExtent = new Vector3(ftr.X, 0, 0);
// var (rbl, ftr) = MainVehicle.Model.Dimensions;
FrontExtent = new Vector3(0, ExtentLength, 0);
RearExtent = -FrontExtent;
TopExtent = new Vector3(0, ExtentLength, 5);
BottomExtent = -TopExtent;
RightExtent = new Vector3(5, ExtentLength, 0);
LeftExtent = -RightExtent;
}
/// <summary>

View File

@ -239,8 +239,10 @@ namespace RageCoop.Client
{
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);
{
Networking.SendBullet(((SyncedVehicle)p.Shooter).MainVehicle.Driver.GetSyncEntity().ID, (uint)VehicleWeaponHash.Tank, p.Position + p.Velocity);
return;
}
if (ProjectilesByID.ContainsKey(p.ID))
ProjectilesByID[p.ID] = p;
else

View File

@ -25,24 +25,13 @@ namespace RageCoop.Client
}, ConnectionChannel.SyncEvents, NetDeliveryMethod.ReliableOrdered);
}
public static void TriggerBulletShot(uint hash, SyncedPed owner, Vector3 impactPosition)
public static void TriggerBulletShot(SyncedPed owner, Vector3 impactPosition)
{
// Main.Logger.Trace($"bullet shot:{(WeaponHash)hash}");
var hash = (uint)owner.MainPed.VehicleWeapon;
if (hash == (uint)VehicleWeaponHash.Invalid)
hash = (uint)owner.MainPed.Weapons.Current.Hash;
var start = owner.MainPed.GetMuzzlePosition();
if (start.DistanceTo(impactPosition) > 10)
// Reduce latency
start = impactPosition - (impactPosition - start).Normalized * 10;
Networking.SendBullet(start, impactPosition, hash, owner.ID);
}
public static void TriggerVehBulletShot(uint hash, Vehicle veh, SyncedPed owner)
{
int i;
if ((i = veh.GetMuzzleIndex(owner.MainPed.VehicleWeapon)) != -1)
Networking.SendVehicleBullet(hash, owner, veh.Bones[i]);
else
Main.Logger.Warning($"Failed to get muzzle info for vehicle:{veh.DisplayName}");
Networking.SendBullet(owner.ID, hash, impactPosition);
}
public static void TriggerNozzleTransform(int vehID, bool hover)
@ -67,7 +56,7 @@ namespace RageCoop.Client
var v = EntityPool.GetVehicleByID(p.ID);
if (v == null) return;
v.OwnerID = p.NewOwnerID;
v.LastSynced = Main.Ticked;
v.SetLastSynced(true);
v.Position = v.MainVehicle.Position;
v.Quaternion = v.MainVehicle.Quaternion;
}
@ -77,42 +66,38 @@ namespace RageCoop.Client
EntityPool.GetVehicleByID(p.VehicleID)?.MainVehicle?.SetNozzleAngel(p.Hover ? 1 : 0);
}
private static void HandleBulletShot(Vector3 start, Vector3 end, uint weaponHash, int ownerID)
private static void HandleBulletShot(int ownerID, uint weaponHash, Vector3 end)
{
var p = EntityPool.GetPedByID(ownerID)?.MainPed;
var c = EntityPool.GetPedByID(ownerID);
var p = c?.MainPed;
if (p == null)
{
p = Game.Player.Character;
Main.Logger.Warning("Failed to find owner for bullet");
return;
// p = Game.Player.Character;
// Main.Logger.Warning("Failed to find owner for bullet");
}
var damage = (int)p.GetWeaponDamage(weaponHash);
// Some weapon hash has some firing issue, so we need to replace it with known good ones
weaponHash = WeaponUtil.GetWeaponFix(weaponHash);
// Request asset for muzzle flash
if (!CorePFXAsset.IsLoaded) CorePFXAsset.Request();
// Request asset for materialising the bullet
var asset = new WeaponAsset(weaponHash);
if (!asset.IsLoaded) asset.Request();
World.ShootBullet(start, end, p, asset, damage);
Prop w;
var turret = false;
if (((w = p.Weapons.CurrentWeaponObject) != null && p.VehicleWeapon == VehicleWeaponHash.Invalid) ||
(turret = p.IsOnTurretSeat()))
World.CreateParticleEffectNonLooped(CorePFXAsset,
p.Weapons.Current.Components.GetSuppressorComponent().Active
? "muz_pistol_silencer"
: ((WeaponHash)weaponHash).GetFlashFX(turret), p.GetMuzzlePosition(),
turret ? p.CurrentVehicle.GetMuzzleBone(p.VehicleWeapon).GetRotation() : w.Rotation);
}
public static void HandleVehicleBulletShot(Packets.VehicleBulletShot p)
{
HandleBulletShot(p.StartPosition, p.EndPosition, p.WeaponHash, p.OwnerID);
var v = EntityPool.GetPedByID(p.OwnerID)?.MainPed.CurrentVehicle;
if (v == null) return;
var b = v.Bones[p.Bone];
bool isVeh = p.VehicleWeapon != VehicleWeaponHash.Invalid;
var bone = c.GetMuzzleBone(isVeh);
World.ShootBullet(bone.Position, end, p, asset, damage);
World.CreateParticleEffectNonLooped(CorePFXAsset,
((WeaponHash)p.WeaponHash).GetFlashFX(true),
b.Position, b.GetRotation());
!isVeh && p.Weapons.Current.Components.GetSuppressorComponent().Active
? "muz_pistol_silencer"
: ((WeaponHash)weaponHash).GetFlashFX(isVeh), bone.Position, isVeh ? bone.GetRotation() : bone.Owner.Rotation);
}
public static void HandleEvent(PacketType type, NetIncomingMessage msg)
@ -120,31 +105,26 @@ namespace RageCoop.Client
switch (type)
{
case PacketType.BulletShot:
{
var p = msg.GetPacket<Packets.BulletShot>();
HandleBulletShot(p.StartPosition, p.EndPosition, p.WeaponHash, p.OwnerID);
break;
}
case PacketType.VehicleBulletShot:
{
HandleVehicleBulletShot(msg.GetPacket<Packets.VehicleBulletShot>());
break;
}
{
var p = msg.GetPacket<Packets.BulletShot>();
HandleBulletShot(p.OwnerID, p.WeaponHash, p.EndPosition);
break;
}
case PacketType.OwnerChanged:
{
HandleOwnerChanged(msg.GetPacket<Packets.OwnerChanged>());
}
{
HandleOwnerChanged(msg.GetPacket<Packets.OwnerChanged>());
}
break;
case PacketType.PedKilled:
{
HandlePedKilled(msg.GetPacket<Packets.PedKilled>());
}
{
HandlePedKilled(msg.GetPacket<Packets.PedKilled>());
}
break;
case PacketType.NozzleTransform:
{
HandleNozzleTransform(msg.GetPacket<Packets.NozzleTransform>());
break;
}
{
HandleNozzleTransform(msg.GetPacket<Packets.NozzleTransform>());
break;
}
}
Networking.Peer.Recycle(msg);
@ -159,55 +139,42 @@ namespace RageCoop.Client
var subject = c.MainPed;
// Check bullets
if (subject.IsShooting)
if (subject.IsShooting && !subject.IsUsingProjectileWeapon())
{
if (!subject.IsUsingProjectileWeapon())
var i = 0;
// Some weapon is not instant hit, so we may need to wait a few ticks to get the impact position
bool getBulletImpact()
{
var i = 0;
Func<bool> getBulletImpact = () =>
var endPos = subject.LastWeaponImpactPosition;
// Impact found
if (endPos != default)
{
var endPos = subject.LastWeaponImpactPosition;
if (endPos == default)
{
if (++i <= 5) return false;
endPos = subject.GetAimCoord();
if (subject.IsInVehicle() && subject.VehicleWeapon != VehicleWeaponHash.Invalid)
{
if (subject.IsOnTurretSeat())
TriggerBulletShot((uint)subject.VehicleWeapon, c, endPos);
else
TriggerVehBulletShot((uint)subject.VehicleWeapon, subject.CurrentVehicle, c);
}
else
{
TriggerBulletShot((uint)subject.Weapons.Current.Hash, c, endPos);
}
return true;
}
if (subject.IsInVehicle() && subject.VehicleWeapon != VehicleWeaponHash.Invalid)
{
if (subject.IsOnTurretSeat())
TriggerBulletShot((uint)subject.VehicleWeapon, c, endPos);
else
TriggerVehBulletShot((uint)subject.VehicleWeapon, subject.CurrentVehicle, c);
}
else
{
TriggerBulletShot((uint)subject.Weapons.Current.Hash, c, endPos);
}
TriggerBulletShot(c, endPos);
return true;
};
}
// Not found, but it's shot from a vehicle
if (subject.VehicleWeapon != VehicleWeaponHash.Invalid)
{
var b = c.GetMuzzleBone(true);
TriggerBulletShot(c, b.Position + b.ForwardVector * 200);
return true;
}
// Get impact in next tick
if (++i <= 5) return false;
// Exceeded maximum wait of 5 ticks, return (inaccurate) aim coordinate
endPos = subject.GetAimCoord();
TriggerBulletShot(c, endPos);
return true;
if (!getBulletImpact()) API.QueueAction(getBulletImpact);
}
else if (subject.VehicleWeapon == VehicleWeaponHash.Tank && subject.LastWeaponImpactPosition != default)
{
TriggerBulletShot((uint)VehicleWeaponHash.Tank, c, subject.LastWeaponImpactPosition);
}
if (!getBulletImpact()) API.QueueAction(getBulletImpact);
}
}

View File

@ -102,12 +102,11 @@ namespace RageCoop.Client
return result;
}
public static Vector3 GetMuzzlePosition(this Ped p)
public static EntityBone GetMuzzleBone(this SyncedPed p, bool veh)
{
if (p.IsOnTurretSeat()) return p.CurrentVehicle.GetMuzzleBone(p.VehicleWeapon).Position;
var wb = p.Weapons?.CurrentWeaponObject?.Bones["gun_muzzle"];
if (wb?.IsValid == true) return wb.Position;
return p.Bones[Bone.SkelRightHand].Position;
if (veh) return p.MainPed.CurrentVehicle.GetMuzzleBone(p.VehicleWeapon);
return p.MainPed?.Weapons.CurrentWeaponObject?.Bones["gun_muzzle"];
}
public static float GetWeaponDamage(this Ped P, uint hash)

View File

@ -22,6 +22,16 @@ namespace RageCoop.Core
};
}
public static Vector3 Limit(this Vector3 v, float length)
{
// Avoid square root to gain more performance
if (v.LengthSquared() > length * length)
{
return v.Normalized * length;
}
return v;
}
/// <summary>
/// </summary>
public static Vector3 ToVector(this Quaternion vec)

View File

@ -44,7 +44,6 @@ namespace RageCoop.Core
PedKilled = 30,
BulletShot = 31,
VehicleBulletShot = 32,
OwnerChanged = 35,
NozzleTransform = 37,

View File

@ -68,7 +68,7 @@ namespace RageCoop.Core
if (Flags.HasPedFlag(PedDataFlags.IsFullSync))
{
m.Write(ModelHash);
m.Write(CurrentWeaponHash);
m.Write((uint)CurrentWeapon);
m.Write(Clothes);
if (WeaponComponents != null)
{
@ -88,6 +88,10 @@ namespace RageCoop.Core
m.Write(WeaponTint);
// In vehicle
if (Speed == 4)
m.Write((uint)VehicleWeapon);
m.Write((byte)BlipColor);
if ((byte)BlipColor != 255)
{
@ -142,7 +146,7 @@ namespace RageCoop.Core
ModelHash = m.ReadInt32();
// Read player weapon hash
CurrentWeaponHash = m.ReadUInt32();
CurrentWeapon = (WeaponHash)m.ReadUInt32();
// Read player clothes
Clothes = m.ReadBytes(36);
@ -157,6 +161,9 @@ namespace RageCoop.Core
WeaponTint = m.ReadByte();
if (Speed == 4)
VehicleWeapon = (VehicleWeaponHash)m.ReadUInt32();
BlipColor = (BlipColor)m.ReadByte();
if ((byte)BlipColor != 255)
@ -181,7 +188,9 @@ namespace RageCoop.Core
public int ModelHash { get; set; }
public uint CurrentWeaponHash { get; set; }
public WeaponHash CurrentWeapon { get; set; }
public VehicleWeaponHash VehicleWeapon { get; set; }
public byte[] Clothes { get; set; }

View File

@ -11,8 +11,7 @@ namespace RageCoop.Core
public int OwnerID { get; set; }
public uint WeaponHash { get; set; }
public Vector3 StartPosition { get; set; }
public Vector3 EndPosition { get; set; }
protected override void Serialize(NetOutgoingMessage m)
@ -23,9 +22,6 @@ namespace RageCoop.Core
// Write weapon hash
m.Write(WeaponHash);
// Write StartPosition
m.Write(StartPosition);
// Write EndPosition
m.Write(EndPosition);
}
@ -37,12 +33,9 @@ namespace RageCoop.Core
// Read OwnerID
OwnerID = m.ReadInt32();
// Read WeponHash
// Read WeaponHash
WeaponHash = m.ReadUInt32();
// Read StartPosition
StartPosition = m.ReadVector3();
// Read EndPosition
EndPosition = m.ReadVector3();

View File

@ -1,41 +0,0 @@
using GTA.Math;
using Lidgren.Network;
namespace RageCoop.Core
{
internal partial class Packets
{
internal class VehicleBulletShot : Packet
{
public override PacketType Type => PacketType.VehicleBulletShot;
public int OwnerID { get; set; }
public ushort Bone { get; set; }
public uint WeaponHash { get; set; }
public Vector3 StartPosition { get; set; }
public Vector3 EndPosition { get; set; }
protected override void Serialize(NetOutgoingMessage m)
{
m.Write(OwnerID);
m.Write(Bone);
m.Write(WeaponHash);
m.Write(StartPosition);
m.Write(EndPosition);
}
public override void Deserialize(NetIncomingMessage m)
{
#region NetIncomingMessageToPacket
OwnerID = m.ReadInt32();
Bone = m.ReadUInt16();
WeaponHash = m.ReadUInt32();
StartPosition = m.ReadVector3();
EndPosition = m.ReadVector3();
#endregion
}
}
}
}

View File

@ -1,4 +1,7 @@
using System.Reflection;

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Resources;
// General Information
@ -12,6 +15,7 @@ using System.Resources;
[assembly: AssemblyCulture("")]
// Version information
[assembly: AssemblyVersion("1.6.0.21")]
[assembly: AssemblyFileVersion("1.6.0.21")]
[assembly: NeutralResourcesLanguageAttribute("en-US")]
[assembly: AssemblyVersion("1.6.0.24")]
[assembly: AssemblyFileVersion("1.6.0.24")]
[assembly: NeutralResourcesLanguageAttribute( "en-US" )]

Binary file not shown.

BIN
libs/ScriptHookVDotNet.pdb Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.