Exemple #1
0
        private void UpdateUI(GameObject root, TextWrapper textCurrentAmmo, TextWrapper textReserveAmmo, CharacterItem characterItem)
        {
            Item weaponItem = characterItem.GetWeaponItem();
            bool isActive   = weaponItem != null && weaponItem.WeaponType.requireAmmoType != null;

            if (root != null)
            {
                root.SetActive(isActive);
            }

            if (textCurrentAmmo != null)
            {
                textCurrentAmmo.gameObject.SetActive(isActive && weaponItem.ammoCapacity > 0);
                if (isActive)
                {
                    textCurrentAmmo.text = characterItem.ammo.ToString("N0");
                }
            }

            if (textReserveAmmo != null)
            {
                textReserveAmmo.gameObject.SetActive(isActive);
                if (isActive)
                {
                    int ammoAmount = character != null && weaponItem.WeaponType.requireAmmoType != null?character.CountAmmos(weaponItem.WeaponType.requireAmmoType) : 0;

                    textReserveAmmo.text = ammoAmount.ToString("N0");
                }
            }
        }
        public bool ValidateAmmo(CharacterItem weapon)
        {
            // Avoid null data
            if (weapon == null)
            {
                return(true);
            }

            Item weaponItem = weapon.GetWeaponItem();

            if (weaponItem.WeaponType.requireAmmoType != null)
            {
                if (weaponItem.ammoCapacity <= 0)
                {
                    // Ammo capacity is 0 so reduce ammo from inventory
                    if (this.CountAmmos(weaponItem.WeaponType.requireAmmoType) == 0)
                    {
                        gameManager.SendServerGameMessage(ConnectionId, GameMessage.Type.NoAmmo);
                        return(false);
                    }
                }
                else
                {
                    // Ammo capacity more than 0 reduce loaded ammo
                    if (weapon.ammo <= 0)
                    {
                        gameManager.SendServerGameMessage(ConnectionId, GameMessage.Type.NoAmmo);
                        return(false);
                    }
                }
            }
            return(true);
        }
    public static CharacterItem GetAvailableWeapon(this ICharacterData data, ref bool isLeftHand)
    {
        CharacterItem rightHand       = data.EquipWeapons.rightHand;
        Item          rightWeaponItem = rightHand.GetWeaponItem();
        CharacterItem leftHand        = data.EquipWeapons.leftHand;
        Item          leftWeaponItem  = leftHand.GetWeaponItem();

        if (!isLeftHand)
        {
            if (rightWeaponItem != null)
            {
                return(rightHand);
            }
            if (rightWeaponItem == null && leftWeaponItem != null)
            {
                isLeftHand = true;
                return(leftHand);
            }
        }
        else
        {
            if (leftWeaponItem != null)
            {
                return(leftHand);
            }
            if (leftWeaponItem == null && rightWeaponItem != null)
            {
                isLeftHand = false;
                return(rightHand);
            }
        }
        isLeftHand = false;
        return(CharacterItem.Create(GameInstance.Singleton.DefaultWeaponItem));
    }
        private void DecreaseEquipWeaponsDurability(BaseCharacterEntity entity, float decreaseDurability)
        {
            bool          tempDestroy  = false;
            EquipWeapons  equipWeapons = entity.EquipWeapons;
            CharacterItem rightHand    = equipWeapons.rightHand;
            CharacterItem leftHand     = equipWeapons.leftHand;

            if (rightHand.GetWeaponItem() != null && rightHand.GetMaxDurability() > 0)
            {
                rightHand = DecreaseDurability(rightHand, decreaseDurability, out tempDestroy);
                if (tempDestroy)
                {
                    equipWeapons.rightHand = CharacterItem.Empty;
                }
                else
                {
                    equipWeapons.rightHand = rightHand;
                }
            }
            if (leftHand.GetWeaponItem() != null && leftHand.GetMaxDurability() > 0)
            {
                leftHand = DecreaseDurability(leftHand, decreaseDurability, out tempDestroy);
                if (tempDestroy)
                {
                    equipWeapons.leftHand = CharacterItem.Empty;
                }
                else
                {
                    equipWeapons.leftHand = leftHand;
                }
            }
            entity.EquipWeapons = equipWeapons;
        }
        public override void ReceiveDamage(IAttackerEntity attacker, CharacterItem weapon, Dictionary <DamageElement, MinMaxFloat> allDamageAmounts, CharacterBuff debuff, uint hitEffectsId)
        {
            if (!IsServer || IsDead() || weapon == null)
            {
                return;
            }

            base.ReceiveDamage(attacker, weapon, allDamageAmounts, debuff, hitEffectsId);
            BaseCharacterEntity attackerCharacter = attacker as BaseCharacterEntity;

            // Play hit effect
            if (hitEffectsId == 0)
            {
                hitEffectsId = gameInstance.DefaultHitEffects.Id;
            }
            if (hitEffectsId > 0)
            {
                RequestPlayEffect(hitEffectsId);
            }
            // Apply damages
            int  totalDamage = 0;
            Item weaponItem  = weapon.GetWeaponItem();
            HarvestEffectiveness harvestEffectiveness;
            WeightedRandomizer <ItemDropByWeight> itemRandomizer;

            if (harvestable.CacheHarvestEffectivenesses.TryGetValue(weaponItem.weaponType, out harvestEffectiveness) &&
                harvestable.CacheHarvestItems.TryGetValue(weaponItem.weaponType, out itemRandomizer))
            {
                totalDamage = (int)(weaponItem.harvestDamageAmount.GetAmount(weapon.level).Random() * harvestEffectiveness.damageEffectiveness);
                ItemDropByWeight receivingItem = itemRandomizer.TakeOne();
                int   dataId           = receivingItem.item.DataId;
                short amount           = (short)(receivingItem.amountPerDamage * totalDamage);
                bool  droppingToGround = collectType == HarvestableCollectType.DropToGround;
                if (attackerCharacter.IncreasingItemsWillOverwhelming(dataId, amount))
                {
                    droppingToGround = true;
                }
                if (!droppingToGround)
                {
                    attackerCharacter.IncreaseItems(CharacterItem.Create(dataId, 1, amount));
                }
                else
                {
                    ItemDropEntity.DropItem(this, CharacterItem.Create(dataId, 1, amount), new uint[0]);
                }
            }
            CurrentHp -= totalDamage;
            ReceivedDamage(attackerCharacter, CombatAmountType.NormalDamage, totalDamage);

            if (IsDead())
            {
                CurrentHp = 0;
                CallNetFunction(NetFuncOnHarvestableDestroy, FunctionReceivers.All);
                DestroyAndRespawn();
            }
        }
        public virtual void GetAttackingData(
            ref bool isLeftHand,
            out AnimActionType animActionType,
            out int dataId,
            out int animationIndex,
            out CharacterItem weapon,
            out float triggerDuration,
            out float totalDuration,
            out DamageInfo damageInfo,
            out Dictionary <DamageElement, MinMaxFloat> allDamageAmounts)
        {
            // Initialize data
            animActionType   = AnimActionType.None;
            dataId           = 0;
            animationIndex   = 0;
            weapon           = this.GetAvailableWeapon(ref isLeftHand);
            triggerDuration  = 0f;
            totalDuration    = 0f;
            damageInfo       = null;
            allDamageAmounts = new Dictionary <DamageElement, MinMaxFloat>();
            // Prepare weapon data
            Item       weaponItem = weapon.GetWeaponItem();
            WeaponType weaponType = weaponItem.WeaponType;

            // Assign data id
            dataId = weaponType.DataId;
            // Assign animation action type
            animActionType = !isLeftHand ? AnimActionType.AttackRightHand : AnimActionType.AttackLeftHand;
            // Random animation
            if (!isLeftHand)
            {
                CharacterModel.GetRandomRightHandAttackAnimation(dataId, out animationIndex, out triggerDuration, out totalDuration);
            }
            else
            {
                CharacterModel.GetRandomLeftHandAttackAnimation(dataId, out animationIndex, out triggerDuration, out totalDuration);
            }
            // Assign damage data
            damageInfo = weaponType.damageInfo;
            // Calculate all damages
            allDamageAmounts = GameDataHelpers.CombineDamages(
                allDamageAmounts,
                weaponItem.GetDamageAmount(weapon.level, weapon.GetEquipmentBonusRate(), this));
            allDamageAmounts = GameDataHelpers.CombineDamages(
                allDamageAmounts,
                CacheIncreaseDamages);
        }
        public void ReduceAmmo(CharacterItem weapon, bool isLeftHand, out Dictionary <DamageElement, MinMaxFloat> increaseDamges)
        {
            increaseDamges = null;
            // Avoid null data
            if (weapon == null)
            {
                return;
            }

            Item weaponItem = weapon.GetWeaponItem();

            if (weaponItem.ammoCapacity <= 0)
            {
                // Ammo capacity is 0 so reduce ammo from inventory
                Dictionary <CharacterItem, short> decreaseAmmoItems;
                if (this.DecreaseAmmos(weaponItem.WeaponType.requireAmmoType, 1, out decreaseAmmoItems))
                {
                    KeyValuePair <CharacterItem, short> firstEntry = decreaseAmmoItems.FirstOrDefault();
                    CharacterItem ammoCharacterItem = firstEntry.Key;
                    Item          ammoItem          = ammoCharacterItem.GetItem();
                    if (ammoItem != null && firstEntry.Value > 0)
                    {
                        // Ammo level always 1 and its bonus rate always 1
                        increaseDamges = ammoItem.GetIncreaseDamages(1, 1f);
                    }
                }
            }
            else
            {
                // Ammo capacity more than 0 reduce loaded ammo
                if (weapon.ammo > 0)
                {
                    weapon.ammo--;
                    EquipWeapons equipWeapons = EquipWeapons;
                    if (isLeftHand)
                    {
                        equipWeapons.leftHand = weapon;
                    }
                    else
                    {
                        equipWeapons.rightHand = weapon;
                    }
                    EquipWeapons = equipWeapons;
                }
            }
        }
        public bool RequestEquipItem(short nonEquipIndex)
        {
            if (!CanDoActions() ||
                nonEquipIndex >= NonEquipItems.Count)
            {
                return(false);
            }
            CharacterItem characterItem = NonEquipItems[nonEquipIndex];
            Item          armorItem     = characterItem.GetArmorItem();
            Item          weaponItem    = characterItem.GetWeaponItem();
            Item          shieldItem    = characterItem.GetShieldItem();

            if (weaponItem != null)
            {
                if (weaponItem.EquipType == WeaponItemEquipType.OneHandCanDual)
                {
                    Item rightWeapon = EquipWeapons.rightHand.GetWeaponItem();
                    if (rightWeapon != null && rightWeapon.EquipType == WeaponItemEquipType.OneHandCanDual)
                    {
                        return(RequestEquipItem(nonEquipIndex, (byte)InventoryType.EquipWeaponLeft, 0));
                    }
                    else
                    {
                        return(RequestEquipItem(nonEquipIndex, (byte)InventoryType.EquipWeaponRight, 0));
                    }
                }
                else
                {
                    return(RequestEquipItem(nonEquipIndex, (byte)InventoryType.EquipWeaponRight, 0));
                }
            }
            else if (shieldItem != null)
            {
                return(RequestEquipItem(nonEquipIndex, (byte)InventoryType.EquipWeaponLeft, 0));
            }
            else if (armorItem != null)
            {
                return(RequestEquipItem(nonEquipIndex, (byte)InventoryType.EquipItems, (short)this.IndexOfEquipItem(armorItem.EquipPosition)));
            }
            return(false);
        }
        private IEnumerator ReloadRoutine(
            AnimActionType animActionType,
            int weaponTypeDataId,
            float triggerDuration,
            float totalDuration,
            bool isLeftHand,
            CharacterItem weapon,
            short reloadingAmount)
        {
            // Play animation on clients
            RequestPlayActionAnimation(animActionType, weaponTypeDataId, 0);

            yield return(new WaitForSecondsRealtime(triggerDuration));

            // Prepare data
            EquipWeapons equipWeapons = EquipWeapons;
            Item         weaponItem   = weapon.GetWeaponItem();
            Dictionary <CharacterItem, short> decreaseItems;

            if (this.DecreaseAmmos(weaponItem.WeaponType.requireAmmoType, reloadingAmount, out decreaseItems))
            {
                weapon.ammo += reloadingAmount;
                if (isLeftHand)
                {
                    equipWeapons.leftHand = weapon;
                }
                else
                {
                    equipWeapons.rightHand = weapon;
                }
                EquipWeapons = equipWeapons;
            }

            yield return(new WaitForSecondsRealtime(totalDuration - triggerDuration));

            isAttackingOrUsingSkill = false;
        }
Exemple #10
0
        protected override void UpdateData()
        {
            cacheStats           = showStatsWithBuffs ? Data.GetStats() : Data.GetStats(true, false);
            cacheAttributes      = showAttributeWithBuffs ? Data.GetAttributes() : Data.GetAttributes(true, false);
            cacheResistances     = showResistanceWithBuffs ? Data.GetResistances() : Data.GetResistances(true, false);
            cacheIncreaseDamages = showDamageWithBuffs ? Data.GetIncreaseDamages() : Data.GetIncreaseDamages(true, false);
            cacheWeightLimit     = cacheStats.weightLimit;
            if (!showStatsWithBuffs)
            {
                // Always increase weight limit by buff bonus because it should always show real weight limit in UIs
                cacheWeightLimit += Data.GetBuffStats().weightLimit;
            }

            if (bonusAttributes == null)
            {
                bonusAttributes = new Dictionary <Attribute, short>();
            }
            if (bonusResistances == null)
            {
                bonusResistances = new Dictionary <DamageElement, float>();
            }
            if (bonusIncreaseDamages == null)
            {
                bonusIncreaseDamages = new Dictionary <DamageElement, MinMaxFloat>();
            }
            if (bonusSkills == null)
            {
                bonusSkills = new Dictionary <Skill, short>();
            }
            if (cacheEquipmentSets == null)
            {
                cacheEquipmentSets = new Dictionary <EquipmentSet, int>();
            }

            Data.GetEquipmentSetBonus(out bonusStats, bonusAttributes, bonusResistances, bonusIncreaseDamages, bonusSkills, cacheEquipmentSets);
            // Increase stats by equipment set bonus
            cacheStats          += bonusStats;
            cacheAttributes      = GameDataHelpers.CombineAttributes(cacheAttributes, bonusAttributes);
            cacheResistances     = GameDataHelpers.CombineResistances(cacheResistances, bonusResistances);
            cacheIncreaseDamages = GameDataHelpers.CombineDamages(cacheIncreaseDamages, bonusIncreaseDamages);
            cacheWeightLimit    += bonusStats.weightLimit;

            if (uiTextWeightLimit != null)
            {
                uiTextWeightLimit.text = string.Format(
                    LanguageManager.GetText(formatKeyWeightLimitStats),
                    GameInstance.Singleton.GameplayRule.GetTotalWeight(Data).ToString("N2"),
                    cacheWeightLimit.ToString("N2"));
            }

            CharacterItem rightHandItem   = Data.EquipWeapons.rightHand;
            CharacterItem leftHandItem    = Data.EquipWeapons.leftHand;
            Item          rightHandWeapon = rightHandItem.GetWeaponItem();
            Item          leftHandWeapon  = leftHandItem.GetWeaponItem();
            Dictionary <DamageElement, MinMaxFloat> rightHandDamages = rightHandWeapon != null?GameDataHelpers.CombineDamages(cacheIncreaseDamages, rightHandWeapon.GetDamageAmount(rightHandItem.level, rightHandItem.GetEquipmentBonusRate(), Data)) : null;

            Dictionary <DamageElement, MinMaxFloat> leftHandDamages = leftHandWeapon != null?GameDataHelpers.CombineDamages(cacheIncreaseDamages, leftHandWeapon.GetDamageAmount(leftHandItem.level, leftHandItem.GetEquipmentBonusRate(), Data)) : null;

            if (uiTextWeaponDamages != null)
            {
                string textDamages = "";
                if (rightHandWeapon != null)
                {
                    MinMaxFloat sumDamages = GameDataHelpers.GetSumDamages(rightHandDamages);
                    if (!string.IsNullOrEmpty(textDamages))
                    {
                        textDamages += "\n";
                    }
                    textDamages += string.Format(
                        LanguageManager.GetText(formatKeyWeaponDamage),
                        sumDamages.min.ToString("N0"),
                        sumDamages.max.ToString("N0"));
                }
                if (leftHandWeapon != null)
                {
                    MinMaxFloat sumDamages = GameDataHelpers.GetSumDamages(leftHandDamages);
                    if (!string.IsNullOrEmpty(textDamages))
                    {
                        textDamages += "\n";
                    }
                    textDamages += string.Format(
                        LanguageManager.GetText(formatKeyWeaponDamage),
                        sumDamages.min.ToString("N0"),
                        sumDamages.max.ToString("N0"));
                }
                if (rightHandWeapon == null && leftHandWeapon == null)
                {
                    Item defaultWeaponItem = GameInstance.Singleton.DefaultWeaponItem;
                    WeaponItemEquipType defaultWeaponItemType = defaultWeaponItem.EquipType;
                    KeyValuePair <DamageElement, MinMaxFloat> damageAmount = defaultWeaponItem.GetDamageAmount(1, 1f, Data);
                    textDamages = string.Format(
                        LanguageManager.GetText(formatKeyWeaponDamage),
                        damageAmount.Value.min.ToString("N0"),
                        damageAmount.Value.max.ToString("N0"));
                }
                uiTextWeaponDamages.text = textDamages;
            }

            if (uiRightHandDamages != null)
            {
                if (rightHandWeapon == null)
                {
                    uiRightHandDamages.Hide();
                }
                else
                {
                    uiRightHandDamages.Show();
                    uiRightHandDamages.Data = rightHandDamages;
                }
            }

            if (uiLeftHandDamages != null)
            {
                if (leftHandWeapon == null)
                {
                    uiLeftHandDamages.Hide();
                }
                else
                {
                    uiLeftHandDamages.Show();
                    uiLeftHandDamages.Data = leftHandDamages;
                }
            }

            if (uiCharacterStats != null)
            {
                uiCharacterStats.Data = cacheStats;
            }

            if (uiCharacterResistances != null)
            {
                uiCharacterResistances.Data = cacheResistances;
            }

            if (CacheUICharacterAttributes.Count > 0 && Data != null)
            {
                CharacterAttribute tempCharacterAttribute;
                Attribute          tempAttribute;
                short tempAmount;
                IList <CharacterAttribute> characterAttributes = Data.Attributes;
                for (int indexOfData = 0; indexOfData < characterAttributes.Count; ++indexOfData)
                {
                    tempCharacterAttribute = characterAttributes[indexOfData];
                    tempAttribute          = tempCharacterAttribute.GetAttribute();
                    UICharacterAttribute cacheUICharacterAttribute;
                    tempAmount = 0;
                    if (CacheUICharacterAttributes.TryGetValue(tempAttribute, out cacheUICharacterAttribute))
                    {
                        if (cacheAttributes.ContainsKey(tempAttribute))
                        {
                            tempAmount = cacheAttributes[tempAttribute];
                        }
                        cacheUICharacterAttribute.Setup(new CharacterAttributeTuple(tempCharacterAttribute, tempAmount), Data, indexOfData);
                        cacheUICharacterAttribute.Show();
                    }
                }
            }

            if (uiCharacterBuffs != null)
            {
                uiCharacterBuffs.UpdateData(Data);
            }
        }
Exemple #11
0
        public virtual void GetUsingSkillData(
            Skill skill,
            short level,
            ref bool isLeftHand,
            out AnimActionType animActionType,
            out int skillOrWeaponTypeDataId,
            out int animationIndex,
            out CharacterItem weapon,
            out float triggerDuration,
            out float totalDuration,
            out DamageInfo damageInfo,
            out Dictionary <DamageElement, MinMaxFloat> allDamageAmounts)
        {
            // Initialize data
            animActionType          = AnimActionType.None;
            skillOrWeaponTypeDataId = 0;
            animationIndex          = 0;
            weapon           = this.GetAvailableWeapon(ref isLeftHand);
            triggerDuration  = 0f;
            totalDuration    = 0f;
            damageInfo       = null;
            allDamageAmounts = new Dictionary <DamageElement, MinMaxFloat>();
            // Prepare skill data
            if (skill == null)
            {
                return;
            }
            // Prepare weapon data
            Item       weaponItem = weapon.GetWeaponItem();
            WeaponType weaponType = weaponItem.WeaponType;
            SkillActivateAnimationType useSkillActivateAnimationType = CharacterModel.UseSkillActivateAnimationType(skill);

            // Prepare animation
            if (useSkillActivateAnimationType == SkillActivateAnimationType.UseAttackAnimation && skill.skillAttackType != SkillAttackType.None)
            {
                // If there is no cast animations
                // Assign data id
                skillOrWeaponTypeDataId = weaponType.DataId;
                // Assign animation action type
                animActionType = !isLeftHand ? AnimActionType.AttackRightHand : AnimActionType.AttackLeftHand;
                // Random animation
                if (!isLeftHand)
                {
                    CharacterModel.GetRandomRightHandAttackAnimation(skillOrWeaponTypeDataId, out animationIndex, out triggerDuration, out totalDuration);
                }
                else
                {
                    CharacterModel.GetRandomLeftHandAttackAnimation(skillOrWeaponTypeDataId, out animationIndex, out triggerDuration, out totalDuration);
                }
            }
            else if (useSkillActivateAnimationType == SkillActivateAnimationType.UseActivateAnimation)
            {
                // Assign data id
                skillOrWeaponTypeDataId = skill.DataId;
                // Assign animation action type
                animActionType = AnimActionType.Skill;
                // Random animation
                CharacterModel.GetSkillActivateAnimation(skillOrWeaponTypeDataId, out triggerDuration, out totalDuration);
            }
            // If it is attack skill
            if (skill.skillAttackType != SkillAttackType.None)
            {
                switch (skill.skillAttackType)
                {
                case SkillAttackType.Normal:
                    // Assign damage data
                    damageInfo = skill.damageInfo;
                    // Calculate all damages
                    allDamageAmounts = weaponItem.GetDamageAmountWithInflictions(weapon.level, weapon.GetEquipmentBonusRate(), this, skill.GetWeaponDamageInflictions(level));
                    // Sum damage with additional damage amounts
                    allDamageAmounts = GameDataHelpers.CombineDamages(
                        allDamageAmounts,
                        skill.GetDamageAmount(level, this));
                    // Sum damage with skill damage
                    allDamageAmounts = GameDataHelpers.CombineDamages(
                        allDamageAmounts,
                        skill.GetAdditionalDamageAmounts(level));
                    break;

                case SkillAttackType.BasedOnWeapon:
                    // Assign damage data
                    damageInfo = weaponType.damageInfo;
                    // Calculate all damages
                    allDamageAmounts = weaponItem.GetDamageAmountWithInflictions(weapon.level, weapon.GetEquipmentBonusRate(), this, skill.GetWeaponDamageInflictions(level));
                    // Sum damage with additional damage amounts
                    allDamageAmounts = GameDataHelpers.CombineDamages(
                        allDamageAmounts,
                        skill.GetAdditionalDamageAmounts(level));
                    break;
                }
                allDamageAmounts = GameDataHelpers.CombineDamages(
                    allDamageAmounts,
                    CacheIncreaseDamages);
            }
        }
        private IEnumerator AttackRoutine(
            AnimActionType animActionType,
            int weaponTypeDataId,
            int animationIndex,
            float triggerDuration,
            float totalDuration,
            bool isLeftHand,
            CharacterItem weapon,
            DamageInfo damageInfo,
            Dictionary <DamageElement, MinMaxFloat> allDamageAmounts,
            bool hasAimPosition,
            Vector3 aimPosition)
        {
            if (onAttackRoutine != null)
            {
                onAttackRoutine.Invoke(animActionType, weaponTypeDataId, animationIndex, triggerDuration, totalDuration, isLeftHand, weapon, damageInfo, allDamageAmounts);
            }

            // Play animation on clients
            RequestPlayActionAnimation(animActionType, weaponTypeDataId, (byte)animationIndex);

            yield return(new WaitForSecondsRealtime(triggerDuration));

            // Reduce ammo amount
            Dictionary <DamageElement, MinMaxFloat> increaseDamages;

            ReduceAmmo(weapon, isLeftHand, out increaseDamages);
            if (increaseDamages != null)
            {
                allDamageAmounts = GameDataHelpers.CombineDamages(allDamageAmounts, increaseDamages);
            }

            // If no aim position set with attack function get aim position which set from client-controller if existed
            if (!hasAimPosition && HasAimPosition)
            {
                hasAimPosition = true;
                aimPosition    = AimPosition;
            }

            byte    fireSpread  = 0;
            Vector3 fireStagger = Vector3.zero;

            if (weapon != null && weapon.GetWeaponItem() != null)
            {
                Item weaponItem = weapon.GetWeaponItem();
                // For monsters, their weapon can be null so have to avoid null exception
                fireSpread  = weaponItem.fireSpread;
                fireStagger = weaponItem.fireStagger;
            }

            Vector3 stagger;

            for (int i = 0; i < fireSpread + 1; ++i)
            {
                stagger = new Vector3(Random.Range(-fireStagger.x, fireStagger.x), Random.Range(-fireStagger.y, fireStagger.y));
                LaunchDamageEntity(
                    isLeftHand,
                    weapon,
                    damageInfo,
                    allDamageAmounts,
                    CharacterBuff.Empty,
                    0,
                    hasAimPosition,
                    aimPosition,
                    stagger);
            }
            RequestPlayWeaponLaunchEffect(isLeftHand);
            yield return(new WaitForSecondsRealtime(totalDuration - triggerDuration));

            isAttackingOrUsingSkill = false;
        }