public bool ConditionMatched(ModuleBlockMover block, bool localInput, float m_Val, float m_Vel) { bool Invert = m_InputParam < 0; switch (m_InputType) { case InputType.AlwaysOn: return(true); case InputType.OnPress: m_InputParam = Mathf.Sign(m_InputParam); return((KeyState(CanInput(block, localInput)) == 1) != Invert); case InputType.OnRelease: m_InputParam = Mathf.Sign(m_InputParam); return((KeyState(CanInput(block, localInput)) == 3) != Invert); case InputType.WhileHeld: m_InputParam = Mathf.Sign(m_InputParam); return((KeyState(CanInput(block, localInput)) != 0) != Invert); case InputType.Toggle: m_InputParam = Mathf.Sign(m_InputParam - 0.001f); if (KeyState(CanInput(block, localInput)) == 1) { m_InputParam = -m_InputParam; } return(m_InputParam > 0); case InputType.EnemyTechIsNear: Visible target = block.GetTarget(); if (target == null) { return(Invert); } return(((target.centrePosition - block.block.centreOfMassWorld).sqrMagnitude < m_InputParam * m_InputParam) != Invert); case InputType.PlayerTechIsNear: if (Singleton.playerTank == null) { return(Invert); } if (Singleton.playerTank == block.block.tank) { return(!Invert); } return(((Singleton.playerTank.visible.centrePosition - block.block.centreOfMassWorld).sqrMagnitude < m_InputParam * m_InputParam) != Invert); case InputType.AboveSurfaceElev: var comw = block.block.centreOfMassWorld; ManWorld.inst.GetTerrainHeight(comw, out float outHeight); return((comw.y > outHeight + m_InputParam) != Invert); case InputType.AboveVelocity: return((block.block.tank.rbody.GetPointVelocity(block.block.centreOfMassWorld).sqrMagnitude > m_InputParam * m_InputParam) != Invert); case InputType.IfPosAbove: if (block.IsPlanarVALUE) { return(((block.PVALUE + 900) % 360) - 180 > m_InputParam); } m_InputParam = Mathf.Max(m_InputParam, 0f); return(block.PVALUE > m_InputParam); case InputType.IfPosBelow: if (block.IsPlanarVALUE) { return(((block.PVALUE + 900) % 360) - 180 < m_InputParam); } m_InputParam = Mathf.Max(m_InputParam, 0f); return(block.PVALUE < m_InputParam); case InputType.IfPosEqual: if (block.IsPlanarVALUE) { return(m_InputParam.Approximately(((block.PVALUE + 900) % 360) - 180)); } m_InputParam = Mathf.Max(m_InputParam, 0f); return(block.PVALUE.Approximately(m_InputParam)); case InputType.IfSpeedAbove: return(m_Vel > m_InputParam); case InputType.IfSpeedBelow: return(m_Vel < m_InputParam); case InputType.IfSpeedEqual: return(m_Vel.Approximately(m_InputParam)); default: return(false); } }
/// <summary> /// Process this operation, checking if it's active and then modifying values based on its function /// </summary> /// <param name="block">The ModuleBlockMover to use for calculations</param> /// <param name="ProjectDirToPlane">Is the value used on a plane, or on an axis</param> /// <param name="Value">Positional value to modify</param> /// <param name="Velocity">Positional velocity to modify</param> /// <param name="FreeJoint">Allow free-moving in the attached body</param> /// <param name="LockJoint">Ghost-phasing</param> /// <returns>Returns true if satisfied</returns> public bool Calculate(ModuleBlockMover blockMover, bool LocalInput, bool ProjectDirToPlane, ref float Value, ref float Velocity, ref ModuleBlockMover.MoverType moverType, out int Skip) { Skip = 0; switch (m_OperationType) { case OperationType.OrThen: return(false); case OperationType.ElseThen: Skip = 1; return(false); default: break; } TankBlock block = blockMover.block; if (ConditionMatched(blockMover, LocalInput, Value, Velocity)) { switch (m_OperationType) { case OperationType.ShiftPos: Value += m_Strength; return(true); case OperationType.SetPos: Value = m_Strength; return(true); case OperationType.ShiftSpeed: Velocity += m_Strength; return(true); case OperationType.SetSpeed: Velocity = m_Strength; return(true); case OperationType.ArrowPoint: var vel = block.tank.rbody.GetPointVelocity(block.centreOfMassWorld); if (blockMover.IsPlanarVALUE) { var planar = Vector3.ProjectOnPlane(vel * Mathf.Sign(m_Strength), block.trans.up); Value += SafePlanarPointAngle(block.trans, planar, Value) * Mathf.Clamp01(m_Strength * m_Strength * planar.magnitude); return(true); } Value += block.trans.InverseTransformDirection(vel * Mathf.Sign(m_Strength)).y *Mathf.Clamp01(m_Strength * m_Strength); return(true); case OperationType.TargetPoint: Visible target = blockMover.GetTarget(); if (target == null) { if (m_ResetTimer) { Value = blockMover.UseLIMIT ? blockMover._CENTERLIMIT : 0f; m_ResetTimer = false; } return(false); } m_ResetTimer = true; Value += PointAtTarget(block.trans, (target.GetAimPoint(block.trans.position) - block.centreOfMassWorld) * Mathf.Sign(m_Strength), ProjectDirToPlane, Value) * m_Strength * m_Strength;// * Mathf.Abs(m_Strength); return(true); case OperationType.TargetPointPredictive: float muzzleVelocity = Mathf.Abs(m_Strength); bool useGravity = m_Strength > 0; Visible targetPred = blockMover.GetTarget(); if (targetPred == null) { if (m_ResetTimer) { Value = blockMover.UseLIMIT ? blockMover._CENTERLIMIT : 0f; m_ResetTimer = false; } return(false); } Vector3 BlockCenter = block.centreOfMassWorld; Vector3 AimPointVector = targetPred.GetAimPoint(BlockCenter); Vector3 vector = AimPointVector - BlockCenter; if (muzzleVelocity > 0f) { Vector3 dist = vector; Rigidbody rbodyTank = block.tank.rbody; Vector3 angularToggle = rbodyTank.angularVelocity; Vector3 relativeVelocity = targetPred.rbody.velocity - (rbodyTank.velocity + angularToggle); float time = dist.magnitude / muzzleVelocity; Vector3 relativeAcceleration = BallisticTargeting.GetAcceleration(targetPred.tank) - BallisticTargeting.GetAcceleration(block.tank); if (useGravity) { relativeAcceleration -= Physics.gravity; } float exactTime = BallisticTargeting.SolveBallisticArc(BlockCenter, muzzleVelocity, AimPointVector, relativeVelocity, relativeAcceleration); if (exactTime != Mathf.Infinity) { time = exactTime; } // vector now represents where the enemy will be - still need elevation vector += (time * relativeVelocity) + (relativeAcceleration * time * time / 2); } m_ResetTimer = true; Value += PointAtTarget(block.trans, vector, ProjectDirToPlane, Value);// * Mathf.Abs(m_Strength); return(true); case OperationType.PlayerPoint: Tank playerTank = Singleton.playerTank; if (playerTank == null) { return(false); } Value += PointAtTarget(block.trans, (playerTank.WorldCenterOfMass - block.centreOfMassWorld) * Mathf.Sign(m_Strength), ProjectDirToPlane, Value) * m_Strength * m_Strength; // * Mathf.Abs(m_Strength); return(true); case OperationType.GroundPoint: var comw = block.centreOfMassWorld; ManWorld.inst.GetTerrainHeight(comw, out float outHeight); //return (comw.y > outHeight + m_InputParam); float reducer = Mathf.Abs(Vector3.Dot(block.trans.up, Vector3.up)); if (blockMover.IsPlanarVALUE) { reducer = 1f - reducer; } Value += PointAtTarget(block.trans, Vector3.up * (outHeight - comw.y) * Mathf.Sign(m_Strength), ProjectDirToPlane, Value) * m_Strength * m_Strength * reducer; //Value += PointAtTarget(block.trans, Vector3.down * Mathf.Sign(m_Strength), ProjectDirToPlane, Value) * m_Strength * m_Strength;// * Mathf.Abs(m_Strength); return(true); case OperationType.NorthPoint: if (blockMover.IsPlanarVALUE) { Value = (Vector3.SignedAngle(block.trans.forward, Vector3.ProjectOnPlane(Vector3.forward, block.trans.up), block.trans.up) + m_Strength + 900f) % 360f - 180f; } else { float rad = m_Strength * Mathf.Deg2Rad; Value = block.trans.InverseTransformDirection(new Vector3(Mathf.Sin(rad), 0f, Mathf.Cos(rad))).y; } return(true); case OperationType.SetFreeJoint: if (blockMover.CanOnlyBeLockJoint) { return(false); } if (blockMover.CannotBeFreeJoint) { moverType = ModuleBlockMover.MoverType.Dynamic; } else { moverType = ModuleBlockMover.MoverType.Physics; } return(true); case OperationType.SetBodyJoint: if (blockMover.CanOnlyBeLockJoint) { return(false); } moverType = ModuleBlockMover.MoverType.Dynamic; return(true); case OperationType.SetLockJoint: if (blockMover.CanOnlyBeLockJoint) { return(false); } moverType = ModuleBlockMover.MoverType.Static; return(true); case OperationType.CameraPoint: var camTr = Singleton.cameraTrans; if (camTr == null) { return(false); } Value += PointAtTarget(block.trans, camTr.forward * Mathf.Sign(m_Strength), ProjectDirToPlane, Value) * m_Strength * m_Strength; // * Mathf.Abs(m_Strength); return(true); case OperationType.IfThen: if (m_ResetTimer) { m_InternalTimer = 0f; m_ResetTimer = false; } if (m_Strength == 0f) { return(true); } m_InternalTimer += Time.fixedDeltaTime; // If time is satisfied and strength is positive, do not skip. Negative strength will only activate within that timeframe bool met = (m_InternalTimer >= Mathf.Abs(m_Strength)) == (m_Strength >= 0f); Skip = met ? 0 : 1; return(met); case OperationType.CursorPoint: Value += PointAtTarget(block.trans, (AdjustAttachPosition.PointerPos - block.centreOfMassWorld) * Mathf.Sign(m_Strength), ProjectDirToPlane, Value) * m_Strength * m_Strength; // * Mathf.Abs(m_Strength); return(true); case OperationType.Nothing: return(true); // Light it up in the GUI. Technically, the task did not fail case OperationType.FireWeapons: if (blockMover.Holder == null) { return(false); } if (m_Strength < 0) { blockMover.Holder.ForceNoFireNextFrame = true; } else { blockMover.Holder.ForceFireNextFrame = true; } return(true); default: return(false); } } else if (m_OperationType == OperationType.IfThen) { if (m_Strength != 0) { m_InternalTimer += Time.fixedDeltaTime; } if (m_ResetTimer) { m_InternalTimer = 0f; } else { m_ResetTimer = true; } Skip = 1; } return(false); }