/// <summary> /// Wrap a position equation around a cylinder. /// </summary> /// <param name="radius">Radius of the cylinder</param> /// <param name="ang0">Starting angle offset (radians) on the cylinder. 0 = z-axis</param> /// <param name="maxWrap">Maximum angle value (radians) of the wrap. After this, the function will continue along the tangent. Starting offset not included. Absolute value tested.</param> /// <param name="axisOff">Offset angle (radians) of the axis of the cylinder from the y-axis</param> /// <param name="position">Position equation</param> /// <returns></returns> public static tv3 CylinderWrap(efloat radius, efloat ang0, efloat maxWrap, efloat axisOff, ev2 position) => EEx.Resolve(radius, ang0, axisOff, position, (r, a0, axis, _v2) => { var cs = new TExV2(); var xyd = new TExV2(); var v2 = new TExV2(_v2); var v3 = new TExV3(); var a = ExUtils.VFloat(); var aRem = ExUtils.VFloat(); var aMax = ExUtils.VFloat(); var a_cs = new TExV2(); var a0_cs = new TExV2(); return(Ex.Block(new[] { v3, cs, xyd, a, aRem, aMax, a_cs, a0_cs }, aMax.Is(maxWrap), cs.Is(CosSin(axis)), xyd.Is(ConvertBasis(v2, cs)), a.Is(xyd.x.Div(r)), aRem.Is(E0), Ex.IfThen(Abs(a).GT(aMax), Ex.Block( Ex.IfThen(a.LT0(), MulAssign(aMax, EN1)), aRem.Is(a.Sub(aMax)), a.Is(aMax) )), a0_cs.Is(CosSin(a0)), a_cs.Is(CosSin(a.Add(a0))), xyd.x.Is(r.Mul(a_cs.y.Sub(a0_cs.y).Add(aRem.Mul(a_cs.x)))), v3.Is(TP3(DeconvertBasis(xyd, cs))), v3.z.Is(r.Mul(a_cs.x.Sub(a0_cs.x).Sub(aRem.Mul(a_cs.y)))), v3 )); });
/// <summary> /// Note: requires that normalVec and planeVec are perpendicular. /// </summary> public static tv3 RotateInPlane(tfloat rot, tv3 normalVec, ev3 planeVec) => EEx.Resolve(planeVec, p => { var cs = new TExV2(); var cross = new TExV3(); return(Ex.Block(new ParameterExpression[] { cs, cross }, cs.Is(CosSinDeg(rot)), cross.Is(CrossProduct(normalVec, p)), cs.x.Mul(p).Add(cs.y.Mul(v3Mag(p).Div(v3Mag(cross)).Mul(cross))) )); });
public static tv3 FromSphere(tfloat radius, ev2 sphere) => radius.Mul(EEx.ResolveV2(sphere, s => { var cst = new TExV2(); var csp = new TExV2(); return(Ex.Block(new ParameterExpression[] { cst, csp }, cst.Is(CosSinDeg(s.x)), csp.Is(CosSinDeg(s.y)), V3(cst.x.Mul(csp.y), cst.y.Mul(csp.y), csp.x) )); }));
public static ExTP LNearestEnemy() => b => { var loc = new TExV2(); return(Ex.Block(new ParameterExpression[] { loc }, Ex.IfThen(Ex.Not(Enemy.findNearest.Of(b.loc, loc)), loc.Is(Ex.Constant(new Vector2(0f, 50f))) ), loc )); };
public static ExTP LSaveNearestEnemy() => b => { var key = b.Ctx.NameWithSuffix("_LSaveNearestEnemyKey"); var eid_in = ExUtils.V <int?>(); var eid = ExUtils.V <int>(); var loc = new TExV2(); return(Ex.Block(new[] { eid_in, eid, loc }, eid_in.Is(Ex.Condition(FiringCtx.Contains <int>(b, key), FiringCtx.GetValue <int>(b, key).As <int?>(), Ex.Constant(null).As <int?>()) ), Ex.IfThenElse(Enemy.findNearestSave.Of(b.loc, eid_in, eid, loc), FiringCtx.SetValue <int>(b, key, eid), loc.Is(Ex.Constant(new Vector2(0f, 50f))) ), loc )); };