/// <summary> /// Loops through all the Options of the minion. The action has 4 useful parameters to use. /// The first parameter refers to the Option/Multiple itself. It is a GameObject. /// The second parameter refers to the OptionBehavior component in the Option/Multiple. /// The third parameter refers to the target of the Option/Multiple owner. It is also a GameObject. /// The last parameter refers to the direction from the option to the target. It is a normalized Vector3. /// </summary> /// <param name="optionOwner">The owner of the option.</param> /// <param name="actionToRun">An action to execute for each Option. The inputs are as follows: /// GameObject option, OptionBehavior behavior, GameObject target, Vector3 direction.</param> public void FireForAllOptions(CharacterBody optionOwner, Action <GameObject, OptionBehavior, GameObject, Vector3> actionToRun) { if (!optionOwner) { return; } OptionTracker optionTracker = optionOwner.GetComponent <OptionTracker>(); if (!optionTracker) { return; } GameObject target = null; GameObject masterObject = optionOwner.masterObject; if (masterObject) { BaseAI ai = masterObject.GetComponent <BaseAI>(); BaseAI.Target mainTarget = ai.currentEnemy; if (mainTarget != null && mainTarget.gameObject) { target = mainTarget.gameObject; } } foreach (GameObject option in optionTracker.existingOptions) { OptionBehavior behavior = option.GetComponent <OptionBehavior>(); if (behavior) { Vector3 direction; if (target) { direction = (target.transform.position - option.transform.position).normalized; if (includeModelInsideOrb) { behavior.target = target; NetworkIdentity targetNetworkIdentity = target.GetComponent <NetworkIdentity>(); if (targetNetworkIdentity) { OptionSync(optionOwner, (networkIdentity, nullTracker) => { optionTracker.targetIds.Add(Tuple.Create( GameObjectType.Body, networkIdentity.netId, (short)behavior.numbering, targetNetworkIdentity.netId )); }, false); } } } else { direction = optionOwner.inputBank.GetAimRay().direction.normalized; } actionToRun(option, behavior, target, direction); } } }
private void Awake() { IL.RoR2.CharacterBody.HandleConstructTurret += (il) => { var c = new ILCursor(il); c.GotoNext(x => x.MatchStloc(4)); c.Emit(OpCodes.Ldloc_2); c.EmitDelegate <Func <CharacterMaster, CharacterMaster, CharacterMaster> >((turret, master) => { turret.gameObject.AddComponent <AIOwnership>().ownerMaster = master; return(turret); }); }; IL.RoR2.CharacterAI.BaseAI.FixedUpdate += (il2) => { var c2 = new ILCursor(il2); c2.Emit(OpCodes.Ldarg_0); c2.EmitDelegate <Action <BaseAI> >((ai) => { if (ai.leader.characterBody != null) { BaseAI.Target leader = ai.leader; if (leader.characterBody.isPlayerControlled) { PingerController p = null; //leader.characterBody.master.GetComponent<PingerController>(); foreach (PlayerCharacterMasterController item in PlayerCharacterMasterController.instances) { if (item.master.alive) { if (item.master.GetBody().GetUserName() == leader.characterBody.GetUserName()) { p = (PingerController)pingerController.GetValue(item); } } } if (p != null) { if (p.currentPing.targetGameObject != null) { ((BaseAI.Target)currentEnemy.GetValue(ai)).gameObject = p.currentPing.targetGameObject; } } } } }); }; }
// Token: 0x06000974 RID: 2420 RVA: 0x0002F30C File Offset: 0x0002D50C public override void FixedUpdate() { base.FixedUpdate(); if (base.ai && base.body) { Vector3 footPosition = base.body.footPosition; base.ai.pathFollower.UpdatePosition(footPosition); this.updateTimer -= Time.fixedDeltaTime; this.pathUpdateTimer -= Time.fixedDeltaTime; this.strafeTimer -= Time.fixedDeltaTime; if (this.updateTimer <= 0f) { this.updateTimer = UnityEngine.Random.Range(0.16666667f, 0.2f); AISkillDriver.MovementType movementType = AISkillDriver.MovementType.Stop; SkillSlot skillSlot = SkillSlot.None; bool flag = false; BaseAI.SkillDriverEvaluation skillDriverEvaluation = base.ai.skillDriverEvaluation; this.dominantSkillDriver = skillDriverEvaluation.dominantSkillDriver; BaseAI.Target target = skillDriverEvaluation.target; if (this.dominantSkillDriver) { movementType = this.dominantSkillDriver.movementType; skillSlot = this.dominantSkillDriver.skillSlot; flag = this.dominantSkillDriver.activationRequiresTargetLoS; } Vector3 position = base.body.transform.position; Vector3 b = base.bodyInputBank ? base.bodyInputBank.aimOrigin : position; Vector3 vector = position; Vector3 vector2 = vector; this.moveTargetPositionFound = (target != null && target.GetBullseyePosition(out vector)); if (this.moveTargetPositionFound) { CharacterBody characterBody = target.characterBody; if (characterBody) { vector2 = characterBody.footPosition; } else { vector2 = vector; } if (this.pathUpdateTimer <= 0f) { base.ai.RefreshPath(footPosition, vector2); this.pathUpdateTimer = this.pathUpdateInterval; } } Vector3 normalized = (vector - b).normalized; bool flag2 = true; if (this.dominantSkillDriver && this.dominantSkillDriver.activationRequiresAimConfirmation) { flag2 = false; if (base.bodyInputBank && Vector3.Dot(base.bodyInputBank.aimDirection.normalized, normalized) >= 0.95f) { flag2 = true; } } Vector3 normalized2 = (((this.dominantSkillDriver && this.dominantSkillDriver.ignoreNodeGraph) ? ((base.ai.nodegraphType == MapNodeGroup.GraphType.Ground) ? vector2 : vector) : base.ai.pathFollower.GetNextPosition()) - footPosition).normalized; Vector3 vector3 = Vector3.Cross(Vector3.up, normalized2); Vector3 vector4 = position; if (movementType == AISkillDriver.MovementType.ChaseMoveTarget) { vector4 += normalized2; } else if (movementType == AISkillDriver.MovementType.FleeMoveTarget) { vector4 -= normalized2; } else if (movementType == AISkillDriver.MovementType.StrafeMovetarget) { if (this.strafeTimer <= 0f) { this.strafeDirection = 0f; } if (this.strafeDirection == 0f) { LayerMask mask = LayerIndex.world.mask | LayerIndex.defaultLayer.mask; float num = 0.25f * base.body.moveSpeed; float num2 = num; float num3 = num; HullDef hullDef = HullDef.Find(base.body.hullClassification); float radius = hullDef.radius; float height = hullDef.height; Vector3 b2 = Vector3.up * (height * 0.5f - radius); RaycastHit raycastHit; if (Physics.CapsuleCast(position + b2, position - b2, radius, vector3, out raycastHit, num, mask)) { num2 = raycastHit.distance; } if (Physics.CapsuleCast(position + b2, position - b2, radius, -vector3, out raycastHit, num, mask)) { num3 = raycastHit.distance; } if (num3 == num2) { this.strafeDirection = ((UnityEngine.Random.Range(0, 1) == 0) ? -1f : 1f); } else { this.strafeDirection = ((num3 < num2) ? 1f : -1f); } if (this.strafeDirection != 0f) { this.strafeTimer = 0.25f; } } vector4 += vector3 * this.strafeDirection; } base.ai.localNavigator.targetPosition = vector4; base.ai.localNavigator.Update(Time.fixedDeltaTime); bool newState = false; bool newState2 = false; bool newState3 = false; bool newState4 = false; if (((target != null) ? target.gameObject : null) && flag2 && (!flag || base.ai.HasLOS(position, vector))) { switch (skillSlot) { case SkillSlot.Primary: newState = true; break; case SkillSlot.Secondary: newState2 = true; break; case SkillSlot.Utility: newState3 = true; break; case SkillSlot.Special: newState4 = true; break; } } Vector3 vector5 = base.ai.localNavigator.moveVector; if (base.bodyCharacterMotor && movementType == AISkillDriver.MovementType.ChaseMoveTarget && Vector3.Dot(vector5, base.bodyCharacterMotor.velocity.normalized) <= 0.5f) { vector5 *= 0.5f; } if (this.dominantSkillDriver) { vector5 *= this.dominantSkillDriver.moveInputScale; } if (base.bodyInputBank) { base.bodyInputBank.skill1.PushState(newState); base.bodyInputBank.skill2.PushState(newState2); base.bodyInputBank.skill3.PushState(newState3); base.bodyInputBank.skill4.PushState(newState4); bool newState5 = false; if (base.bodyCharacterMotor && base.bodyCharacterMotor.isGrounded && Mathf.Max(base.ai.pathFollower.CalculateJumpVelocityNeededToReachNextWaypoint(base.body.moveSpeed), base.ai.localNavigator.jumpSpeed) > 0f) { newState5 = true; } base.bodyInputBank.jump.PushState(newState5); base.bodyInputBank.moveVector = vector5; } if (!this.dominantSkillDriver) { this.outer.SetNextState(new LookBusy()); return; } } this.activeSoundTimer -= Time.fixedDeltaTime; if (this.activeSoundTimer <= 0f) { this.activeSoundTimer = UnityEngine.Random.Range(3f, 8f); base.body.CallRpcBark(); } } }