internal override void ActionCommand(Game game) { OrderableProcessor.ProcessOrderList(game, NestedCommands); if (NestedCommands.Count == 0) { if (!IsRunning) { var entPos = _entityCommanding.GetDataBlob <PositionDB>().PositionInKm; var tarPos = _targetEntity.GetDataBlob <PositionDB>().PositionInKm; double distanceAU = PositionDB.GetDistanceBetween(_entityCommanding.GetDataBlob <PositionDB>(), _targetEntity.GetDataBlob <PositionDB>()); var rangeAU = ApihelionInKM / GameConstants.Units.KmPerAu; if (Math.Abs(rangeAU - distanceAU) <= 500 / GameConstants.Units.MetersPerAu) //distance within 500m { DateTime datenow = _entityCommanding.Manager.ManagerSubpulses.SystemLocalDateTime; var newOrbit = ShipMovementProcessor.CreateOrbitHereWithPerihelion(_entityCommanding, _targetEntity, PerhelionInKM, datenow); _entityCommanding.SetDataBlob(newOrbit); IsRunning = true; } else //insert new translate move { var cmd = new TranslateMoveCommand() { RequestingFactionGuid = this.RequestingFactionGuid, EntityCommandingGuid = this.EntityCommandingGuid, CreatedDate = this.CreatedDate, TargetEntityGuid = this.TargetEntityGuid, RangeInKM = this.ApihelionInKM }; NestedCommands.Insert(0, cmd); cmd.IsValidCommand(game); cmd.ActionCommand(game); } } } }
/* * public TimeSpan RunFrequency => TimeSpan.FromMinutes(60); * * public void ProcessEntity(Entity entity, int deltaSeconds) * { * SetEntityProfile(entity); * } * * public void ProcessManager(EntityManager manager, int deltaSeconds) * { * Stopwatch timer = new Stopwatch(); * timer.Start(); * var entites = manager.GetAllEntitiesWithDataBlob<SensorProfileDB>(); * foreach (var entity in entites) * { * ProcessEntity(entity, deltaSeconds); * } * var ms = timer.ElapsedMilliseconds; * var numEntites = entites.Count; * } */ internal static void SetEntityProfile(Entity entity, DateTime atDate) { var position = entity.GetDataBlob <PositionDB>(); var sensorSig = entity.GetDataBlob <SensorProfileDB>(); sensorSig.LastPositionOfReflectionSet = position.AbsolutePosition_AU; sensorSig.LastDatetimeOfReflectionSet = atDate; var emmiters = entity.Manager.GetAllEntitiesWithDataBlob <SensorProfileDB>(); int numberOfEmmitters = emmiters.Count; sensorSig.ReflectedEMSpectra.Clear(); PercentValue reflectionPercent = 0.1f; //TODO: this should be calculated from crossSection(size), distance, and a reflectivity value(stealth armor?/ other design factors?). foreach (var emittingEntity in emmiters) { if (emittingEntity != entity) // don't reflect our own emmision. { double distance = PositionDB.GetDistanceBetween(position, emittingEntity.GetDataBlob <PositionDB>()); var emmissionDB = emittingEntity.GetDataBlob <SensorProfileDB>(); foreach (var emitedItem in emmissionDB.EmittedEMSpectra) { var reflectedMagnatude = SensorProcessorTools.AttenuationCalc(emitedItem.Value, distance) * reflectionPercent; sensorSig.ReflectedEMSpectra.Add(emitedItem.Key, emitedItem.Value); } } } }
internal static void DetectEntites(SensorReceverAtbDB receverDB, Entity detectableEntity, DateTime atDate) { Entity receverFaction = receverDB.OwningEntity.GetDataBlob <OwnedDB>().OwnedByFaction; var knownContacts = receverFaction.GetDataBlob <FactionInfoDB>().SensorEntites; SensorProfileDB sensorProfile = detectableEntity.GetDataBlob <SensorProfileDB>(); TimeSpan timeSinceLastCalc = atDate - sensorProfile.LastDatetimeOfReflectionSet; PositionDB positionOfSensorProfile = detectableEntity.GetDataBlob <PositionDB>();//sensorProfile.OwningEntity.GetDataBlob<ComponentInstanceInfoDB>().ParentEntity.GetDataBlob<PositionDB>(); double distanceInAUSinceLastCalc = PositionDB.GetDistanceBetween(sensorProfile.LastPositionOfReflectionSet, positionOfSensorProfile); //Only set the reflectedEMProfile of the target if it's not been done recently: //TODO: is this still neccicary now that I've found and fixed the loop? (refelctions were getting bounced around) if (timeSinceLastCalc > TimeSpan.FromMinutes(30) || distanceInAUSinceLastCalc > 0.1) //TODO: move the time and distance numbers here to settings? { SetReflectedEMProfile.SetEntityProfile(detectableEntity, atDate); } SensorReturnValues detectionValues = DetectonQuality(receverDB, sensorProfile); SensorInfoDB sensorInfo; if (detectionValues.SignalStrength_kW > 0.0) { if (knownContacts.ContainsKey(detectableEntity.Guid)) { sensorInfo = knownContacts[detectableEntity.Guid].GetDataBlob <SensorInfoDB>(); sensorInfo.LatestDetectionQuality = detectionValues; sensorInfo.LastDetection = atDate; if (sensorInfo.HighestDetectionQuality.SignalQuality < detectionValues.SignalQuality) { sensorInfo.HighestDetectionQuality.SignalQuality = detectionValues.SignalQuality; } if (sensorInfo.HighestDetectionQuality.SignalStrength_kW < detectionValues.SignalStrength_kW) { sensorInfo.HighestDetectionQuality.SignalStrength_kW = detectionValues.SignalStrength_kW; } SensorEntityFactory.UpdateSensorContact(receverFaction, sensorInfo); } else { sensorInfo = new SensorInfoDB(receverFaction, detectableEntity, atDate); //knownContacts.Add(detectableEntity.Guid, SensorEntityFactory.UpdateSensorContact(receverFaction, sensorInfo)); moved this line to the SensorInfoDB constructor } } }
/// <summary> /// Creates orbit here using the current distance between the two entites as aphelion(furthest distance) and a given semiMajorAxis /// </summary> /// <returns>An OrbitDB. Does Not set DB to Entity.</returns> /// <param name="shipEntity">Ship entity.</param> /// <param name="parentEntity">The Entity to orbit</param> /// <param name="semiMajorAxsis">Largest Radius</param> public static OrbitDB CreateOrbitHereWithSemiMajAxis(Entity shipEntity, Entity parentEntity, double semiMajAxsisKM, DateTime time) { PositionDB parentPosition = parentEntity.GetDataBlob <PositionDB>(); PositionDB myPosition = shipEntity.GetDataBlob <PositionDB>(); double parentMass = parentEntity.GetDataBlob <MassVolumeDB>().Mass; double myMass = shipEntity.GetDataBlob <MassVolumeDB>().Mass; double aphelionAU = PositionDB.GetDistanceBetween(parentPosition, myPosition); double semiMajAxisAU = semiMajAxsisKM / GameConstants.Units.KmPerAu; double linierEcentricity = aphelionAU - semiMajAxisAU; double semiMinorAxsis = Math.Sqrt(Math.Pow(semiMajAxisAU, 2) - Math.Pow(linierEcentricity, 2)); double ecentricity = linierEcentricity / semiMajAxisAU; Vector4 ralitivePos = (myPosition.AbsolutePosition - parentPosition.AbsolutePosition); double angle = Math.Tan(ralitivePos.X / ralitivePos.Y); OrbitDB newOrbit = OrbitDB.FromAsteroidFormat(parentEntity, parentMass, myMass, semiMajAxisAU, ecentricity, 0, 0, angle, 0, time); return(newOrbit); }
/// <summary> /// Creates orbit here using the current distance between the two entites as aphelion(furthest distance) and a given perihelion /// </summary> /// <returns>An OrbitDB. Does Not set DB to Entity.</returns> /// <param name="shipEntity">Ship entity.</param> /// <param name="parentEntity">The Entity to orbit</param> /// <param name="perihelionKM">closest distance to the parent in KM</param> public static OrbitDB CreateOrbitHereWithPerihelion(Entity shipEntity, Entity parentEntity, double perihelionKM, DateTime time) { PositionDB parentPosition = parentEntity.GetDataBlob <PositionDB>(); PositionDB myPosition = shipEntity.GetDataBlob <PositionDB>(); double parentMass = parentEntity.GetDataBlob <MassVolumeDB>().Mass; double myMass = shipEntity.GetDataBlob <MassVolumeDB>().Mass; double aphelionAU = PositionDB.GetDistanceBetween(parentPosition, myPosition); double perihelionAU = perihelionKM / GameConstants.Units.KmPerAu; double semiMajorAxsis = (perihelionAU + aphelionAU) / 2; double linierEcentricity = aphelionAU - semiMajorAxsis; double ecentricity = linierEcentricity / semiMajorAxsis; Vector3 ralitivePos = (myPosition.AbsolutePosition_AU - parentPosition.AbsolutePosition_AU); double inclination = 0; double loAN = 0; //longditude of Acending Node double aoP = Math.Tan(ralitivePos.X / ralitivePos.Y);; //arguemnt of Periapsis //double ecentricAnomaly = 0; double meanAnomaly = 0; //ecentricAnomaly - ecentricity * Math.Sin(ecentricAnomaly); OrbitDB newOrbit = OrbitDB.FromAsteroidFormat(parentEntity, parentMass, myMass, semiMajorAxsis, ecentricity, inclination, loAN, aoP, meanAnomaly, time); return(newOrbit); }
/// <summary> /// Creates orbit here using the current distance between the two entites as aphelion(furthest distance) and a given semiMajorAxis /// *NOTE BUG* this only returns a correct orbit DB if the position is y=0 and is +x (ie the position is in the reference direction) /// </summary> /// <returns>An OrbitDB. Does Not set DB to Entity.</returns> /// <param name="shipEntity">Ship entity.</param> /// <param name="parentEntity">The Entity to orbit</param> /// <param name="semiMajorAxsis">Largest Radius</param> public static OrbitDB CreateOrbitHereWithSemiMajAxis(Entity shipEntity, Entity parentEntity, double semiMajAxsisKM, DateTime time) { PositionDB parentPosition = parentEntity.GetDataBlob <PositionDB>(); PositionDB myPosition = shipEntity.GetDataBlob <PositionDB>(); double parentMass = parentEntity.GetDataBlob <MassVolumeDB>().Mass; double myMass = shipEntity.GetDataBlob <MassVolumeDB>().Mass; double aphelionAU = PositionDB.GetDistanceBetween(parentPosition, myPosition); double semiMajAxisAU = semiMajAxsisKM / GameConstants.Units.KmPerAu; double linierEcentricity = aphelionAU - semiMajAxisAU; double semiMinorAxsis = Math.Sqrt(Math.Pow(semiMajAxisAU, 2) - Math.Pow(linierEcentricity, 2)); double ecentricity = linierEcentricity / semiMajAxisAU; Vector3 ralitivePos = myPosition.RelativePosition_AU; double angle = Math.Atan2(ralitivePos.Y, ralitivePos.X); var theta = Angle.ToDegrees(angle); OrbitDB newOrbit = OrbitDB.FromAsteroidFormat(parentEntity, parentMass, myMass, semiMajAxisAU, ecentricity, 0, 0, angle, angle, time); var pos = OrbitProcessor.GetPosition_AU(newOrbit, time); var pos2 = Distance.AuToKm(pos); return(newOrbit); }
internal static SensorReturnValues DetectonQuality(SensorReceverAtbDB recever, SensorProfileDB target) { /* * Thoughts (spitballing): * * What we need: * detect enough of a signal to get a position * decide what "enough" is. probibly get this from the signal strength. - should the target SensorSigDB define what enough is? * we could require more than one detection (ie two ships in different locations) to get an acurate position, but that could get tricky to code. * and how would we display a non acurate position? maybe a line out to a question mark, showing the angle of detection but not range? * * detect enough of a signal to get intel if it's a ship * decide what "enough" for this is. maybe compare the detected waveform and the emited waveform and compare the angles to see if the triangle is simular. * * it'd be nifty if we could include background noise in there too, ie so ships close to a sun would be hidden. * also have resoulution be required to pick out multiple ships close together instead of just one big signal. * * With range attenuation, we'll never get the full signal uneless we're right ontop of it. * maybe if we get half the emited strength and its a simular triange (all same angles) we get "Full" intel? * * should we add time into the mix as well? multiple detections over a given time period to get position/velocity/orbitDB? * * * how are multiple components on a ship going to work? they are entitys in and of themselfs, so they could have a SensorSigDB all of thier own. * that could help with getting intel on individual components of a target. * * recever resolution should play into how much gets detected. * * Note that each entity will(may) have multiple waveforms. * * Data that can be glened from this detection system: * detectedStrength (altitide of the intersecting triangle) * detectedArea - the area of the detected intersection, could compare this to the target signal as well. * compare angles of the detected intersection and the target signal to see if the shape is simular? * if range is known acurately, this could affect the intel gathered. */ var myPosition = recever.OwningEntity.GetDataBlob <ComponentInstanceInfoDB>().ParentEntity.GetDataBlob <PositionDB>();//recever is a componentDB. not a shipDB PositionDB targetPosition; if (target.OwningEntity.HasDataBlob <PositionDB>()) { targetPosition = target.OwningEntity.GetDataBlob <PositionDB>(); } else { targetPosition = target.OwningEntity.GetDataBlob <ComponentInstanceInfoDB>().ParentEntity.GetDataBlob <PositionDB>();//target may be a componentDB. not a shipDB } double distance = PositionDB.GetDistanceBetween(myPosition, targetPosition); var detectionResolution = recever.Resolution; var signalAtPosition = AttenuatedForDistance(target, distance); double receverSensitivityFreqMin = recever.RecevingWaveformCapabilty.WavelengthMin_nm; double receverSensitivityFreqAvg = recever.RecevingWaveformCapabilty.WavelengthAverage_nm; double receverSensitivityFreqMax = recever.RecevingWaveformCapabilty.WavelengthMax_nm; double receverSensitivityBest = recever.BestSensitivity_kW; double receverSensitivityAltitiude = recever.BestSensitivity_kW - recever.WorstSensitivity_kW; PercentValue quality = new PercentValue(0.0f); double detectedMagnatude = 0; foreach (var waveSpectra in signalAtPosition) { double signalWaveSpectraFreqMin = waveSpectra.Key.WavelengthMin_nm; double signalWaveSpectraFreqAvg = waveSpectra.Key.WavelengthAverage_nm; double signalWaveSpectraFreqMax = waveSpectra.Key.WavelengthMax_nm; double signalWaveSpectraMagnatude_kW = waveSpectra.Value; if (signalWaveSpectraMagnatude_kW > recever.BestSensitivity_kW) //check if the sensitivy is enough to pick anything up at any frequency. { if (Math.Max(receverSensitivityFreqMin, signalWaveSpectraFreqMin) < Math.Max(signalWaveSpectraFreqMin, signalWaveSpectraFreqMax)) { //we've got something we can detect double minDetectableWavelength = Math.Min(receverSensitivityFreqMin, signalWaveSpectraFreqMin); double maxDetectableWavelenght = Math.Min(receverSensitivityFreqMax, signalWaveSpectraFreqMax); double detectedAngleA = Math.Atan(receverSensitivityAltitiude / (receverSensitivityFreqAvg - receverSensitivityFreqMin)); double receverBaseLen = maxDetectableWavelenght - minDetectableWavelength; double detectedAngleB = Math.Atan(signalWaveSpectraMagnatude_kW / (signalWaveSpectraFreqAvg - signalWaveSpectraFreqMax)); bool doesIntersect; double intersectPointX; double intersectPointY; double distortion; if (signalWaveSpectraFreqAvg < receverSensitivityFreqAvg) //RightsideDetection (recever's ideal wavelenght is higher than the signal wavelenght at it's loudest) { doesIntersect = Get_line_intersection( signalWaveSpectraFreqAvg, signalWaveSpectraMagnatude_kW, signalWaveSpectraFreqMin, 0, receverSensitivityFreqAvg, recever.BestSensitivity_kW, receverSensitivityFreqMax, recever.WorstSensitivity_kW, out intersectPointX, out intersectPointY); //offsetFromCenter = intersectPointX - signalWaveSpectraFreqAvg; //was going to use this for distortion but decided to simplify. distortion = receverSensitivityFreqAvg - signalWaveSpectraFreqAvg; } else //LeftSideDetection { doesIntersect = Get_line_intersection( signalWaveSpectraFreqAvg, signalWaveSpectraMagnatude_kW, signalWaveSpectraFreqMax, 0, receverSensitivityFreqAvg, recever.BestSensitivity_kW, receverSensitivityFreqMin, recever.WorstSensitivity_kW, out intersectPointX, out intersectPointY); //offsetFromCenter = intersectPointX - signalWaveSpectraFreqAvg; distortion = signalWaveSpectraFreqAvg - receverSensitivityFreqAvg; } if (doesIntersect) // then we're not detecting the peak of the signal { detectedMagnatude = intersectPointY - recever.BestSensitivity_kW; distortion *= 2; //pentalty to quality of signal } else { detectedMagnatude = signalWaveSpectraMagnatude_kW - recever.BestSensitivity_kW; } quality = new PercentValue((float)(100 - distortion / signalWaveSpectraFreqMax)); } } } return(new SensorReturnValues() { SignalStrength_kW = detectedMagnatude, SignalQuality = quality }); }
internal static void DetectEntites(SystemSensorContacts sensorMgr, FactionInfoDB factionInfo, PositionDB receverPos, SensorReceverAtbDB receverDB, Entity detectableEntity, DateTime atDate) { Entity receverFaction = sensorMgr.FactionEntity; //Entity receverFaction;// = receverDB.OwningEntity.GetDataBlob<OwnedDB>().OwnedByFaction; //detectableEntity.Manager.FindEntityByGuid(receverDB.OwningEntity.FactionOwner, out receverFaction); var knownContacts = factionInfo.SensorContacts; //receverFaction.GetDataBlob<FactionInfoDB>().SensorEntites; var knownContacts1 = sensorMgr.GetAllContacts(); SensorProfileDB sensorProfile = detectableEntity.GetDataBlob <SensorProfileDB>(); TimeSpan timeSinceLastCalc = atDate - sensorProfile.LastDatetimeOfReflectionSet; PositionDB positionOfSensorProfile = detectableEntity.GetDataBlob <PositionDB>();//sensorProfile.OwningEntity.GetDataBlob<ComponentInstanceInfoDB>().ParentEntity.GetDataBlob<PositionDB>(); double distanceInAUSinceLastCalc = PositionDB.GetDistanceBetween(sensorProfile.LastPositionOfReflectionSet, positionOfSensorProfile); //Only set the reflectedEMProfile of the target if it's not been done recently: //TODO: is this still neccicary now that I've found and fixed the loop? (refelctions were getting bounced around) if (timeSinceLastCalc > TimeSpan.FromMinutes(30) || distanceInAUSinceLastCalc > 0.1) //TODO: move the time and distance numbers here to settings? { SetReflectedEMProfile.SetEntityProfile(detectableEntity, atDate); } PositionDB targetPosition; if (detectableEntity.HasDataBlob <PositionDB>()) { targetPosition = detectableEntity.GetDataBlob <PositionDB>(); } else { targetPosition = detectableEntity.GetDataBlob <ComponentInstanceInfoDB>().ParentEntity.GetDataBlob <PositionDB>();//target may be a componentDB. not a shipDB } var distance = PositionDB.GetDistanceBetween(receverPos, targetPosition); SensorReturnValues detectionValues = DetectonQuality(receverDB, AttenuatedForDistance(sensorProfile, distance)); SensorInfoDB sensorInfo; if (detectionValues.SignalStrength_kW > 0.0) { if (sensorMgr.SensorContactExists(detectableEntity.Guid)) { //sensorInfo = knownContacts[detectableEntity.Guid].GetDataBlob<SensorInfoDB>(); sensorInfo = sensorMgr.GetSensorContact(detectableEntity.Guid).SensorInfo; sensorInfo.LatestDetectionQuality = detectionValues; sensorInfo.LastDetection = atDate; if (sensorInfo.HighestDetectionQuality.SignalQuality < detectionValues.SignalQuality) { sensorInfo.HighestDetectionQuality.SignalQuality = detectionValues.SignalQuality; } if (sensorInfo.HighestDetectionQuality.SignalStrength_kW < detectionValues.SignalStrength_kW) { sensorInfo.HighestDetectionQuality.SignalStrength_kW = detectionValues.SignalStrength_kW; } SensorEntityFactory.UpdateSensorContact(receverFaction, sensorInfo); } else { SensorContact contact = new SensorContact(receverFaction, detectableEntity, atDate); sensorMgr.AddContact(contact); //knownContacts.Add(detectableEntity.Guid, SensorEntityFactory.UpdateSensorContact(receverFaction, sensorInfo)); moved this line to the SensorInfoDB constructor } } }