Syncronize reloading over the network

main
copygirl 4 years ago
parent ba7f4412f9
commit 2371574766
  1. 153
      src/Items/Weapon.cs

@ -2,9 +2,8 @@ using System;
using Godot; using Godot;
// TODO: "Click" sound when attempting to fire when not ready, or empty. // TODO: "Click" sound when attempting to fire when not ready, or empty.
// TODO: "Reload" sound when reloading.
// TODO: "Single reload" for revolver & shotgun. // TODO: "Single reload" for revolver & shotgun.
// TODO: Add outline around sprites. // TODO: Add outline around weapon sprites.
public class Weapon : Sprite public class Weapon : Sprite
{ {
@ -58,8 +57,7 @@ public class Weapon : Sprite
if (!(Player is LocalPlayer)) return; if (!(Player is LocalPlayer)) return;
if (ev.IsActionPressed("interact_primary")) if (ev.IsActionPressed("interact_primary"))
{ HoldingTrigger = TimeSpan.Zero; OnTriggerPressed(); } { HoldingTrigger = TimeSpan.Zero; OnTriggerPressed(); }
if (ev.IsActionPressed("interact_reload") && (Rounds < Capacity) && (_reloading == null)) if (ev.IsActionPressed("interact_reload")) Reload();
{ _reloading = ReloadTime; }
} }
protected virtual void OnTriggerPressed() => Fire(); protected virtual void OnTriggerPressed() => Fire();
@ -82,9 +80,7 @@ public class Weapon : Sprite
Rounds = Capacity; Rounds = Capacity;
_reloading = null; _reloading = null;
} }
} else if (Rounds <= 0) }
// Automatically reload when out of rounds.
_reloading = ReloadTime;
if (_fireDelay > 0) { if (_fireDelay > 0) {
_fireDelay -= delta; _fireDelay -= delta;
@ -96,6 +92,9 @@ public class Weapon : Sprite
} }
if (Player is LocalPlayer) { if (Player is LocalPlayer) {
// Automatically reload when out of rounds.
if (Rounds <= 0) Reload();
if (HoldingTrigger != null) { if (HoldingTrigger != null) {
if (!Input.IsActionPressed("interact_primary")) { if (!Input.IsActionPressed("interact_primary")) {
HoldingTrigger = null; HoldingTrigger = null;
@ -126,7 +125,7 @@ public class Weapon : Sprite
AimDirection = Cursor.Position.AngleToPoint(Player.Position) - angleC; AimDirection = Cursor.Position.AngleToPoint(Player.Position) - angleC;
// FIXME: Angle calculation when cursor is too close to player. // FIXME: Angle calculation when cursor is too close to player.
RpcId(1, nameof(SendAimAngle), AimDirection); RpcUnreliableId(1, nameof(SendAimAngle), AimDirection);
Update(); Update();
} }
} else { } else {
@ -140,50 +139,6 @@ public class Weapon : Sprite
Rotation = AimDirection - _currentRecoil * ((Scale.y > 0) ? 1 : -1); Rotation = AimDirection - _currentRecoil * ((Scale.y > 0) ? 1 : -1);
} }
public override void _Draw()
{
if (!(Player is LocalPlayer)) return;
// Draws an "aiming cone" to show where bullets might travel.
var tip = TipOffset + new Vector2(4, 0);
var angle = Mathf.Sin((Mathf.Deg2Rad(Spread) + _currentSpreadInc) / 2);
var color = Colors.Black;
var points = new Vector2[8];
var colors = new Color[8];
colors[0] = colors[7] = new Color(color, 0.0F);
points[0] = points[7] = tip;
colors[1] = colors[6] = new Color(color, 0.15F);
points[1] = tip + new Vector2(1, angle) * 64;
points[6] = tip + new Vector2(1, -angle) * 64;
colors[2] = colors[5] = new Color(color, 0.15F);
points[2] = tip + new Vector2(1, angle) * EffectiveRange;
points[5] = tip + new Vector2(1, -angle) * EffectiveRange;
colors[3] = colors[4] = new Color(color, 0.0F);
points[3] = tip + new Vector2(1, angle) * MaximumRange;
points[4] = tip + new Vector2(1, -angle) * MaximumRange;
var st = new SurfaceTool();
st.Begin(Mesh.PrimitiveType.TriangleStrip);
st.AddColor(colors[0]);
st.AddVertex(To3(points[0]));
st.AddColor(colors[1]);
st.AddVertex(To3(points[1]));
st.AddVertex(To3(points[6]));
st.AddColor(colors[2]);
st.AddVertex(To3(points[2]));
st.AddVertex(To3(points[5]));
st.AddColor(colors[3]);
st.AddVertex(To3(points[3]));
st.AddVertex(To3(points[4]));
st.Index();
DrawMesh(st.Commit(), null);
DrawPolylineColors(points, colors, antialiased: true);
}
private static Vector3 To3(Vector2 vec)
=> new Vector3(vec.x, vec.y, 0);
[Remote] [Remote]
private void SendAimAngle(float value) private void SendAimAngle(float value)
@ -197,26 +152,15 @@ public class Weapon : Sprite
AimDirection = value; AimDirection = value;
} }
private void Fire() private void Fire()
{ {
var seed = unchecked((int)GD.Randi()); var seed = unchecked((int)GD.Randi());
if (!FireInternal(AimDirection, Scale.y > 0, seed)) return; if (!FireInternal(AimDirection, Scale.y > 0, seed)) return;
RpcId(1, nameof(Fire), AimDirection, Scale.y > 0, seed); RpcId(1, nameof(SendFire), AimDirection, Scale.y > 0, seed);
((LocalPlayer)Player).Velocity -= Mathf.Polar2Cartesian(Knockback, Rotation); ((LocalPlayer)Player).Velocity -= Mathf.Polar2Cartesian(Knockback, Rotation);
} }
[Remote]
private void Fire(float aimDirection, bool toRight, int seed)
{
if (this.GetGame() is Server) {
if (Player.NetworkID != GetTree().GetRpcSenderId()) return;
// TODO: Verify input.
if (FireInternal(aimDirection, toRight, seed))
Rpc(nameof(Fire), aimDirection, toRight, seed);
} else if (!(Player is LocalPlayer))
FireInternal(aimDirection, toRight, seed);
}
protected virtual bool FireInternal(float aimDirection, bool toRight, int seed) protected virtual bool FireInternal(float aimDirection, bool toRight, int seed)
{ {
if ((_reloading != null) || (Rounds <= 0) || (_fireDelay > 0)) return false; if ((_reloading != null) || (Rounds <= 0) || (_fireDelay > 0)) return false;
@ -246,4 +190,83 @@ public class Weapon : Sprite
} }
return true; return true;
} }
[Remote]
private void SendFire(float aimDirection, bool toRight, int seed)
{
if (this.GetGame() is Server) {
if (Player.NetworkID != GetTree().GetRpcSenderId()) return;
// TODO: Verify input.
if (FireInternal(aimDirection, toRight, seed))
Rpc(nameof(SendFire), aimDirection, toRight, seed);
} else if (!(Player is LocalPlayer))
FireInternal(aimDirection, toRight, seed);
}
private void Reload()
{ if (ReloadInternal()) RpcId(1, nameof(SendReload)); }
private bool ReloadInternal()
{
if ((Rounds >= Capacity) || (_reloading != null)) return false;
// TODO: Play reload sound.
_reloading = ReloadTime;
return true;
}
[Remote]
private void SendReload()
{
if (this.GetGame() is Server) {
if (Player.NetworkID != GetTree().GetRpcSenderId()) return;
if (ReloadInternal()) Rpc(nameof(SendReload));
} else if (!(Player is LocalPlayer))
ReloadInternal();
}
public override void _Draw()
{
if (!(Player is LocalPlayer)) return;
// Draws an "aiming cone" to show where bullets might travel.
var tip = TipOffset + new Vector2(4, 0);
var angle = Mathf.Sin((Mathf.Deg2Rad(Spread) + _currentSpreadInc) / 2);
var color = Colors.Black;
var points = new Vector2[8];
var colors = new Color[8];
colors[0] = colors[7] = new Color(color, 0.0F);
points[0] = points[7] = tip;
colors[1] = colors[6] = new Color(color, 0.15F);
points[1] = tip + new Vector2(1, angle) * 64;
points[6] = tip + new Vector2(1, -angle) * 64;
colors[2] = colors[5] = new Color(color, 0.15F);
points[2] = tip + new Vector2(1, angle) * EffectiveRange;
points[5] = tip + new Vector2(1, -angle) * EffectiveRange;
colors[3] = colors[4] = new Color(color, 0.0F);
points[3] = tip + new Vector2(1, angle) * MaximumRange;
points[4] = tip + new Vector2(1, -angle) * MaximumRange;
var st = new SurfaceTool();
st.Begin(Mesh.PrimitiveType.TriangleStrip);
st.AddColor(colors[0]);
st.AddVertex(To3(points[0]));
st.AddColor(colors[1]);
st.AddVertex(To3(points[1]));
st.AddVertex(To3(points[6]));
st.AddColor(colors[2]);
st.AddVertex(To3(points[2]));
st.AddVertex(To3(points[5]));
st.AddColor(colors[3]);
st.AddVertex(To3(points[3]));
st.AddVertex(To3(points[4]));
st.Index();
DrawMesh(st.Commit(), null);
DrawPolylineColors(points, colors, antialiased: true);
}
private static Vector3 To3(Vector2 vec)
=> new Vector3(vec.x, vec.y, 0);
} }

Loading…
Cancel
Save