/// <summary> /// Raises the "OnStateSucceeded" event and switches to the given state. /// </summary> protected void Success(ElveState nextState = null) { Owner.CurrentState = nextState; if (OnStateSucceeded != null) { OnStateSucceeded(this); } }
public override void OnStateStarting(ElveState oldState) { Vector3 myPos = Owner.MyTransform.position; switch (Owner.CurrentSurface) { case ElveBehavior.Surfaces.Floor: case ElveBehavior.Surfaces.Ceiling: targetPos = (int)myPos.x; targetPos += (Dir > 0.0f) ? 1 : 0; break; case ElveBehavior.Surfaces.LeftWall: case ElveBehavior.Surfaces.RightWall: targetPos = (int)myPos.y; targetPos += (Dir > 0.0f) ? 1 : 0; break; } }
public ElveState_MoveToEdge(ElveBehavior owner, ElveState toResume, float dir) : base(owner) { Dir = dir; ToResume = toResume; }
/// <summary> /// An empty callback. Used above when triggering the "OnStateChanged" event. /// </summary> private static void DummyFunc(ElveBehavior m, ElveState s1, ElveState s2) { }
public override void OnStateStarting(ElveState oldState) { //Enable the correct animation and set the x/y scale. float xScale = Owner.MyTransform.localScale.x, yScale = Owner.MyTransform.localScale.y; switch (Owner.CurrentSurface) { case ElveBehavior.Surfaces.Floor: yScale = 1.0f; switch (Target) { case ElveBehavior.Surfaces.Floor: Owner.MyAnimator.AnimState = ElveAnimStates.UseMagicFloorToFloor; break; case ElveBehavior.Surfaces.Ceiling: Owner.MyAnimator.AnimState = ElveAnimStates.UseMagicFloorToCeiling; break; case ElveBehavior.Surfaces.LeftWall: Owner.MyAnimator.AnimState = ElveAnimStates.UseMagicFloorToWall; xScale = -1.0f; break; case ElveBehavior.Surfaces.RightWall: Owner.MyAnimator.AnimState = ElveAnimStates.UseMagicFloorToWall; xScale = 1.0f; break; default: Assert.IsTrue(false); break; } break; case ElveBehavior.Surfaces.Ceiling: yScale = 1.0f; switch (Target) { case ElveBehavior.Surfaces.Floor: Owner.MyAnimator.AnimState = ElveAnimStates.UseMagicCeilingToFloor; break; case ElveBehavior.Surfaces.Ceiling: Owner.MyAnimator.AnimState = ElveAnimStates.UseMagicCeilingToCeiling; break; case ElveBehavior.Surfaces.LeftWall: Owner.MyAnimator.AnimState = ElveAnimStates.UseMagicCeilingToWall; xScale = -1.0f; break; case ElveBehavior.Surfaces.RightWall: Owner.MyAnimator.AnimState = ElveAnimStates.UseMagicCeilingToWall; xScale = 1.0f; break; default: Assert.IsTrue(false); break; } break; case ElveBehavior.Surfaces.LeftWall: xScale = 1.0f; switch (Target) { case ElveBehavior.Surfaces.Floor: Owner.MyAnimator.AnimState = ElveAnimStates.UseMagicWallToCeiling; yScale = -1.0f; break; case ElveBehavior.Surfaces.Ceiling: Owner.MyAnimator.AnimState = ElveAnimStates.UseMagicWallToCeiling; yScale = 1.0f; break; case ElveBehavior.Surfaces.LeftWall: Owner.MyAnimator.AnimState = ElveAnimStates.UseMagicWallToSelf; break; case ElveBehavior.Surfaces.RightWall: Owner.MyAnimator.AnimState = ElveAnimStates.UseMagicWallToWall; break; default: Assert.IsTrue(false); break; } break; case ElveBehavior.Surfaces.RightWall: xScale = -1.0f; switch (Target) { case ElveBehavior.Surfaces.Floor: Owner.MyAnimator.AnimState = ElveAnimStates.UseMagicWallToCeiling; yScale = -1.0f; break; case ElveBehavior.Surfaces.Ceiling: Owner.MyAnimator.AnimState = ElveAnimStates.UseMagicWallToCeiling; yScale = 1.0f; break; case ElveBehavior.Surfaces.LeftWall: Owner.MyAnimator.AnimState = ElveAnimStates.UseMagicWallToWall; break; case ElveBehavior.Surfaces.RightWall: Owner.MyAnimator.AnimState = ElveAnimStates.UseMagicWallToSelf; break; default: Assert.IsTrue(false); break; } break; default: Assert.IsTrue(false); break; } Owner.MyTransform.localScale = new Vector3(xScale, yScale, Owner.MyTransform.localScale.z); }
public override void OnStateStarting(ElveState oldState) { Vector3 pos = Owner.MyTransform.position; Vector2i posI = ToPosI(pos); float distToEdge; //See if we have to move to the edge of the voxel first. switch (Owner.CurrentSurface) { case ElveBehavior.Surfaces.Floor: case ElveBehavior.Surfaces.Ceiling: if (MoveAmount.x == -1) { distToEdge = pos.x - posI.x; } else { distToEdge = (posI.x + 1) - pos.x; } if (distToEdge > 0.001f) { Owner.CurrentState = new ElveState_MoveToEdge(Owner, this, MoveAmount.x); return; } break; case ElveBehavior.Surfaces.LeftWall: case ElveBehavior.Surfaces.RightWall: if (MoveAmount.y == -1) { distToEdge = pos.y - posI.y; } else { distToEdge = (posI.y + 1) - pos.y; } if (distToEdge > 0.001f) { Owner.CurrentState = new ElveState_MoveToEdge(Owner, this, MoveAmount.y); return; } break; default: Assert.IsTrue(false); break; } //Different but similar code will run based on which direction is being moved in. //Basically, for either of the 4 movement directions for ledge crossing, // it can either be for a right-side-up ledge (from/to the floor) // or an upside-down ledge (from/to the ceiling). Vector2i testPos = posI; ElveBehavior.Surfaces rightSideUpTargetSurface, upsideDownTargetSurface, rightSideUpFinalSurface, upsideDownFinalSurface; ElveAnimStates rightSideUpAnim, upsideDownAnim; float xScale; if (MoveAmount.x == 1 && MoveAmount.y == 1) { testPos.x += 1; rightSideUpTargetSurface = ElveBehavior.Surfaces.RightWall; rightSideUpAnim = ElveAnimStates.MountingLedge; rightSideUpFinalSurface = ElveBehavior.Surfaces.Floor; upsideDownTargetSurface = ElveBehavior.Surfaces.Ceiling; upsideDownAnim = ElveAnimStates.DroppingToLedgeUpsideDown; upsideDownFinalSurface = ElveBehavior.Surfaces.LeftWall; xScale = 1.0f; } else if (MoveAmount.x == -1 && MoveAmount.y == 1) { testPos.x -= 1; rightSideUpTargetSurface = ElveBehavior.Surfaces.LeftWall; rightSideUpAnim = ElveAnimStates.MountingLedge; rightSideUpFinalSurface = ElveBehavior.Surfaces.Floor; upsideDownTargetSurface = ElveBehavior.Surfaces.Ceiling; upsideDownAnim = ElveAnimStates.DroppingToLedgeUpsideDown; upsideDownFinalSurface = ElveBehavior.Surfaces.RightWall; xScale = -1.0f; } else if (MoveAmount.x == 1 && MoveAmount.y == -1) { testPos.y -= 1; rightSideUpTargetSurface = ElveBehavior.Surfaces.Floor; rightSideUpAnim = ElveAnimStates.DroppingToLedge; rightSideUpFinalSurface = ElveBehavior.Surfaces.LeftWall; upsideDownTargetSurface = ElveBehavior.Surfaces.RightWall; upsideDownAnim = ElveAnimStates.MountingLedgeUpsideDown; upsideDownFinalSurface = ElveBehavior.Surfaces.Ceiling; xScale = -1.0f; } else if (MoveAmount.x == -1 && MoveAmount.y == -1) { testPos.y -= 1; rightSideUpTargetSurface = ElveBehavior.Surfaces.Floor; rightSideUpAnim = ElveAnimStates.DroppingToLedge; rightSideUpFinalSurface = ElveBehavior.Surfaces.RightWall; upsideDownTargetSurface = ElveBehavior.Surfaces.LeftWall; upsideDownAnim = ElveAnimStates.MountingLedgeUpsideDown; upsideDownFinalSurface = ElveBehavior.Surfaces.Ceiling; xScale = 1.0f; } else { throw new InvalidOperationException("Should never see this! MoveAmount is " + MoveAmount); } //Get whether this is a right-side-up ledge or not. if (WorldVoxels.IsSolid(WorldVoxels.Instance.Voxels[testPos.x, testPos.y])) { //Switch to the correct surface if needed. if (Owner.CurrentSurface != rightSideUpTargetSurface) { Owner.CurrentState = new ElveState_ChangeSurface(Owner, this, Owner.CurrentSurface, rightSideUpTargetSurface); return; } //Otherwise, everything is in place; play the animation. else { Owner.MyAnimator.AnimState = rightSideUpAnim; targetSurface = rightSideUpFinalSurface; } } else { //Switch to the correct surface if needed. if (Owner.CurrentSurface != upsideDownTargetSurface) { Owner.CurrentState = new ElveState_ChangeSurface(Owner, this, Owner.CurrentSurface, upsideDownTargetSurface); return; } //Otherwise, everything is in place; play the animation. else { Owner.MyAnimator.AnimState = upsideDownAnim; targetSurface = upsideDownFinalSurface; } } Owner.MyTransform.localScale = new Vector3(xScale, 1.0f, Owner.MyTransform.localScale.z); Owner.MyAnimator.ActiveAnim.GetComponent<ElveAnimFinishEvent>().OnAnimFinished += OnAnimFinished; }
private void OnStateFinished(ElveState oldState) { UpdatePos(); Assert.IsTrue(currentPos == targetPos, "Target was " + targetPos + " but actual pos is " + currentPos); Path.RemoveAt(Path.Count - 1); if (Path.Count > 0) { targetPos = Path[Path.Count - 1].WorldPos; Vector2i delta = targetPos - currentPos; Assert.IsTrue(delta.x == -1 || delta.x == 1 || delta.y == -1 || delta.y == 1); //Choose the correct state based on movement. ElveState state; if (delta.y == 0) { state = new ElveState_Walk(fsm, (float)delta.x); } else if (delta.x == 0) { state = new ElveState_Climb(fsm, (float)delta.y); } else { state = new ElveState_CrossLedge(fsm, delta); } state.OnStateSucceeded += OnStateFinished; fsm.CurrentState = state; } else { if (OnPathCompleted != null) { //Store the event in a temp variable and wipe out the actual event // so new subscribers can be added for the next path. PathCompletedCallback tempEvent = (OnPathCompleted + DummyFunc); OnPathCompleted = null; tempEvent(this); } } }
public override void OnStateStarting(ElveState oldState) { Vector3 myPos = Owner.MyTransform.position; TargetPos = ToPosI(myPos) + new Vector2i(0, Mathf.RoundToInt(Dir)); //See if any surface transitions need to be made before engaging in this state. VoxelTypes[,] vxs = WorldVoxels.Instance.Voxels; switch (Owner.CurrentSurface) { case ElveBehavior.Surfaces.LeftWall: Assert.IsTrue(TargetPos.x > 0); if (!WorldVoxels.IsSolid(vxs[TargetPos.x - 1, TargetPos.y])) { Assert.IsTrue(TargetPos.x < vxs.GetLength(0) - 1); Assert.IsTrue(WorldVoxels.IsSolid(vxs[TargetPos.x + 1, TargetPos.y])); Owner.CurrentState = new ElveState_ChangeSurface(Owner, this, ElveBehavior.Surfaces.LeftWall, ElveBehavior.Surfaces.RightWall); } break; case ElveBehavior.Surfaces.RightWall: Assert.IsTrue(TargetPos.x < vxs.GetLength(0) - 1); if (!WorldVoxels.IsSolid(vxs[TargetPos.x + 1, TargetPos.y])) { Assert.IsTrue(TargetPos.x > 0 && WorldVoxels.IsSolid(vxs[TargetPos.x - 1, TargetPos.y])); Owner.CurrentState = new ElveState_ChangeSurface(Owner, this, ElveBehavior.Surfaces.RightWall, ElveBehavior.Surfaces.LeftWall); } break; case ElveBehavior.Surfaces.Floor: case ElveBehavior.Surfaces.Ceiling: if (TargetPos.x > 0 && WorldVoxels.IsSolid(vxs[TargetPos.x - 1, TargetPos.y])) { ElveState changeSurface = new ElveState_ChangeSurface(Owner, this, Owner.CurrentSurface, ElveBehavior.Surfaces.LeftWall); //If we need to move to the edge of this voxel first, do it. int targetX = (int)myPos.x; if (Mathf.Abs((float)targetX - myPos.x) < 0.001f) { Owner.CurrentState = changeSurface; } else { Owner.CurrentState = new ElveState_MoveToEdge(Owner, changeSurface, -1.0f); } } else { Assert.IsTrue(TargetPos.x < vxs.GetLength(0) - 1); Assert.IsTrue(WorldVoxels.IsSolid(vxs[TargetPos.x + 1, TargetPos.y])); ElveState changeSurface = new ElveState_ChangeSurface(Owner, this, Owner.CurrentSurface, ElveBehavior.Surfaces.RightWall); //If we need to move to the edge of this voxel first, do it. int targetX = (int)myPos.x + 1; if (Mathf.Abs((float)targetX - myPos.x) < 0.001f) { Owner.CurrentState = changeSurface; } else { Owner.CurrentState = new ElveState_MoveToEdge(Owner, changeSurface, 1.0f); } } break; default: Assert.IsTrue(false, "Unknown state " + Owner.CurrentSurface); break; } }
public virtual void OnStateStarting(ElveState oldState) { }
public virtual void OnStateEnding(ElveState nextState) { }