Various weapon fixes and some change on vehicle sync
This commit is contained in:
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -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")]
|
@ -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";
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
@ -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>
|
||||
|
@ -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
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -44,7 +44,6 @@ namespace RageCoop.Core
|
||||
|
||||
PedKilled = 30,
|
||||
BulletShot = 31,
|
||||
VehicleBulletShot = 32,
|
||||
OwnerChanged = 35,
|
||||
NozzleTransform = 37,
|
||||
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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
BIN
libs/ScriptHookVDotNet.pdb
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user