public override void Fire() { const float ATTACK_RADIUS = 3.0f; const float ATTACK_LENGTH = 4.0f; // Play 'thwack' sound Actor owner = GameResources.ActorManager.GetActorById(OwnerActorId); BipedControllerComponent bipedControl = owner.GetComponent <BipedControllerComponent>(ActorComponent.ComponentType.Control); RigidTransform alignCapsule = new RigidTransform(BepuVec3.Forward * ATTACK_LENGTH * 0.5f + BepuConverter.Convert(MuzzleOffset), BepuQuaternion.CreateFromAxisAngle(BepuVec3.Right, MathHelper.PiOver2)); Vector3 aim = (bipedControl.WorldAim.HasValue ? bipedControl.WorldAim.Value : BepuConverter.Convert(bipedControl.Controller.ViewDirection)); RigidTransform positionAndAim = new RigidTransform(bipedControl.Controller.Body.Position, BepuConverter.Convert( SpaceUtils.GetOrientation(aim, Vector3.Up))); RigidTransform attackTransform; RigidTransform.Transform(ref alignCapsule, ref positionAndAim, out attackTransform); ConvexShape bashShape = new CapsuleShape(ATTACK_LENGTH, ATTACK_RADIUS); BepuVec3 noSweep = BepuVec3.Zero; List <RayCastResult> dudesBashed = new List <RayCastResult>(); AttackFilter filter = new AttackFilter(GameResources.ActorManager.IsMob(OwnerActorId)); GameResources.ActorManager.SimSpace.ConvexCast(bashShape, ref attackTransform, ref noSweep, filter.Test, dudesBashed); foreach (RayCastResult dude in dudesBashed) { EntityCollidable otherEntityCollidable = dude.HitObject as EntityCollidable; Terrain otherTerrain = dude.HitObject as Terrain; if (otherEntityCollidable != null && otherEntityCollidable.Entity != null && otherEntityCollidable.Entity.Tag != null) { Actor actorHit = GameResources.ActorManager.GetActorById((int)(otherEntityCollidable.Entity.Tag)); IDamagable damage = actorHit.GetBehaviorThatImplementsType <IDamagable>(); if (damage != null) { damage.TakeDamage(Damage); // TODO: P2: Query hit actor for appropiate damage effect e.g. blood and create it; } BashDust(dude.HitData.Location); } else if (otherTerrain != null) { BashDust(dude.HitData.Location); } } }
private void ProcessAIStepHandler(object sender, UpdateStepEventArgs e) { // Check FOV, add any new foes to memory. And update existing ones. We may also have gained new memories by other means. // Get players and mobs in field of vision: List <RayCastResult> actorsInView = new List <RayCastResult>(); ConeShape visionCone = new ConeShape(VisionDistance, VisionDistance); BipedControllerComponent bcc = Owner.GetComponent <BipedControllerComponent>(ActorComponent.ComponentType.Control); RigidTransform tipOverCone = new RigidTransform(BepuVec3.Forward * VisionDistance * 0.75f, BepuQuaternion.CreateFromAxisAngle(BepuVec3.Right, MathHelper.PiOver2)); RigidTransform eyeLevelAndFacing = new RigidTransform(bcc.Controller.Body.Position - bcc.Controller.Down * bcc.Controller.Body.Height * 0.45f, BepuConverter.Convert(SpaceUtils.GetOrientation(BepuConverter.Convert(bcc.Controller.ViewDirection), Vector3.Up))); RigidTransform visionConeTransform; RigidTransform.Transform(ref tipOverCone, ref eyeLevelAndFacing, out visionConeTransform); BepuVec3 noSweep = BepuVec3.Zero; ViewInterestFilter filter = new ViewInterestFilter(bcc.Controller.Body.CollisionInformation); GameResources.ActorManager.SimSpace.ConvexCast(visionCone, ref visionConeTransform, ref noSweep, filter.Test, actorsInView); for (int a = 0; a < actorsInView.Count; ++a) { // Does this actor warrant an addition to be made to our memory? // If so, check for LOS and recheck range. If those tests pass, modify the memory. EntityCollidable otherEntityCollidable = actorsInView[a].HitObject as EntityCollidable; // We can jump to the Id in the Tag property because we know the filter has validated this. int actorId = (int)(otherEntityCollidable.Entity.Tag); Actor viewedActor = GameResources.ActorManager.GetActorById(actorId); BipedControllerComponent viewedActorBcc = viewedActor.GetComponent <BipedControllerComponent>(ActorComponent.ComponentType.Control); BepuVec3 toSubject = viewedActorBcc.Controller.Body.Position - eyeLevelAndFacing.Position; // Check range: if (toSubject.LengthSquared() <= VisionDistance * VisionDistance) { BepuRay losRay = new BepuRay(eyeLevelAndFacing.Position, toSubject); RayCastResult losResult; LOSFilter losFilter = new LOSFilter(bcc.Controller.Body.CollisionInformation, otherEntityCollidable); GameResources.ActorManager.SimSpace.RayCast(losRay, VisionDistance, losFilter.Test, out losResult); EntityCollidable losEC = losResult.HitObject as EntityCollidable; // Test for LOS: if (losEC != null && losEC.Entity != null && losEC.Entity.Tag != null && (int)(losEC.Entity.Tag) == actorId) { // The viewed actor is either a player(foe) or a mob(ally). if (GameResources.ActorManager.IsPlayer(actorId)) { mMemory.SpotFoe(actorId); } else { IAgentStateManager agent = viewedActor.GetBehaviorThatImplementsType <IAgentStateManager>(); if (agent != null && agent.HasProperty(AgentPropertyName.ActiveOpponent)) { int mobFoe = agent.GetProperty <int>(AgentPropertyName.ActiveOpponent); mMemory.SenseFoe(mobFoe); } } } } } // Evaluate current threats and select one to engage: int enemyId = mMemory.GetLargestThreat(); if (enemyId != Actor.INVALID_ACTOR_ID) { if (mAgentProperties.ContainsKey(AgentPropertyName.ActiveOpponent)) { if ((int)(mAgentProperties[AgentPropertyName.ActiveOpponent]) != enemyId) { mAgentProperties[AgentPropertyName.ActiveOpponent] = enemyId; } } else { mAgentProperties.Add(AgentPropertyName.ActiveOpponent, enemyId); } } else { if (mAgentProperties.ContainsKey(AgentPropertyName.ActiveOpponent)) { mAgentProperties.Remove(AgentPropertyName.ActiveOpponent); } } TimeInState += e.GameTime.ElapsedGameTime; CurrentState.Update(mSteering, Owner, this); Vector2 locomotion = mSteering.ComputeForce(Owner); if (locomotion.LengthSquared() == 0.0f) { bcc.OrientationChange = Quaternion.Identity; bcc.HorizontalMovement = Vector2.Zero; } else { bcc.OrientationChange = Quaternion.CreateFromAxisAngle(Vector3.Up, (float)(Math.Atan2(-locomotion.X, locomotion.Y))); bcc.HorizontalMovement = locomotion.Length() * Vector2.UnitY; } mMemory.Fade(e.GameTime); }