Cloaking device in warp to 0 bot

Hello there.

This is my first message and not a programmer, so i will try to explain myself as better as i can:

I tried a warp-to-0 bot, and added the option to activate always one module (a cloaking device).

Everything works fine, but the bot is continuosly switching the cloak device on and off. So de ship isnt cloaked

Watching the bot work, i realized it always see the module inactive, so it has to click on it.

How can i solve this? If i put a hardener instead of a cloak device, it would be switched on/off all the whole time to??

Thank you in advance.

Ps: hope this will the first of many messages. So get patience, please

I don’t have a cloak trained characters but I would say it is because a cloaking device does not use ramp_active when turned on. And the current default knownModulesToActivateAlways uses this flag to tell when a module is off or on.

isActive =
        moduleButtonNode.uiNode.dictEntriesOfInterest
            |> Dict.get "ramp_active"
            |> Maybe.andThen (Json.Decode.decodeValue Json.Decode.bool >> Result.toMaybe)

You would have to record your session and share it.

How to Report an Issue with an App or Request a New Feature

1 Like

It could be that your module has a different appearance than the one used for training the bot so far.
That is not a big issue as we can solve it by adding the training data for your scenario.

You could start by making two screenshots of your module, one in the ‘on’ state and one in the ‘off’ state.
We can then use these samples to generate a function that distinguishes the two states.

As @Mohano has pointed out already, the first step in the basic approach is to share the recording archive as your session.

hello again,

sorry for the late answer.

here are the some screenshots of the cloaking device. Took several because i thought maybe would be easier for the bot, not only to check the buttom, so check the label of the buttom. But

active covert ops cloaking device
INactive covert ops cloaking device

labeled active cloaking device
labaled inactive cloack device

edit: i edit this and the following replies for not charge the topic with my own replies. Here is the link of the recorded data

recorded session

I cannot find the difference between activated cloak or not in the dump. It probably has something to do with ‘ShipModuleReactivationTimer’. Viir might have a keener eye.

I am interested because I am training a character that will be used to transport good in a cloaked ship soon. My work around if Viir does not find a way to detect if it’s activated or not would be to link the cloak to another module when activating.

For exemple if the linked module is inactive I would activate both the cloak and module together. It’s not a pretty way to do it but it would get around this limitation.

Lets way for his findings.

1 Like

there are several strategies in the game to use cloaking. Not just the covert ops cloak what allows you to warp “invisile”.
And maybe this is something must be count with.

when jumped throught a gate or a wormhole, you appear in the destination system cloaked and keep the cloak for 1 minute. If you move before that minute expires, the ship decloaks. Probably you already realized of this.
Having a cloaking device allows you cloak again, but wont be able to warp anywhere if you arent using a “Covert Ops Cloaking Device II” which only a few ships in the game are able to use.
for the strategy a talked before, we wil need a industrial ship with a 50mn MWD, and improved cloaking device.
the key strokes must be quick to be effecive: you first make your ship move to front, inmediately active the cloack and inmediately the microwarpdrive. that gives you a few seconds to align to your destination (maybe another gate or station?), until the ship of your ship begin to decrease. Once aligned, decloak, the ship should have enought speed to instawarp to that destination, letting hazardous gate campers less time to target you.
youtube tutorial
maybe here is better explained

These seem to work well. These screenshots look like the state you are interested in could be distinguished by a green glow on the module button.

These screenshots also seem to confirm the theory by @Mohano about the ‘ramp’ visual:

We could use the image data and check the greenness of the pixels. However, the most popular apps for EVE Online currently all use memory reading, so the faster way to read the module state might be reusing the memory reading infrastructure. The image processing approach would require building some infrastructure first.
Maybe the recording session-2021-03-27T23-51-40-bf273d.zip already contains a part of the memory that is sufficient here.

Thanks for taking a look.
I am taking a look too into session-2021-03-27T23-51-40-bf273d.zip.
In event 49, I see the app clicked the module button. Maybe there is a lag between the click and the glow visual appearing, so it might be safer not to use the immediately following reading for comparison.
I pick the readings from events 46 and 55 to search for the difference.

A first superficial look:

I am not sure the differences seen so far are robust enough, so let’s take a closer look at the properties in the slot’s nodes.

Expanding the nodes in the slot further:

The “glow” sprite looks interesting. Here we can also see it has a greenish color, which matches the impression from the screenshots.

What is confusing me: The reading from event 46 is on the left from event 55 on the right. Why are there more glow nodes in the earlier event?

I did not find a distinction that looks like it would be robust enough. We could look further with a complete sample of your game client.
You could use this approach to collect a sample: bots/how-to-collect-samples-for-64-bit-memory-reading-development.md at main · Viir/bots · GitHub

In the full game client sample, we might find a distinctive property in the node. The low-level part of the memory reading code selects a subset of the node’s dictionary entries to include in dictEntriesOfInterest. Maybe it is time to expand this list.

The current list of interesting names is here:

Maybe we find another one that is interesting for ship module buttons.

In April 2020, there was this expansion to support reading the agent missions dialogues:

For the module state detection, you’d need two samples. Before taking a sample for the ‘off’ state, make sure you activate the module first and then deactivate it. Because it looks like some things only change with the first transition to ‘on’ (Looks like this is the case for the ramp_active property)

After thinking about it again, I am now more inclined to skip the memory reading route and do image-based detection right away. I do not need the full sample of your game client process for this route, as I can use the screenshots you already linked above.

One of the steps on this route is to extract and label the portions of the screenshots most relevant for our project. I did this for these screenshots linked above by cropping an area more relevant for training:

Examples inactive:

  • image

Examples active:

  • image

Text to distinguish which kinds of module buttons to use the image processing on:

image

The idea is to use the information we already have from memory reading about the display region to depend on only the image data only in that region.

I will look into the implementation side for the image processing and then update this thread here.

1 Like

I have not seen how to implement image processing in EvE yet. I’m curious so see.

In April 2020, there was this expansion to support reading the agent missions dialogues:

Damn, I wrote a whole new function to decipher the agent missions dialogues. Could have used this.

Image processing in EVE Online is now ready to use.
I adapted the frameworks here:

The same commit also expands the autopilot example to use image-processing to support the module button type discovered by Victor above.

@Zalain you can run that bot from https://catalog.botengine.org/e5aaceaf8cf0c755402abb610970e043134dfde3ce1a72cf5090d7a52c82de6b

Decided to buy a cloak to test some more.

On
image

Off
image

When it is turned On, there is a “glow” effect added to the module.

1 Like
activateCloakDevice : BotDecisionContext -> Maybe DecisionPathNode
activateCloakDevice context =
    case
        context.readingFromGameClient.shipUI
            |> Maybe.map .moduleButtons
            |> Maybe.withDefault []
            |> List.filter (.slotUINode >> .uiNode >> .pythonObjectTypeName >> (==) "ShipModuleReactivationTimer")
            |> List.head
    of
        Nothing ->
            Nothing

        Just cloakDevice ->
            case
                cloakDevice.uiNode
                    |> EveOnline.ParseUserInterface.listDescendantsWithDisplayRegion
                    |> List.filter (.uiNode >> .pythonObjectTypeName >> (==) "glow")
                    |> List.head
            of
                Nothing ->
                    Nothing

                Just _ ->
                    Just (clickModuleButtonButWaitIfClickedInPreviousStep context cloakDevice)

This is not working yet. I’ll spend more time making it work. I’m sure its a small thing I overlooked.

Cant quite figure out how to look for .pythonObjectTypeName >> (==) "ShipModuleReactivationTimer" in every module.

Have to use listDescendantsWithDisplayRegion in a list.map I think but not sure how to implement it.

Really late so ill go to bed. Viir if you can come up with a way to fix my code I think that would work.

1 Like

Sure, I found a fix.
I opened the autopilot example and added the function from your post.
The problem here is the use of the undeclared name clickModuleButtonButWaitIfClickedInPreviousStep, as we can see in this error message from the editor:

On the internet, I found this function with that name here:

After pasting that one into the project too, it compiles without errors:

Here is a link to the fixed project code: Elm Editor

I have explained myself wrong.

This version works for me. It activate the cloak and then detect that it is activated. But it is really ugly and unwieldy. I would like a cleaner way to find find the correct ShipUIModuleButton from the shipUI.moduleButtons list of List ShipUIModuleButton that has (.uiNode >> .pythonObjectTypeName >> (==) "ShipModuleReactivationTimer") as children.

I would like to use that previous ShipUIModuleButton to look for glow and if not found, press on it to activate the cloak.

Right now this function works in a hacky kind of way. I know my cloak is set at F1 and if I find glow I know it is activated but its too wide of an approach. I would like to only search for glow inside the cloaking device shipUI.moduleButtons and not the whole Maybe shipUI

activateCloakDevice : BotDecisionContext -> DecisionPathNode
activateCloakDevice context =
    case context.readingFromGameClient.shipUI of
        Nothing ->
            describeBranch "Nothing step 1" waitForProgressInGame

        Just shipUI ->
            case
                shipUI.moduleButtons
                    |> List.map
                        (\module1 ->
                            module1
                                |> (.slotUINode >> EveOnline.ParseUserInterface.listDescendantsWithDisplayRegion)
                                |> List.filter (.uiNode >> .pythonObjectTypeName >> (==) "ShipModuleReactivationTimer")
                        )
                    |> List.head
                    |> Maybe.withDefault []
                    |> List.head
            of
                Nothing ->
                    describeBranch "Nothing step 2" waitForProgressInGame

                Just _ ->
                    case
                        getDescendantWithDisplayName "glow" shipUI.uiNode
                    of
                        Nothing ->
                            endDecisionPath
                                (actWithoutFurtherReadings
                                    ( "Activating cloak."
                                    , EffectOnWindow.effectsMouseClickAtLocation EffectOnWindow.MouseButtonLeft
                                        { x = 850
                                        , y = 200
                                        }
                                        ++ [ EffectOnWindow.KeyDown EffectOnWindow.vkey_F1
                                           , EffectOnWindow.KeyUp EffectOnWindow.vkey_F1
                                           ]
                                    )
                                )

                        Just _ ->
                            describeBranch "Cloak activated." waitForProgressInGame




getDescendantWithDisplayName : String -> UIElement -> Maybe UIElement
getDescendantWithDisplayName displayText parent =
    parent
        |> EveOnline.ParseUserInterface.listDescendantsWithDisplayRegion
        |> List.filter (.uiNode >> EveOnline.ParseUserInterface.getDisplayName >> (==) (Just displayText))
        |> List.head

Again, this only works if cloak is set at F1.

1 Like

Ok, that is a different goal indeed.
I started from the code you posted, simplified it, and changed its function to get the module button.
How about this version:

activateCloakDevice : BotDecisionContext -> DecisionPathNode
activateCloakDevice context =
    case context.readingFromGameClient.shipUI of
        Nothing ->
            describeBranch "Nothing step 1" waitForProgressInGame

        Just shipUI ->
            case
                shipUI.moduleButtons
                    |> List.filter
                        (.slotUINode
                            >> EveOnline.ParseUserInterface.listDescendantsWithDisplayRegion
                            >> List.filter (.uiNode >> .pythonObjectTypeName >> (==) "ShipModuleReactivationTimer")
                            >> List.isEmpty
                            >> not
                        )
                    |> List.head
            of
                Nothing ->
                    describeBranch "Nothing step 2" waitForProgressInGame

                Just moduleButton ->

One of the steps was switching the pipeline from pipe operators to function composition operators, as explained in https://to.botengine.org/guide/elm-programming-language-forward-pipe-and-function-composition-operators

Thanks. This function works to toggle the cloak.

activateCloakDevice : BotDecisionContext -> DecisionPathNode
activateCloakDevice context =
    case context.readingFromGameClient.shipUI of
        Nothing ->
            describeBranch "Nothing step 1" waitForProgressInGame

        Just shipUI ->
            case
                shipUI.moduleButtons
                    |> List.filter
                        (.slotUINode
                            >> EveOnline.ParseUserInterface.listDescendantsWithDisplayRegion
                            >> List.filter (.uiNode >> .pythonObjectTypeName >> (==) "ShipModuleReactivationTimer")
                            >> List.isEmpty
                            >> not
                        )
                    |> List.head
            of
                Nothing ->
                    describeBranch "Nothing step 2" waitForProgressInGame

                Just moduleButton ->
                    case
                        getDescendantWithDisplayName "glow" moduleButton.slotUINode
                    of
                        Nothing ->
                            clickModuleButtonButWaitIfClickedInPreviousStep context moduleButton

                        {- endDecisionPath
                                (actWithoutFurtherReadings
                                    ( "Activating cloak."
                                    , [ EffectOnWindow.KeyDown EffectOnWindow.vkey_F1
                                      , EffectOnWindow.KeyUp EffectOnWindow.vkey_F1
                                      ]
                                    )
                                )
                        -}
                        Just _ ->
                            describeBranch "Cloak activated." waitForProgressInGame


getDescendantWithDisplayName : String -> UIElement -> Maybe UIElement
getDescendantWithDisplayName displayText parent =
    parent
        |> EveOnline.ParseUserInterface.listDescendantsWithDisplayRegion
        |> List.filter (.uiNode >> EveOnline.ParseUserInterface.getDisplayName >> (==) (Just displayText))
        |> List.head

The commented out portion is to send the shortcut key instead of mouse click. It can be faster. It can also be linked with propulsion module if wanted so they both activate around the same time.

Also, it is more of a proof of concept as well. To use it effectively in the MWD + cloak trick you would need much more than just this function.

To figure out if ship is fully aligned you could use max speed and figure out when the ship is @ 75% of max speed before decloaking and hitting warp.

1 Like

Successfully ran my Blockade runner with covers ops cloaking device for over 45 jumps with no issues. Always cloaking pretty quickly. I would not use it for Jita considering I have not scripted insta-dock and insta-undock but anywhere else I would.

Scripting the full MWD + Cloak trick for an industrial would be a lot of work. Need to track max speed when cloaked and uncloaked. Need to account for cloak failing due to proximity and need to track MWD duration to turn off cloak at the right time.

Actually one issue: ShipModuleReactivationTimer does not appear untill you activate the cloak at least once manually. It needs to be initialized before letting botengine take over. When not initialzed botengine cannot detect the cloaking device.

@Zalain has found a way to identify the cloaking device module here: Cloaking device in warp to 0 bot

The guides on EVE Online also explain that approach:

The module button tooltip helps us to learn more about the module buttons displayed in the ship UI. This UI element appears when we move the mouse over a module button and shows details of the ship module(s) it represents.

This is from the guide at https://to.botengine.org/guide/parsed-user-interface-of-the-eve-online-game-client

An alternative way would be using the different appearance in screenshots to distinguish that module button from others. This way, you do not even need to trigger the tooltip.

This catch-all approach is too slow when handling time sensitive life-saving modules. That is why I steer away from it for this application.

For my scripts I have top row for weapon, middle row for tank and bottom row for support modules. I only use the tooltip reading for the bottom row to allow flexibility.

It is not so bad right now because my cloaking module is treated as a tank module until the first activation where botengine realize it is a cloaking device after activating it and act accordingly.