internal void UpdateSubGrids(GridAi ai, bool resetTick = false) { foreach (var sub in ai.SubGrids) { if (ai.MyGrid == sub) { continue; } GridAi gridAi; if (ai.Session.GridTargetingAIs.TryGetValue(sub, out gridAi)) { if (resetTick) { gridAi.TargetResetTick = gridAi.Session.Tick + 1; } for (int i = 0; i < gridAi.Focus.Target.Length; i++) { gridAi.Focus.Target[i] = Target[i]; gridAi.Focus.HasFocus = HasFocus; gridAi.Focus.ActiveId = ActiveId; } } } }
internal void Update(Vector3D hitPos, GridAi ai, MyEntity ent = null, long entId = 0) { if ((ent != null || entId != 0 && MyEntities.TryGetEntityById(entId, out ent)) && ent.Physics != null) { var referenceWorldMatrix = ent.PositionComp.WorldMatrixRef; Vector3D referenceWorldPosition = referenceWorldMatrix.Translation; Vector3D worldDirection = hitPos - referenceWorldPosition; EntityId = ent.EntityId; LocalPosition = Vector3D.TransformNormal(worldDirection, MatrixD.Transpose(referenceWorldMatrix)); } else { if (Type == FakeType.Manual) { FakeInfo.WorldPosition = hitPos; } EntityId = 0; LocalPosition = Vector3D.Zero; FakeInfo.LinearVelocity = Vector3.Zero; FakeInfo.Acceleration = Vector3.Zero; } Dirty = false; LastInfoTick = 0; LastUpdateTick = ai.Session.Tick; }
internal Constructs(GridAi ai) { FatMap fatMap; if (ai?.MyGrid != null && ai.Session.GridToFatMap.TryGetValue(ai.MyGrid, out fatMap)) { BlockCount = fatMap.MostBlocks; OptimalDps = ai.OptimalDps; foreach (var grid in ai.SubGrids) { if (grid == ai.MyGrid) { continue; } if (ai.Session.GridToFatMap.TryGetValue(grid, out fatMap)) { BlockCount += ai.Session.GridToFatMap[grid].MostBlocks; OptimalDps += ai.OptimalDps; } } return; } OptimalDps = 0; BlockCount = 0; }
internal bool ServerIsFocused(GridAi ai) { var fd = ai.Construct.Data.Repo.FocusData; fd.HasFocus = false; for (int i = 0; i < fd.Target.Length; i++) { if (fd.Target[i] > 0) { if (MyEntities.GetEntityById(fd.Target[fd.ActiveId]) != null) { fd.HasFocus = true; } else { fd.Target[i] = -1; fd.Locked[i] = LockModes.None; } } if (fd.Target[0] <= 0 && fd.HasFocus) { fd.Target[0] = fd.Target[i]; fd.Locked[0] = fd.Locked[i]; fd.Target[i] = -1; fd.Locked[i] = LockModes.None; fd.ActiveId = 0; } } return(fd.HasFocus); }
internal void Clean() { Target = null; MyGrid = null; MyAi = null; TargetAi = null; }
internal void ServerNextActive(bool addSecondary, GridAi ai) { var fd = ai.Construct.Data.Repo.FocusData; var prevId = fd.ActiveId; var newActiveId = prevId; if (newActiveId + 1 > fd.Target.Length - 1) { newActiveId -= 1; } else { newActiveId += 1; } if (addSecondary && fd.Target[newActiveId] <= 0) { fd.Target[newActiveId] = fd.Target[prevId]; fd.ActiveId = newActiveId; } else if (!addSecondary && fd.Target[newActiveId] > 0) { fd.ActiveId = newActiveId; } ServerIsFocused(ai); ai.Construct.UpdateConstruct(GridAi.Constructs.UpdateType.Focus, ChangeDetected(ai)); }
internal void Init(ref DetectInfo detectInfo, MyCubeGrid myGrid, GridAi myAi, GridAi targetAi) { EntInfo = detectInfo.EntInfo; Target = detectInfo.Parent; PartCount = detectInfo.PartCount; FatCount = detectInfo.FatCount; IsStatic = Target.Physics.IsStatic; IsGrid = detectInfo.IsGrid; LargeGrid = detectInfo.LargeGrid; MyGrid = myGrid; MyAi = myAi; TargetAi = targetAi; Velocity = Target.Physics.LinearVelocity; VelLenSqr = Velocity.LengthSquared(); var targetSphere = Target.PositionComp.WorldVolume; TargetPos = targetSphere.Center; TargetRadius = targetSphere.Radius; var myCenter = myAi.GridVolume.Center; if (!MyUtils.IsZero(Velocity, 1E-02F)) { var targetMag = myCenter - TargetPos; Approaching = MathFuncs.IsDotProductWithinTolerance(ref Velocity, ref targetMag, myAi.Session.ApproachDegrees); } else { Approaching = false; TargetHeading = Vector3D.Zero; } if (targetAi != null) { OffenseRating = targetAi.Construct.OptimalDps / myAi.Construct.OptimalDps; if (OffenseRating <= 0 && detectInfo.Armed) { OffenseRating = 0.0001f; } } else if (detectInfo.Armed) { OffenseRating = 0.0001f; } else { OffenseRating = 0; } var myRadius = myAi.MyGrid.PositionComp.LocalVolume.Radius; var sphereDistance = MyUtils.GetSmallestDistanceToSphere(ref myCenter, ref targetSphere); if (sphereDistance <= myRadius) { sphereDistance = 0; } else { sphereDistance -= myRadius; } DistSqr = sphereDistance * sphereDistance; }
internal FakeWorldTargetInfo GetFakeTargetInfo(GridAi ai) { MyEntity ent; if (EntityId != 0 && (MyEntities.TryGetEntityById(EntityId, out ent) && ent.Physics != null)) { if (ai.Session.Tick != LastInfoTick) { LastInfoTick = ai.Session.Tick; if (Type != FakeType.Painted || ai.Targets.ContainsKey(ent)) { FakeInfo.WorldPosition = Vector3D.Transform(LocalPosition, ent.PositionComp.WorldMatrixRef); FakeInfo.LinearVelocity = ent.Physics.LinearVelocity; FakeInfo.Acceleration = ent.Physics.LinearAcceleration; } else if (Type == FakeType.Painted) { Dirty = true; } } } else if (Type == FakeType.Painted) { Dirty = true; } return(FakeInfo); }
internal void NextActive(bool addSecondary, GridAi ai, bool alreadySynced = false) { var prevId = ActiveId; var newActiveId = prevId; if (newActiveId + 1 > Target.Length - 1) { newActiveId -= 1; } else { newActiveId += 1; } if (addSecondary && Target[newActiveId] == null) { Target[newActiveId] = Target[prevId]; ActiveId = newActiveId; } else if (!addSecondary && Target[newActiveId] != null) { ActiveId = newActiveId; } IsFocused(ai); if (ai.Session.MpActive && ai.Session.HandlesInput && !alreadySynced) { ai.Session.SendNextActiveUpdate(ai, addSecondary); } }
internal bool IsFocused(GridAi ai) { HasFocus = false; for (int i = 0; i < Target.Length; i++) { if (Target[i] != null) { if (!Target[i].MarkedForClose) { HasFocus = true; } else { Target[i] = null; } } if (Target[0] == null && HasFocus) { Target[0] = Target[i]; Target[i] = null; ActiveId = 0; } } UpdateSubGrids(ai); return(HasFocus); }
internal void Refresh(GridAi ai, RefreshCaller caller) { if (RootAi.Session.IsServer && RootAi.Construct.RecentItems.Count > 0) { CheckEmptyWeapons(); } OptimalDps = 0; BlockCount = 0; FatMap fatMap; if (ai.Session.GridToFatMap.TryGetValue(ai.MyGrid, out fatMap)) { GridAi leadingAi = null; foreach (var grid in ai.SubGrids) { GridAi thisAi; if (ai.Session.GridTargetingAIs.TryGetValue(grid, out thisAi)) { if (leadingAi == null) { leadingAi = thisAi; } else { if (leadingAi.MyGrid.EntityId > grid.EntityId) { leadingAi = thisAi; } } } if (ai.Session.GridToFatMap.TryGetValue(grid, out fatMap)) { BlockCount += ai.Session.GridToFatMap[grid].MostBlocks; if (thisAi != null) { OptimalDps += thisAi.OptimalDps; } } else { Log.Line($"ConstructRefresh Failed sub no fatmap, sub is caller:{grid == ai.MyGrid}"); } } RootAi = leadingAi; if (RootAi == null) { Log.Line($"[rootAi is null in Update] subCnt:{ai.SubGrids.Count}(includeMe:{ai.SubGrids.Contains(ai.MyGrid)}) - caller:{caller}, forcing rootAi to caller - inGridTarget:{ai.Session.GridTargetingAIs.ContainsKey(ai.MyGrid)} - myGridMarked:{ai.MyGrid.MarkedForClose} - aiMarked:{ai.MarkedForClose} - lastClosed:{ai.AiCloseTick} - aiSpawned:{ai.AiSpawnTick} - diff:{ai.AiSpawnTick - ai.AiCloseTick} - sinceSpawn:{ai.Session.Tick - ai.AiSpawnTick}"); RootAi = ai; } UpdateWeaponCounters(ai); return; } Log.Line($"ConstructRefresh Failed main Ai no FatMap: {caller} - Marked: {ai.MyGrid.MarkedForClose}"); RootAi = null; }
internal void Clean() { Data.Clean(); OptimalDps = 0; BlockCount = 0; RootAi = null; Counter.Clear(); RefreshedAis.Clear(); }
internal void RequestNextActive(bool addSecondary, GridAi ai) { if (ai.Session.IsServer) { ServerNextActive(addSecondary, ai); } else { ai.Session.SendNextActiveUpdate(ai, addSecondary); } }
internal void ServerReleaseActive(GridAi ai) { var fd = ai.Construct.Data.Repo.FocusData; fd.Target[fd.ActiveId] = -1; fd.Locked[fd.ActiveId] = LockModes.None; ServerIsFocused(ai); ai.Construct.UpdateConstruct(GridAi.Constructs.UpdateType.Focus, ChangeDetected(ai)); }
internal void Clean() { Data.Clean(); OptimalDps = 0; BlockCount = 0; RootAi = null; LargestAi = null; Counter.Clear(); RefreshedAis.Clear(); PreviousTargets.Clear(); }
internal void Close() { // Reset only vars that are not always set Hit = new Hit(); if (AmmoSound) { TravelEmitter.StopSound(true); AmmoSound = false; } HitVelocity = Vector3D.Zero; TracerBack = Vector3D.Zero; TracerFront = Vector3D.Zero; ClosestPointOnLine = Vector3D.Zero; Color = Vector4.Zero; OnScreen = Screen.None; Tracer = TracerState.Off; Trail = TrailState.Off; LifeTime = 0; TracerSteps = 0; TracerStep = 0; DistanceToLine = 0; TracerWidth = 0; TrailWidth = 0; TrailScaler = 0; MaxTrajectory = 0; ShotFade = 0; ParentId = ulong.MaxValue; Dirty = false; AmmoSound = false; HitSoundActive = false; StartSoundActived = false; IsShrapnel = false; HasTravelSound = false; HitParticle = ParticleState.None; Triggered = false; Cloaked = false; Active = false; TrailActivated = false; ShrinkInited = false; Hitting = false; Back = false; LastStep = false; DetonateFakeExp = false; TracerShrinks.Clear(); GlowSteps.Clear(); Offsets.Clear(); // FiringWeapon = null; PrimeEntity = null; TriggerEntity = null; Ai = null; AmmoDef = null; System = null; }
internal void ReleaseActive(GridAi ai, bool alreadySynced = false) { Target[ActiveId] = null; IsFocused(ai); if (ai.Session.MpActive && ai.Session.HandlesInput && !alreadySynced) { ai.Session.SendReleaseActiveUpdate(ai); } }
internal void RequestAddLock(GridAi ai) { if (ai.Session.IsServer) { ServerCycleLock(ai); } else { ai.Session.SendFocusLockUpdate(ai); } }
internal void RequestReleaseActive(GridAi ai) { if (ai.Session.IsServer) { ServerReleaseActive(ai); } else { ai.Session.SendReleaseActiveUpdate(ai); } }
internal void ServerAddFocus(MyEntity target, GridAi ai) { var session = ai.Session; var fd = ai.Construct.Data.Repo.FocusData; fd.Target[fd.ActiveId] = target.EntityId; ai.TargetResetTick = session.Tick + 1; ServerIsFocused(ai); ai.Construct.UpdateConstruct(GridAi.Constructs.UpdateType.Focus, ChangeDetected(ai)); }
internal void RequestAddFocus(MyEntity target, GridAi ai) { if (ai.Session.IsServer) { ServerAddFocus(target, ai); } else { ai.Session.SendFocusTargetUpdate(ai, target.EntityId); } }
internal void AddFocus(MyEntity target, GridAi ai, bool alreadySynced = false) { var session = ai.Session; Target[ActiveId] = target; ai.TargetResetTick = session.Tick + 1; IsFocused(ai); if (session.MpActive && session.HandlesInput && !alreadySynced) { session.SendFocusTargetUpdate(ai, target.EntityId); } }
private static bool AcquireBlock(WeaponSystem system, GridAi ai, Target target, TargetInfo info, Vector3D weaponPos, WeaponRandomGenerator wRng, RandomType type, ref BoundingSphereD waterSphere, Weapon w = null, bool checkPower = true) { if (system.TargetSubSystems) { var subSystems = system.Values.Targeting.SubSystems; var targetLinVel = info.Target.Physics?.LinearVelocity ?? Vector3D.Zero; var targetAccel = (int)system.Values.HardPoint.AimLeadingPrediction > 1 ? info.Target.Physics?.LinearAcceleration ?? Vector3D.Zero : Vector3.Zero; var focusSubSystem = w != null && w.Comp.Data.Repo.Base.Set.Overrides.FocusSubSystem; foreach (var blockType in subSystems) { var bt = focusSubSystem ? w.Comp.Data.Repo.Base.Set.Overrides.SubSystem : blockType; ConcurrentDictionary <BlockTypes, ConcurrentCachingList <MyCubeBlock> > blockTypeMap; system.Session.GridToBlockTypeMap.TryGetValue((MyCubeGrid)info.Target, out blockTypeMap); if (bt != Any && blockTypeMap != null && blockTypeMap[bt].Count > 0) { var subSystemList = blockTypeMap[bt]; if (system.ClosestFirst) { if (target.Top5.Count > 0 && (bt != target.LastBlockType || target.Top5[0].CubeGrid != subSystemList[0].CubeGrid)) { target.Top5.Clear(); } target.LastBlockType = bt; if (GetClosestHitableBlockOfType(subSystemList, ai, target, weaponPos, targetLinVel, targetAccel, ref waterSphere, w, checkPower)) { return(true); } } else if (FindRandomBlock(system, ai, target, weaponPos, info, subSystemList, w, wRng, type, ref waterSphere, checkPower)) { return(true); } } if (focusSubSystem) { break; } } if (system.OnlySubSystems || focusSubSystem && w.Comp.Data.Repo.Base.Set.Overrides.SubSystem != Any) { return(false); } } FatMap fatMap; return(system.Session.GridToFatMap.TryGetValue((MyCubeGrid)info.Target, out fatMap) && fatMap.MyCubeBocks != null && FindRandomBlock(system, ai, target, weaponPos, info, fatMap.MyCubeBocks, w, wRng, type, ref waterSphere, checkPower)); }
internal void ReassignTarget(MyEntity target, int focusId, GridAi ai) { var fd = ai.Construct.Data.Repo.FocusData; if (focusId >= fd.Target.Length || target == null || target.MarkedForClose) { return; } fd.Target[focusId] = target.EntityId; ServerIsFocused(ai); ai.Construct.UpdateConstruct(GridAi.Constructs.UpdateType.Focus, ChangeDetected(ai)); }
internal void Init(ref DetectInfo detectInfo, MyCubeGrid myGrid, GridAi myAi, GridAi targetAi) { EntInfo = detectInfo.EntInfo; Target = detectInfo.Parent; PartCount = detectInfo.PartCount; FatCount = detectInfo.FatCount; IsGrid = detectInfo.IsGrid; LargeGrid = detectInfo.LargeGrid; MyGrid = myGrid; MyAi = myAi; TargetAi = targetAi; Velocity = Target.Physics.LinearVelocity; VelLenSqr = Velocity.LengthSquared(); var targetSphere = Target.PositionComp.WorldVolume; TargetPos = targetSphere.Center; TargetRadius = targetSphere.Radius; if (!MyUtils.IsZero(Velocity, 1E-02F)) { TargetDir = Vector3D.Normalize(Velocity); var refDir = Vector3D.Normalize(myAi.GridVolume.Center - TargetPos); Approaching = MathFuncs.IsDotProductWithinTolerance(ref TargetDir, ref refDir, myAi.Session.ApproachDegrees); } else { TargetDir = Vector3D.Zero; Approaching = false; } if (targetAi != null) { OffenseRating = targetAi.Construct.OptimalDps / myAi.Construct.OptimalDps; } else if (detectInfo.Armed) { OffenseRating = 0.0001f; } else { OffenseRating = 0; } var targetDist = Vector3D.Distance(myAi.GridVolume.Center, TargetPos) - TargetRadius; targetDist -= myAi.GridVolume.Radius; if (targetDist < 0) { targetDist = 0; } DistSqr = targetDist * targetDist; }
internal void Init(ProInfo info, double firstStepSize, double maxSpeed) { System = info.System; AmmoDef = info.AmmoDef; Ai = info.Ai; IsShrapnel = info.IsShrapnel; if (ParentId != ulong.MaxValue) { Log.Line($"invalid avshot, parentId:{ParentId}"); } ParentId = info.Id; Model = (info.AmmoDef.Const.PrimeModel || info.AmmoDef.Const.TriggerModel) ? Model = ModelState.Exists : Model = ModelState.None; PrimeEntity = info.PrimeEntity; TriggerEntity = info.TriggerEntity; Origin = info.Origin; Offset = AmmoDef.Const.OffsetEffect; MaxTracerLength = info.TracerLength; MuzzleId = info.MuzzleId; WeaponId = info.WeaponId; MaxSpeed = maxSpeed; MaxStepSize = MaxSpeed * MyEngineConstants.PHYSICS_STEP_SIZE_IN_SECONDS; ShootVelStep = info.ShooterVel * MyEngineConstants.PHYSICS_STEP_SIZE_IN_SECONDS; info.Ai.WeaponBase.TryGetValue(info.Target.FiringCube, out FiringWeapon); MaxTrajectory = info.MaxTrajectory; ShotFade = info.ShotFade; ShrinkInited = false; HitEmitter.CanPlayLoopSounds = false; if (AmmoDef.Const.DrawLine) { Tracer = !AmmoDef.Const.IsBeamWeapon && firstStepSize < MaxTracerLength && !MyUtils.IsZero(firstStepSize - MaxTracerLength, 1E-01F) ? TracerState.Grow : TracerState.Full; } else { Tracer = TracerState.Off; } if (AmmoDef.Const.Trail) { MaxGlowLength = MathHelperD.Clamp(AmmoDef.AmmoGraphics.Lines.Trail.DecayTime * MaxStepSize, 0.1f, MaxTrajectory); Trail = AmmoDef.AmmoGraphics.Lines.Trail.Back ? TrailState.Back : Trail = TrailState.Front; GlowShrinkSize = !AmmoDef.AmmoGraphics.Lines.Trail.UseColorFade ? AmmoDef.Const.TrailWidth / AmmoDef.AmmoGraphics.Lines.Trail.DecayTime : 1f / AmmoDef.AmmoGraphics.Lines.Trail.DecayTime; Back = Trail == TrailState.Back; } else { Trail = TrailState.Off; } TotalLength = MathHelperD.Clamp(MaxTracerLength + MaxGlowLength, 0.1f, MaxTrajectory); }
internal void InitVirtual(WeaponSystem system, GridAi ai, AmmoDef ammodef, MyEntity primeEntity, MyEntity triggerEntity, Target target, int weaponId, int muzzleId, Vector3D origin, Vector3D virDirection) { System = system; Ai = ai; AmmoDef = ammodef; PrimeEntity = primeEntity; TriggerEntity = triggerEntity; Target.Entity = target.Entity; Target.Projectile = target.Projectile; Target.FiringCube = target.FiringCube; WeaponId = weaponId; MuzzleId = muzzleId; Direction = virDirection; Origin = origin; }
internal bool ReassignTarget(MyEntity target, int focusId, GridAi ai, bool alreadySynced = false) { if (focusId >= Target.Length || target == null || target.MarkedForClose) { return(false); } Target[focusId] = target; IsFocused(ai); if (ai.Session.MpActive && ai.Session.HandlesInput && !alreadySynced) { ai.Session.SendReassignTargetUpdate(ai, target.EntityId, focusId); } return(true); }
internal void ServerCycleLock(GridAi ai) { var session = ai.Session; var fd = ai.Construct.Data.Repo.FocusData; var currentMode = fd.Locked[fd.ActiveId]; var modeCount = Enum.GetNames(typeof(LockModes)).Length; var nextMode = (int)currentMode + 1 < modeCount ? currentMode + 1 : (LockModes)0; fd.Locked[fd.ActiveId] = nextMode; ai.TargetResetTick = session.Tick + 1; ServerIsFocused(ai); ai.Construct.UpdateConstruct(GridAi.Constructs.UpdateType.Focus, ChangeDetected(ai)); }
internal void Update(Vector3D hitPos, GridAi ai, MyEntity ent = null, bool networkUpdate = false) { Position = hitPos; if (ent != null) { LinearVelocity = ent.Physics?.LinearVelocity ?? Vector3.Zero; Acceleration = ent.Physics?.LinearAcceleration ?? Vector3.Zero; } if (ai.Session.MpActive && !networkUpdate) { ai.Session.SendFakeTargetUpdate(ai, hitPos); } ClearTarget = false; }