示例#1
0
        public static void SharedUpdateReloading(
            WeaponState weaponState,
            ICharacter character,
            double deltaTime,
            out bool isReloadingNow)
        {
            var reloadingState = weaponState.WeaponReloadingState;

            if (reloadingState is null)
            {
                isReloadingNow = false;
                return;
            }

            if (reloadingState.Item != weaponState.ItemWeapon)
            {
                Logger.Info("Can reload only the current weapon. Reloading aborted");
                SharedTryAbortReloading(character, reloadingState.Item);
                isReloadingNow = false;
                return;
            }

            if (IsServer &&
                weaponState.SharedGetInputIsFiring() &&
                weaponState.ItemWeapon is not null &&
                weaponState.ItemWeapon.GetPrivateState <WeaponPrivateState>().AmmoCount > 0)
            {
                var shotsRemains = (long)weaponState.ServerLastClientReportedShotsDoneCount - weaponState.ShotsDone;
                if (shotsRemains > 0 &&
                    weaponState.ServerLastClientReportedShotsDoneCount > 0)
                {
                    // sometimes the client reloading requests are received by the server
                    // too early (before the server fired all the shots) so the server should fire them first
                    //Logger.Dev("Server cannot reload while client is firing. Shot remains: " + shotsRemains);
                    isReloadingNow = false;
                    return;
                }
            }

            // process reloading
            reloadingState.SecondsToReloadRemains -= deltaTime;
            if (reloadingState.SecondsToReloadRemains > 0)
            {
                // need more time to reload
                isReloadingNow = true;
                return;
            }

            // reloaded
            reloadingState.SecondsToReloadRemains = 0;
            SharedProcessWeaponReload(character,
                                      weaponState,
                                      out var isAmmoTypeChanged);

            if (isAmmoTypeChanged)
            {
                weaponState.ClearFiringStateData();
                //Api.Logger.Dev("Reset ServerLastClientReportedShotsDoneCount. Last value: "
                //               + weaponState.ServerLastClientReportedShotsDoneCount);
            }

            weaponState.FirePatternCooldownSecondsRemains = 0;
            weaponState.IsIdleAutoReloadingAllowed        = true;
            isReloadingNow = false;
        }
示例#2
0
        public static void SharedUpdateCurrentWeapon(
            ICharacter character,
            WeaponState state,
            double deltaTime)
        {
            var protoWeapon = state.ActiveProtoWeapon;

            if (protoWeapon == null)
            {
                return;
            }

            if (state.CooldownSecondsRemains > 0)
            {
                // decrease cooldown
                state.CooldownSecondsRemains -= deltaTime;
            }

            if (!state.IsFiring)
            {
                WeaponAmmoSystem.SharedUpdateReloading(state, character, ref deltaTime);
            }

            if (deltaTime <= 0)
            {
                // the weapon reloading process is consumed the whole delta time
                return;
            }

            if (state.SharedGetInputIsFiring() &&
                !character.IsOnline)
            {
                state.SetInputIsFiring(false);
            }

            if (state.SharedGetInputIsFiring() &&
                StatusEffectDazed.SharedIsCharacterDazed(character,
                                                         StatusEffectDazed.NotificationCannotAttackWhileDazed))
            {
                state.SetInputIsFiring(false);
            }

            // check ammo (if applicable to this weapon prototype)
            var canFire = protoWeapon.SharedCanFire(character, state);

            if (state.CooldownSecondsRemains > 0)
            {
                // firing cooldown is not completed
                if (!state.SharedGetInputIsFiring() &&
                    state.IsEventWeaponStartSent)
                {
                    // not firing anymore
                    SharedCallOnWeaponInputStop(state, character);
                }

                return;
            }

            var wasFiring = state.IsFiring;

            if (!state.IsFiring)
            {
                state.IsFiring = state.SharedGetInputIsFiring();
            }
            else // if IsFiring
            {
                if (!SharedShouldFireMore(state))
                {
                    state.IsFiring = state.SharedGetInputIsFiring();
                }
            }

            if (!canFire)
            {
                // cannot fire (no ammo, etc)
                state.IsFiring = false;
            }

            if (!state.IsFiring)
            {
                if (wasFiring)
                {
                    // just stopped firing
                    SharedCallOnWeaponFinished(state, character);
                }

                // the character is not firing
                // reset delay for the next shot (it will be set when firing starts next time)
                state.DamageApplyDelaySecondsRemains = 0;
                return;
            }

            // let's process what happens when we're in the firing mode
            if (!state.IsEventWeaponStartSent)
            {
                // started firing
                SharedCallOnWeaponStart(state, character);
            }

            if (state.DamageApplyDelaySecondsRemains <= 0)
            {
                // initialize delay to next shot
                state.DamageApplyDelaySecondsRemains = protoWeapon.DamageApplyDelay;
                SharedCallOnWeaponShot(character);
            }

            // decrease the remaining time to the damage application
            state.DamageApplyDelaySecondsRemains -= deltaTime;

            if (state.DamageApplyDelaySecondsRemains > 0)
            {
                // firing delay not completed
                return;
            }

            // firing delay completed
            state.ShotsDone++;
            //Logger.Dev("Weapon fired, shots done: " + state.ShotsDone);
            SharedFireWeapon(character, state.ActiveItemWeapon, protoWeapon, state);
            state.CooldownSecondsRemains += protoWeapon.FireInterval - protoWeapon.DamageApplyDelay;

            if (!protoWeapon.IsLoopedAttackAnimation)
            {
                // we don't want to stuck this animation in the last frame
                // that's fix for the issue:
                // "Fix extended animation "stuck" issue for mobs (like limbs stuck in the end position and movement animation appears broken)"
                state.IsEventWeaponStartSent = false;
            }
        }
示例#3
0
        public static void SharedUpdateCurrentWeapon(
            ICharacter character,
            WeaponState state,
            double deltaTime)
        {
            var protoWeapon = state.ProtoWeapon;

            if (protoWeapon == null)
            {
                return;
            }

            if (deltaTime > 0.4)
            {
                // too large delta time probably due to a frame skip
                deltaTime = 0.4;
            }

            if (state.CooldownSecondsRemains > 0)
            {
                state.CooldownSecondsRemains -= deltaTime;
                if (state.CooldownSecondsRemains < -0.2)
                {
                    // clamp the remaining cooldown in case of a frame skip
                    state.CooldownSecondsRemains = -0.2;
                }
            }

            if (state.ReadySecondsRemains > 0)
            {
                state.ReadySecondsRemains -= deltaTime;
            }

            if (state.FirePatternCooldownSecondsRemains > 0)
            {
                state.FirePatternCooldownSecondsRemains -= deltaTime;

                if (state.FirePatternCooldownSecondsRemains <= 0)
                {
                    state.FirePatternCurrentShotNumber = 0;
                }
            }

            // TODO: restore this condition when we redo UI countdown animation for ViewModelHotbarItemWeaponOverlayControl.ReloadDurationSeconds
            //if (state.CooldownSecondsRemains <= 0)
            //{
            WeaponAmmoSystem.SharedUpdateReloading(state, character, deltaTime);
            //}

            if (Api.IsServer &&
                !character.ServerIsOnline &&
                state.SharedGetInputIsFiring())
            {
                state.SharedSetInputIsFiring(false);
            }

            // check ammo (if applicable to this weapon prototype)
            var canFire = (Api.IsClient || character.ServerIsOnline) &&
                          state.WeaponReloadingState is null &&
                          protoWeapon.SharedCanFire(character, state);

            if (state.CooldownSecondsRemains > 0)
            {
                // firing cooldown is not completed
                if (!state.SharedGetInputIsFiring() &&
                    state.IsEventWeaponStartSent)
                {
                    // not firing anymore
                    SharedCallOnWeaponInputStop(state, character);
                }

                return;
            }

            var wasFiring = state.IsFiring;

            if (!state.IsFiring)
            {
                state.IsFiring = state.SharedGetInputIsFiring();
            }
            else // if IsFiring
            {
                if (!SharedShouldFireMore(state))
                {
                    state.IsFiring = state.SharedGetInputIsFiring();
                }
            }

            if (!canFire)
            {
                // cannot fire (no ammo, etc)
                state.IsFiring = false;
            }

            if (!state.IsFiring)
            {
                if (wasFiring)
                {
                    // just stopped firing
                    SharedCallOnWeaponFinished(state, character);
                }

                // the character is not firing
                // reset delay for the next shot (it will be set when firing starts next time)
                state.DamageApplyDelaySecondsRemains = 0;
                return;
            }

            if (state.WeaponCache is null)
            {
                SharedRebuildWeaponCache(character, state);
            }

            // let's process what happens when we're in the firing mode
            if (!state.IsEventWeaponStartSent)
            {
                // started firing
                SharedCallOnWeaponStart(state, character);
            }

            if (state.DamageApplyDelaySecondsRemains <= 0)
            {
                // initialize delay to next shot
                state.DamageApplyDelaySecondsRemains =
                    Shared.RoundDurationByServerFrameDuration(protoWeapon.DamageApplyDelay);

                SharedCallOnWeaponShot(character, protoWeapon);
            }

            // decrease the remaining time to the damage application
            state.DamageApplyDelaySecondsRemains -= deltaTime;

            if (state.DamageApplyDelaySecondsRemains > 0)
            {
                // firing delay not completed
                return;
            }

            // firing delay completed
            state.ShotsDone++;
            //Logger.Dev("Weapon fired, shots done: " + state.ShotsDone);
            SharedFireWeapon(character, state.ItemWeapon, protoWeapon, state);
            var cooldownDuration = Shared.RoundDurationByServerFrameDuration(protoWeapon.FireInterval)
                                   - Shared.RoundDurationByServerFrameDuration(protoWeapon.DamageApplyDelay);

            //Logger.Dev($"Cooldown adding: {cooldownDuration} for {protoWeapon}");

            state.CooldownSecondsRemains += cooldownDuration;

            if (!protoWeapon.IsLoopedAttackAnimation)
            {
                // we don't want to stuck this animation in the last frame
                // that's fix for the issue:
                // "Fix extended animation "stuck" issue for mobs (like limbs stuck in the end position and movement animation appears broken)"
                state.IsEventWeaponStartSent = false;
            }
        }