public void SetBodyPart(BodyPartType bodyPartType, Element element) { switch (bodyPartType) { case BodyPartType.Head: Head.gameObject.GetComponent<SpriteRenderer> ().sprite = BodyPartCollections [(int)element].Head; break; case BodyPartType.Body: Body.gameObject.GetComponent<SpriteRenderer> ().sprite = BodyPartCollections [(int)element].Body; LeftWing.gameObject.SetActive(BodyPartCollections[(int)element].UseSecondaryWings == false); RightWing.gameObject.SetActive(BodyPartCollections[(int)element].UseSecondaryWings == false); SecondLeftWing.gameObject.SetActive(BodyPartCollections[(int)element].UseSecondaryWings); SecondRightWing.gameObject.SetActive(BodyPartCollections[(int)element].UseSecondaryWings); break; case BodyPartType.Wings: SecondLeftWing.gameObject.GetComponent<SpriteRenderer> ().sprite = BodyPartCollections [(int)element].LeftWing; SecondRightWing.gameObject.GetComponent<SpriteRenderer> ().sprite = BodyPartCollections [(int)element].RightWing; LeftWing.gameObject.GetComponent<SpriteRenderer> ().sprite = BodyPartCollections [(int)element].LeftWing; RightWing.gameObject.GetComponent<SpriteRenderer> ().sprite = BodyPartCollections [(int)element].RightWing; break; } }
public override void Shoot(Vector2 direction, GameObject controlledByPlayer, Gun fromWeapon, BodyPartType targetZone = BodyPartType.Chest) { WillHurtShooter = false; StartShoot(direction, controlledByPlayer, fromWeapon, targetZone); }
public BodyPartSlot(string id, BodyPartType partType, IEnumerable <BodyPartSlot> connections) { Id = id; PartType = partType; Connections = new HashSet <BodyPartSlot>(connections); }
public BodyPart[] GetAllParts(BodyPartType type) { return(allParts[(int)type].parts); }
public abstract void Suicide(GameObject controlledByPlayer, Gun fromWeapon, BodyPartType targetZone = BodyPartType.Chest);
/// <summary> /// Sends a message to all players about an attack that took place /// </summary> /// <param name="attacker">GameObject of the player that attacked</param> /// <param name="victim">GameObject of the player hat was the victim</param> /// <param name="damage">damage done</param> /// <param name="hitZone">zone that was damaged</param> /// <param name="item">optional gameobject with an itemattributes, representing the item the attack was made with</param> /// <param name="customAttackVerb">If you want to override the attack verb then pass the verb here</param> /// <param name="attackedTile">If attacking a particular tile, the layer tile being attacked</param> public static void AddAttackMsgToChat(GameObject attacker, GameObject victim, BodyPartType hitZone = BodyPartType.None, GameObject item = null, string customAttackVerb = "", LayerTile attackedTile = null) { string attackVerb; string attack; if (item) { var itemAttributes = item.GetComponent <ItemAttributesV2>(); attackVerb = itemAttributes.ServerAttackVerbs.PickRandom() ?? "attacked"; attack = $" with {itemAttributes.ArticleName}"; } else { // Punch attack as there is no item. attackVerb = "punched"; attack = ""; } if (!string.IsNullOrEmpty(customAttackVerb)) { attackVerb = customAttackVerb; } var player = victim.Player(); if (player == null) { hitZone = BodyPartType.None; } string victimName; string victimNameOthers = ""; if (attacker == victim) { victimName = "yourself"; if (player != null) { if (player.Script.characterSettings.Gender == Gender.Female) { victimNameOthers = "herself"; } if (player.Script.characterSettings.Gender == Gender.Male) { victimNameOthers = "himself"; } if (player.Script.characterSettings.Gender == Gender.Neuter) { victimNameOthers = "itself"; } } else { victimNameOthers = "itself"; } } else if (attackedTile != null) { victimName = attackedTile.DisplayName; victimNameOthers = victimName; } else { victimName = victim.ExpensiveName(); victimNameOthers = victimName; } var attackerName = attacker.Player()?.Name; if (string.IsNullOrEmpty(attackerName)) { var mobAi = attacker.GetComponent <MobAI>(); if (mobAi != null) { attackerName = mobAi.mobName; } else { attackerName = "Unknown"; } } var messageOthers = $"{attackerName} has {attackVerb} {victimNameOthers}{InTheZone(hitZone)}{attack}!"; var message = $"You {attackVerb} {victimName}{InTheZone(hitZone)}{attack}!"; Instance.addChatLogServer.Invoke(new ChatEvent { channels = ChatChannel.Combat, message = message, messageOthers = messageOthers, position = attacker.WorldPosServer(), speaker = attacker.name, originator = attacker }); }
private Bounds LoadObject(BodyPartType bodyPart, int id) { Bounds objectBounds = new Bounds(skeleton.transform.position, Vector3.zero); ZSC zsc = rm.getZSC(charModel.gender, bodyPart); for (int i = 0; i < zsc.Objects[id].Models.Count; i++) { int ModelID = zsc.Objects[id].Models[i].ModelID; int TextureID = zsc.Objects[id].Models[i].TextureID; Bounds partBounds = LoadPart(bodyPart, zsc.Objects[id].Models[i].DummyIndex, zsc.Models[ModelID], zsc.Textures[TextureID].Path); objectBounds.Encapsulate(partBounds); } return objectBounds; }
/// <summary> /// Sends a message to all players about an attack that took place /// </summary> /// <param name="item">gameobject with an itemattributes, representing the item the attack was made with</param> /// <param name="attacker">GameObject of the player that attacked</param> /// <param name="victim">GameObject of the player hat was the victim</param> /// <param name="damage">damage done</param> /// <param name="hitZone">zone that was damaged</param> public static void SendItemAttackMessage(GameObject item, GameObject attacker, GameObject victim, float damage, BodyPartType hitZone = BodyPartType.None) { var itemAttributes = item.GetComponent <ItemAttributes>(); var player = victim.Player(); if (player == null) { hitZone = BodyPartType.None; } string victimName; if (attacker == victim) { victimName = "self"; } else { victimName = victim.ExpensiveName(); } var attackVerb = itemAttributes.attackVerb.GetRandom() ?? "attacked"; var message = $"{attacker.Player()?.Name} has {attackVerb} {victimName}{InTheZone( hitZone )} with {itemAttributes.itemName}!"; // var message = $"{victim.Name} has been {attackVerb}{zone} with {itemAttributes.itemName}!"; ChatRelay.Instance.AddToChatLogServer(new ChatEvent { channels = ChatChannel.Combat, message = message, position = victim.transform.position, radius = 9f, sizeMod = Mathf.Clamp(damage / 15, 1, 3) }); }
public BodyPart(BodyPartType type) { Type = type; MaxStacks = 1; }
/// <summary> /// Get the ZSC object associated with the given gender and bodyPart /// </summary> /// <param name="gender"></param> /// <param name="bodyPart"></param> /// <returns></returns> public ZSC getZSC( GenderType gender, BodyPartType bodyPart) { bool male = gender == GenderType.MALE; switch(bodyPart) { case BodyPartType.BODY: return male ? zsc_body_male : zsc_body_female; case BodyPartType.ARMS: return male ? zsc_arms_male : zsc_arms_female; case BodyPartType.FOOT: return male ? zsc_foot_male : zsc_foot_female; case BodyPartType.FACE: return male ? zsc_face_male : zsc_face_female; case BodyPartType.HAIR: return male ? zsc_hair_male : zsc_hair_female; case BodyPartType.CAP: return male ? zsc_cap_male : zsc_cap_female; case BodyPartType.BACK: return zsc_back; case BodyPartType.FACEITEM: return zsc_faceItem; case BodyPartType.WEAPON: return zsc_weapon; case BodyPartType.SUBWEAPON: return zsc_subweapon; default: return null; } }
/* void Spawn() { m_PuppetParts = new BodyPart[m_BodyParts.Length]; for (int i = 0; i < m_BodyParts.Length; i++) { if (m_BodyParts[i].m_Parts == null || m_BodyParts[i].m_Parts.Length == 0 ) continue; BodyPart part = Instantiate(m_BodyParts[i].m_Parts[0]) as BodyPart; m_PuppetParts[i] = part; } } */ BodyPart[] GetBodyParts( BodyPartType type ) { for (int i = 0; i < m_BodyParts.Length; i++) { if (m_BodyParts[i].m_Type == type) return m_BodyParts[i].m_Parts; } return null; }
public void changeID(BodyPartType bodyPart, int id) { switch (bodyPart) { case BodyPartType.ARMS: equip.handID = id; break; case BodyPartType.BACK: equip.backID = id; break; case BodyPartType.BODY: equip.chestID = id; break; case BodyPartType.CAP: equip.capID = id; break; case BodyPartType.FACE: equip.faceID = id; break; case BodyPartType.FACEITEM: equip.maskID = id; break; case BodyPartType.FOOT: equip.footID = id; break; case BodyPartType.HAIR: equip.hairID = id; break; case BodyPartType.SUBWEAPON: equip.shieldID = id; break; case BodyPartType.WEAPON: equip.weaponID = id; break; default: break; } }
public void OnChangeEquip(BodyPartType bodyPart, int id) { rosePlayer.equip (bodyPart, id); }
public void equip(BodyPartType bodyPart, int id, bool changeId = true) { if (bodyPart == BodyPartType.WEAPON) { WeaponType weapType = rm.getWeaponType (id); charModel.equip.weaponID = id; // if this weapon is two-handed and a subweapon is equipped, unequip the subweapon first if ( !Utils.isOneHanded(weapType) && charModel.equip.shieldID > 0) equip(BodyPartType.SUBWEAPON, 0); // Change skeleton if weapon type is different if (weapType != charModel.weapon) { charModel.weapon = weapType; LoadPlayerSkeleton ( charModel ); return; } } // If equipping subweapon and a two-hand weapon is equipped, first unequip the 2-hand if (( bodyPart == BodyPartType.SUBWEAPON) && id > 0 && !Utils.isOneHanded(charModel.weapon)) equip(BodyPartType.WEAPON, 0); // If equipping cap, first make sure the hair is changed to the right type if(bodyPart == BodyPartType.CAP) { String hairOffsetStr = rm.stb_cap_list.Cells[id][34]; int hairOffset = (hairOffsetStr == "") ? 0 : int.Parse(hairOffsetStr); equip(BodyPartType.HAIR, charModel.equip.hairID - (charModel.equip.hairID)%5 + hairOffset, false); } if( changeId) charModel.changeID(bodyPart, id); List<Transform> partTransforms = Utils.findChildren (player, bodyPart.ToString()); foreach (Transform partTransform in partTransforms) Utils.Destroy(partTransform.gameObject); LoadObject(bodyPart, id); }
private Bounds LoadPart(BodyPartType bodyPart, ZSC.DummyType dummy, string zmsPath, string texPath) { zmsPath = Utils.FixPath(zmsPath); texPath = Utils.FixPath (texPath).Replace ("dds", "png"); // Cached load of ZMS and texture ResourceManager rm = ResourceManager.Instance; ZMS zms = (ZMS)rm.cachedLoad(zmsPath); Texture2D tex = (Texture2D)rm.cachedLoad(texPath); // Create material string shader = "VertexLit"; if (bodyPart == BodyPartType.BACK) shader = "Transparent/Cutout/VertexLit"; Material mat = new Material(Shader.Find(shader)); mat.SetTexture("_MainTex", tex); mat.SetColor("_Emission", new Color(0.15f, 0.15f, 0.15f)); GameObject modelObject = new GameObject(); switch ( bodyPart ) { case BodyPartType.FACE: case BodyPartType.HAIR: modelObject.transform.parent = Utils.findChild(skeleton, "b1_head"); break; case BodyPartType.CAP: // TODO: figure out how to fix issue of hair coming out of cap modelObject.transform.parent = Utils.findChild(skeleton, "p_06"); break; case BodyPartType.BACK: modelObject.transform.parent = Utils.findChild(skeleton, "p_03"); break; case BodyPartType.WEAPON: if(charModel.weapon == WeaponType.DSW || charModel.weapon == WeaponType.KATAR ) modelObject.transform.parent = Utils.findChild(skeleton, dummy == ZSC.DummyType.RightHand? "p_00" : "p_01"); else modelObject.transform.parent = Utils.findChild(skeleton, "p_00"); break; case BodyPartType.SUBWEAPON: modelObject.transform.parent = Utils.findChild(skeleton, "p_02"); break; default: modelObject.transform.parent = skeleton.transform.parent.transform; break; } modelObject.transform.localPosition = Vector3.zero; modelObject.transform.localRotation = Quaternion.identity; modelObject.transform.localScale = Vector3.one; modelObject.name = bodyPart.ToString (); Mesh mesh = zms.getMesh(); if (zms.support.bones) { SkinnedMeshRenderer renderer = modelObject.AddComponent<SkinnedMeshRenderer>(); mesh.bindposes = bindPoses.bindPoses; renderer.sharedMesh = mesh; renderer.material = mat; renderer.bones = bindPoses.boneTransforms; } else { modelObject.AddComponent<MeshFilter>().mesh = mesh; MeshRenderer renderer = modelObject.AddComponent<MeshRenderer>(); renderer.material = mat; } return mesh.bounds; }
public void CmdShootBullet(GameObject weapon, GameObject magazine, Vector2 direction, string bulletName, BodyPartType damageZone) { if (!playerMove.allowInput || playerMove.isGhost) { return; } //get componants Weapon wepBehavior = weapon.GetComponent <Weapon>(); MagazineBehaviour magBehaviour = magazine.GetComponent <MagazineBehaviour>(); //reduce ammo for shooting magBehaviour.ammoRemains--; //TODO: remove more bullets if burst //get the bullet prefab being shot GameObject bullet = PoolManager.PoolClientInstantiate(Resources.Load(bulletName) as GameObject, transform.position, Quaternion.identity); var angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg; //if we have recoil variance add it, and get the new attack angle if (wepBehavior != null && wepBehavior.CurrentRecoilVariance > 0) { direction = GetRecoilOffset(wepBehavior, angle); } BulletBehaviour b = bullet.GetComponent <BulletBehaviour>(); b.Shoot(direction, angle, gameObject.name, damageZone); //add additional recoil after shooting for the next round AppendRecoil(wepBehavior, angle); //This is used to determine where bullet shot should head towards on client Ray2D ray = new Ray2D(transform.position, direction); RpcShootBullet(weapon, ray.GetPoint(30f), bulletName, damageZone); //TODO add a check to see if bullet or energy weapon SpawnBulletCaseing(); if (!isFlashing) { isFlashing = true; StartCoroutine(ShowMuzzleFlash()); } }
private static string InTheZone(BodyPartType hitZone) { return(hitZone == BodyPartType.None ? "" : $" in the {hitZone.ToString().ToLower().Replace( "_", " " )}"); }
public void ChangeBodySprite(Sprite partSprite, BodyPartType bodyPart, int spriteID) { imageLookup[(int)bodyPart].sprite = partSprite; characterData.partSelection[(int)bodyPart] = spriteID; Debug.Log("Part: " + partSprite.ToString() + "Sprite ID: " + spriteID.ToString()); }
/// <summary> /// Shoot the controlledByPlayer /// </summary> /// <param name="controlledByPlayer">player doing the shooting</param> /// <param name="targetZone">body part being targeted</param> /// <param name="fromWeapon">Weapon the shot is being fired from</param> public void Suicide(GameObject controlledByPlayer, Gun fromWeapon, BodyPartType targetZone = BodyPartType.Chest) { isSuicide = true; StartShoot(Vector2.zero, controlledByPlayer, fromWeapon, targetZone); }
public void ChangePartColor(Color partColor, BodyPartType bodyPart, int colourID) { imageLookup[(int)bodyPart].color = partColor; characterData.colourSelection[(int)bodyPart] = colourID; }
private BodyPart FindBodyPart(BodyPartType bodyPartType) { return(bodyParts.FirstOrDefault(bodyParts => bodyParts.BodyPartType == bodyPartType)); }
/// <summary> /// Grabs the <see cref="BodyPartType"/> of the given slotName if there is one. Returns true if the slot is found, false otherwise. If false, result will be null. /// </summary> public bool TryGetSlotType(string slotName, out BodyPartType result) { return(_template.Slots.TryGetValue(slotName, out result)); }
public BodyManagerHealthChangeParams(BodyPartType part) { Part = part; }
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; }
public abstract void Shoot(Vector2 direction, GameObject controlledByPlayer, Gun fromWeapon, BodyPartType targetZone = BodyPartType.Chest);
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.ApplyDamage((int)damage, AttackType.Melee, worldPos); didHit = true; } } else { //a regular object being attacked LivingHealthBehaviour victimHealth = victim.GetComponent <LivingHealthBehaviour>(); 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) { SoundManager.PlayNetworkedAtPos(integrity.soundOnHit, gameObject.WorldPosServer(), Random.Range(0.9f, 1.1f), sourceObj: gameObject); } else if (isWeapon && weaponStats != null && weaponStats.hitSoundSettings == SoundItemSettings.OnlyObject && integrity.soundOnHit != "") { SoundManager.PlayNetworkedAtPos(integrity.soundOnHit, gameObject.WorldPosServer(), Random.Range(0.9f, 1.1f), sourceObj: gameObject); 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)) { 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("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 (!string.IsNullOrEmpty(attackSoundName)) { SoundManager.PlayNetworkedAtPos(attackSoundName, 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); }
public BodyPartSlot(string id, BodyPartType partType) { Id = id; PartType = partType; Connections = new HashSet <BodyPartSlot>(); }
public void OnShoot(Vector2 direction, GameObject shooter, Gun weapon, BodyPartType targetZone = BodyPartType.Chest) { this.shooter = shooter; this.targetZone = targetZone; }
protected void ApplyDamageToPartyType(LivingHealthMasterBase health, BodyPartType type) { health.ApplyDamageToBodyPart(gameObject, damageToGive, attackType, damageType, type, armorPentration, traumaChance, traumaType); }
public RuleSolution(ToolBox.Tool t, BodyPartType b) { tool = t; isBodyPartSpecific = true; bodyPart = b; }
private void StartShoot(Vector2 direction, GameObject controlledByPlayer, Gun fromWeapon, BodyPartType targetZone) { shooter = controlledByPlayer; var startPosition = new Vector3(direction.x, direction.y, thisTransform.position.z) * 0.2f; thisTransform.position += startPosition; if (overrideVelocity == false && fromWeapon != null) { projectileVelocity = fromWeapon.ProjectileVelocity; } movingProjectile.SetUpBulletTransform(direction, projectileVelocity); foreach (var behaviour in behavioursOnShoot) { behaviour.OnShoot(direction, controlledByPlayer, fromWeapon, targetZone); } }
// Eval a rule: given the current body state, the tool applied and to what body part, we apply our rules // Returns true if we did something right (even if the rule isn't resolved) and false on a mistake public static bool EvaluateCure(BodyPart[] bodyParts, ToolBox.Tool playersTool, BodyPartType playersTargetBodyPart, BodyPartColor bodyColor, ref int bodyHeartbeat, out bool fixesColor) { fixesColor = false; // Count number of each symptom we have int kSymptomCount = System.Enum.GetNames(typeof(Symptom)).Length; int[] symptomCount = new int[kSymptomCount]; // How many of each symptom do we have? for (int i = 1; i < kSymptomCount; i++) { symptomCount[i] = CountSymptom(bodyParts, (Symptom)i); } int lastGroupId = -1; bool groupDidFail = false; // For each rule, see which is applicable! foreach (Rule rule in rules) { bool ruleDoesApply = false; // What was the last rule's group and did it get applied but failed? If so, stop applying this group's rules.. if (lastGroupId != rule.GroupID) { groupDidFail = false; lastGroupId = rule.GroupID; } else if (groupDidFail) { continue; } // ExactCount: Checks if there is X number of Y symptoms on fixesBodyPartType. if (rule.ruleType == RuleType.ExactCount) { // Check count of this symptom, followed by if the symptom matches if (symptomCount [(int)rule.countSymptom] == rule.count && bodyParts [(int)rule.fixesBodyPartType].symptom == rule.countSymptom) { ruleDoesApply = true; } } // MinCount: Checks if there is 1 number of Y sumptom on fixesBodyPartType and at least X (inclusive) number overall. else if (rule.ruleType == RuleType.MinCount) { if (symptomCount [(int)rule.countSymptom] >= rule.count && bodyParts [(int)rule.fixesBodyPartType].symptom == rule.countSymptom) { ruleDoesApply = true; } } // ExactMatch: Rule is applied if the matching pattern (color, body part, symptom) i. else if (rule.ruleType == RuleType.ExactMatch) { // Does the target body part have this symptom? bool symptomMatches = (rule.exactSymptom == bodyParts [(int)rule.fixesBodyPartType].symptom); bool colorMatches = true; if (rule.exactColorIsSpecific && rule.exactColorNegate == false) { colorMatches = (rule.exactColor == bodyColor); } else if (rule.exactColorNegate) { colorMatches = (rule.exactColor != bodyColor); } if (symptomMatches && colorMatches) { ruleDoesApply = true; } } // ColorMatch: Check if there is a color match. Simple. else if (rule.ruleType == RuleType.ColorMatch) { ruleDoesApply = (bodyColor == rule.exactColor); } // Heartbeat: Check if heartbeat is below or above. else if (rule.ruleType == RuleType.Heartbeat) { if (rule.heartbeatGreater == true) { ruleDoesApply = (bodyHeartbeat > rule.heartbeatValue); } } // If rule applies... if (ruleDoesApply) { // Did it succeed? If so we're done! if (EvaluateRuleSolutions(rule, playersTool, playersTargetBodyPart)) { BodyPart fixedBodyPart = bodyParts [(int)rule.fixesBodyPartType]; fixedBodyPart.symptom = Symptom.None; fixesColor = (rule.fixesColor && rule.ruleSolutions.Count <= 0); // Color is fixed if all requirements met if (fixedBodyPart.BloodSpurt != null) { Object.Destroy(fixedBodyPart.BloodSpurt); fixedBodyPart.BloodSpurt = null; } if (fixedBodyPart.PainEffect != null) { Object.Destroy(fixedBodyPart.PainEffect); fixedBodyPart.PainEffect = null; } // Hack: if it's a heart rule that passes, we assume heartrate is fixed if (rule.ruleType == RuleType.Heartbeat) { bodyHeartbeat = BodyController.kTargetHeartbeat; } return(true); // No, so we can't apply any other rules in this group } else { groupDidFail = true; } } } // No success.. return(false); }
public override int ReceiveAndCalculateDamage(string damagedBy, int damage, DamageType damageType, BodyPartType bodyPartAim) { base.ReceiveAndCalculateDamage(damagedBy, damage, damageType, bodyPartAim); //if this living is on the server: // if (b != null && b.shooterName != gameObject.name && mobStat != MobConsciousStat.DEAD) { var simpleAnimal = GetComponent <SimpleAnimal>(); if (simpleAnimal != null && simpleAnimal.mobStat != MobConsciousStat.DEAD && CustomNetworkManager.Instance._isServer) { //delegated to Living atm GetComponent <Living>().ReceiveDamage(damagedBy, damage, damageType, bodyPartAim); } return(damage); }
/// <summary> /// Applies burn damage to the specified victim's bodyparts. /// Attack type is internal, so as to avoid needing to add electrical resistances to Armor class. /// </summary> /// <param name="damage">The amount of damage to apply to the bodypart</param> /// <param name="bodypart">The BodyPartType to damage.</param> private void DealElectrocutionDamage(float damage, BodyPartType bodypart) { ApplyDamageToBodyPart(null, damage, AttackType.Internal, DamageType.Burn, bodypart); }
public static void SendThrowHitMessage(GameObject item, GameObject victim, int damage, BodyPartType hitZone = BodyPartType.None) { var player = victim.Player(); if (player == null) { hitZone = BodyPartType.None; } var message = $"{victim.ExpensiveName()} has been hit by {item.Item()?.itemName ?? item.name}{InTheZone( hitZone )}"; ChatRelay.Instance.AddToChatLogServer(new ChatEvent { channels = ChatChannel.Combat, message = message, position = victim.transform.position, radius = 9f, sizeMod = Mathf.Clamp(damage / 15, 1, 3) }); }
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]; 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; } //Tilemap stuff: var tileMapDamage = tileChangeManager.GetTilemap(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.transform.position)) { return; } //Meaty bodies: HealthBehaviour victimHealth = victim.GetComponent <HealthBehaviour>(); if (victimHealth.IsDead && weaponAttr.type == ItemType.Knife) { if (victim.GetComponent <SimpleAnimal>()) { SimpleAnimal attackTarget = victim.GetComponent <SimpleAnimal>(); RpcMeleeAttackLerp(stabDirection, weapon); playerMove.allowInput = false; attackTarget.Harvest(); soundNetworkActions.RpcPlayNetworkSound("BladeSlice", transform.position); } else { PlayerHealth attackTarget = victim.GetComponent <PlayerHealth>(); RpcMeleeAttackLerp(stabDirection, weapon); playerMove.allowInput = false; attackTarget.Harvest(); soundNetworkActions.RpcPlayNetworkSound("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); } soundNetworkActions.RpcPlayNetworkSound(weaponAttr.hitSound, transform.position); StartCoroutine(AttackCoolDown()); }
/// <summary> /// Inventory move in which the object in the slot is thrown into the world from the location of its root storage /// </summary> /// <param name="fromSlot"></param> /// <param name="worldTargetVector">world space vector pointing from origin to targeted position to throw</param> /// <param name="spinMode"></param> /// <param name="aim">body part to target</param> /// <returns>true if successful</returns> public static bool ServerThrow(ItemSlot fromSlot, Vector2 worldTargetVector, SpinMode spinMode = SpinMode.CounterClockwise, BodyPartType aim = BodyPartType.Chest) { return(ServerPerform(InventoryMove.Throw(fromSlot, worldTargetVector, spinMode, aim))); }
/// <summary> /// Perform and display the shot locally (i.e. only on this instance of the game). Does not /// communicate anything to other players (unless this is the server, in which case the server /// will determine the effects of the bullet). Does not do any validation. This should only be invoked /// when displaying the results of a shot (i.e. after receiving a ShootMessage or after this client performs a shot) /// or when server is determining the outcome of the shot. /// </summary> /// <param name="shooter">gameobject of the shooter</param> /// <param name="finalDirection">direction the shot should travel (accuracy deviation should already be factored into this)</param> /// <param name="damageZone">targeted damage zone</param> /// <param name="isSuicideShot">if this is a suicide shot (aimed at shooter)</param> public void DisplayShot(GameObject shooter, Vector2 finalDirection, BodyPartType damageZone, bool isSuicideShot) { if (!MatrixManager.IsInitialized) { return; } //if this is our gun (or server), last check to ensure we really can shoot if ((isServer || PlayerManager.LocalPlayer == shooter) && CurrentMagazine.ClientAmmoRemains <= 0) { if (isServer) { Logger.LogTrace("Server rejected shot - out of ammo", Category.Firearms); } return; } //TODO: If this is not our gun, simply display the shot, don't run any other logic if (shooter == PlayerManager.LocalPlayer) { //this is our gun so we need to update our predictions FireCountDown += 1.0 / FireRate; //add additional recoil after shooting for the next round AppendRecoil(); //Default camera recoil params until each gun is configured separately if (CameraRecoilConfig == null || CameraRecoilConfig.Distance == 0f) { CameraRecoilConfig = new CameraRecoilConfig { Distance = 0.2f, RecoilDuration = 0.05f, RecoveryDuration = 0.6f }; } Camera2DFollow.followControl.Recoil(-finalDirection, CameraRecoilConfig); } if (CurrentMagazine == null) { Logger.Log("Why is CurrentMagazine null on this client?"); } else { //call ExpendAmmo outside of previous check, or it won't run serverside and state will desync. CurrentMagazine.ExpendAmmo(); } //display the effects of the shot //get the bullet prefab being shot if (isSuicideShot) { GameObject bullet = Spawn.ClientPrefab(Projectile.name, shooter.transform.position, parent: shooter.transform.parent).GameObject; var b = bullet.GetComponent <Projectile>(); b.Suicide(shooter, this, damageZone); } else { for (int n = 0; n < ProjectilesFired; n++) { GameObject Abullet = Spawn.ClientPrefab(Projectile.name, shooter.transform.position, parent: shooter.transform.parent).GameObject; var A = Abullet.GetComponent <Projectile>(); var finalDirectionOverride = CalcDirection(finalDirection, n); A.Shoot(finalDirectionOverride, shooter, this, damageZone); } } SoundManager.PlayAtPosition(FiringSound, shooter.transform.position, shooter); shooter.GetComponent <PlayerSprites>().ShowMuzzleFlash(); }
public BodyPart(Texture2D texture, BodyPartType type) { _texture = texture; Type = type; MaxStacks = 1; }
public override void Deserialize(NetworkReader reader) { base.Deserialize(reader); var componentID = reader.ReadUInt16(); if (componentID == UNKNOWN_COMPONENT_TYPE_ID) { //client didn't know which to trigger, leave ComponentType null ComponentType = null; } else { //client requested a specific component. ComponentType = componentIDToComponentType[componentID]; } InteractionType = interactionIDToInteractionType[reader.ReadByte()]; if (componentID != UNKNOWN_COMPONENT_TYPE_ID) { // client specified exact component ProcessorObject = reader.ReadUInt32(); } else { // client requested server to check the interaction ProcessorObject = NetId.Invalid; } Intent = (Intent)reader.ReadByte(); if (InteractionType == typeof(PositionalHandApply)) { TargetObject = reader.ReadUInt32(); TargetVector = reader.ReadVector2(); TargetBodyPart = (BodyPartType)reader.ReadUInt32(); } else if (InteractionType == typeof(HandApply)) { TargetObject = reader.ReadUInt32(); TargetBodyPart = (BodyPartType)reader.ReadUInt32(); IsAltUsed = reader.ReadBoolean(); } else if (InteractionType == typeof(AimApply)) { TargetVector = reader.ReadVector2(); MouseButtonState = reader.ReadBoolean() ? MouseButtonState.PRESS : MouseButtonState.HOLD; } else if (InteractionType == typeof(MouseDrop)) { TargetObject = reader.ReadUInt32(); UsedObject = reader.ReadUInt32(); } else if (InteractionType == typeof(InventoryApply)) { UsedObject = reader.ReadUInt32(); Storage = reader.ReadUInt32(); SlotIndex = reader.ReadInt32(); NamedSlot = (NamedSlot)reader.ReadInt32(); IsAltUsed = reader.ReadBoolean(); } else if (InteractionType == typeof(TileApply)) { TargetVector = reader.ReadVector2(); } else if (InteractionType == typeof(TileMouseDrop)) { UsedObject = reader.ReadUInt32(); TargetVector = reader.ReadVector2(); } }