Determining Activated Modules on Targets

As far as I see, SetAbilityIcon is of type IEnumerable<ISquadronAbilityIcon>.
To access an element of an IEnumerable<> by index, you can use the method ElementAt

If you also want to cover cases where there could be fewer elements in the sequence, use ElementAtOrDefault to avoid an ArgumentOutOfRangeException.

To map from your example code, it would look like this instead:

SetAbilityIcon?.ElementAtOrDefault(2)?.RampActive?.ToString()

@AbbadonDespoiler

I have already made some function on activate/deactivate the various attacks of squadrons on the targhet, you wrong the “approach” on read the “RampActive” value, the value is boolean.

Btw if you wait max 1-2 days I will finished the combattask of squadrons, then I will give to you the various functions and the point where to add them.

About the special attack I have in mind to execute only on ship >= the battleships, so I will had an checking function on the actually targhet. But I need time to fix something on my repository.

@Viir Thank you! While I’m indulging in your generosity, how would I obtain the index from a FirstOrDefault with a Lambda? For example, I want to find the index in the Overview Listview for a certain name or ID.

@Master thank you as well! So, I’m not using Sanderling to “do” anything, just read info from memory every 500ms or so and then use AHK to act on it, so 99% of the C# code I need is just how to retrieve information. That said, seeing how you obtain the info you need for those functions would be useful.

@AbbadonDespoiler this is an example of my function:

yield return bot.SquadronAction(SquadronsMainAttack, memoryMeasurement?.ShipUi?.SquadronsUI); 

internal IBotTask SquadronAction(VirtualKeyCode SquadronKeyAction, ISquadronsUI squadronsUI)
		{
			return new ActiveSquadronActionF { ActionKey = SquadronKeyAction, SquadronUI = squadronsUI };
		}

public class ActiveSquadronActionF : IBotTask
	{
		public Bot bot;

		public Interface.MemoryStruct.ISquadronsUI SquadronUI;

		public IEnumerable<IBotTask> Component => null;

		public VirtualKeyCode ActionKey;
		public IEnumerable<MotionParam> Effects
		{
			get
			{
				if (ActionKey != VirtualKeyCode.F1)
				{
					yield return ActionKey.KeyboardPress();
				}
				else
				{
					var squadrons = SquadronUI?.SetSquadron;
					if (squadrons != null)
					{
						var array = (IList<Interface.MemoryStruct.ISquadronUI>)squadrons;

						var firstyAbilityArray = (IList<Interface.MemoryStruct.ISquadronAbilityIcon>)array[0].SetAbilityIcon;
						var secondAbilityArray = (IList<Interface.MemoryStruct.ISquadronAbilityIcon>)array[1].SetAbilityIcon;
						var thirdAbilityArray = (IList<Interface.MemoryStruct.ISquadronAbilityIcon>)array[2].SetAbilityIcon;

						if ((firstyAbilityArray != null && firstyAbilityArray[2].RampActive == true) && (secondAbilityArray != null && secondAbilityArray[2].RampActive == true) && (thirdAbilityArray != null && thirdAbilityArray[2].RampActive == true))
						{
							yield break;
						}
						else
						{
							yield return ActionKey.KeyboardPress();

							if ((firstyAbilityArray != null && firstyAbilityArray[2].RampActive == true) || (secondAbilityArray != null && secondAbilityArray[2].RampActive == true) || (thirdAbilityArray != null && thirdAbilityArray[2].RampActive == true))
							{
								yield break;
							}
							else
							{
								var SquadronBonus = VirtualKeyCode.F2;
								yield return SquadronBonus.KeyboardPress();
							}
						}
					}
				}
			}
		}
	}

The logical is that:

If the virtualkey is different then F1 mean Im activating the speed bonus or the special attack, those 2 activation for me not need any kind of check, so if I go to ask to activate F2 / F3, the bot active it without any check.

But… if the virtualkey is F1 mean Im asking to activate the main attack of the squadrons, this mean I need to check if the attack is already active.

so I chekc whit this condition if the squadrons are already shooting

if ((firstyAbilityArray != null && firstyAbilityArray[2].RampActive == true) && (secondAbilityArray != null && secondAbilityArray[2].RampActive == true) && (thirdAbilityArray != null && thirdAbilityArray[2].RampActive == true))

If all of them are shooting I break the function, else I continue to activating the main attack, then I check if the speed bonus is already active or no, whit this condition:

if ((firstyAbilityArray != null && firstyAbilityArray[1].RampActive == true) || (secondAbilityArray != null && secondAbilityArray[1].RampActive == true) || (thirdAbilityArray != null && thirdAbilityArray[1].RampActive == true))

If all squadrons have the speed bonus active I break the yielde, else I active it too


Maybe is not what you want do, but here you can see in action how I read etc…

@Viir

var ModuleR1C1 = measurement?.Value?.ShipUi.Module?.FirstOrDefault(module => module?.Region.Min1 == 590 && module?.Region.Min0 == 582)?.RampActive?.ToString();

The problem I’m having with this is that Windows Studio says I can’t apply the ? operator to the operand of type “bool” with RampActive. What’s confusing about that is that it is permitted and for doing a similar function for Fighter Squadrons:

var Squadron1GunsActive = measurement?.Value?.ShipUi?.SquadronsUI?.SetSquadron?.FirstOrDefault(squadron => squadron?.Squadron?.SquadronNumber == 1)?.SetAbilityIcon?.ElementAtOrDefault(2)?.RampActive?.ToString();

Any thoughts?

You can get this index with following code:

var indexAsInt =
	Sanderling?.MemoryMeasurementParsed?.Value?.WindowOverview?.FirstOrDefault()
	?.ListView?.Entry
	//	Note: Use case specific to AbbadonDespoiler, not useful to obtain entries.
	?.FirstIndexOrNull(entry => entry.Name == "certainName");

Thank you! This is helpful :slight_smile: I know it probably seems weird or suboptimal with Sanderling, but knowing line numbers helps a great deal.

@Viir do you have any idea why this is happening? The issue I have with it is that the program I’m writing crashes if it’s docked and there aren’t modules to read. As I stated in the last post, nearly the same code works for Fighter modules.

Ok, then let’s look at the information about the crash next:
When the crash is caused by an exception, these are the first questions we are interested in:

  • What type is the exception of?
  • What is the exception message?
  • What source code is the exception pointing too?

It’s not a very helpful error message, I had compiled this without the ? after RampActive. It just won’t compile WITH the ? there because of the error I described above.

image

Here you can see that one is ‘bool’ and the other is ‘bool?’ but I have no idea why. Is it possible that the use of the FirstOrDefault with the && would somehow change the quality of the bool?

I found a workaround: I’m using RampRotationMilli instead of RampActive. If it’s not on, RampRotationMilli returns null anyway, and my code will basically be reading whether the value is null. Even a “0” would appraise as True in this case, so problem solved.

Edit: solved by just taking an array of the modules and then using a foreach loop to do it that way.

The reason is that in C# properties can have different types. Those two strings you quoted are the two types of the two properties. Each of those properties has one type and in your case, as can be seen in your screenshot, the types are different.

Right, I understand data types and data structures, I just wasn’t sure why a module was a different type, and why one could use the ? operator and the other could not. Either way, I worked around it by just sending all the modules to an array and using a switch case rather than using a lambda to select each one. Thank you again for your help, this is a really wonderful tool.

Out of curiosity, do you have resources or tutorials on how to find/analyze memory to define new entries in the measurement? I haven’t found anything I would want yet, except I think overview icon info, but knowing how to do it in my own would be good. I think I saw that the memory parsing actually happens in Python, which is my first programming language :slight_smile:

For resources on how to find and analyze stuff in memory of the eve online client on a low level, to start, see the posts in the topic at

@Viir @AbbadonDespoiler

About this, I give to you an advice, I can’t tell where you can find what I will say but you can find it on internet.

You can use the decompiled EVE code, using the python class decompiled you can find all reference name and the type of value used from a particular module.

After that @Viir have already made some function to get the values from the reference’s name.

@Master Gotcha, I’ll take a look. I had another question for you: What OS do you use for Sanderling, and have you measured the time it takes to take a measurement? Mine are going VERY slowly (1000-2500ms!) and I don’t understand why: even when nothing else is running, CPU use is <10%, it’s an i7-4790K 4Ghz processor, 32 gigs of RAM, Windows Server 2016, but it still takes a long time. I’d be eager to know if yours runs faster and on what hardware/OS.

@AbbadonDespoiler

Are speaking about real hardware composition or about an virtual machine?

However the “standards” time are the same you wrote, I can say that, Im in testing my new “interaction way” because from what I see what make “slow” the execution of yield are all action with “menu” because sanderling have to reload the statements and after interact with them.

For this I changed my approach, I removed all interaction with menu (where I could do it) and from my first results the actions managements are improved.

The why is simple, using shortcuts the code have not wait the graphics results for after read the ram statement from the memoryMeasurement.

Actually Im still in testing all that, I changed the enter/skip/completed anomaly logic too I think in 2-3 days I will do various test on a Virtual Machine with Windows 10 Lite Verions (with cortana and more stupid stuff disabled) then I will be able to say something about the ram reading times.

Apologies, I’m having a difficult time understanding what you’re saying, so I’ll just say this: I’m talking about the Host hardware and OS, not the virtual machine. I’m not really sure what the rest of what you’re saying, but my concern isn’t the code at this point. The same code run on my colleague’s computer ran in 100-200ms vs. 700-2500ms on mine (despite the fact my processor is patently “better”).