LENpolygon / Build-Order-Tool-AoE4-

Build Order Tool (for Age of Empires IV)
30 stars 15 forks source link

Illustrated build order - copy to clipboard #33

Closed CraftySalamander closed 2 years ago

CraftySalamander commented 2 years ago

Hi, Here is the code to include a button to output the build orders in the new AoE4_Overlay format: using illustrated build orders.

The main contribution is the function 'copyForIllustratedOverlay' in AoE4_Overlay.js, which performs the same action as your function 'copyForOverlay' (which I renamed 'copyForSimpleTxtOverlay'), but for the new format.

Unfortunately, I did not manage to run your full code locally (I did not have access to the images...). What I did is to save this page and then I worked on the corresponding code. It was working well on this example.

Then, I tried to mimic what you did for the calls to 'copyForOverlay' in this github project, but I could not test it.

So, in short, the main contribution of this pull request is the 'copyForIllustratedOverlay' function in AoE4_Overlay.js, that I could test. For the rest of the code, I could not test it fully, so check all the modifications that are not in AoE4_Overlay.js (not a lot of them fortunately, as you can see).

coreyjansen commented 2 years ago

+1 #24

coreyjansen commented 2 years ago

@CraftySalamander

I refactored your copyForIllustratedOverlay() function so that it builds an object and then converts it into a string so its a little easier to read. In doing so I also tried to estimate the population and villagers by adding up the people on the resources.

To get the current age I parse the notes string looking for age/age_ and then if it exists I use regex to parse the current age.

I am not too sure how I can go about pushing into your branch so I will put it here

/**
 * Extract the age from the image string param
 * @param {String} string
 * @returns
 */
function getAgeFromNotes(string) {
    try {
        var regex = /age\/age_(\d)\.png/g;

        var result = regex.exec(string);
        return result[1];
    } catch (e) {
        return false;
    }
}

// Copy to clipboard for Illustrated Build Order format
function copyForIllustratedOverlay() {
    var rows = document.getElementById("buildTable").rows;
    var currentAge = 1;
    // selected civilization
    var civName = civToOverlayName(document.getElementById("civilizationName").innerHTML);
    //Start JSON Obj
    var jsonObj = {civilization: civName, name: focusToBuildOrderName(document.getElementById("civilizationFocus").innerHTML), author: focusToAuthorName(document.getElementById("civilizationFocus").innerHTML), source: "unknown", build_order: []};

    var firstRow = true;
    for (var currentLine of rows) {
        if (firstRow) {
            firstRow = false;
            continue;
        }
        var timeTarget = parseFloat(currentLine.cells[0].innerHTML);

        // notes in a single line
        var single_line_notes = convertNotesIllustrations(civName, currentLine.cells[5].innerHTML);
        //Check if the notes contain the age up illustration and parse the age if it does
        if (single_line_notes.indexOf("age/age_") > -1) {
            var ageResponse = getAgeFromNotes(single_line_notes);
            if (ageResponse) {
                currentAge = parseInt(ageResponse);
            }
        }

        var newLineJson = {
            age: currentAge,
            time: timeTarget,
            // split the single line to multiple ones, using the '. ' pattern
            notes: single_line_notes.split(". "),
            resources: {
                food: resourceValue(currentLine.cells[1].innerHTML),
                wood: resourceValue(currentLine.cells[2].innerHTML),
                gold: resourceValue(currentLine.cells[4].innerHTML),
                stone: resourceValue(currentLine.cells[3].innerHTML),
            },
        };
        //Set Population Count and Villager Count to all of the villagers on resouces combined
        newLineJson["villager_count"] = newLineJson["population_count"] = newLineJson.resources.food + newLineJson.resources.wood + newLineJson.resources.gold + newLineJson.resources.stone;
        jsonObj["build_order"].push(newLineJson);
    }
    var str = JSON.stringify(jsonObj);
    //console.log(str);

    navigator.clipboard.writeText(htmlDecode(str)).then(
        function () {
            //console.log('Async: Copying to clipboard was successful!');
        },
        function (err) {
            console.error("Async: Could not copy text: ", err);
        },
    );
}
CraftySalamander commented 2 years ago

@coreyjansen Thank you for your input and your code adaptations. I updated it in this commit.

I kept your villager count (which should be correct most of the time, except when some villagers are busy building structures), but I removed the estimation of the population because there will be a few scouts, imperial officers, prelates... which are not taken into account, and which would make this number wrong. For the age estimation, it was a nice idea, but it is not robust (if a wrong image is used, if no next age image is used for several steps...). On top of that, it is not very important for AoE4 (aging up often happens in the middle of a step); it was mainly coming from my AoE2 implementation where it is more crucial. So, I removed it.

@LENpolygon I could test the above commit on my local sample and it works well. So, when you are ready, you can accept the pull request, it is ready. There will maybe be a few adaptations to make, but this should be pretty short and easy, as I described above.

coreyjansen commented 2 years ago

Awesome, thanks for the feedback @CraftySalamander . That makes perfect sense. I have been playing with this with a javascript injector plugin to overwrite the function that they have to copy the text and it's working great on the live site.

CraftySalamander commented 2 years ago

@LENpolygon Great, I played a bit with your updated website, and everything seems to work as expected!

@coreyjansen Out of curiosity, what tool do you use as javascript injector?

LENpolygon commented 2 years ago

Good to hear. Cheers for the great addition to the website and the AoE4_Overlay!

coreyjansen commented 2 years ago

Thanks @CraftySalamander I was using Scripty - Javascript Injector to inject javascript which you can find here

CraftySalamander commented 2 years ago

@coreyjansen Thank you for the link.