public void LoadUnloadAmmo(NetworkInstanceId magazineID) { //if the magazine ID is invalid remove the magazine if (magazineID == NetworkInstanceId.Invalid) { CurrentMagazine = null; } else { //find the magazine by NetworkID GameObject magazine = ClientScene.FindLocalObject(magazineID); if (magazine != null) { MagazineBehaviour magazineBehavior = magazine.GetComponent <MagazineBehaviour>(); CurrentMagazine = magazineBehavior; Logger.LogTraceFormat("MagazineBehaviour found ok: {0}", Category.Firearms, magazineID); } } }
public void LoadUnloadAmmo(NetworkInstanceId magazineID) { //if the magazine ID is invalid remove the magazine if (magazineID == NetworkInstanceId.Invalid) { CurrentMagazine = null; } else { //find the magazine by NetworkID GameObject magazine = ClientScene.FindLocalObject(magazineID); if (magazine != null) { MagazineBehaviour magazineBehavior = magazine.GetComponent <MagazineBehaviour>(); CurrentMagazine = magazineBehavior; } else { Debug.Log("Could not find MagazineBehaviour"); } } }
/// <summary> /// attempt to reload the weapon with the item given /// </summary> private void TryReload(GameObject ammo) { MagazineBehaviour magazine = ammo.GetComponent <MagazineBehaviour>(); if (CurrentMagazine == null || (MagInternal && magazine.isClip)) { //RELOAD // If the item used on the gun is a magazine, check type and reload AmmoType ammoType = magazine.ammoType; if (this.ammoType == ammoType) { var hand = UIManager.Hands.CurrentSlot.NamedSlot; RequestReload(magazine.gameObject, hand); } if (this.ammoType != ammoType) { Chat.AddExamineMsgToClient("You try to load the wrong ammo into your weapon"); } } else if (ammoType == magazine.ammoType) { Chat.AddExamineMsgToClient("You weapon is already loaded, you can't fit more Magazines in it, silly!"); } }
/// <summary> /// Returns true if it is possible to fill this magazine with the interaction target object, /// which occurs when the interaction target is a clip of the same ammo type. /// </summary> public bool WillInteract(InventoryApply interaction, NetworkSide side) { if (!DefaultWillInteract.Default(interaction, side)) { return(false); } MagazineBehaviour mag = interaction.TargetObject.GetComponent <MagazineBehaviour>(); if (mag == null) { return(false); } if (interaction.UsedObject == null) { return(false); } if (mag.ammoType != ammoType || magType != MagType.Clip) { return(false); } return(true); }
public virtual void ServerPerformInteraction(InventoryApply interaction) { if (interaction.TargetObject == gameObject && interaction.IsFromHandSlot) { if (interaction.UsedObject != null) { MagazineBehaviour mag = interaction.UsedObject.GetComponent <MagazineBehaviour>(); if (mag) { RequestReload(mag.gameObject); } else if (Validations.HasItemTrait(interaction.UsedObject, CommonTraits.Instance.Suppressor) && !isSuppressed && isSuppressible) { SyncIsSuppressed(isSuppressed, true); Inventory.ServerTransfer(interaction.FromSlot, suppressorSlot); } } else if (isSuppressed && isSuppressible && suppressorSlot.Item != null) { SyncIsSuppressed(isSuppressed, false); Inventory.ServerTransfer(suppressorSlot, interaction.FromSlot); } } }
void Update() { if (ControlledByPlayer == NetworkInstanceId.Invalid) { return; } //don't start it too early: if (!PlayerManager.LocalPlayer) { return; } //Only update if it is inhand of localplayer if (PlayerManager.LocalPlayer != ClientScene.FindLocalObject(ControlledByPlayer)) { return; } if (FireCountDown > 0) { FireCountDown -= Time.deltaTime; //prevents the next projectile taking miliseconds longer than it should if (FireCountDown < 0) { FireCountDown = 0; } } //Check if magazine in opposite hand or if unloading if (Input.GetKeyDown(KeyCode.E)) { //PlaceHolder for click UI GameObject currentHandItem = UIManager.Hands.CurrentSlot.Item; GameObject otherHandItem = UIManager.Hands.OtherSlot.Item; string hand; if (currentHandItem != null) { if (CurrentMagazine == null) { //RELOAD MagazineBehaviour magazine = currentHandItem.GetComponent <MagazineBehaviour>(); if (magazine != null && otherHandItem.GetComponent <Weapon>() != null) { hand = UIManager.Hands.CurrentSlot.eventName; Reload(currentHandItem, hand); } } else { //UNLOAD Weapon weapon = currentHandItem.GetComponent <Weapon>(); if (weapon != null && otherHandItem == null) { ManualUnload(CurrentMagazine); } } } } if (Input.GetMouseButtonUp(0)) { InAutomaticAction = false; //remove recoil after shooting is released CurrentRecoilVariance = 0; } if (InAutomaticAction && FireCountDown <= 0) { AttemptToFireWeapon(); } }
private void UpdateMe() { //don't process if we are server and the gun is not held by anyone if (isServer && serverHolder == null) { return; } //if we are client, make sure we've initialized if (!isServer && !PlayerManager.LocalPlayer) { return; } //if we are client, only process this if we are holding it if (!isServer) { if (UIManager.Hands == null || UIManager.Hands.CurrentSlot == null) { return; } var heldItem = UIManager.Hands.CurrentSlot.ItemObject; if (gameObject != heldItem) { return; } } //update the time until the next shot can happen if (FireCountDown > 0) { FireCountDown -= Time.deltaTime; //prevents the next projectile taking miliseconds longer than it should if (FireCountDown < 0) { FireCountDown = 0; } } //remaining logic is server side only //this will only be executed on the server since only the server //maintains the queued actions if (queuedShots.Count > 0 && FireCountDown <= 0) { //fire the next shot in the queue DequeueAndProcessServerShot(); } if (queuedUnload && queuedShots.Count == 0 && allowMagazineRemoval && !MagInternal) { // done processing shot queue, // perform the queued unload action, causing all clients and server to update their version of this Weapon // due to the syncvar hook // there should not be an unload action for internal magazines Inventory.ServerDrop(magSlot); queuedUnload = false; } if (queuedLoadMagNetID != NetId.Invalid && queuedShots.Count == 0) { if (CurrentMagazine == null) { Logger.LogWarning($"Why is {nameof(CurrentMagazine)} null for {this}?"); } //done processing shot queue, perform the reload, causing all clients and server to update their version of this Weapon //due to the syncvar hook if (MagInternal) { var clip = NetworkIdentity.spawned[queuedLoadMagNetID]; MagazineBehaviour clipComp = clip.GetComponent <MagazineBehaviour>(); string message = CurrentMagazine.LoadFromClip(clipComp); Chat.AddExamineMsg(serverHolder, message); queuedLoadMagNetID = NetId.Invalid; } else { var magazine = NetworkIdentity.spawned[queuedLoadMagNetID]; var fromSlot = magazine.GetComponent <Pickupable>().ItemSlot; Inventory.ServerTransfer(fromSlot, magSlot); queuedLoadMagNetID = NetId.Invalid; } } }
private void Start() { magazineBehaviour = GetComponent <Gun>().CurrentMagazine; }
/// <summary> /// Perform and display the shot locally (i.e. only on this instance of the game). Does not /// communicate anything to other players (unless this is the server, in which case the server /// will determine the effects of the bullet). Does not do any validation. This should only be invoked /// when displaying the results of a shot (i.e. after receiving a ShootMessage or after this client performs a shot) /// or when server is determining the outcome of the shot. /// </summary> /// <param name="shooter">gameobject of the shooter</param> /// <param name="finalDirection">direction the shot should travel (accuracy deviation should already be factored into this)</param> /// <param name="damageZone">targeted damage zone</param> /// <param name="isSuicideShot">if this is a suicide shot (aimed at shooter)</param> public void DisplayShot(GameObject shooter, Vector2 finalDirection, BodyPartType damageZone, bool isSuicideShot) { if (!MatrixManager.IsInitialized) { return; } //if this is our gun (or server), last check to ensure we really can shoot if ((isServer || PlayerManager.LocalPlayer == shooter) && CurrentMagazine.ClientAmmoRemains <= 0) { if (isServer) { Logger.LogTrace("Server rejected shot - out of ammo", Category.Firearms); } return; } if (shooter == PlayerManager.LocalPlayer) { //this is our gun so we need to update our predictions FireCountDown += 1.0 / FireRate; //add additional recoil after shooting for the next round AppendRecoil(); //Default camera recoil params until each gun is configured separately if (CameraRecoilConfig == null || CameraRecoilConfig.Distance == 0f) { CameraRecoilConfig = new CameraRecoilConfig { Distance = 0.2f, RecoilDuration = 0.05f, RecoveryDuration = 0.6f }; } Camera2DFollow.followControl.Recoil(-finalDirection, CameraRecoilConfig); if (CurrentMagazine == null) { Logger.LogWarning($"Why is {nameof(CurrentMagazine)} null for {this} on this client?"); } else { //call ExpendAmmo outside of previous check, or it won't run serverside and state will desync. CurrentMagazine.ExpendAmmo(); } } MagazineBehaviour magazine = ammoPrefab.GetComponent <MagazineBehaviour>(); if (isSuicideShot) { GameObject bullet = Spawn.ClientPrefab(magazine.Projectile.name, shooter.transform.position, parent: shooter.transform.parent).GameObject; var b = bullet.GetComponent <Projectile>(); b.Suicide(shooter, this, damageZone); } else { for (int n = 0; n < magazine.ProjectilesFired; n++) { GameObject Abullet = Spawn.ClientPrefab(magazine.Projectile.name, shooter.transform.position, parent: shooter.transform.parent).GameObject; var A = Abullet.GetComponent <Projectile>(); var finalDirectionOverride = CalcDirection(finalDirection, n); A.Shoot(finalDirectionOverride, shooter, this, damageZone); } } SoundManager.PlayAtPosition(FiringSound, shooter.transform.position, shooter); shooter.GetComponent <PlayerSprites>().ShowMuzzleFlash(); }