Ejemplo n.º 1
0
    public void ServerPerformMeleeAttack(GameObject victim, Vector2 attackDirection,
                                         BodyPartType damageZone, LayerType layerType)
    {
        if (Cooldowns.IsOnServer(playerScript, CommonCooldowns.Instance.Melee))
        {
            return;
        }
        var weapon = playerScript.playerNetworkActions.GetActiveHandItem();

        var tiles = victim.GetComponent <InteractableTiles>();

        if (tiles)
        {
            //validate based on position of target vector
            if (!Validations.CanApply(playerScript, victim, NetworkSide.Server, targetVector: attackDirection))
            {
                return;
            }
        }
        else
        {
            //validate based on position of target object
            if (!Validations.CanApply(playerScript, victim, NetworkSide.Server))
            {
                return;
            }
        }

        if (!playerMove.allowInput ||
            playerScript.IsGhost ||
            !victim ||
            !playerScript.playerHealth.serverPlayerConscious
            )
        {
            return;
        }

        var isWeapon = weapon != null;
        ItemAttributesV2 weaponAttr = isWeapon ? weapon.GetComponent <ItemAttributesV2>() : null;
        var       damage            = isWeapon ? weaponAttr.ServerHitDamage : fistDamage;
        var       damageType        = isWeapon ? weaponAttr.ServerDamageType : DamageType.Brute;
        var       attackSoundName   = isWeapon ? weaponAttr.ServerHitSound : "Punch#";
        LayerTile attackedTile      = null;
        bool      didHit            = false;

        ItemAttributesV2 weaponStats = null;

        if (isWeapon)
        {
            weaponStats = weapon.GetComponent <ItemAttributesV2>();
        }


        // If Tilemap LayerType is not None then it is a tilemap being attacked
        if (layerType != LayerType.None)
        {
            var tileChangeManager = victim.GetComponent <TileChangeManager>();
            if (tileChangeManager == null)
            {
                return;                                        //Make sure its on a matrix that is destructable
            }
            //Tilemap stuff:
            var tileMapDamage = victim.GetComponentInChildren <MetaTileMap>().Layers[layerType].gameObject
                                .GetComponent <TilemapDamage>();
            if (tileMapDamage != null)
            {
                if (isWeapon && weaponStats != null &&
                    weaponStats.hitSoundSettings == SoundItemSettings.OnlyObject)
                {
                    attackSoundName = "";
                }
                var worldPos = (Vector2)transform.position + attackDirection;
                attackedTile = tileChangeManager.InteractableTiles.LayerTileAt(worldPos, true);
                tileMapDamage.DoMeleeDamage(worldPos,
                                            gameObject, (int)damage);
                didHit = true;
            }
        }
        else
        {
            //a regular object being attacked

            LivingHealthBehaviour victimHealth = victim.GetComponent <LivingHealthBehaviour>();

            var integrity = victim.GetComponent <Integrity>();
            if (integrity != null)
            {
                //damaging an object
                if (isWeapon && weaponStats != null &&
                    weaponStats.hitSoundSettings == SoundItemSettings.Both)
                {
                    SoundManager.PlayNetworkedAtPos(integrity.soundOnHit, gameObject.WorldPosServer(), Random.Range(0.9f, 1.1f));
                }
                else if (isWeapon && weaponStats != null &&
                         weaponStats.hitSoundSettings == SoundItemSettings.OnlyObject && integrity.soundOnHit != "")
                {
                    SoundManager.PlayNetworkedAtPos(integrity.soundOnHit, gameObject.WorldPosServer(), Random.Range(0.9f, 1.1f));
                    attackSoundName = "";
                }
                integrity.ApplyDamage((int)damage, AttackType.Melee, damageType);
                didHit = true;
            }
            else
            {
                //damaging a living thing
                var rng = new System.Random();
                // This is based off the alien/humanoid/attack_hand punch code of TGStation's codebase.
                // Punches have 90% chance to hit, otherwise it is a miss.
                if (isWeapon || 90 >= rng.Next(1, 100))
                {
                    // The attack hit.
                    victimHealth.ApplyDamageToBodypart(gameObject, (int)damage, AttackType.Melee, damageType, damageZone);
                    didHit = true;
                }
                else
                {
                    // The punch missed.
                    string victimName = victim.Player()?.Name;
                    SoundManager.PlayNetworkedAtPos("PunchMiss", transform.position);
                    Chat.AddCombatMsgToChat(gameObject, $"You attempted to punch {victimName} but missed!",
                                            $"{gameObject.Player()?.Name} has attempted to punch {victimName}!");
                }
            }
        }

        //common logic to do if we hit something
        if (didHit)
        {
            if (!string.IsNullOrEmpty(attackSoundName))
            {
                SoundManager.PlayNetworkedAtPos(attackSoundName, transform.position);
            }

            if (damage > 0)
            {
                Chat.AddAttackMsgToChat(gameObject, victim, damageZone, weapon, attackedTile: attackedTile);
            }
            if (victim != gameObject)
            {
                RpcMeleeAttackLerp(attackDirection, weapon);
                //playerMove.allowInput = false;
            }
        }

        Cooldowns.TryStartServer(playerScript, CommonCooldowns.Instance.Melee);
    }
Ejemplo n.º 2
0
    public void ServerPerformMeleeAttack(GameObject victim, Vector2 attackDirection, BodyPartType damageZone, LayerType layerType)
    {
        if (victim == null)
        {
            return;
        }
        if (Cooldowns.IsOnServer(playerScript, CommonCooldowns.Instance.Melee))
        {
            return;
        }
        if (playerMove.allowInput == false)
        {
            return;
        }
        if (playerScript.IsGhost)
        {
            return;
        }
        if (playerScript.playerHealth.serverPlayerConscious == false)
        {
            return;
        }

        if (victim.TryGetComponent <InteractableTiles>(out var tiles))
        {
            // validate based on position of target vector
            if (Validations.CanApply(playerScript, victim, NetworkSide.Server, targetVector: attackDirection) == false)
            {
                return;
            }
        }
        else
        {
            // validate based on position of target object
            if (Validations.CanApply(playerScript, victim, NetworkSide.Server) == false)
            {
                return;
            }
        }

        float                  damage           = fistDamage;
        DamageType             damageType       = DamageType.Brute;
        AddressableAudioSource weaponSound      = meleeSounds.PickRandom();
        GameObject             weapon           = playerScript.playerNetworkActions.GetActiveHandItem();
        ItemAttributesV2       weaponAttributes = weapon == null ? null : weapon.GetComponent <ItemAttributesV2>();

        if (weaponAttributes != null)
        {
            damage       = weaponAttributes.ServerHitDamage;
            damageType   = weaponAttributes.ServerDamageType;
            weaponSound  = weaponAttributes.hitSoundSettings == SoundItemSettings.OnlyObject ? null : weaponAttributes.ServerHitSound;
            slashChance  = weaponAttributes.SlashChance;
            slashDamage  = weaponAttributes.SlashDamage;
            pierceChance = weaponAttributes.PierceChance;
            pierceDamage = weaponAttributes.PierceDamage;
            burnDamage   = weaponAttributes.BurnDamage;
        }

        LayerTile attackedTile = null;
        bool      didHit       = false;

        // If Tilemap LayerType is not None then it is a tilemap being attacked
        if (layerType != LayerType.None)
        {
            var tileChangeManager = victim.GetComponent <TileChangeManager>();
            if (tileChangeManager == null)
            {
                return;                                        // Make sure its on a matrix that is destructable
            }
            // Tilemap stuff:
            var tileMapDamage = victim.GetComponentInChildren <MetaTileMap>().Layers[layerType].gameObject.GetComponent <TilemapDamage>();
            if (tileMapDamage == null)
            {
                return;
            }

            var worldPos = (Vector2)transform.position + attackDirection;
            attackedTile = tileChangeManager.InteractableTiles.LayerTileAt(worldPos, true);

            // Tile itself is responsible for playing victim damage sound
            tileMapDamage.ApplyDamage(damage, AttackType.Melee, worldPos);
            didHit = true;
        }
        // Damaging an object
        else if (victim.TryGetComponent <Integrity>(out var integrity) &&
                 victim.TryGetComponent <Meleeable>(out var meleeable) && meleeable.IsMeleeable)
        {
            if (weaponAttributes != null && weaponAttributes.hitSoundSettings != SoundItemSettings.OnlyItem)
            {
                AudioSourceParameters audioSourceParameters = new AudioSourceParameters(pitch: Random.Range(0.9f, 1.1f));
                SoundManager.PlayNetworkedAtPos(integrity.soundOnHit, gameObject.WorldPosServer(), audioSourceParameters, sourceObj: gameObject);
            }

            integrity.ApplyDamage(damage, AttackType.Melee, damageType);
            didHit = true;
        }