private void FixedUpdate() { //Tick up the stopwatch this.trackerUpdateStopwatch += Time.fixedDeltaTime; //If the stopwatch has gone on for .1 seconds... if (this.trackerUpdateStopwatch >= 1f / this.trackerUpdateFrequency) { //Reset the timer this.trackerUpdateStopwatch -= 1f / this.trackerUpdateFrequency; //Poisoncounter to 0 cause we haven't found any poisoned creatures yet this.poisonCounter = 0; //Spheresearch it foreach (HurtBox hurtBox in new SphereSearch { origin = characterBody.footPosition, radius = this.maxTrackingDistance, mask = LayerIndex.entityPrecise.mask }.RefreshCandidates().FilterCandidatesByHurtBoxTeam(TeamMask.GetEnemyTeams(this.teamComponent.teamIndex)).OrderCandidatesByDistance().FilterCandidatesByDistinctHurtBoxEntities().GetHurtBoxes()) { //Get the targets body component CharacterBody body = hurtBox.healthComponent.body; //Make sure they stats ain't brokeded body.RecalculateStats(); //If they have either buff, tick up the counter if (body.HasBuff(RoR2Content.Buffs.Poisoned) || body.HasBuff(RoR2Content.Buffs.Blight)) { this.poisonCounter += 1; } } //Set the totalpoisoned count to what we found this.totalPoisoned = this.poisonCounter; } }
private void SiphonNearbyController_SearchForTargets(On.RoR2.SiphonNearbyController.orig_SearchForTargets orig, SiphonNearbyController self, List <HurtBox> dest) { orig(self, dest); self.sphereSearch.ClearCandidates(); self.sphereSearch.RefreshCandidates(); self.sphereSearch.FilterCandidatesByHurtBoxTeam(TeamMask.GetEnemyTeams(self.networkedBodyAttachment.attachedBody.teamComponent.teamIndex)); var destCopy = new List <HurtBox>(dest); foreach (var hurtBox in destCopy) { //Debug.Log("Mired Urn: Checking " + hurtBox.healthComponent.body.GetDisplayName()); if ((bool)hurtBox.healthComponent?.body?.hasCloakBuff) { dest.Remove(hurtBox); //Debug.Log("Removed"); } else { //Debug.Log("Kept"); } } self.sphereSearch.OrderCandidatesByDistance(); self.sphereSearch.FilterCandidatesByDistinctHurtBoxEntities(); self.sphereSearch.GetHurtBoxes(dest); self.sphereSearch.ClearCandidates(); }
public override void OnEnter() { attackSoundString = SummonEggs.attackSoundString; spitPrefab = SummonEggs.spitPrefab; guardSpawnCard = SummonEggs.spawnCard; base.OnEnter(); animator = GetModelAnimator(); modelTransform = GetModelTransform(); childLocator = modelTransform.GetComponent <ChildLocator>(); duration = baseDuration; PlayCrossfade("Gesture", "SummonEggs", 0.5f); Util.PlaySound(attackSoundString, base.gameObject); if (NetworkServer.active) { enemySearch = new BullseyeSearch(); enemySearch.filterByDistinctEntity = false; enemySearch.filterByLoS = false; enemySearch.maxDistanceFilter = float.PositiveInfinity; enemySearch.minDistanceFilter = 0f; enemySearch.minAngleFilter = 0f; enemySearch.maxAngleFilter = 180f; enemySearch.teamMaskFilter = TeamMask.GetEnemyTeams(GetTeam()); enemySearch.sortMode = BullseyeSearch.SortMode.Distance; enemySearch.viewer = base.characterBody; } }
public void Pull() { //Check if this pulse crits this.isCrit = base.RollCrit(); //Spheresearch foreach (HurtBox hurtBox in new SphereSearch { origin = base.characterBody.corePosition, radius = this.baseRadius, mask = LayerIndex.entityPrecise.mask }.RefreshCandidates().FilterCandidatesByHurtBoxTeam(TeamMask.GetEnemyTeams(base.teamComponent.teamIndex)).OrderCandidatesByDistance().FilterCandidatesByDistinctHurtBoxEntities().GetHurtBoxes()) { //force calc //Get body of the enemy CharacterBody body = hurtBox.healthComponent.body; //Calc for finding direction Vector3 a = hurtBox.transform.position - base.characterBody.corePosition; //Determine distance float magnitude = a.magnitude; //Grab direction Vector3 direction = a.normalized; //Get mass of enemy float mass = body.GetComponent <Rigidbody>().mass; //Hold this float massEval; //If not flying, we can pull harder if (!body.isFlying) { massEval = mass * -20f - 400f; } //If flying, pull softer else { massEval = (mass * -20f - 400f) / 2; } //Cap the mass evaluation so big creatures don't fly float[] maxMass = new float[] { massEval, -6000 }; //Determine applied force with mass, direction, and magnitude scaling with distance Vector3 appliedForce = maxMass.Max() * direction * ((magnitude + 15) / (this.baseRadius * 2)); //damage //Network check if (NetworkServer.active) { //Prep damage DamageInfo damageInfo = new DamageInfo { attacker = base.gameObject, inflictor = base.gameObject, crit = this.isCrit, damage = base.damageStat * this.damageCoefficient, damageColorIndex = DamageColorIndex.Default, damageType = DamageType.Stun1s, force = appliedForce, procCoefficient = 0.4f, procChainMask = default,
private static void CharacterMotor_OnHitGround(On.RoR2.CharacterMotor.orig_OnHitGround orig, CharacterMotor self, CharacterMotor.HitGroundInfo hitGroundInfo) { bool hasGoombad = false; bool restoreFallDamage = false; if (RunArtifactManager.instance.IsArtifactEnabled(GoombaArtifactDef.artifactIndex)) { if (self.body) { if (Math.Abs(hitGroundInfo.velocity.y) >= minFallSpeed) { Chat.AddMessage("Speed: " + Math.Abs(hitGroundInfo.velocity.y) + "/" + minFallSpeed); var bodySearch = new BullseyeSearch() //let's just get the nearest player { viewer = self.body, sortMode = BullseyeSearch.SortMode.Distance, teamMaskFilter = TeamMask.GetEnemyTeams(self.body.teamComponent.teamIndex), }; bodySearch.RefreshCandidates(); Debug.Log("Nearest Enemies: " + bodySearch.GetResults().ToList()); var nearestBody = bodySearch.GetResults().ToList(); // We very likely landed on an enemy. if (nearestBody.Count > 0) { var firstBody = nearestBody.FirstOrDefault(); var distance = Vector3.Distance(hitGroundInfo.position, Helpers.GetHeadPosition(firstBody.healthComponent.body)); if (distance <= maxDistance) { goombaDamageInfo.attacker = self.body.gameObject; firstBody.healthComponent.TakeDamage(goombaDamageInfo); if ((self.body.bodyFlags & CharacterBody.BodyFlags.IgnoreFallDamage) == CharacterBody.BodyFlags.None) { self.body.bodyFlags |= CharacterBody.BodyFlags.IgnoreFallDamage; restoreFallDamage = true; } Chat.AddMessage("Goomba!"); hasGoombad = true; } } } } } orig(self, hitGroundInfo); if (hasGoombad) { self.Motor.ForceUnground(); self.ApplyForce(Vector3.up * bounceForce); } if (restoreFallDamage) { self.body.bodyFlags &= ~CharacterBody.BodyFlags.IgnoreFallDamage; } }
private void GenerateSphereSearch(CharacterBody origin, bool getSameTeam = false) { List <HurtBox> hurtBoxesList = new List <HurtBox>(); TeamMask enemyTeams = TeamMask.GetEnemyTeams(origin.teamComponent.teamIndex); SphereSearch sphereSearch = new RoR2.SphereSearch() { mask = LayerIndex.entityPrecise.mask, origin = origin.transform.position, queryTriggerInteraction = QueryTriggerInteraction.Collide, radius = sphereSearchRadius }; #if DEBUG TurboEdition._logger.LogWarning(EquipmentName + ": generated " + sphereSearch + " with radius " + sphereSearchRadius + " and origin " + origin.transform); #endif if (!getSameTeam) { #if DEBUG TurboEdition._logger.LogWarning(EquipmentName + ": filtering the sphereSearch by enemy teams."); #endif sphereSearch.RefreshCandidates().FilterCandidatesByHurtBoxTeam(enemyTeams).FilterCandidatesByDistinctHurtBoxEntities().GetHurtBoxes(hurtBoxesList); } else { #if DEBUG TurboEdition._logger.LogWarning(EquipmentName + ": filtering the sphereSearch by SAME TEAM as origin."); #endif TeamMask selfdestructionguaranteed = new TeamMask(); selfdestructionguaranteed.AddTeam(origin.teamComponent.teamIndex); sphereSearch.RefreshCandidates().FilterCandidatesByHurtBoxTeam(selfdestructionguaranteed).FilterCandidatesByDistinctHurtBoxEntities().GetHurtBoxes(hurtBoxesList); } for (int i = 0, j = 0; i < hurtBoxesList.Count && j < sphereLinkCount; i++) { var hc = hurtBoxesList[i].healthComponent; if (hc) { var body = hc.body; if (body) { var linkGameObject = body.GetComponentInChildren <LinkComponent>()?.gameObject; #if DEBUG TurboEdition._logger.LogWarning(EquipmentName + ": adding linkedBuff to someone, theres " + (i + 1) + " out of " + hurtBoxesList.Count + " hurtboxes with max " + sphereLinkCount); #endif body.AddTimedBuff(linkedBuff, linkedBuffDuration); if (!linkGameObject) { //If they dont have a component that means they are brand new and unique //If they do, this doesn't get executed and they just get their debuff updated j++; } } } } }
internal void GetTargets(Vector3 impactPos) { //Spheresearch around the spot we hit foreach (HurtBox hurtBox in new SphereSearch { origin = impactPos, radius = 25, mask = LayerIndex.entityPrecise.mask }.RefreshCandidates().FilterCandidatesByHurtBoxTeam(TeamMask.GetEnemyTeams(base.GetComponent <TeamComponent>().teamIndex)).OrderCandidatesByDistance().FilterCandidatesByDistinctHurtBoxEntities().GetHurtBoxes()) { //Every valid target we find, add them to the hitlist >:) this.AddToTargets(hurtBox); } }
private void ServerPulse(TeamIndex teamIndex) { #if DEBUG TurboEdition._logger.LogWarning("Server Pulse made."); #endif this.sphereSearch = new RoR2.SphereSearch() { mask = LayerIndex.entityPrecise.mask, //This should be ok too origin = owner.transform.position, //This should be ok queryTriggerInteraction = QueryTriggerInteraction.Collide, radius = 0f //it starts with 0 radius, yea }; this.finalRadius = radius; this.rate = 1f / duration; this.enemyTeams = TeamMask.GetEnemyTeams(teamIndex); //inb4 this will give issues with chaos and you will get affected by yourself }
internal void AddKill(CharacterBody body) { foreach (HurtBox hurtBox in new SphereSearch { origin = characterBody.corePosition, radius = 16, mask = LayerIndex.entityPrecise.mask }.RefreshCandidates().FilterCandidatesByHurtBoxTeam(TeamMask.GetEnemyTeams(teamComponent.teamIndex)).OrderCandidatesByDistance().FilterCandidatesByDistinctHurtBoxEntities().GetHurtBoxes()) { nearbyEnemies.Add(hurtBox.hurtBoxGroup.mainHurtBox); } if (nearbyEnemies.Contains(body.mainHurtBox)) { kills += 1; } }
//What to do when attempting to richochet the bullet private void HandleRichochet(Vector3 pos) { //Hold variable for whether target is found or not bool targetFound = false; //If the bullet can still recurse... if (this.recursion < this.maxRecursion) { //Half the damage this.damage /= 2; //Loop via spheresearch foreach (HurtBox hurtBox in new SphereSearch { origin = pos, radius = 25f, mask = LayerIndex.entityPrecise.mask, }.RefreshCandidates().FilterCandidatesByHurtBoxTeam(TeamMask.GetEnemyTeams(base.teamComponent.teamIndex)).OrderCandidatesByDistance().FilterCandidatesByDistinctHurtBoxEntities().GetHurtBoxes()) { //Get the mainhurtbox HurtBox mainBox = hurtBox.hurtBoxGroup.mainHurtBox; //If the mainhurtbox is not yet in our list... if (!hitHurtBoxes.Contains(mainBox)) { //Add the found target to the list this.hitHurtBoxes.Add(mainBox); //Trip the bool flag targetFound = true; //Mark that we recursed this.recursion += 1; //Emulate the bullet, because doing another ACTUAL bullet attack is hell and a half, also feels bad to have all your shots miss cause some geometry SimulateBullet(pos, mainBox); //End the loop cause we found our target break; } } //If we go through having never found a target, max out the recursion so the loop ends completely if (!targetFound) { this.recursion = this.maxRecursion; } } }
private void AttemptGrab(float grabRadius) { if (this.grabController) { return; } Ray aimRay = base.GetAimRay(); BullseyeSearch search = new BullseyeSearch { teamMaskFilter = TeamMask.GetEnemyTeams(base.GetTeam()), filterByLoS = false, searchOrigin = this.grabTransform.position, searchDirection = Random.onUnitSphere, sortMode = BullseyeSearch.SortMode.Distance, maxDistanceFilter = grabRadius, maxAngleFilter = 360f }; search.RefreshCandidates(); search.FilterOutGameObject(base.gameObject); HurtBox target = search.GetResults().FirstOrDefault <HurtBox>(); if (target) { if (target.healthComponent && target.healthComponent.body) { if (BodyMeetsGrabConditions(target.healthComponent.body)) { this.grabController = target.healthComponent.body.gameObject.AddComponent <RegigigasGrabController>(); this.grabController.pivotTransform = this.grabTransform; this.grabController.grabberHealthComponent = base.healthComponent; this.grabTarget = target; return; } } } }
public override void OnEnter() { //Do normal onenter things first base.OnEnter(); //Play the animation base.PlayAnimation("Gesture, Mouth", "FireSpit", "FireSpit.playbackRate", 1f); //Spheresearch for enemies in range, starting from doggo foots foreach (HurtBox hurtBox in new SphereSearch { origin = base.characterBody.footPosition, radius = this.maxTrackingDistance, mask = LayerIndex.entityPrecise.mask }.RefreshCandidates().FilterCandidatesByHurtBoxTeam(TeamMask.GetEnemyTeams(base.teamComponent.teamIndex)).OrderCandidatesByDistance().FilterCandidatesByDistinctHurtBoxEntities().GetHurtBoxes()) { //Get the characterbody cause we need buffcount CharacterBody body = hurtBox.healthComponent.body; //Get health component for poison calc HealthComponent component = hurtBox.healthComponent; //If they have the poison debuff... if (body.HasBuff(RoR2Content.Buffs.Poisoned)) { //Network check if (base.isAuthority) { //Make blast attack and fire it at pos of all enemies new BlastAttack { position = body.corePosition, baseDamage = component.fullHealth * this.healthFraction + base.damageStat * this.poisonDamageCoefficient, baseForce = 0f, radius = this.detonationRadius, attacker = base.gameObject, inflictor = base.gameObject, teamIndex = base.teamComponent.teamIndex, crit = base.RollCrit(), procChainMask = default,
private void CharacterMotor_OnHitGroundServer(On.RoR2.CharacterMotor.orig_OnHitGroundServer orig, CharacterMotor self, CharacterMotor.HitGroundInfo hitGroundInfo) { if (!RunArtifactManager.instance.IsArtifactEnabled(GoombaArtifactDef.artifactIndex)) { orig(self, hitGroundInfo); return; } bool hasGoombad = false; bool restoreFallDamage = false; var goombaComponent = self.GetComponent <GoombaComponent>(); if (self.body) { if (goombaComponent.inGoombaState || Math.Abs(hitGroundInfo.velocity.y) >= minFallSpeed.Value) { TeamMask teamMask = TeamMask.GetEnemyTeams(self.body.teamComponent.teamIndex); if (FriendlyFireManager.friendlyFireMode != FriendlyFireManager.FriendlyFireMode.Off && friendlyFire.Value) { teamMask = TeamMask.allButNeutral; } //Chat.AddMessage("Speed: " + Math.Abs(hitGroundInfo.velocity.y) + "/" + minFallSpeed); var enemySearch = new BullseyeSearch() { filterByDistinctEntity = false, filterByLoS = false, maxDistanceFilter = maxDistance.Value, minDistanceFilter = 0f, minAngleFilter = 0f, maxAngleFilter = angleCheck.Value, teamMaskFilter = teamMask, sortMode = BullseyeSearch.SortMode.Distance, viewer = self.body, searchDirection = Vector3.down, searchOrigin = hitGroundInfo.position }; enemySearch.RefreshCandidates(); var listOfEnemies = enemySearch.GetResults().ToList(); /*var str = "Nearest Enemies: "; * * foreach(var enemy in listOfEnemies) * { * if (enemy) * str += enemy.healthComponent.body.GetDisplayName() + ", "; * } * Debug.Log(str);*/ HurtBox enemyHurtbox = GetValidEnemy(listOfEnemies); if (enemyHurtbox) { //var headPos = Helpers.GetHeadPosition(enemyHurtbox.healthComponent.body); //var distance = Vector3.Distance(hitGroundInfo.position, headPos); //Chat.AddMessage("Distance to enemy is "+ distance); goombaComponent.inGoombaState = true; if (enemyHurtbox.healthComponent != goombaComponent.currentHealthComponent) { goombaComponent.bounces = 1; goombaComponent.currentHealthComponent = enemyHurtbox.healthComponent; } enemyHurtbox.healthComponent.TakeDamage(new DamageInfo() { attacker = self.body.gameObject, damage = multiplyDmgPerBounce.Value ? goombaDamage.Value * goombaComponent.bounces : goombaDamage.Value, inflictor = goombaGameObject, position = hitGroundInfo.position, damageColorIndex = DamageColorIndex.Bleed }); if ((self.body.bodyFlags & CharacterBody.BodyFlags.IgnoreFallDamage) == CharacterBody.BodyFlags.None) { self.body.bodyFlags |= CharacterBody.BodyFlags.IgnoreFallDamage; restoreFallDamage = true; } if (goombaInChat.Value) { Chat.AddMessage("Goomba!"); } hasGoombad = true; } } } orig(self, hitGroundInfo); if (hasGoombad) { self.Motor.ForceUnground(); self.ApplyForce(Vector3.up * bounceForce.Value); goombaComponent.bounces++; } else { goombaComponent.ExitGoombaState(); } if (restoreFallDamage) { self.body.bodyFlags &= ~CharacterBody.BodyFlags.IgnoreFallDamage; } }
private void DoExplode() { if (!this.hasFired) { this.hasFired = true; base.characterBody.AddSpreadBloom(1.25f); EffectManager.SimpleMuzzleFlash(Commando.CommandoWeapon.FirePistol.effectPrefab, base.gameObject, this.muzzleString, false); if (NetworkServer.active) { EffectManager.SimpleEffect(WispSurvivor.WispSurvivor.burstPrefab, transform.position, transform.rotation, true); EffectManager.SimpleEffect(WispSurvivor.WispSurvivor.burstSecondary, transform.position, transform.rotation, true); //Get all nearby hurtboxes BullseyeSearch selfSearch = new BullseyeSearch(); selfSearch.searchOrigin = base.transform.position; selfSearch.maxDistanceFilter = burstRadius; selfSearch.teamMaskFilter = TeamMask.GetEnemyTeams(base.teamComponent.teamIndex); selfSearch.RefreshCandidates(); HurtBox[] hurtboxes = selfSearch.GetResults().ToArray(); //Debug.Log("Found " + hurtboxes.Length + " hurtboxes within " + burstRadius + " of self"); //Set up damage, add bonus based on percent of full barrier DamageInfo damageInfo = new DamageInfo(); damageInfo.attacker = base.characterBody.gameObject; damageInfo.crit = base.RollCrit(); float bonusDamage = base.healthComponent.barrier / base.healthComponent.fullBarrier; damageInfo.damage = base.damageStat * (this.damageCoefficient + bonusDamage); //Drain barrier base.healthComponent.barrier = 0f; damageInfo.damageColorIndex = DamageColorIndex.Default; damageInfo.damageType = DamageType.AOE; damageInfo.procCoefficient = 0f; //Boom for (int i = 0; i < hurtboxes.Length; i++) { hurtboxes[i].healthComponent.TakeDamage(damageInfo); } if (!grappleHandler.hasGrappleTarget()) { return; } //Now do an explosion on each grappled target List <GrappleTarget> targets = grappleHandler.GetGrappleTargets(); foreach (GrappleTarget target in targets) { Transform grappleTransform = target.grappleTarget.transform; EffectManager.SimpleEffect(WispSurvivor.WispSurvivor.burstPrefab, grappleTransform.position, grappleTransform.rotation, true); EffectManager.SimpleEffect(WispSurvivor.WispSurvivor.burstSecondary, grappleTransform.position, grappleTransform.rotation, true); BullseyeSearch grappleSearch = new BullseyeSearch(); grappleSearch.searchOrigin = target.grappleTarget.transform.position; grappleSearch.maxDistanceFilter = burstRadius; grappleSearch.teamMaskFilter = TeamMask.GetEnemyTeams(base.teamComponent.teamIndex); grappleSearch.RefreshCandidates(); hurtboxes = grappleSearch.GetResults().ToArray(); //Debug.Log("Found " + hurtboxes.Length + " hurtboxes within " + burstRadius + " of grapple target"); for (int i = 0; i < hurtboxes.Length; i++) { hurtboxes[i].healthComponent.TakeDamage(damageInfo); } } } } }
private void DoSiphon() { if (this.hasFired) { return; } this.hasFired = true; //if (base.isAuthority) //{ tetherHandler = base.GetComponent <TetherHandler>(); HurtBox closestHurtbox = null; //First check to see if we're aiming at a valid target Ray aimRay = base.GetAimRay(); RaycastHit raycastHit = new RaycastHit(); bool foundTarget = Physics.Raycast(aimRay, out raycastHit, maxDistanceFilter); if (foundTarget && raycastHit.collider.GetComponent <HurtBox>()) { TeamIndex targetTeamIndex = raycastHit.collider.GetComponent <HurtBox>().healthComponent.body.teamComponent.teamIndex; //Make sure we're not targeting the same team if (base.GetTeam() != targetTeamIndex) { closestHurtbox = raycastHit.collider.GetComponent <HurtBox>(); Debug.Log("Found aimed at object " + closestHurtbox.transform.root.name); } } //If we weren't aiming at something, just search for a valid nearby target else { //Search for all nearby targets BullseyeSearch bullseyeSearch = new BullseyeSearch(); bullseyeSearch.searchOrigin = base.transform.position; bullseyeSearch.searchDirection = UnityEngine.Random.onUnitSphere; bullseyeSearch.maxDistanceFilter = maxDistanceFilter; bullseyeSearch.teamMaskFilter = TeamMask.GetEnemyTeams(base.GetTeam()); //Sort by distance bullseyeSearch.sortMode = BullseyeSearch.SortMode.Distance; bullseyeSearch.RefreshCandidates(); //Remove ourselves from the search results //(shouldn't be there in the first place, but hey) bullseyeSearch.FilterOutGameObject(base.gameObject); //Get the closest hurtbox closestHurtbox = bullseyeSearch.GetResults().FirstOrDefault <HurtBox>(); Debug.Log("Found object " + closestHurtbox.transform.root.name); if (closestHurtbox == default(HurtBox)) { Debug.LogError("Default value!"); } if (closestHurtbox == null) { Debug.LogError("Null value!"); } } //Set up our grapple handler if (tetherHandler == null) { tetherHandler = base.gameObject.AddComponent <TetherHandler>(); Debug.LogWarning("Added grapple handler via siphon"); } //Then establish our grapple target if (closestHurtbox == null) { Debug.LogError("Null hurtbox"); return; } //If we've successfully established a tether if (closestHurtbox) { Debug.Log("Attempting to establish tether"); //If adding a new grapple target would go beyond our max stock int curNumGrappled = tetherHandler.GetGrappleTargets().Count; if (curNumGrappled + 1 > base.activatorSkillSlot.maxStock) { //Remove the oldest grapple target tetherHandler.ClearGrappleTarget(tetherHandler.GetGrappleTargets()[0]); } tetherHandler.SetGrappleTarget(closestHurtbox); tetherHandler.TETHER_TYPE = TETHER_TYPE.SIPHON; base.characterBody.AddBuff(WispSurvivor.Modules.Buffs.siphonSelf); closestHurtbox.healthComponent.body.AddBuff(WispSurvivor.Modules.Buffs.siphonTarget); } //} this.animator = base.GetModelAnimator(); this.muzzleString = "Muzzle"; base.PlayAnimation("Gesture, Override", "FireGrapple", "FireGrapple.playbackRate", this.duration); }