public void CmdKnifeHarvestMob(GameObject npcObj, Vector2 stabDirection) { if (!playerMove.allowInput || playerMove.isGhost) { return; } SimpleAnimal attackTarget = npcObj.GetComponent <SimpleAnimal>(); RpcKnifeAttackLerp(stabDirection); attackTarget.Harvest(); soundNetworkActions.RpcPlayNetworkSound("BladeSlice", transform.position); }
[Command] //TODO fixme ghetto proof-of-concept public void CmdKnifeAttackMob(GameObject npcObj, GameObject weapon, Vector2 stabDirection, BodyPartType damageZone) { HealthBehaviour healthBehaviour = npcObj.GetComponent <HealthBehaviour>(); if (healthBehaviour.IsDead == false) { if (!playerMove.allowInput || !allowAttack || playerMove.isGhost) { return; } if (npcObj != gameObject) { RpcMeleAttackLerp(stabDirection, weapon); } healthBehaviour .ApplyDamage(gameObject.name, 20, DamageType.BRUTE, damageZone); //this crap will remain here until moved to netmessages healthBehaviour.RpcApplyDamage(gameObject.name, 20, DamageType.BRUTE, damageZone); soundNetworkActions.RpcPlayNetworkSound("BladeSlice", transform.position); StartCoroutine(AttackCoolDown()); } else { if (!playerMove.allowInput || playerMove.isGhost) { return; } if (npcObj.GetComponent <SimpleAnimal>()) { SimpleAnimal attackTarget = npcObj.GetComponent <SimpleAnimal>(); RpcMeleAttackLerp(stabDirection, weapon); attackTarget.Harvest(); soundNetworkActions.RpcPlayNetworkSound("BladeSlice", transform.position); } else { PlayerHealth attackTarget = npcObj.GetComponent <PlayerHealth>(); RpcMeleAttackLerp(stabDirection, weapon); attackTarget.Harvest(); soundNetworkActions.RpcPlayNetworkSound("BladeSlice", transform.position); } } }
public void CmdRequestMeleeAttack(GameObject victim, Vector2 attackDirection, BodyPartType damageZone, LayerType layerType) { 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; } if (!allowAttack) { 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; // 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) { var worldPos = (Vector2)transform.position + attackDirection; attackedTile = tileChangeManager.InteractableTiles.LayerTileAt(worldPos); tileMapDamage.DoMeleeDamage(worldPos, gameObject, (int)damage); didHit = true; } } else { //a regular object being attacked //butchering //TODO: Move butchering logic to IF2, it should be a progress action done on corpses (make a Corpse component probably) LivingHealthBehaviour victimHealth = victim.GetComponent <LivingHealthBehaviour>(); if (victimHealth != null && victimHealth.IsDead && isWeapon && weaponAttr.HasTrait(KnifeTrait)) { if (victim.GetComponent <SimpleAnimal>()) { SimpleAnimal attackTarget = victim.GetComponent <SimpleAnimal>(); RpcMeleeAttackLerp(attackDirection, weapon); playerMove.allowInput = false; attackTarget.Harvest(); SoundManager.PlayNetworkedAtPos("BladeSlice", transform.position); } else { PlayerHealth attackTarget = victim.GetComponent <PlayerHealth>(); RpcMeleeAttackLerp(attackDirection, weapon); playerMove.allowInput = false; attackTarget.Harvest(); SoundManager.PlayNetworkedAtPos("BladeSlice", transform.position); } } var integrity = victim.GetComponent <Integrity>(); if (integrity != null) { //damaging an object 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) { 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; } } //no matter what, start a cooldown for attacking again so they can't spam attack requests StartCoroutine(AttackCoolDown()); }
public void CmdRequestMeleeAttack(GameObject victim, string slot, Vector2 stabDirection, BodyPartType damageZone) { if (!playerMove.allowInput || playerMove.isGhost || !victim || !playerScript.playerNetworkActions.SlotNotEmpty(slot) || !PlayerManager.PlayerInReach(victim.transform) ) { return; } var weapon = playerScript.playerNetworkActions.Inventory[slot]; ItemAttributes weaponAttr = weapon.GetComponent <ItemAttributes>(); HealthBehaviour victimHealth = victim.GetComponent <HealthBehaviour>(); // checks object and component existence before defining healthBehaviour variable. if (victimHealth.IsDead == false) { if (!allowAttack) { return; } if (victim != gameObject) { RpcMeleeAttackLerp(stabDirection, weapon); } victimHealth.ApplyDamage(gameObject, ( int )weaponAttr.hitDamage, DamageType.BRUTE, damageZone); if (weaponAttr.hitDamage > 0) { PostToChatMessage.SendItemAttackMessage(weapon, gameObject, victim, (int)weaponAttr.hitDamage, damageZone); } soundNetworkActions.RpcPlayNetworkSound(weaponAttr.hitSound, transform.position); StartCoroutine(AttackCoolDown()); } else { //Butchering if we can if (weaponAttr.type != ItemType.Knife) { return; } if (victim.GetComponent <SimpleAnimal>()) { SimpleAnimal attackTarget = victim.GetComponent <SimpleAnimal>(); RpcMeleeAttackLerp(stabDirection, weapon); attackTarget.Harvest(); soundNetworkActions.RpcPlayNetworkSound("BladeSlice", transform.position); } else { PlayerHealth attackTarget = victim.GetComponent <PlayerHealth>(); RpcMeleeAttackLerp(stabDirection, weapon); attackTarget.Harvest(); soundNetworkActions.RpcPlayNetworkSound("BladeSlice", transform.position); } } }
public void CmdRequestMeleeAttack(GameObject victim, GameObject weapon, Vector2 stabDirection, BodyPartType damageZone, LayerType layerType) { if (!playerMove.allowInput || playerScript.IsGhost || !victim || !playerScript.playerHealth.serverPlayerConscious ) { return; } if (!allowAttack) { return; } ItemAttributes weaponAttr = weapon.GetComponent <ItemAttributes>(); // 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) { //Wire cutters should snip the grills instead: if (weaponAttr.itemName == "wirecutters" && tileMapDamage.Layer.LayerType == LayerType.Grills) { tileMapDamage.WireCutGrill((Vector2)transform.position + stabDirection); StartCoroutine(AttackCoolDown()); return; } tileMapDamage.DoMeleeDamage((Vector2)transform.position + stabDirection, gameObject, (int)weaponAttr.hitDamage); playerMove.allowInput = false; RpcMeleeAttackLerp(stabDirection, weapon); StartCoroutine(AttackCoolDown()); return; } return; } //This check cannot be used with TilemapDamage as the transform position is always far away if (!playerScript.IsInReach(victim, true)) { return; } // Consider moving this into a MeleeItemTrigger for knifes //Meaty bodies: LivingHealthBehaviour victimHealth = victim.GetComponent <LivingHealthBehaviour>(); if (victimHealth != null && victimHealth.IsDead && weaponAttr.itemType == ItemType.Knife) { if (victim.GetComponent <SimpleAnimal>()) { SimpleAnimal attackTarget = victim.GetComponent <SimpleAnimal>(); RpcMeleeAttackLerp(stabDirection, weapon); playerMove.allowInput = false; attackTarget.Harvest(); SoundManager.PlayNetworkedAtPos("BladeSlice", transform.position); } else { PlayerHealth attackTarget = victim.GetComponent <PlayerHealth>(); RpcMeleeAttackLerp(stabDirection, weapon); playerMove.allowInput = false; attackTarget.Harvest(); SoundManager.PlayNetworkedAtPos("BladeSlice", transform.position); } } if (victim != gameObject) { RpcMeleeAttackLerp(stabDirection, weapon); playerMove.allowInput = false; } var integrity = victim.GetComponent <Integrity>(); if (integrity != null) { //damaging an object integrity.ApplyDamage((int)weaponAttr.hitDamage, AttackType.Melee, weaponAttr.damageType); } else { //damaging a living thing victimHealth.ApplyDamage(gameObject, (int)weaponAttr.hitDamage, AttackType.Melee, weaponAttr.damageType, damageZone); } SoundManager.PlayNetworkedAtPos(weaponAttr.hitSound, transform.position); if (weaponAttr.hitDamage > 0) { Chat.AddAttackMsgToChat(gameObject, victim, damageZone, weapon); } StartCoroutine(AttackCoolDown()); }
public void CmdRequestMeleeAttack(GameObject victim, string slot, Vector2 stabDirection, BodyPartType damageZone, LayerType layerType) { if (!playerMove.allowInput || playerMove.isGhost || !victim || !playerScript.playerNetworkActions.SlotNotEmpty(slot) || !playerScript.playerHealth.serverPlayerConscious ) { return; } if (!allowAttack) { return; } var weapon = playerScript.playerNetworkActions.Inventory[slot].Item; ItemAttributes weaponAttr = weapon.GetComponent <ItemAttributes>(); // If Tilemap LayerType is not None then it is a tilemap being attacked if (layerType != LayerType.None) { TileChangeManager tileChangeManager = victim.GetComponent <TileChangeManager>(); MetaTileMap metaTileMap = victim.GetComponentInChildren <MetaTileMap>(); if (tileChangeManager == null) { return; } //Tilemap stuff: var tileMapDamage = metaTileMap.Layers[layerType].GetComponent <TilemapDamage>(); if (tileMapDamage != null) { //Wire cutters should snip the grills instead: if (weaponAttr.itemName == "wirecutters" && tileMapDamage.Layer.LayerType == LayerType.Grills) { tileMapDamage.WireCutGrill((Vector2)transform.position + stabDirection); StartCoroutine(AttackCoolDown()); return; } tileMapDamage.DoMeleeDamage((Vector2)transform.position + stabDirection, gameObject, (int)weaponAttr.hitDamage); playerMove.allowInput = false; RpcMeleeAttackLerp(stabDirection, weapon); StartCoroutine(AttackCoolDown()); return; } return; } //This check cannot be used with TilemapDamage as the transform position is always far away if (!playerScript.IsInReach(victim)) { return; } //Meaty bodies: LivingHealthBehaviour victimHealth = victim.GetComponent <LivingHealthBehaviour>(); if (victimHealth.IsDead && weaponAttr.type == ItemType.Knife) { if (victim.GetComponent <SimpleAnimal>()) { SimpleAnimal attackTarget = victim.GetComponent <SimpleAnimal>(); RpcMeleeAttackLerp(stabDirection, weapon); playerMove.allowInput = false; attackTarget.Harvest(); SoundManager.PlayNetworkedAtPos("BladeSlice", transform.position); } else { PlayerHealth attackTarget = victim.GetComponent <PlayerHealth>(); RpcMeleeAttackLerp(stabDirection, weapon); playerMove.allowInput = false; attackTarget.Harvest(); SoundManager.PlayNetworkedAtPos("BladeSlice", transform.position); } return; } if (victim != gameObject) { RpcMeleeAttackLerp(stabDirection, weapon); playerMove.allowInput = false; } victimHealth.ApplyDamage(gameObject, (int)weaponAttr.hitDamage, DamageType.Brute, damageZone); if (weaponAttr.hitDamage > 0) { PostToChatMessage.SendItemAttackMessage(weapon, gameObject, victim, (int)weaponAttr.hitDamage, damageZone); } SoundManager.PlayNetworkedAtPos(weaponAttr.hitSound, transform.position); StartCoroutine(AttackCoolDown()); }