private IEnumerator CritHonk(PositionalHandApply clickData, LivingHealthMasterBase livingHealth) { yield return(WaitFor.Seconds(0.02f)); AudioSourceParameters audioSourceParameters = new AudioSourceParameters(pitch: -1f); //This plays it backwards, is that what you wanted? ShakeParameters shakeParameters = new ShakeParameters(true, 20, 5); SoundManager.PlayNetworkedAtPos(CommonSounds.Instance.ClownHonk, gameObject.AssumedWorldPosServer(), audioSourceParameters, true, sourceObj: GetHonkSoundObject(), shakeParameters: shakeParameters); livingHealth.ApplyDamageToBodyPart(clickData.Performer, CritDamage, AttackType.Energy, DamageType.Brute, BodyPartType.Head); }
//We need to slow the attack down because clients are behind server private async Task AttackFleshRoutine(Vector2 dir, LivingHealthBehaviour targetHealth, LivingHealthMasterBase livingHealth, Vector3 worldPos, NetworkConnection ctc, float rtt) { if (targetHealth == null && livingHealth == null) { return; } if (ctc == null) { return; } ServerDoLerpAnimation(dir); if (PlayerManager.LocalPlayerScript != null && PlayerManager.LocalPlayerScript.playerHealth != null && PlayerManager.LocalPlayerScript.playerHealth == livingHealth || rtt < 0.02f) { //Wait until the end of the frame await Task.Delay(1); } else { //Wait until RTT/2 seconds? Logger.Log($"WAIT FOR ATTACK: {rtt / 2f}", Category.Mobs); await Task.Delay((int)(rtt * 500)); } if (Vector3.Distance(mobTile.WorldPositionServer, worldPos) < 1.5f) { var bodyPartTarget = defaultTarget.Randomize(); if (targetHealth != null) { targetHealth.ApplyDamageToBodyPart(gameObject, hitDamage, AttackType.Melee, DamageType.Brute, bodyPartTarget); Chat.AddAttackMsgToChat(gameObject, targetHealth.gameObject, bodyPartTarget, null, attackVerb); } else { livingHealth.ApplyDamageToBodyPart(gameObject, hitDamage, AttackType.Melee, DamageType.Brute, bodyPartTarget); Chat.AddAttackMsgToChat(gameObject, livingHealth.gameObject, bodyPartTarget, null, attackVerb); } SoundManager.PlayNetworkedAtPos(attackSound, mobTile.WorldPositionServer, sourceObj: gameObject); } }
protected void ApplyDamageToPartyType(LivingHealthMasterBase health, BodyPartType type) { health.ApplyDamageToBodyPart(gameObject, damageToGive, attackType, damageType, type, armorPentration, traumaChance, traumaType); }
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 attackSound = isWeapon ? weaponAttr.ServerHitSound : null; 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) { attackSound = null; } var worldPos = (Vector2)transform.position + attackDirection; attackedTile = tileChangeManager.InteractableTiles.LayerTileAt(worldPos, true); tileMapDamage.ApplyDamage((int)damage, AttackType.Melee, worldPos); didHit = true; } } else { //a regular object being attacked LivingHealthMasterBase victimHealth = victim.GetComponent <LivingHealthMasterBase>(); var integrity = victim.GetComponent <Integrity>(); var meleeable = victim.GetComponent <Meleeable>(); if (integrity != null) { if (meleeable.GetMeleeable()) { //damaging an object if (isWeapon && weaponStats != null && weaponStats.hitSoundSettings == SoundItemSettings.Both) { AudioSourceParameters audioSourceParameters = new AudioSourceParameters(pitch: Random.Range(0.9f, 1.1f)); SoundManager.PlayNetworkedAtPos(integrity.soundOnHit, gameObject.WorldPosServer(), audioSourceParameters, sourceObj: gameObject); } else if (isWeapon && weaponStats != null && weaponStats.hitSoundSettings == SoundItemSettings.OnlyObject && integrity.soundOnHit == null) { AudioSourceParameters audioSourceParameters = new AudioSourceParameters(pitch: Random.Range(0.9f, 1.1f)); SoundManager.PlayNetworkedAtPos(integrity.soundOnHit, gameObject.WorldPosServer(), audioSourceParameters, sourceObj: gameObject); attackSound = null; } 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)) { if (victimHealth == null || gameObject == null) { return; } // 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(SingletonSOSounds.Instance.PunchMiss, transform.position, sourceObj: gameObject); 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 (attackSound != null) { SoundManager.PlayNetworkedAtPos(attackSound, transform.position, sourceObj: gameObject); } 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); }