A Comprehensive Tier List of Triple Elemental Magics Combos (+ a bonus Tier List of Double Elemental Magic Combos)

As is known, the release of AO will bring the ability to obtain a second magic and change your first magic, among other things.
Knowing this, and that the release is far away into the future, many will try to theory craft a strong magic combo, the peak form of which is making a comprehensive tier list. So, given that my school is going fully online (again) which means I have an increase in free time, I decided to join the early birds and make a tier list right now.

But alas, I’m too lazy to actually think about all the possible combinations and their strengths and weaknesses, so I made my computer do all that, and I will reap the benefits.
Since I didn’t do anything manually, I went a step further and made one for when we get our 3 total elemental magics as well.

Triple Magic Tier List

Baste your eyes upon this behemoth, all 1140 possible magic combinations, sorted by “strength”. which in this case means the sum of strengths of the magic present in the combo, derived from their stats, and the strengths of interactions between these magics, as well as utility, like hazards created and status effect clears.
I decide to have 7 tiers, and split the list of magic in this manner:

10% / 15% / 15% / 20% / 15% / 15% / 10% per tier, respectively

So here are the results:

One tier per image:







Double Magic Tier List (BONUS)

With minimal modifications, I made the same program spit out results for 2 magics, its a bit less huge then the last image so here it is:

Some Caveats

While I think the tier list is decently accurate, it still fails to address some things that could be crucial to a combos success.
Mainly, interactions with other top tier combos, and it’s matchups against other combos in general. Frankly I couldn’t be bothered to do that, so I skipped it.

This is the list of magics by themselves, sorted by the written “statscore”:

Shadow 13.5
Earth 13
Wind 12.5
Water 12.5
Magma 12
Iron 12
Explosion 11
Ash 10.5
Sand 10.5
Crystal 10
Snow 9
Acid 9
Glass 9
Wood 9
Lightning 8.5
Ice 8
Plasma 8
Fire 8
Light 7.5
Poison 7

These scores took in consideration the magics damage, speed, size, DoT, hazards it creates and clash rates, but doesn’t include destruction (because I don’t think it matters that much and would probably create an even greater disbalance) and interactions (clears, status procs, +/-damage on enemies with a certain effect) because those only only come in play when there’s multiple magics present, which is when I include calculations for those.

At the end of the day, If you disagree that’s fine. I have a comprehensive tier list, you don’t, so I guess you gotta make your own to prove me wrong.

Source Code for the program used to generate the triple magic tier list

#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

struct magic
{
    string name;
    double statscore = 0;
    string status = "none";
    vector<pair<string, string>> procs;
    vector<string> clears;
    vector<pair<string, double>> interactions;
};

struct combo
{
    double score;
    int id;
    vector<string> magics;
    vector<string> clears;
    vector<string> statuses;
};

//for the sort
bool CompareCombos(combo c1, combo c2)
{
    return c1.score > c2.score;
}

//check if another magic in the combo already clears a status
bool AlreadyCleared(vector<string> CurrentClears, string NewClear)
{
    for(int i = 0; i < CurrentClears.size(); i++)
    {
        if(NewClear == CurrentClears[i])
            return 1;
    }

    return 0;
}

vector<magic> Magics;
vector<combo> Combos;

int main(void)
{
    ios::sync_with_stdio(false);

    //things used for reading from input file
    string sInput;
    double nInput;
    ifstream in("magicinput.txt");

    //skip the first 15 lines from the file, which have notes on the format
    for(int i = 0; i < 15; i++)
        getline(in, sInput);
    /*
    The format is:
    **Name**
    damage (number)
    speed (number)
    others (size, hazards, status threshold, dot, clash) (number, again)
    has status (0/1)
    status name
    # of procs
    procs pair<required status, proced status>
    # of clears
    clears (name of cleared status)
    # of interactions
    interactions pair<required status, interaction score>
    */

    //interaction strength is +/-0.5 points per +/-5% up to +/-40%, from where it is half of that

    for(int i = 0; i < 20; i++)
    {
        magic mInput;

        //get magics name from file
        in >> sInput;
        mInput.name = sInput;

        //get magics damage from file and add to statscore
        in >> nInput;
        mInput.statscore += (nInput - 0.75)/0.025;

        //get magics speed from file and add to statscore
        in >> nInput;
        if(nInput < 1)
            mInput.statscore -= (1 - nInput) / 0.05 * 0.5;
        else
        {
            mInput.statscore += max(0.0, min((nInput - 1.0), 0.4)) / 0.05 * 0.5;
            mInput.statscore += max(0.0, nInput - 1.4) / 0.05 * 0.25;
        }

        //get additional statscore (for DoT, hazards, clash, size)
        in >> nInput;
        mInput.statscore += nInput;

        //get the status that the magic gives on hit
        in >> nInput;
        if(nInput)
        {
            in >> sInput;
            mInput.status = sInput;
        }

        //get statuses that magics procs on targets with some existing status on them
        in >> nInput;
        for(int j = 0; j < nInput; j++)
        {
            string proc_result;

            in >> sInput;
            in >> proc_result;

            mInput.procs.push_back(make_pair(sInput, proc_result));
        }

        //get statuses the magic clears
        in >> nInput;
        for(int j = 0; j < nInput; j++)
        {
            in >> sInput;

            mInput.clears.push_back(sInput);
        }

        //get statuses that +/- the magics damage, and the strength of the interaction
        in >> nInput;
        for(int j = 0; j < nInput; j++)
        {
            double interaction_score;

            in >> sInput;
            in >> interaction_score;

            mInput.interactions.push_back(make_pair(sInput, interaction_score));
        }

        //add to magic list, duh
        Magics.push_back(mInput);
    }

    //id used for html
    int id = 1;

    for(int i = 0; i < 20; i++)
    {
        for(int j = i+1; j < 20; j++)
        {
            for(int k = j+1; k < 20; k++)
            {
                combo cInput;

                cInput.id = id++;

                //add names of magics in the combo
                cInput.magics.push_back(Magics[i].name);
                cInput.magics.push_back(Magics[j].name);
                cInput.magics.push_back(Magics[k].name);

                //add each magics status to the total statuses the combo can proc
                if(Magics[i].status != "none")
                    cInput.statuses.push_back(Magics[i].status);
                if(Magics[j].status != "none")
                    cInput.statuses.push_back(Magics[j].status);
                if(Magics[k].status != "none")
                    cInput.statuses.push_back(Magics[k].status);


                //add statuses that the magics can proc on enemies which were hit by other magic in the combo
                for(int x = 0; x < Magics[i].procs.size(); x++)
                {
                    for(int y = 0; y < cInput.statuses.size(); y++)
                    {
                        if(Magics[i].procs[x].first == cInput.statuses[y])
                            cInput.statuses.push_back(Magics[i].procs[x].second);
                    }
                }
                for(int x = 0; x < Magics[j].procs.size(); x++)
                {
                    for(int y = 0; y < cInput.statuses.size(); y++)
                    {
                        if(Magics[j].procs[x].first == cInput.statuses[y])
                            cInput.statuses.push_back(Magics[j].procs[x].second);
                    }
                }
                for(int x = 0; x < Magics[k].procs.size(); x++)
                {
                    for(int y = 0; y < cInput.statuses.size(); y++)
                    {
                        if(Magics[k].procs[x].first == cInput.statuses[y])
                            cInput.statuses.push_back(Magics[k].procs[x].second);
                    }
                }

                //add each magics statscores to the combo score
                cInput.score = (Magics[i].statscore + Magics[j].statscore + Magics[k].statscore) / 3;


                //add statuses which the combo can clear, check for overlap
                for(int x = 0; x < Magics[i].clears.size(); x++)
                    cInput.clears.push_back(Magics[i].clears[x]);

                for(int x = 0; x < Magics[j].clears.size(); x++)
                {
                    if(!AlreadyCleared(cInput.clears, Magics[j].clears[x]))
                        cInput.clears.push_back(Magics[j].clears[x]);
                }

                for(int x = 0; x < Magics[k].clears.size(); x++)
                {
                    if(!AlreadyCleared(cInput.clears, Magics[k].clears[x]))
                        cInput.clears.push_back(Magics[k].clears[x]);
                }

                //score the clears
                cInput.score += cInput.clears.size() * 0.5;

                //decrease score slightly if the combo clears its own statuses
                for(int x = 0; x < cInput.clears.size(); x++)
                    for(int y = 0; y < cInput.statuses.size(); y++)
                        cInput.score -= 0.25 * (cInput.clears[x] == cInput.statuses[y]);

                //add interaction strength between each magic with the total statuses
                for(int x = 0; x < Magics[i].interactions.size(); x++)
                {
                    for(int y = 0; y < cInput.statuses.size(); y++)
                    {
                        if(Magics[i].interactions[x].first == cInput.statuses[y])
                            cInput.score += Magics[i].interactions[x].second;
                    }
                }
                for(int x = 0; x < Magics[j].interactions.size(); x++)
                {
                    for(int y = 0; y < cInput.statuses.size(); y++)
                    {
                        if(Magics[j].interactions[x].first == cInput.statuses[y])
                            cInput.score += Magics[j].interactions[x].second;
                    }
                }
                for(int x = 0; x < Magics[k].interactions.size(); x++)
                {
                    for(int y = 0; y < cInput.statuses.size(); y++)
                    {
                        if(Magics[k].interactions[x].first == cInput.statuses[y])
                            cInput.score += Magics[k].interactions[x].second;
                    }
                }

                //add to combo list
                Combos.push_back(cInput);
            }
        }
    }

    //sort combos in ascending order
    sort(Combos.begin(), Combos.end(), CompareCombos);

    //print all combos andtheir scores, just to make sure it didi stuff
    for(int i = 0; i < Combos.size(); i++)
    {
        for(int j = 0; j < 3; j++)
            cout << Combos[i].magics[j] << " ";
        cout << Combos[i].score << endl << endl;
    }

    //lists of combos per tier, could've been all in one list but I'm not changing it now
    vector<string> Stier, Atier, Btier, Ctier, Dtier, Etier, Ftier;
    string tier;

    //how many combos per tier, respectively
    // 114, 171, 171, 228, 171, 171, 114

    int i = 1;

    //the gruesome proccess of generating the html for the combos image
    while(i <= 114)
    {
        //put the correct id for the combo
        tier += "<div class=\"character\" id=\"";
        tier += to_string(Combos[i-1].id);
        tier += "\" style=\"background-image: url(&quot;/images/chart/chart/arcane-oddesy-triple-magic-combination-tier-list-841197/";

        //Yandere-dev tier if/else wall to add the things that are from different batches of uploads
        if(Combos[i-1].id > 1075)
            tier += "zz1613954656";
        else if(Combos[i-1].id > 1004)
            tier += "zz1613954655";
        else if(Combos[i-1].id > 931)
            tier += "zz1613954654";
        else if(Combos[i-1].id > 867)
            tier += "zz1613954653";
        else if(Combos[i-1].id > 854)
            tier += "zz1613954652";
        else if(Combos[i-1].id > 853)
            tier += "zz1613954564";
        else if(Combos[i-1].id > 783)
            tier += "zz1613954563";
        else if(Combos[i-1].id > 711)
            tier += "zz1613954562";
        else if(Combos[i-1].id > 640)
            tier += "zz1613954561";
        else if(Combos[i-1].id > 580)
            tier += "zz1613954560";
        else if(Combos[i-1].id > 556)
            tier += "zz1613954500";
        else if(Combos[i-1].id > 492)
            tier += "zz1613954499";
        else if(Combos[i-1].id > 429)
            tier += "zz1613954498";
        else if(Combos[i-1].id > 366)
            tier += "zz1613954497";
        else if(Combos[i-1].id > 324)
            tier += "zz1613954496";

        //magic names from the combo
        tier += Combos[i-1].magics[0];
        tier += "-and-";
        tier += Combos[i-1].magics[1];
        tier += "-and-";
        tier += Combos[i-1].magics[2];
        tier += "-magicpng.png&quot;);\"></div>";

        //add to respective tier list
        Stier.push_back(tier);

        //increment counter and clear string used for generating the html
        i++;
        tier.clear();
    }

    //repeat for other tiers because ctrl+c/ctrl+v is easier that partitioning one big list later
    while(i <= 114+171)
    {
        tier += "<div class=\"character\" id=\"";
        tier += to_string(Combos[i-1].id);
        tier += "\" style=\"background-image: url(&quot;/images/chart/chart/arcane-oddesy-triple-magic-combination-tier-list-841197/";

        if(Combos[i-1].id > 1075)
            tier += "zz1613954656";
        else if(Combos[i-1].id > 1004)
            tier += "zz1613954655";
        else if(Combos[i-1].id > 931)
            tier += "zz1613954654";
        else if(Combos[i-1].id > 867)
            tier += "zz1613954653";
        else if(Combos[i-1].id > 854)
            tier += "zz1613954652";
        else if(Combos[i-1].id > 853)
            tier += "zz1613954564";
        else if(Combos[i-1].id > 783)
            tier += "zz1613954563";
        else if(Combos[i-1].id > 711)
            tier += "zz1613954562";
        else if(Combos[i-1].id > 640)
            tier += "zz1613954561";
        else if(Combos[i-1].id > 580)
            tier += "zz1613954560";
        else if(Combos[i-1].id > 556)
            tier += "zz1613954500";
        else if(Combos[i-1].id > 492)
            tier += "zz1613954499";
        else if(Combos[i-1].id > 429)
            tier += "zz1613954498";
        else if(Combos[i-1].id > 366)
            tier += "zz1613954497";
        else if(Combos[i-1].id > 324)
            tier += "zz1613954496";

        tier += Combos[i-1].magics[0];
        tier += "-and-";
        tier += Combos[i-1].magics[1];
        tier += "-and-";
        tier += Combos[i-1].magics[2];
        tier += "-magicpng.png&quot;);\"></div>";

        Atier.push_back(tier);

        i++;
        tier.clear();
    }

    //repeat for other tiers because ctrl+c/ctrl+v is easier that partitioning one big list later
    while(i <= 114+171+171)
    {
        tier += "<div class=\"character\" id=\"";
        tier += to_string(Combos[i-1].id);
        tier += "\" style=\"background-image: url(&quot;/images/chart/chart/arcane-oddesy-triple-magic-combination-tier-list-841197/";

        if(Combos[i-1].id > 1075)
            tier += "zz1613954656";
        else if(Combos[i-1].id > 1004)
            tier += "zz1613954655";
        else if(Combos[i-1].id > 931)
            tier += "zz1613954654";
        else if(Combos[i-1].id > 867)
            tier += "zz1613954653";
        else if(Combos[i-1].id > 854)
            tier += "zz1613954652";
        else if(Combos[i-1].id > 853)
            tier += "zz1613954564";
        else if(Combos[i-1].id > 783)
            tier += "zz1613954563";
        else if(Combos[i-1].id > 711)
            tier += "zz1613954562";
        else if(Combos[i-1].id > 640)
            tier += "zz1613954561";
        else if(Combos[i-1].id > 580)
            tier += "zz1613954560";
        else if(Combos[i-1].id > 556)
            tier += "zz1613954500";
        else if(Combos[i-1].id > 492)
            tier += "zz1613954499";
        else if(Combos[i-1].id > 429)
            tier += "zz1613954498";
        else if(Combos[i-1].id > 366)
            tier += "zz1613954497";
        else if(Combos[i-1].id > 324)
            tier += "zz1613954496";

        tier += Combos[i-1].magics[0];
        tier += "-and-";
        tier += Combos[i-1].magics[1];
        tier += "-and-";
        tier += Combos[i-1].magics[2];
        tier += "-magicpng.png&quot;);\"></div>";

        Btier.push_back(tier);

        i++;
        tier.clear();
    }

    //repeat for other tiers because ctrl+c/ctrl+v is easier that partitioning one big list later
    while(i <= 114+171+171+228)
    {
        tier += "<div class=\"character\" id=\"";
        tier += to_string(Combos[i-1].id);
        tier += "\" style=\"background-image: url(&quot;/images/chart/chart/arcane-oddesy-triple-magic-combination-tier-list-841197/";

        if(Combos[i-1].id > 1075)
            tier += "zz1613954656";
        else if(Combos[i-1].id > 1004)
            tier += "zz1613954655";
        else if(Combos[i-1].id > 931)
            tier += "zz1613954654";
        else if(Combos[i-1].id > 867)
            tier += "zz1613954653";
        else if(Combos[i-1].id > 854)
            tier += "zz1613954652";
        else if(Combos[i-1].id > 853)
            tier += "zz1613954564";
        else if(Combos[i-1].id > 783)
            tier += "zz1613954563";
        else if(Combos[i-1].id > 711)
            tier += "zz1613954562";
        else if(Combos[i-1].id > 640)
            tier += "zz1613954561";
        else if(Combos[i-1].id > 580)
            tier += "zz1613954560";
        else if(Combos[i-1].id > 556)
            tier += "zz1613954500";
        else if(Combos[i-1].id > 492)
            tier += "zz1613954499";
        else if(Combos[i-1].id > 429)
            tier += "zz1613954498";
        else if(Combos[i-1].id > 366)
            tier += "zz1613954497";
        else if(Combos[i-1].id > 324)
            tier += "zz1613954496";

        tier += Combos[i-1].magics[0];
        tier += "-and-";
        tier += Combos[i-1].magics[1];
        tier += "-and-";
        tier += Combos[i-1].magics[2];
        tier += "-magicpng.png&quot;);\"></div>";

        Ctier.push_back(tier);

        i++;
        tier.clear();
    }

    //repeat for other tiers because ctrl+c/ctrl+v is easier that partitioning one big list later
    while(i <= 114+171+171+228+171)
    {
        tier += "<div class=\"character\" id=\"";
        tier += to_string(Combos[i-1].id);
        tier += "\" style=\"background-image: url(&quot;/images/chart/chart/arcane-oddesy-triple-magic-combination-tier-list-841197/";

        if(Combos[i-1].id > 1075)
            tier += "zz1613954656";
        else if(Combos[i-1].id > 1004)
            tier += "zz1613954655";
        else if(Combos[i-1].id > 931)
            tier += "zz1613954654";
        else if(Combos[i-1].id > 867)
            tier += "zz1613954653";
        else if(Combos[i-1].id > 854)
            tier += "zz1613954652";
        else if(Combos[i-1].id > 853)
            tier += "zz1613954564";
        else if(Combos[i-1].id > 783)
            tier += "zz1613954563";
        else if(Combos[i-1].id > 711)
            tier += "zz1613954562";
        else if(Combos[i-1].id > 640)
            tier += "zz1613954561";
        else if(Combos[i-1].id > 580)
            tier += "zz1613954560";
        else if(Combos[i-1].id > 556)
            tier += "zz1613954500";
        else if(Combos[i-1].id > 492)
            tier += "zz1613954499";
        else if(Combos[i-1].id > 429)
            tier += "zz1613954498";
        else if(Combos[i-1].id > 366)
            tier += "zz1613954497";
        else if(Combos[i-1].id > 324)
            tier += "zz1613954496";

        tier += Combos[i-1].magics[0];
        tier += "-and-";
        tier += Combos[i-1].magics[1];
        tier += "-and-";
        tier += Combos[i-1].magics[2];
        tier += "-magicpng.png&quot;);\"></div>";

        Dtier.push_back(tier);

        i++;
        tier.clear();
    }

    //repeat for other tiers because ctrl+c/ctrl+v is easier that partitioning one big list later
    while(i <= 114+171+171+228+171+171)
    {
        tier += "<div class=\"character\" id=\"";
        tier += to_string(Combos[i-1].id);
        tier += "\" style=\"background-image: url(&quot;/images/chart/chart/arcane-oddesy-triple-magic-combination-tier-list-841197/";

        if(Combos[i-1].id > 1075)
            tier += "zz1613954656";
        else if(Combos[i-1].id > 1004)
            tier += "zz1613954655";
        else if(Combos[i-1].id > 931)
            tier += "zz1613954654";
        else if(Combos[i-1].id > 867)
            tier += "zz1613954653";
        else if(Combos[i-1].id > 854)
            tier += "zz1613954652";
        else if(Combos[i-1].id > 853)
            tier += "zz1613954564";
        else if(Combos[i-1].id > 783)
            tier += "zz1613954563";
        else if(Combos[i-1].id > 711)
            tier += "zz1613954562";
        else if(Combos[i-1].id > 640)
            tier += "zz1613954561";
        else if(Combos[i-1].id > 580)
            tier += "zz1613954560";
        else if(Combos[i-1].id > 556)
            tier += "zz1613954500";
        else if(Combos[i-1].id > 492)
            tier += "zz1613954499";
        else if(Combos[i-1].id > 429)
            tier += "zz1613954498";
        else if(Combos[i-1].id > 366)
            tier += "zz1613954497";
        else if(Combos[i-1].id > 324)
            tier += "zz1613954496";

        tier += Combos[i-1].magics[0];
        tier += "-and-";
        tier += Combos[i-1].magics[1];
        tier += "-and-";
        tier += Combos[i-1].magics[2];
        tier += "-magicpng.png&quot;);\"></div>";

        Etier.push_back(tier);

        i++;
        tier.clear();
    }

    //repeat for other tiers because ctrl+c/ctrl+v is easier that partitioning one big list later
    while(i <= 114+171+171+228+171+171+114)
    {
        tier += "<div class=\"character\" id=\"";
        tier += to_string(Combos[i-1].id);
        tier += "\" style=\"background-image: url(&quot;/images/chart/chart/arcane-oddesy-triple-magic-combination-tier-list-841197/";

        if(Combos[i-1].id > 1075)
                tier += "zz1613954656";
        else if(Combos[i-1].id > 1004)
            tier += "zz1613954655";
        else if(Combos[i-1].id > 931)
            tier += "zz1613954654";
        else if(Combos[i-1].id > 867)
            tier += "zz1613954653";
        else if(Combos[i-1].id > 854)
            tier += "zz1613954652";
        else if(Combos[i-1].id > 853)
            tier += "zz1613954564";
        else if(Combos[i-1].id > 783)
            tier += "zz1613954563";
        else if(Combos[i-1].id > 711)
            tier += "zz1613954562";
        else if(Combos[i-1].id > 640)
            tier += "zz1613954561";
        else if(Combos[i-1].id > 580)
            tier += "zz1613954560";
        else if(Combos[i-1].id > 556)
            tier += "zz1613954500";
        else if(Combos[i-1].id > 492)
            tier += "zz1613954499";
        else if(Combos[i-1].id > 429)
            tier += "zz1613954498";
        else if(Combos[i-1].id > 366)
            tier += "zz1613954497";
        else if(Combos[i-1].id > 324)
            tier += "zz1613954496";

        tier += Combos[i-1].magics[0];
        tier += "-and-";
        tier += Combos[i-1].magics[1];
        tier += "-and-";
        tier += Combos[i-1].magics[2];
        tier += "-magicpng.png&quot;);\"></div>";

        Ftier.push_back(tier);

        i++;
        tier.clear();
    }

    //time to write to the output file
    ofstream out("3magicoutput.txt");

    //write each tier separately with a nice indicator for easier inspect elementing
    out << "S tier:" << endl << endl;
    out << "<div class=\"tier sort\">";
    for(int i = 0; i < Stier.size(); i++)
        out << Stier[i] << endl;
    out << "</div>" << endl << endl;

    out << "A tier:" << endl << endl;
    out << "<div class=\"tier sort\">";
    for(int i = 0; i < Atier.size(); i++)
        out << Atier[i] << endl;
    out << "</div>" << endl << endl;

    out << "B tier:" << endl << endl;
    out << "<div class=\"tier sort\">";
    for(int i = 0; i < Btier.size(); i++)
        out << Btier[i] << endl;
    out << "</div>" << endl << endl;

    out << "C tier:" << endl << endl;
    out << "<div class=\"tier sort\">";
    for(int i = 0; i < Ctier.size(); i++)
        out << Ctier[i] << endl;
    out << "</div>" << endl << endl;

    out << "D tier:" << endl << endl;
    out << "<div class=\"tier sort\">";
    for(int i = 0; i < Dtier.size(); i++)
        out << Dtier[i] << endl;
    out << "</div>" << endl << endl;

    out << "E tier:" << endl << endl;
    out << "<div class=\"tier sort\">";
    for(int i = 0; i < Etier.size(); i++)
        out << Etier[i] << endl;
    out << "</div>" << endl << endl;

    out << "F tier:" << endl << endl;
    out << "<div class=\"tier sort\">";
    for(int i = 0; i < Ftier.size(); i++)
        out << Ftier[i] << endl;
    out << "</div>" << endl << endl;

    //profit

    return 0;
}
  • Should compile with any C++ compiler
  • By default, reads from a file called “magicinput.txt”, where magic info is stored in the format that is shown in a comment block at the beginning of the main() function, keep in mind it skips the first 15 lines which by default contain those same notes on the format
  • By default, writes to a file called “3magicoutput.txt”, where it creates html for each tier, that can be inspect elemented into the TierMaker tier lists to visualize the results, keep in mind that you should replace the whole “tier sort” type element with the html block for the appropriate tier
  • Feel free to yoink it, reuse it, edit it and whatever else you want

Credits

@NoBanana for the tier list templates and ideas that further improved the ranking.
@Meta for the Magic’s document, and I also used his magic strength scoring system with slight modifications to determine the strength of just the stats of each magic.

Change Log

Day 1 Patch (7th of March 2021)

Version 1.1 (9th of March 2021)

27 Likes

im too lazy to read this

3 Likes

I can’t even zoom in to see the triple magic tier list :frpensive:

2 Likes

poision users malding… ash on top :muscle:

3 Likes

I chopped up the huge image, it’s all visible now. Doesn’t have quite the intimidating effect that the long rectangle had though…

1 Like

My planned magic combo is A tier :sunglasses:

Did you write a program to automatically fill in the tierlist, or did you actually drag every magic into the correct tier by hand? Impressive either way. I was planning on doing this myself, but I wanted to factor in matchups which made it more effort than I was willing to put in.
also you should definitely keep the huge long rectangle of the full list in the post, even if it’s not actually readable

I’d be interested in seeing the source code for this. Some placments are obvious given your criteria (Lightning/Ice/Water in S tier), but others not so much (Acid/Fire/Poison in E tier?). I’d love to see exactly how everything was weighted.

I made the program automatically generate html that I could inspect element into the right places to then generate the tier list.
The process was still gruesome for the triple tier list, mainly because of the hellish way you uploaded the images, I had to go through all of them to find out at which IDs does the html for the image change, and in which way.

I’d gladly slide you the source code, but its quite lengthy and bloated, so I think I should put at least a bit of comments so it isn’t just a load of gibberish. Also I should probably add some explanation as to what the format of the data I loaded from a file is.
If you don’t mind 600 lines raw, I can send it here immediately, otherwise I will make it a bit more readable first (It’s actually quite readable imo, it’s just that it’d be easier to understand with some comments)

And for the weird placements, it’s because I couldn’t be bothered getting the scoring system just right, I figured it was good enough and went with it.

The inspect element trick is actually pretty clever.
If you didn’t figure out the pattern, every magic permutation is iterated through in alphabetical order, and then duplicate combinations are thrown away.
So it first tries Acid/Ash/Crystal, then Acid/Ash/Earth, etc. When it tries Ash/Acid/Crystal, it’ll detect the duplicate and not use that.

I’m happy to read raw source code, but comments wouldn’t hurt either. I’m not going to read it right away, so you can take your time if you like.

The biggest issue with the html wasn’t the order, that made it easier, but the way that the uploaded files are named. Since they we’re put up in batches, as you said, they’re names don’t only differ in the magics that are in the combo, but some other stuff I manually went through to check at what ID does it change, and in which way. You’ll see the beautiful implementation, you can’t miss it.

I took the time to add some comments, hopefully there aren’t too many of them.

#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

struct magic
{
    string name;
    double statscore = 0;
    string status = "none";
    vector<pair<string, string>> procs;
    vector<string> clears;
    vector<pair<string, double>> interactions;
};

struct combo
{
    double score;
    int id;
    vector<string> magics;
    vector<string> clears;
    vector<string> statuses;
};

//for the sorts
bool CompareCombos(combo c1, combo c2)
{
    return c1.score > c2.score;
}

//check if another magic in the combo already clears a status
bool AlreadyCleared(vector<string> CurrentClears, string NewClear)
{
    for(int i = 0; i < CurrentClears.size(); i++)
    {
        if(NewClear == CurrentClears[i])
            return 1;
    }

    return 0;
}

vector<magic> Magics;
vector<combo> Combos;

int main(void)
{
    ios::sync_with_stdio(false);

    //things used for reading from input file
    string sInput;
    double nInput;
    ifstream in("magicinput.txt");

    //skip the first 15 lines from the file, which have notes on the format
    for(int i = 0; i < 15; i++)
        getline(in, sInput);
    /*
    The format is:
    **Name**
    damage (number)
    speed (number)
    others (size, hazards, status threshold, dot, clash) (number, again)
    has status (0/1)
    status name
    # of procs
    procs pair<required status, proced status>
    # of clears
    clears (name of cleared status)
    # of interactions
    interactions pair<required status, interaction score>
    */

    //interaction strength is +/-0.5 points per +/-5% up to +/-40%, from where it is half of that

    for(int i = 0; i < 20; i++)
    {
        magic mInput;

        //get magics name from file
        in >> sInput;
        mInput.name = sInput;

        //get magics damage from file and add to statscore
        in >> nInput;
        mInput.statscore += (nInput - 0.75)/0.025;

        //get magics speed from file and add to statscore
        in >> nInput;
        if(nInput < 1)
            mInput.statscore -= (1 - nInput) / 0.05 * 0.5;
        else
        {
            mInput.statscore += max(0.0, min((nInput - 1.0), 0.4)) / 0.05 * 0.5;
            mInput.statscore += max(0.0, nInput - 1.4) / 0.05 * 0.25;
        }

        //get additional statscore (for DoT, hazards, clash, size)
        in >> nInput;
        mInput.statscore += nInput;

        //get the status that the magic gives on hit
        in >> nInput;
        if(nInput)
        {
            in >> sInput;
            mInput.status = sInput;
        }

        //get statuses that magics procs on targets with some existing status on them
        in >> nInput;
        for(int j = 0; j < nInput; j++)
        {
            string proc_result;

            in >> sInput;
            in >> proc_result;

            mInput.procs.push_back(make_pair(sInput, proc_result));
        }

        //get statuses the magic clears
        in >> nInput;
        for(int j = 0; j < nInput; j++)
        {
            in >> sInput;

            mInput.clears.push_back(sInput);
        }

        //get statuses that +/- the magics damage, and the strength of the interaction
        in >> nInput;
        for(int j = 0; j < nInput; j++)
        {
            double interaction_score;

            in >> sInput;
            in >> interaction_score;

            mInput.interactions.push_back(make_pair(sInput, interaction_score));
        }

        //add to magic list, duh
        Magics.push_back(mInput);
    }

    //id used for html
    int id = 1;

    for(int i = 0; i < 20; i++)
    {
        for(int j = i+1; j < 20; j++)
        {
            for(int k = j+1; k < 20; k++)
            {
                combo cInput;

                cInput.id = id++;

                //add names of magics in the combo
                cInput.magics.push_back(Magics[i].name);
                cInput.magics.push_back(Magics[j].name);
                cInput.magics.push_back(Magics[k].name);

                //add each magics status to the total statuses the combo can proc
                if(Magics[i].status != "none")
                    cInput.statuses.push_back(Magics[i].status);
                if(Magics[j].status != "none")
                    cInput.statuses.push_back(Magics[j].status);
                if(Magics[k].status != "none")
                    cInput.statuses.push_back(Magics[k].status);


                //add statuses that the magics can proc on enemies which were hit by other magic in the combo
                for(int x = 0; x < Magics[i].procs.size(); x++)
                {
                    for(int y = 0; y < cInput.statuses.size(); y++)
                    {
                        if(Magics[i].procs[x].first == cInput.statuses[y])
                            cInput.statuses.push_back(Magics[i].procs[x].second);
                    }
                }
                for(int x = 0; x < Magics[j].procs.size(); x++)
                {
                    for(int y = 0; y < cInput.statuses.size(); y++)
                    {
                        if(Magics[j].procs[x].first == cInput.statuses[y])
                            cInput.statuses.push_back(Magics[j].procs[x].second);
                    }
                }
                for(int x = 0; x < Magics[k].procs.size(); x++)
                {
                    for(int y = 0; y < cInput.statuses.size(); y++)
                    {
                        if(Magics[k].procs[x].first == cInput.statuses[y])
                            cInput.statuses.push_back(Magics[k].procs[x].second);
                    }
                }

                //add each magics statscores to teh combo score
                cInput.score = Magics[i].statscore + Magics[j].statscore + Magics[k].statscore;


                //add statuses which the combo can clear, check for overlap
                for(int x = 0; x < Magics[i].clears.size(); x++)
                    cInput.clears.push_back(Magics[i].clears[x]);

                for(int x = 0; x < Magics[j].clears.size(); x++)
                {
                    if(!AlreadyCleared(cInput.clears, Magics[j].clears[x]))
                        cInput.clears.push_back(Magics[j].clears[x]);
                }

                for(int x = 0; x < Magics[k].clears.size(); x++)
                {
                    if(!AlreadyCleared(cInput.clears, Magics[k].clears[x]))
                        cInput.clears.push_back(Magics[k].clears[x]);
                }

                //score the clears
                cInput.score += cInput.clears.size() * 0.5;

                //decrease score slightly if the combo clears its own statuses
                for(int x = 0; x < cInput.clears.size(); x++)
                    for(int y = 0; y < cInput.statuses.size(); y++)
                        cInput.score -= 0.25 * (cInput.clears[x] == cInput.statuses[y]);

                //add interaction strength between each magic with the total statuses
                for(int x = 0; x < Magics[i].interactions.size(); x++)
                {
                    for(int y = 0; y < cInput.statuses.size(); y++)
                    {
                        if(Magics[i].interactions[x].first == cInput.statuses[y])
                            cInput.score += Magics[i].interactions[x].second;
                    }
                }
                for(int x = 0; x < Magics[j].interactions.size(); x++)
                {
                    for(int y = 0; y < cInput.statuses.size(); y++)
                    {
                        if(Magics[j].interactions[x].first == cInput.statuses[y])
                            cInput.score += Magics[j].interactions[x].second;
                    }
                }
                for(int x = 0; x < Magics[k].interactions.size(); x++)
                {
                    for(int y = 0; y < cInput.statuses.size(); y++)
                    {
                        if(Magics[k].interactions[x].first == cInput.statuses[y])
                            cInput.score += Magics[k].interactions[x].second;
                    }
                }

                //add to combo list
                Combos.push_back(cInput);
            }
        }
    }

    //sort combos in ascending order
    sort(Combos.begin(), Combos.end(), CompareCombos);

    //print all combos andtheir scores, just to make sure it didi stuff
    for(int i = 0; i < Combos.size(); i++)
    {
        for(int j = 0; j < 3; j++)
            cout << Combos[i].magics[j] << " ";
        cout << Combos[i].score << endl << endl;
    }

    //lists of combos per tier, could've been all in one list but I'm not changing it now
    vector<string> Stier, Atier, Btier, Ctier, Dtier, Etier, Ftier;
    string tier;

    //how many combos per tier, respectively
    // 114, 171, 171, 228, 171, 171, 114

    int i = 1;

    //the gruesome proccess of generating the html for the combos image
    while(i <= 114)
    {
        //put the correct id for the combo
        tier += "<div class=\"character\" id=\"";
        tier += to_string(Combos[i-1].id);
        tier += "\" style=\"background-image: url(&quot;/images/chart/chart/arcane-oddesy-triple-magic-combination-tier-list-841197/";

        //Yandere-dev tier if/else wall to add the things that are from different batches of uploads
        if(Combos[i-1].id > 1075)
            tier += "zz1613954656";
        else if(Combos[i-1].id > 1004)
            tier += "zz1613954655";
        else if(Combos[i-1].id > 931)
            tier += "zz1613954654";
        else if(Combos[i-1].id > 867)
            tier += "zz1613954653";
        else if(Combos[i-1].id > 854)
            tier += "zz1613954652";
        else if(Combos[i-1].id > 853)
            tier += "zz1613954564";
        else if(Combos[i-1].id > 783)
            tier += "zz1613954563";
        else if(Combos[i-1].id > 711)
            tier += "zz1613954562";
        else if(Combos[i-1].id > 640)
            tier += "zz1613954561";
        else if(Combos[i-1].id > 580)
            tier += "zz1613954560";
        else if(Combos[i-1].id > 556)
            tier += "zz1613954500";
        else if(Combos[i-1].id > 492)
            tier += "zz1613954499";
        else if(Combos[i-1].id > 429)
            tier += "zz1613954498";
        else if(Combos[i-1].id > 366)
            tier += "zz1613954497";
        else if(Combos[i-1].id > 324)
            tier += "zz1613954496";

        //magic names from the combo
        tier += Combos[i-1].magics[0];
        tier += "-and-";
        tier += Combos[i-1].magics[1];
        tier += "-and-";
        tier += Combos[i-1].magics[2];
        tier += "-magicpng.png&quot;);\"></div>";

        //add to respective tier list
        Stier.push_back(tier);

        //increment counter and clear string used for generating the html
        i++;
        tier.clear();
    }

    //repeat for other tiers because ctrl+c/ctrl+v is easier that partitioning one big list later
    while(i <= 114+171)
    {
        tier += "<div class=\"character\" id=\"";
        tier += to_string(Combos[i-1].id);
        tier += "\" style=\"background-image: url(&quot;/images/chart/chart/arcane-oddesy-triple-magic-combination-tier-list-841197/";

        if(Combos[i-1].id > 1075)
            tier += "zz1613954656";
        else if(Combos[i-1].id > 1004)
            tier += "zz1613954655";
        else if(Combos[i-1].id > 931)
            tier += "zz1613954654";
        else if(Combos[i-1].id > 867)
            tier += "zz1613954653";
        else if(Combos[i-1].id > 854)
            tier += "zz1613954652";
        else if(Combos[i-1].id > 853)
            tier += "zz1613954564";
        else if(Combos[i-1].id > 783)
            tier += "zz1613954563";
        else if(Combos[i-1].id > 711)
            tier += "zz1613954562";
        else if(Combos[i-1].id > 640)
            tier += "zz1613954561";
        else if(Combos[i-1].id > 580)
            tier += "zz1613954560";
        else if(Combos[i-1].id > 556)
            tier += "zz1613954500";
        else if(Combos[i-1].id > 492)
            tier += "zz1613954499";
        else if(Combos[i-1].id > 429)
            tier += "zz1613954498";
        else if(Combos[i-1].id > 366)
            tier += "zz1613954497";
        else if(Combos[i-1].id > 324)
            tier += "zz1613954496";

        tier += Combos[i-1].magics[0];
        tier += "-and-";
        tier += Combos[i-1].magics[1];
        tier += "-and-";
        tier += Combos[i-1].magics[2];
        tier += "-magicpng.png&quot;);\"></div>";

        Atier.push_back(tier);

        i++;
        tier.clear();
    }

    //repeat for other tiers because ctrl+c/ctrl+v is easier that partitioning one big list later
    while(i <= 114+171+171)
    {
        tier += "<div class=\"character\" id=\"";
        tier += to_string(Combos[i-1].id);
        tier += "\" style=\"background-image: url(&quot;/images/chart/chart/arcane-oddesy-triple-magic-combination-tier-list-841197/";

        if(Combos[i-1].id > 1075)
            tier += "zz1613954656";
        else if(Combos[i-1].id > 1004)
            tier += "zz1613954655";
        else if(Combos[i-1].id > 931)
            tier += "zz1613954654";
        else if(Combos[i-1].id > 867)
            tier += "zz1613954653";
        else if(Combos[i-1].id > 854)
            tier += "zz1613954652";
        else if(Combos[i-1].id > 853)
            tier += "zz1613954564";
        else if(Combos[i-1].id > 783)
            tier += "zz1613954563";
        else if(Combos[i-1].id > 711)
            tier += "zz1613954562";
        else if(Combos[i-1].id > 640)
            tier += "zz1613954561";
        else if(Combos[i-1].id > 580)
            tier += "zz1613954560";
        else if(Combos[i-1].id > 556)
            tier += "zz1613954500";
        else if(Combos[i-1].id > 492)
            tier += "zz1613954499";
        else if(Combos[i-1].id > 429)
            tier += "zz1613954498";
        else if(Combos[i-1].id > 366)
            tier += "zz1613954497";
        else if(Combos[i-1].id > 324)
            tier += "zz1613954496";

        tier += Combos[i-1].magics[0];
        tier += "-and-";
        tier += Combos[i-1].magics[1];
        tier += "-and-";
        tier += Combos[i-1].magics[2];
        tier += "-magicpng.png&quot;);\"></div>";

        Btier.push_back(tier);

        i++;
        tier.clear();
    }

    //repeat for other tiers because ctrl+c/ctrl+v is easier that partitioning one big list later
    while(i <= 114+171+171+228)
    {
        tier += "<div class=\"character\" id=\"";
        tier += to_string(Combos[i-1].id);
        tier += "\" style=\"background-image: url(&quot;/images/chart/chart/arcane-oddesy-triple-magic-combination-tier-list-841197/";

        if(Combos[i-1].id > 1075)
            tier += "zz1613954656";
        else if(Combos[i-1].id > 1004)
            tier += "zz1613954655";
        else if(Combos[i-1].id > 931)
            tier += "zz1613954654";
        else if(Combos[i-1].id > 867)
            tier += "zz1613954653";
        else if(Combos[i-1].id > 854)
            tier += "zz1613954652";
        else if(Combos[i-1].id > 853)
            tier += "zz1613954564";
        else if(Combos[i-1].id > 783)
            tier += "zz1613954563";
        else if(Combos[i-1].id > 711)
            tier += "zz1613954562";
        else if(Combos[i-1].id > 640)
            tier += "zz1613954561";
        else if(Combos[i-1].id > 580)
            tier += "zz1613954560";
        else if(Combos[i-1].id > 556)
            tier += "zz1613954500";
        else if(Combos[i-1].id > 492)
            tier += "zz1613954499";
        else if(Combos[i-1].id > 429)
            tier += "zz1613954498";
        else if(Combos[i-1].id > 366)
            tier += "zz1613954497";
        else if(Combos[i-1].id > 324)
            tier += "zz1613954496";

        tier += Combos[i-1].magics[0];
        tier += "-and-";
        tier += Combos[i-1].magics[1];
        tier += "-and-";
        tier += Combos[i-1].magics[2];
        tier += "-magicpng.png&quot;);\"></div>";

        Ctier.push_back(tier);

        i++;
        tier.clear();
    }

    //repeat for other tiers because ctrl+c/ctrl+v is easier that partitioning one big list later
    while(i <= 114+171+171+228+171)
    {
        tier += "<div class=\"character\" id=\"";
        tier += to_string(Combos[i-1].id);
        tier += "\" style=\"background-image: url(&quot;/images/chart/chart/arcane-oddesy-triple-magic-combination-tier-list-841197/";

        if(Combos[i-1].id > 1075)
            tier += "zz1613954656";
        else if(Combos[i-1].id > 1004)
            tier += "zz1613954655";
        else if(Combos[i-1].id > 931)
            tier += "zz1613954654";
        else if(Combos[i-1].id > 867)
            tier += "zz1613954653";
        else if(Combos[i-1].id > 854)
            tier += "zz1613954652";
        else if(Combos[i-1].id > 853)
            tier += "zz1613954564";
        else if(Combos[i-1].id > 783)
            tier += "zz1613954563";
        else if(Combos[i-1].id > 711)
            tier += "zz1613954562";
        else if(Combos[i-1].id > 640)
            tier += "zz1613954561";
        else if(Combos[i-1].id > 580)
            tier += "zz1613954560";
        else if(Combos[i-1].id > 556)
            tier += "zz1613954500";
        else if(Combos[i-1].id > 492)
            tier += "zz1613954499";
        else if(Combos[i-1].id > 429)
            tier += "zz1613954498";
        else if(Combos[i-1].id > 366)
            tier += "zz1613954497";
        else if(Combos[i-1].id > 324)
            tier += "zz1613954496";

        tier += Combos[i-1].magics[0];
        tier += "-and-";
        tier += Combos[i-1].magics[1];
        tier += "-and-";
        tier += Combos[i-1].magics[2];
        tier += "-magicpng.png&quot;);\"></div>";

        Dtier.push_back(tier);

        i++;
        tier.clear();
    }

    //repeat for other tiers because ctrl+c/ctrl+v is easier that partitioning one big list later
    while(i <= 114+171+171+228+171+171)
    {
        tier += "<div class=\"character\" id=\"";
        tier += to_string(Combos[i-1].id);
        tier += "\" style=\"background-image: url(&quot;/images/chart/chart/arcane-oddesy-triple-magic-combination-tier-list-841197/";

        if(Combos[i-1].id > 1075)
            tier += "zz1613954656";
        else if(Combos[i-1].id > 1004)
            tier += "zz1613954655";
        else if(Combos[i-1].id > 931)
            tier += "zz1613954654";
        else if(Combos[i-1].id > 867)
            tier += "zz1613954653";
        else if(Combos[i-1].id > 854)
            tier += "zz1613954652";
        else if(Combos[i-1].id > 853)
            tier += "zz1613954564";
        else if(Combos[i-1].id > 783)
            tier += "zz1613954563";
        else if(Combos[i-1].id > 711)
            tier += "zz1613954562";
        else if(Combos[i-1].id > 640)
            tier += "zz1613954561";
        else if(Combos[i-1].id > 580)
            tier += "zz1613954560";
        else if(Combos[i-1].id > 556)
            tier += "zz1613954500";
        else if(Combos[i-1].id > 492)
            tier += "zz1613954499";
        else if(Combos[i-1].id > 429)
            tier += "zz1613954498";
        else if(Combos[i-1].id > 366)
            tier += "zz1613954497";
        else if(Combos[i-1].id > 324)
            tier += "zz1613954496";

        tier += Combos[i-1].magics[0];
        tier += "-and-";
        tier += Combos[i-1].magics[1];
        tier += "-and-";
        tier += Combos[i-1].magics[2];
        tier += "-magicpng.png&quot;);\"></div>";

        Etier.push_back(tier);

        i++;
        tier.clear();
    }

    //repeat for other tiers because ctrl+c/ctrl+v is easier that partitioning one big list later
    while(i <= 114+171+171+228+171+171+114)
    {
        tier += "<div class=\"character\" id=\"";
        tier += to_string(Combos[i-1].id);
        tier += "\" style=\"background-image: url(&quot;/images/chart/chart/arcane-oddesy-triple-magic-combination-tier-list-841197/";

        if(Combos[i-1].id > 1075)
                tier += "zz1613954656";
        else if(Combos[i-1].id > 1004)
            tier += "zz1613954655";
        else if(Combos[i-1].id > 931)
            tier += "zz1613954654";
        else if(Combos[i-1].id > 867)
            tier += "zz1613954653";
        else if(Combos[i-1].id > 854)
            tier += "zz1613954652";
        else if(Combos[i-1].id > 853)
            tier += "zz1613954564";
        else if(Combos[i-1].id > 783)
            tier += "zz1613954563";
        else if(Combos[i-1].id > 711)
            tier += "zz1613954562";
        else if(Combos[i-1].id > 640)
            tier += "zz1613954561";
        else if(Combos[i-1].id > 580)
            tier += "zz1613954560";
        else if(Combos[i-1].id > 556)
            tier += "zz1613954500";
        else if(Combos[i-1].id > 492)
            tier += "zz1613954499";
        else if(Combos[i-1].id > 429)
            tier += "zz1613954498";
        else if(Combos[i-1].id > 366)
            tier += "zz1613954497";
        else if(Combos[i-1].id > 324)
            tier += "zz1613954496";

        tier += Combos[i-1].magics[0];
        tier += "-and-";
        tier += Combos[i-1].magics[1];
        tier += "-and-";
        tier += Combos[i-1].magics[2];
        tier += "-magicpng.png&quot;);\"></div>";

        Ftier.push_back(tier);

        i++;
        tier.clear();
    }

    //time to write to the output file
    ofstream out("3magicoutput.txt");

    //write each tier separately with a nice indicator for easier inspect elementing
    out << "S tier:" << endl << endl;
    for(int i = 0; i < Stier.size(); i++)
        out << Stier[i] << endl;
    out << endl;

    out << "A tier:" << endl << endl;
    for(int i = 0; i < Atier.size(); i++)
        out << Atier[i] << endl;
    out << endl;

    out << "B tier:" << endl << endl;
    for(int i = 0; i < Btier.size(); i++)
        out << Btier[i] << endl;
    out << endl;

    out << "C tier:" << endl << endl;
    for(int i = 0; i < Ctier.size(); i++)
        out << Ctier[i] << endl;
    out << endl;

    out << "D tier:" << endl << endl;
    for(int i = 0; i < Dtier.size(); i++)
        out << Dtier[i] << endl;
    out << endl;

    out << "E tier:" << endl << endl;
    for(int i = 0; i < Etier.size(); i++)
        out << Etier[i] << endl;
    out << endl;

    out << "F tier:" << endl << endl;
    for(int i = 0; i < Ftier.size(); i++)
        out << Ftier[i] << endl;
    out << endl;

    //profit

    return 0;
}

2 Likes

Aaand i now remembered that I forgot to include the crystallizes status effect to any magics clear list.

At least now I know what I’ll be doing tomorrow morning.

man with dedication

i guess my planned combination of crystal, metal, and magma is meta lol

Eventual Resurrection of Magma. Though did it really die.

yes metal crystal magma on top

This isn’t very reliable at all but neat anyways.

nope poison by far has worst synergies its canon facts now… :troll:

im boutta be accused of metamancing

how much free time do you have

it was done using a program its definitely not done by hand

what the hell is this and is it accurate

taking one look at the lowest tiers tells me no
taking a closer look also tells me no, but thats mainly because it puts neutral combinations at high tiers

1 Like