public bool WillInteract(HandApply interaction, NetworkSide side) { // standard validation for interaction and harm intent if (!DefaultWillInteract.Default(interaction, side)) { return(false); } ItemAttributesV2 attr = interaction.TargetObject.GetComponent <ItemAttributesV2>(); return(attr.HasTrait(LightableSurface) && interaction.Intent == Intent.Harm); }
public void RefreshParts(IDictionary <GameObject, int> partsInFrame) { // Get the machine stock parts used in this instance and get the tier of each part. // Collection is unorganized so run through the whole list. foreach (GameObject part in partsInFrame.Keys) { ItemAttributesV2 partAttributes = part.GetComponent <ItemAttributesV2>(); if (partAttributes.HasTrait(MachinePartsItemTraits.Instance.MicroLaser)) { laserTier = part.GetComponent <StockTier>().Tier; } if (partAttributes.HasTrait(MachinePartsItemTraits.Instance.MatterBin)) { int binTier = part.GetComponent <StockTier>().Tier; // Decide ItemStorageStructure based on tier. Currently: slot size == twice the bin tier. storage.AcceptNewStructure(TierStorage[binTier - 1]); } } }
public void RefreshParts(IDictionary <GameObject, int> partsInFrame) { // Get the machine stock parts used in this instance and get the tier of each part. // Collection is unorganized so run through the whole list. foreach (GameObject part in partsInFrame.Keys) { ItemAttributesV2 partAttributes = part.GetComponent <ItemAttributesV2>(); if (partAttributes.HasTrait(MachinePartsItemTraits.Instance.MicroLaser)) { laserTier = part.GetComponent <StockTier>().Tier; } } }
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()); }